[scene] Add functions for scene and entity create/delete

Scene creation was already there, but now can be deleted, as can
entities.
This commit is contained in:
Bill Currie 2022-02-14 16:41:38 +09:00
parent f3559cedb0
commit f6ac614e09
4 changed files with 92 additions and 23 deletions

View file

@ -172,8 +172,8 @@ typedef struct renderer_s {
typedef struct entity_s { typedef struct entity_s {
struct entity_s *next; struct entity_s *next;
struct transform_s *transform; struct transform_s *transform;
int id; ///< scene id
animation_t animation; animation_t animation;
visibility_t visibility; visibility_t visibility;
renderer_t renderer; renderer_t renderer;

View file

@ -40,21 +40,16 @@
*/ */
///@{ ///@{
typedef struct hierarchyset_s DARRAY_TYPE (struct hierarchy_s *)
hierarchyset_t;
typedef struct visibilityset_s DARRAY_TYPE (struct visibility_s *)
visibilityset_t;
typedef struct scene_s { typedef struct scene_s {
struct scene_resources_s *const resources; struct scene_resources_s *const resources;
hierarchyset_t roots; xformset_t roots;
xformset_t transforms;
entityset_t entities;
visibilityset_t visibility;
} scene_t; } scene_t;
scene_t *Scene_NewScene (void); scene_t *Scene_NewScene (void);
void Scene_DeleteScene (scene_t *scene);
struct entity_s *Scene_CreateEntity (scene_t *scene); struct entity_s *Scene_CreateEntity (scene_t *scene);
struct entity_s *Scene_GetEntity (scene_t *scene, int id);
void Scene_DestroyEntity (scene_t *scene, struct entity_s *entity);
void Scene_FreeAllEntities (scene_t *scene); void Scene_FreeAllEntities (scene_t *scene);

View file

@ -43,10 +43,12 @@
typedef struct transform_s { typedef struct transform_s {
struct hierarchy_s *hierarchy; struct hierarchy_s *hierarchy;
uint32_t index; uint32_t index; ///< index in hierarchy
int32_t id; ///< scene id
} transform_t; } transform_t;
transform_t *Transform_New (transform_t *parent); transform_t *Transform_New (transform_t *parent);
/* Deletes all child transforms, and transform names */
void Transform_Delete (transform_t *transform); void Transform_Delete (transform_t *transform);
transform_t *Transform_NewNamed (transform_t *parent, const char *name); transform_t *Transform_NewNamed (transform_t *parent, const char *name);
uint32_t Transform_ChildCount (const transform_t *transform) __attribute__((pure)); uint32_t Transform_ChildCount (const transform_t *transform) __attribute__((pure));

View file

@ -36,6 +36,7 @@
#endif #endif
#include "QF/progs.h" // for PR_RESMAP #include "QF/progs.h" // for PR_RESMAP
#include "QF/sys.h"
#include "QF/scene/entity.h" #include "QF/scene/entity.h"
#include "QF/scene/scene.h" #include "QF/scene/scene.h"
@ -56,34 +57,105 @@ Scene_NewScene (void)
*(scene_resources_t **)&scene->resources = res; *(scene_resources_t **)&scene->resources = res;
DARRAY_INIT (&scene->roots, 16); DARRAY_INIT (&scene->roots, 16);
DARRAY_INIT (&scene->transforms, 16);
DARRAY_INIT (&scene->entities, 16);
DARRAY_INIT (&scene->visibility, 16);
return scene; return scene;
} }
void
Scene_DeleteScene (scene_t *scene)
{
Scene_FreeAllEntities (scene);
scene_resources_t *res = scene->resources;
for (unsigned i = 0; i < res->entities._size; i++) {
free (res->entities._map[i]);
}
free (res->entities._map);
DARRAY_CLEAR (&scene->roots);
free (scene->resources);
free (scene);
}
entity_t * entity_t *
Scene_CreateEntity (scene_t *scene) Scene_CreateEntity (scene_t *scene)
{ {
scene_resources_t *res = scene->resources; scene_resources_t *res = scene->resources;
entity_t *ent = PR_RESNEW_NC (res->entities); entity_t *ent = PR_RESNEW_NC (res->entities);
ent->transform = 0; ent->transform = Transform_New (0);
DARRAY_APPEND (&scene->entities, ent); ent->id = PR_RESINDEX (res->entities, ent);
hierarchy_t *h = ent->transform->hierarchy;
h->entity.a[ent->transform->index] = ent;
DARRAY_APPEND (&scene->roots, ent->transform);
return ent; return ent;
} }
entity_t *
Scene_GetEntity (scene_t *scene, int id)
{
scene_resources_t *res = scene->resources;
return PR_RESGET (res->entities, id);
}
static void
unroot_transform (scene_t *scene, transform_t *transform)
{
if (!Transform_GetParent (transform)) {
for (size_t i = 0; i < scene->roots.size; i++) {
if (scene->roots.a[i] == transform) {
DARRAY_REMOVE_AT (&scene->roots, i);
break;
}
}
}
}
static void
destroy_entity (scene_t *scene, entity_t *ent)
{
scene_resources_t *res = scene->resources;
// ent->transform will be trampled by the loop below
transform_t *transform = ent->transform;
// Transform_Delete takes care of all hierarchy stuff (transforms
// themselves, name strings, hierarchy table)
hierarchy_t *h = transform->hierarchy;
for (size_t i = 0; i < h->entity.size; i++) {
entity_t *e = h->entity.a[0];
e->transform = 0;
PR_RESFREE (res->entities, ent);
}
Transform_Delete (transform);
}
void
Scene_DestroyEntity (scene_t *scene, entity_t *ent)
{
scene_resources_t *res = scene->resources;
if (PR_RESGET (res->entities, ent->id) != ent) {
Sys_Error ("Scene_DestroyEntity: entity not owned by scene");
}
unroot_transform (scene, ent->transform);
// pull the transform out of the hierarchy to make it easier to destory
// all the child entities
Transform_SetParent (ent->transform, 0);
destroy_entity (scene, ent);
}
void void
Scene_FreeAllEntities (scene_t *scene) Scene_FreeAllEntities (scene_t *scene)
{ {
scene_resources_t *res = scene->resources; for (size_t i = 0; i < scene->roots.size; i++) {
for (size_t i = 0; i < scene->entities.size; i++) { hierarchy_t *h = scene->roots.a[i]->hierarchy;
entity_t *ent = scene->entities.a[i]; // deleting the root entity deletes all child entities
if (ent->transform) { entity_t *ent = h->entity.a[0];
Transform_Delete (ent->transform); destroy_entity (scene, ent);
ent->transform = 0;
}
} }
scene_resources_t *res = scene->resources;
PR_RESRESET (res->entities); PR_RESRESET (res->entities);
} }