power_play/src/entity.c

101 lines
2.8 KiB
C

#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;
}
}