From c0f8d102ad3a31c014608eb5e8572d6320f0d272 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 22 Jul 2023 16:43:08 +0900 Subject: [PATCH] [scene] Implement Scene_FreeAllEntities (and use it) I guess I wasn't sure how to find all the allocated entities from within the registry, but it turned out to be trivial. This takes care of leaked static entities (and, in a later commit, leaked light entities, which is how I found the problem). --- include/client/view.h | 2 ++ include/client/world.h | 1 + libs/client/cl_view.c | 18 ++++++++++++------ libs/client/cl_world.c | 7 +++++++ libs/scene/scene.c | 19 +++++++++++++++++++ nq/source/cl_ents.c | 10 +--------- nq/source/cl_main.c | 4 +--- nq/source/cl_parse.c | 2 ++ qw/source/cl_ents.c | 5 +---- qw/source/cl_main.c | 4 +--- qw/source/cl_parse.c | 1 + 11 files changed, 48 insertions(+), 25 deletions(-) diff --git a/include/client/view.h b/include/client/view.h index 4915b77cc..2f713d631 100644 --- a/include/client/view.h +++ b/include/client/view.h @@ -101,7 +101,9 @@ typedef struct viewstate_s { #define VF_GIB 2 struct msg_s; +struct scene_s; +void V_NewScene (viewstate_t *vs, struct scene_s *scene); void V_Init (viewstate_t *vs); void V_Init_Cvars (void); void V_RenderView (viewstate_t *vs); diff --git a/include/client/world.h b/include/client/world.h index 2e1f79107..c756a6b98 100644 --- a/include/client/world.h +++ b/include/client/world.h @@ -66,6 +66,7 @@ void CL_ParseBaseline (struct msg_s *msg, struct entity_state_s *baseline, void CL_ParseStatic (struct msg_s *msg, int version); void CL_MapCfg (const char *mapname); void CL_World_NewMap (const char *mapname, const char *skyname); +void CL_World_Clear (void); void CL_LoadLights (struct plitem_s *entities, struct scene_s *scene); #endif//__client_world_h diff --git a/libs/client/cl_view.c b/libs/client/cl_view.c index 2774f3ae3..5520f2e74 100644 --- a/libs/client/cl_view.c +++ b/libs/client/cl_view.c @@ -932,9 +932,11 @@ void V_RenderView (viewstate_t *vs) { if (!vs->active) { - vec4f_t base = { 0, 0, 0, 1 }; - Transform_SetWorldPosition (vs->camera_transform, base); - Transform_SetWorldRotation (vs->camera_transform, base); + if (Transform_Valid (vs->camera_transform)) { + vec4f_t base = { 0, 0, 0, 1 }; + Transform_SetWorldPosition (vs->camera_transform, base); + Transform_SetWorldRotation (vs->camera_transform, base); + } return; } @@ -952,6 +954,13 @@ V_RenderView (viewstate_t *vs) } } +void +V_NewScene (viewstate_t *viewstate, scene_t *scene) +{ + viewstate->camera_transform = Transform_New (cl_world.scene->reg, + nulltransform); +} + void V_Init (viewstate_t *viewstate) { @@ -965,9 +974,6 @@ V_Init (viewstate_t *viewstate) "currently being displayed.\n" "Used when you are underwater, hit, have the Ring of " "Shadows, or Quad Damage. (v_cshift r g b intensity)"); - - viewstate->camera_transform = Transform_New (cl_world.scene->reg, - nulltransform); } void diff --git a/libs/client/cl_world.c b/libs/client/cl_world.c index 8b8303136..5a30e89b9 100644 --- a/libs/client/cl_world.c +++ b/libs/client/cl_world.c @@ -233,3 +233,10 @@ CL_World_NewMap (const char *mapname, const char *skyname) SCR_NewScene (cl_world.scene); map_cfg (mapname, 1); } + +void +CL_World_Clear (void) +{ + Scene_FreeAllEntities (cl_world.scene); + CL_ClearTEnts (); +} diff --git a/libs/scene/scene.c b/libs/scene/scene.c index d7cfa519f..e6b1c6305 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -39,6 +39,7 @@ #include "QF/sys.h" #include "QF/model.h" +#include "QF/plugin/vid_render.h" #include "QF/scene/entity.h" #include "QF/scene/scene.h" #include "QF/scene/transform.h" @@ -73,6 +74,15 @@ destroy_visibility (void *_visibility) } } +static void +destroy_renderer (void *_renderer) +{ + renderer_t *renderer = _renderer; + if (renderer->skin) { + mod_funcs->Skin_Free (renderer->skin); + } +} + static void sw_identity_matrix (void *_mat) { @@ -115,6 +125,7 @@ static const component_t scene_components[scene_comp_count] = { [scene_renderer] = { .size = sizeof (renderer_t), .create = 0,//create_renderer, + .destroy = destroy_renderer, .name = "renderer", }, [scene_active] = { @@ -255,4 +266,12 @@ Scene_DestroyEntity (scene_t *scene, entity_t ent) void Scene_FreeAllEntities (scene_t *scene) { + auto reg = scene->reg; + for (uint32_t i = 0; i < reg->num_entities; i++) { + uint32_t ent = reg->entities[i]; + uint32_t ind = Ent_Index (ent); + if (ind == i) { + ECS_DelEntity (reg, ent); + } + } } diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index b09a2977e..2b7a7c8c7 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -72,15 +72,7 @@ CL_ClearEnts (void) size_t i; for (i = 0; i < MAX_EDICTS; i++) { - if (Entity_Valid (cl_entities[i])) { - entity_t ent = cl_entities[i]; - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); - if (renderer && renderer->skin) { - mod_funcs->Skin_Free (renderer->skin); - } - Scene_DestroyEntity (cl_world.scene, cl_entities[i]); - cl_entities[i] = nullentity; - } + cl_entities[i] = nullentity; } // clear other arrays diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index b82c74f77..34a6f7d4b 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -228,13 +228,11 @@ CL_ClearMemory (void) Info_Destroy (cl.players[i].userinfo); } // wipe the entire cl structure - __auto_type cam = cl.viewstate.camera_transform; memset (&cl, 0, sizeof (cl)); Sbar_Intermission (cl.intermission = 0, cl.time); - cl.viewstate.camera_transform = cam; cl.viewstate.demoplayback = cls.demoplayback; - CL_ClearTEnts (); + CL_World_Clear (); CL_ClearEnts (); SCR_NewScene (0); diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 02eacdefa..08f841982 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -251,6 +251,8 @@ static void CL_NewMap (const char *mapname) { CL_World_NewMap (mapname, 0); + V_NewScene (&cl.viewstate, cl_world.scene); + cl.chasestate.worldmodel = cl_world.scene->worldmodel; Con_NewMap (); diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 7a4be0705..e543ec84e 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -72,10 +72,7 @@ CL_ClearEnts (void) size_t i; for (i = 0; i < MAX_CLIENTS; i++) { - if (Entity_Valid (cl_flag_ents[i])) { - Scene_DestroyEntity (cl_world.scene, cl_flag_ents[i]); - cl_flag_ents[i] = nullentity; - } + cl_flag_ents[i] = nullentity; } for (i = 0; i < 512; i++) { diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 51222a43c..db4587710 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -624,9 +624,7 @@ CL_ClearState (void) if (cl.serverinfo) Info_Destroy (cl.serverinfo); __auto_type players = cl.players; - __auto_type cam = cl.viewstate.camera_transform; memset (&cl, 0, sizeof (cl)); - cl.viewstate.camera_transform = cam; cl.players = players; SCR_SetFullscreen (0); @@ -651,7 +649,7 @@ CL_ClearState (void) if (host_hunklevel) // FIXME: check this... Hunk_FreeToLowMark (0, host_hunklevel); - CL_ClearEnts (); + CL_World_Clear (); CL_ClearTEnts (); cl.viewstate.weapon_entity = Scene_CreateEntity (cl_world.scene); diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 6e999d26c..14f535343 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -267,6 +267,7 @@ CL_NewMap (const char *mapname) skyname = Info_ValueForKey (cl.serverinfo, "sky"); } CL_World_NewMap (mapname, skyname); + V_NewScene (&cl.viewstate, cl_world.scene); cl.chasestate.worldmodel = cl_world.scene->worldmodel; Team_NewMap ();