[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 {
struct entity_s *next;
struct transform_s *transform;
int id; ///< scene id
animation_t animation;
visibility_t visibility;
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 {
struct scene_resources_s *const resources;
hierarchyset_t roots;
xformset_t transforms;
entityset_t entities;
visibilityset_t visibility;
xformset_t roots;
} scene_t;
scene_t *Scene_NewScene (void);
void Scene_DeleteScene (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);

View file

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

View file

@ -36,6 +36,7 @@
#endif
#include "QF/progs.h" // for PR_RESMAP
#include "QF/sys.h"
#include "QF/scene/entity.h"
#include "QF/scene/scene.h"
@ -56,34 +57,105 @@ Scene_NewScene (void)
*(scene_resources_t **)&scene->resources = res;
DARRAY_INIT (&scene->roots, 16);
DARRAY_INIT (&scene->transforms, 16);
DARRAY_INIT (&scene->entities, 16);
DARRAY_INIT (&scene->visibility, 16);
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 *
Scene_CreateEntity (scene_t *scene)
{
scene_resources_t *res = scene->resources;
entity_t *ent = PR_RESNEW_NC (res->entities);
ent->transform = 0;
DARRAY_APPEND (&scene->entities, ent);
ent->transform = Transform_New (0);
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;
}
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
Scene_FreeAllEntities (scene_t *scene)
{
scene_resources_t *res = scene->resources;
for (size_t i = 0; i < scene->entities.size; i++) {
entity_t *ent = scene->entities.a[i];
if (ent->transform) {
Transform_Delete (ent->transform);
ent->transform = 0;
}
for (size_t i = 0; i < scene->roots.size; i++) {
hierarchy_t *h = scene->roots.a[i]->hierarchy;
// deleting the root entity deletes all child entities
entity_t *ent = h->entity.a[0];
destroy_entity (scene, ent);
}
scene_resources_t *res = scene->resources;
PR_RESRESET (res->entities);
}