#include "entity.h" #include "math.h" READONLY struct entity _g_entity_nil = { .rel_xform = XFORM_IDENT, .world_xform = XFORM_IDENT, .sprite_xform = XFORM_IDENT, .sprite_tint = COLOR_WHITE }; /* ========================== * * Store allocation * ========================== */ struct entity_store entity_store_alloc(void) { struct entity_store store = { 0 }; store.arena = arena_alloc(GIGABYTE(64)); return store; } void entity_store_release(struct entity_store *store) { arena_release(&store->arena); } void entity_store_copy_replace(struct entity_store *dest, struct entity_store *src) { struct arena orig_arena = dest->arena; MEMCPY_STRUCT(dest, src); dest->arena = orig_arena; arena_copy_replace(&dest->arena, &src->arena); } /* ========================== * * Allocation * ========================== */ struct entity *entity_alloc(struct entity_store *store) { struct entity *entity = NULL; if (store->first_free.gen) { /* Reuse from free list */ entity = entity_from_handle(store, store->first_free); store->first_free = entity->next_free; entity->next_free = (struct entity_handle) { 0 }; } else { /* Make new */ u64 idx = store->count++; entity = arena_push(&store->arena, struct entity); *entity = *entity_nil(); entity->handle = (struct entity_handle) { .gen = 1, .idx = idx }; } return entity; } void entity_release(struct entity_store *store, struct entity *entity) { struct entity_handle handle = (struct entity_handle) { .gen = entity->handle.gen, .idx = entity->handle.idx }; *entity = *entity_nil(); entity->handle = handle; entity->next_free = store->first_free; store->first_free = handle; } /* ========================== * * Lookup * ========================== */ /* Returns a valid entity or nil entity. Always safe to read result, need to check to write. */ struct entity *entity_from_handle(struct entity_store *store, struct entity_handle handle) { if (handle.idx < store->count) { struct entity *entities = (struct entity *)store->arena.base; struct entity *entity = &entities[handle.idx]; if (entity->handle.gen == handle.gen) { return entity; } } return entity_nil(); } void entity_link(struct entity_store *store, struct entity *parent, struct entity *child) { struct entity *first_child = entity_from_handle(store, parent->first); struct entity *last_child = entity_from_handle(store, parent->last); child->prev = last_child->handle; child->parent = parent->handle; if (last_child->valid) { last_child->next = child->handle; } parent->last = child->handle; if (!first_child->valid) { parent->first = child->handle; } }