add root entity. release children with parent.
This commit is contained in:
parent
3776c2fab0
commit
53ae299816
69
src/entity.c
69
src/entity.c
@ -29,6 +29,11 @@ struct entity_store *entity_store_alloc(void)
|
|||||||
store->arena = arena;
|
store->arena = arena;
|
||||||
store->entities = arena_dry_push(&arena, struct entity);
|
store->entities = arena_dry_push(&arena, struct entity);
|
||||||
ASSERT((u64)store->entities - (u64)store == STORE_ENTITIES_OFFSET); /* Offset must be correct */
|
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;
|
return store;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +56,7 @@ void entity_store_copy_replace(struct entity_store *dest, struct entity_store *s
|
|||||||
* Allocation
|
* Allocation
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct entity *entity_alloc(struct entity_store *store)
|
struct entity *entity_alloc_unlinked(struct entity_store *store)
|
||||||
{
|
{
|
||||||
struct entity *entity = NULL;
|
struct entity *entity = NULL;
|
||||||
struct entity_handle handle = { 0 };
|
struct entity_handle handle = { 0 };
|
||||||
@ -71,13 +76,34 @@ struct entity *entity_alloc(struct entity_store *store)
|
|||||||
return entity;
|
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)
|
void entity_release(struct entity_store *store, struct entity *entity)
|
||||||
{
|
{
|
||||||
/* FIXME: Unlink entity */
|
|
||||||
++entity->handle.gen;
|
++entity->handle.gen;
|
||||||
entity->valid = false;
|
entity->valid = false;
|
||||||
entity->next_free = store->first_free;
|
entity->next_free = store->first_free;
|
||||||
store->first_free = entity->handle;
|
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 *entity_get_store(struct entity *ent)
|
||||||
{
|
{
|
||||||
struct entity_store *store = entity_store_nil();
|
|
||||||
if (ent->valid) {
|
if (ent->valid) {
|
||||||
u64 first_entity_addr = (u64)(ent - ent->handle.idx);
|
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);
|
ASSERT(store->entities == (struct entity *)first_entity_addr);
|
||||||
}
|
|
||||||
return store;
|
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. */
|
/* 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)
|
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];
|
struct entity *entity = &store->entities[handle.idx];
|
||||||
if (entity->handle.gen == handle.gen) {
|
if (entity->handle.gen == handle.gen) {
|
||||||
return entity;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
28
src/entity.h
28
src/entity.h
@ -29,6 +29,7 @@ struct entity_store {
|
|||||||
struct arena arena;
|
struct arena arena;
|
||||||
u64 count;
|
u64 count;
|
||||||
struct entity_handle first_free;
|
struct entity_handle first_free;
|
||||||
|
struct entity_handle root;
|
||||||
struct entity *entities;
|
struct entity *entities;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -43,6 +44,9 @@ struct entity {
|
|||||||
/* Special value stored in first entity in store array */
|
/* Special value stored in first entity in store array */
|
||||||
u64 store_offset;
|
u64 store_offset;
|
||||||
|
|
||||||
|
/* Is this the root entity */
|
||||||
|
b32 root;
|
||||||
|
|
||||||
/* Tree */
|
/* Tree */
|
||||||
struct entity_handle parent;
|
struct entity_handle parent;
|
||||||
struct entity_handle next;
|
struct entity_handle next;
|
||||||
@ -118,6 +122,25 @@ struct entity_prop_array {
|
|||||||
u64 count;
|
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
|
* 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);
|
void entity_store_copy_replace(struct entity_store *dest, struct entity_store *src);
|
||||||
|
|
||||||
/* Entity */
|
/* 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);
|
void entity_release(struct entity_store *store, struct entity *entity);
|
||||||
|
|
||||||
/* Xform */
|
/* Xform */
|
||||||
@ -188,5 +213,6 @@ struct entity *entity_find_first_match_all(struct entity_store *store, struct en
|
|||||||
|
|
||||||
/* Tree */
|
/* Tree */
|
||||||
void entity_link(struct entity *parent, struct entity *child);
|
void entity_link(struct entity *parent, struct entity *child);
|
||||||
|
void entity_unlink(struct entity *ent);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -173,7 +173,7 @@ INTERNAL void game_update(void)
|
|||||||
struct v2 size = V2(1, 1);
|
struct v2 size = V2(1, 1);
|
||||||
f32 r = 0;
|
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->xform = XFORM_TRS(.t = pos, .r = r, .s = size);
|
||||||
|
|
||||||
e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase"));
|
e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase"));
|
||||||
@ -195,7 +195,7 @@ INTERNAL void game_update(void)
|
|||||||
|
|
||||||
/* Camera ent */
|
/* 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;
|
e->xform = XFORM_IDENT;
|
||||||
|
|
||||||
entity_enable_prop(e, ENTITY_PROP_CAMERA);
|
entity_enable_prop(e, ENTITY_PROP_CAMERA);
|
||||||
|
|||||||
@ -755,6 +755,7 @@ INTERNAL void user_update(void)
|
|||||||
|
|
||||||
struct entity *ent = &entities_array.entities[entity_index];
|
struct entity *ent = &entities_array.entities[entity_index];
|
||||||
if (!ent->valid) continue;
|
if (!ent->valid) continue;
|
||||||
|
if (ent->root) continue;
|
||||||
|
|
||||||
b32 skip_debug_draw = !G.debug_camera && ent == active_camera;
|
b32 skip_debug_draw = !G.debug_camera && ent == active_camera;
|
||||||
b32 skip_debug_draw_transform = ent == active_camera;
|
b32 skip_debug_draw_transform = ent == active_camera;
|
||||||
@ -871,7 +872,7 @@ INTERNAL void user_update(void)
|
|||||||
|
|
||||||
/* Draw hierarchy */
|
/* Draw hierarchy */
|
||||||
struct entity *parent = entity_from_handle(G.world.entity_store, ent->parent);
|
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);
|
u32 color = RGBA_32_F(0.6, 0.6, 1, 0.75);
|
||||||
f32 thickness = 5;
|
f32 thickness = 5;
|
||||||
f32 arrow_height = 15;
|
f32 arrow_height = 15;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user