add root entity. release children with parent.

This commit is contained in:
jacob 2024-08-06 15:09:57 -05:00
parent 3776c2fab0
commit 53ae299816
4 changed files with 93 additions and 11 deletions

View File

@ -29,6 +29,11 @@ struct entity_store *entity_store_alloc(void)
store->arena = arena;
store->entities = arena_dry_push(&arena, struct entity);
ASSERT((u64)store->entities - (u64)store == STORE_ENTITIES_OFFSET); /* Offset must be correct */
struct entity *root = entity_alloc_unlinked(store);
root->root = true;
store->root = root->handle;
return store;
}
@ -51,7 +56,7 @@ void entity_store_copy_replace(struct entity_store *dest, struct entity_store *s
* Allocation
* ========================== */
struct entity *entity_alloc(struct entity_store *store)
struct entity *entity_alloc_unlinked(struct entity_store *store)
{
struct entity *entity = NULL;
struct entity_handle handle = { 0 };
@ -71,13 +76,34 @@ struct entity *entity_alloc(struct entity_store *store)
return entity;
}
struct entity *entity_alloc_top(struct entity_store *store)
{
struct entity *e = entity_alloc_unlinked(store);
struct entity *root = entity_from_handle(store, store->root);
entity_link(root, e);
return e;
}
struct entity *entity_alloc_child(struct entity *parent)
{
struct entity_store *store = entity_get_store(parent);
struct entity *e = entity_alloc_unlinked(store);
entity_link(parent, e);
return e;
}
void entity_release(struct entity_store *store, struct entity *entity)
{
/* FIXME: Unlink entity */
++entity->handle.gen;
entity->valid = false;
entity->next_free = store->first_free;
store->first_free = entity->handle;
/* Release children */
if (entity->first.gen) {
for (struct entity *child = entity_from_handle(store, entity->first); child->valid; child = entity_from_handle(store, child->next)) {
entity_release(store, child);
}
}
}
/* ========================== *
@ -86,19 +112,20 @@ void entity_release(struct entity_store *store, struct entity *entity)
struct entity_store *entity_get_store(struct entity *ent)
{
struct entity_store *store = entity_store_nil();
if (ent->valid) {
u64 first_entity_addr = (u64)(ent - ent->handle.idx);
store = (struct entity_store *)(first_entity_addr - STORE_ENTITIES_OFFSET);
struct entity_store *store = (struct entity_store *)(first_entity_addr - STORE_ENTITIES_OFFSET);
ASSERT(store->entities == (struct entity *)first_entity_addr);
}
return store;
} else {
return entity_store_nil();
}
}
/* Returns a valid entity or nil entity. Always safe to read result, need to check `valid` to write. */
struct entity *entity_from_handle(struct entity_store *store, struct entity_handle handle)
{
if (handle.idx < store->count) {
if (handle.gen != 0 && handle.idx < store->count) {
struct entity *entity = &store->entities[handle.idx];
if (entity->handle.gen == handle.gen) {
return entity;
@ -202,4 +229,32 @@ void entity_link(struct entity *parent, struct entity *child)
}
}
/* TODO: entity_unlink() */
void entity_unlink(struct entity *ent)
{
struct entity_store *store = entity_get_store(ent);
ASSERT(!entity_handle_eq(ent->handle, store->root));
struct entity *parent = entity_from_handle(store, ent->parent);
struct entity *prev = entity_from_handle(store, ent->prev);
struct entity *next = entity_from_handle(store, ent->next);
/* Unlink from parent & siblings */
if (prev->valid) {
prev->next = next->handle;
} else {
parent->first = next->handle;
}
if (next->valid) {
next->prev = prev->handle;
} else {
parent->last = prev->handle;
}
/* Link children to grandparent */
if (ent->first.gen) {
struct entity_handle parent_handle = parent->handle;
for (struct entity *child = entity_from_handle(store, ent->first); child->valid; child = entity_from_handle(store, child->next)) {
child->parent = parent_handle;
}
}
}

View File

@ -29,6 +29,7 @@ struct entity_store {
struct arena arena;
u64 count;
struct entity_handle first_free;
struct entity_handle root;
struct entity *entities;
};
@ -43,6 +44,9 @@ struct entity {
/* Special value stored in first entity in store array */
u64 store_offset;
/* Is this the root entity */
b32 root;
/* Tree */
struct entity_handle parent;
struct entity_handle next;
@ -118,6 +122,25 @@ struct entity_prop_array {
u64 count;
};
/* ========================== *
* Handle helpers
* ========================== */
INLINE struct entity_handle entity_nil_handle(void)
{
return (struct entity_handle) { 0 };
}
INLINE b32 entity_handle_is_nil(struct entity_handle h)
{
return h.gen == 0;
}
INLINE b32 entity_handle_eq(struct entity_handle a, struct entity_handle b)
{
return a.gen == b.gen && a.idx == b.idx;
}
/* ========================== *
* Nil
* ========================== */
@ -171,7 +194,9 @@ void entity_store_release(struct entity_store *store);
void entity_store_copy_replace(struct entity_store *dest, struct entity_store *src);
/* Entity */
struct entity *entity_alloc(struct entity_store *store);
struct entity *entity_alloc_unlinked(struct entity_store *store);
struct entity *entity_alloc_top(struct entity_store *store);
struct entity *entity_alloc_child(struct entity *parent);
void entity_release(struct entity_store *store, struct entity *entity);
/* Xform */
@ -188,5 +213,6 @@ struct entity *entity_find_first_match_all(struct entity_store *store, struct en
/* Tree */
void entity_link(struct entity *parent, struct entity *child);
void entity_unlink(struct entity *ent);
#endif

View File

@ -173,7 +173,7 @@ INTERNAL void game_update(void)
struct v2 size = V2(1, 1);
f32 r = 0;
struct entity *e = entity_alloc(G.world.entity_store);
struct entity *e = entity_alloc_top(G.world.entity_store);
e->xform = XFORM_TRS(.t = pos, .r = r, .s = size);
e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase"));
@ -195,7 +195,7 @@ INTERNAL void game_update(void)
/* Camera ent */
{
struct entity *e = entity_alloc(G.world.entity_store);
struct entity *e = entity_alloc_top(G.world.entity_store);
e->xform = XFORM_IDENT;
entity_enable_prop(e, ENTITY_PROP_CAMERA);

View File

@ -755,6 +755,7 @@ INTERNAL void user_update(void)
struct entity *ent = &entities_array.entities[entity_index];
if (!ent->valid) continue;
if (ent->root) continue;
b32 skip_debug_draw = !G.debug_camera && ent == active_camera;
b32 skip_debug_draw_transform = ent == active_camera;
@ -871,7 +872,7 @@ INTERNAL void user_update(void)
/* Draw hierarchy */
struct entity *parent = entity_from_handle(G.world.entity_store, ent->parent);
if (parent->valid) {
if (parent->valid && !parent->root) {
u32 color = RGBA_32_F(0.6, 0.6, 1, 0.75);
f32 thickness = 5;
f32 arrow_height = 15;