summaryrefslogtreecommitdiff
path: root/src/game/world
diff options
context:
space:
mode:
authorkasull <qsullian@gmail.com>2026-03-11 00:24:47 -0400
committerkasull <qsullian@gmail.com>2026-03-11 00:24:47 -0400
commitae6718ec0fb21077b767e189aca26b0fed488775 (patch)
treea4216103d8a9a77edbc470dc4ab094e77ac30261 /src/game/world
parentbc1ea16c5be92e3bc810b0a30e01fbc9a7f191a9 (diff)
editor object placement and context menus
replace the editor menubar dropdown flow with a reusable context menu component merge sprite/entity placement into a single object tool persist entities, and add undo support for created sprites and entities
Diffstat (limited to 'src/game/world')
-rw-r--r--src/game/world/map.cpp56
-rw-r--r--src/game/world/map.h2
2 files changed, 58 insertions, 0 deletions
diff --git a/src/game/world/map.cpp b/src/game/world/map.cpp
index ba6bb00..a44f191 100644
--- a/src/game/world/map.cpp
+++ b/src/game/world/map.cpp
@@ -303,6 +303,40 @@ STAT map_sprites_from_section( WORLD_MAP* m, GAME_DATA* g, CFG_SECTION* sprites,
return parsec > 0 ? STAT_OK : STAT_ERR;
}
+STAT map_entities_from_section( WORLD_MAP* m, GAME_DATA*, CFG_SECTION* entities, U32 entityc ) {
+ if( !entityc ) {
+ dlog( "map_entities_from_section() : no entities in %s\n", m->name );
+ return STAT_OK;
+ }
+
+ U32 parsec = 0;
+ char entitysec[256] = { 0 };
+ for( U32 i = 0; i < entityc; ++i ) {
+ MAP_ENTITY entity{};
+
+ sprintf( entitysec, "%d", i );
+ CFG_SECTION* s = cfg_section( entities, entitysec );
+ if( !s ) {
+ dlog( "map_entities_from_section() : missing entity %d in %s\n", i, m->name );
+ continue;
+ }
+
+ CFG_INT* classid = cfg_int( s, "classid" );
+ CFG_VEC3* pos = cfg_vec3( s, "pos" );
+ if( !classid || !pos ) {
+ dlog( "map_entities_from_section() : invalid entity %d in %s\n", i, m->name );
+ continue;
+ }
+
+ entity.classid = (U32)classid->value;
+ entity.pos = pos->value;
+ m->entities.push( entity );
+ ++parsec;
+ }
+
+ return parsec > 0 ? STAT_OK : STAT_ERR;
+}
+
STAT map_skybox_from_section( CFG_SECTION* s, GAME_DATA* g, WORLD_MAP* m ) {
CFG_SECTION* props = cfg_section( s, "props" );
if( !props )
@@ -496,6 +530,13 @@ WORLD_MAP* map_from_file( GAME_DATA* game, const char* path ) {
if( !OK( map_sprites_from_section( m, game, sprites, spritec->value ) ) ) { delete m; return 0; }
}
+ CFG_INT* entityc = cfg_int( s, "entitycount" );
+ if( entityc ) {
+ CFG_SECTION* entities = cfg_section( s, "entities" );
+ if( !entities ) { dlog( errstr, path, "entities" ); delete m; return 0; }
+ if( !OK( map_entities_from_section( m, game, entities, entityc->value ) ) ) { delete m; return 0; }
+ }
+
CFG_VEC3* startpos = cfg_vec3( s, "startpos" );
if( !startpos ) {
dlog( errstr, path, "startpos" );
@@ -537,6 +578,7 @@ void map_serialize_info( CFG_SECTION* s, WORLD_MAP* map ) {
cfg_int( "polycount", s, map->polygons.size );
cfg_int( "propcount", s, map->props.size );
cfg_int( "spritecount", s, map->sprites.size );
+ cfg_int( "entitycount", s, map->entities.size );
cfg_vec3( "startpos", s, map->startpos );
cfg_float( "startang", s, map->startang );
}
@@ -597,6 +639,19 @@ void map_serialize_sprites( CFG_SECTION* s, WORLD_MAP* map ) {
} );
}
+void map_serialize_entities( CFG_SECTION* s, WORLD_MAP* map ) {
+ CFG_SECTION* entities = cfg_section_new( "entities", s );
+ char name[64];
+
+ U32 i = 0;
+ map->entities.each( fn( MAP_ENTITY* e ) {
+ sprintf( name, "%d", i++ );
+ CFG_SECTION* entitysec = cfg_section_new( name, entities );
+ cfg_int( "classid", entitysec, e->classid );
+ cfg_vec3( "pos", entitysec, e->pos );
+ } );
+}
+
void map_serialize_props( CFG_SECTION* s, WORLD_MAP* map ) {
CFG_SECTION* props = cfg_section_new( "props", s );
char name[64];
@@ -623,6 +678,7 @@ CFG_SECTION* map_serialize( WORLD_MAP* map ) {
map_serialize_walls( s, map );
map_serialize_polygons( s, map );
map_serialize_sprites( s, map );
+ map_serialize_entities( s, map );
return s;
}
diff --git a/src/game/world/map.h b/src/game/world/map.h
index 29022db..f3f56f8 100644
--- a/src/game/world/map.h
+++ b/src/game/world/map.h
@@ -68,6 +68,7 @@ struct MAP_SPRITE {
};
struct MAP_ENTITY {
+ VEC3 pos;
U32 classid;
LIST<struct OBJECT_PROP*> props;
};
@@ -82,6 +83,7 @@ struct WORLD_MAP {
LIST<MAP_WALL> walls;
LIST<MAP_POLYGON> polygons;
LIST<MAP_SPRITE> sprites;
+ LIST<MAP_ENTITY> entities;
LIST<SURF_PROPS> props;
MAP_SKYBOX skybox;
F32 w;