101 lines
2.8 KiB
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;
|
|
}
|
|
}
|