#ifndef _ALIAS_ECS_LOCAL_H_
#define _ALIAS_ECS_LOCAL_H_
#include <alias/ecs.h>
#include <alias/data_structure/vector.h>
#include <alias/data_structure/paged_soa.h>
#include <stdlib.h>
#include <stdalign.h>
#include <string.h>
#define UNUSED(X) (void)X
#define sizeof_alignof(X) sizeof(X), alignof(X)
typedef uint32_t alias_ecs_ArchetypeHandle;
typedef struct alias_ecs_Layer {
uint32_t dirty : 1;
uint32_t at_max : 1;
uint32_t _reserved : 30;
alias_Vector(uint32_t) entities;
} alias_ecs_Layer;
typedef struct alias_ecs_Component {
union {
struct {
uint32_t non_null : 1;
uint32_t _flags_unused : 31;
};
uint32_t flags;
};
uint32_t size;
uint32_t num_required_components;
const alias_ecs_ComponentHandle * required_components;
alias_ecs_ComponentInitCB init;
alias_ecs_ComponentCleanupCB cleanup;
} alias_ecs_Component;
typedef struct alias_ecs_ComponentSet {
uint32_t count;
uint32_t * index;
} alias_ecs_ComponentSet;
#define TOTAL_BLOCK_SIZE (1 << 16)
#define BLOCK_DATA_SIZE (TOTAL_BLOCK_SIZE - (sizeof(uint32_t) * 2))
typedef struct alias_ecs_Archetype {
alias_ecs_ComponentSet components;
uint32_t any_init : 1;
uint32_t any_cleanup : 1;
uint32_t _reserved : 30;
alias_Vector(uint32_t) free_codes;
alias_PagedSOA paged_soa;
} alias_ecs_Archetype;
struct alias_ecs_Instance {
alias_MemoryCB memory_cb;
struct {
alias_Vector(uint32_t) free_indexes;
uint32_t capacity;
uint32_t length;
uint32_t * generation;
alias_ecs_Layer * data;
} layer;
struct {
alias_Vector(uint32_t) free_indexes;
uint32_t capacity;
uint32_t length;
uint32_t * generation;
uint32_t * layer_index;
uint32_t * archetype_index;
uint32_t * archetype_code;
} entity;
struct {
uint32_t capacity;
uint32_t length;
uint32_t * components_index;
alias_ecs_Archetype * data;
} archetype;
alias_Vector(alias_ecs_Component) component;
};
struct alias_ecs_Query {
alias_ecs_ComponentSet component_set;
uint32_t last_archetype_tested;
alias_ecs_ComponentSet require_component_set;
alias_ecs_ComponentSet exclude_component_set;
uint32_t component_count;
uint32_t first_component_read;
alias_ecs_ComponentHandle * component;
uint8_t ** runtime;
uint32_t archetype_capacity;
uint32_t archetype_length;
alias_ecs_ArchetypeHandle * archetype;
uint32_t * size_offset;
};
#define ENTITY_GENERATION(I, E) (I)->entity.generation[E]
#define ENTITy_LAYER_INDEX(I, E) (I)->entity.layer_index[E]
#define ENTITY_ARCHETYPE_INDEX(I, E) (I)->entity.archetype_index[E]
#define ENTITY_ARCHETYPE_CODE(I, E) (I)->entity.archetype_code[E]
#define ENTITY_ARCHETYPE_CODE_PAGE(I, E) (ENTITY_ARCHETYPE_CODE(I, E) >> 16)
#define ENTITY_ARCHETYPE_CODE_INDEX(I, E) (ENTITY_ARCHETYPE_CODE(I, E) & 0xFFFF)
#define ENTITY_ARCHETYPE_DATA(I, E) (&(I)->archetype.data[ENTITY_ARCHETYPE_INDEX(I, E)])
#define ENTITY_DATA_BLOCK(I, E) ENTITY_ARCHETYPE_DATA(I, E)->paged_soa.pages[ENTITY_ARCHETYPE_CODE_PAGE(I, E)]
#define ENTITY_DATA_BLOCK_DATA(I, E) ((void *)(ENTITY_DATA_BLOCK(I, E) + sizeof(uint32_t)))
#define ENTITY_DATA_ENTITY_INDEX(I, E) ((uint32_t *)ENTITY_DATA_BLOCK_DATA(I, E))[ENTITY_ARCHETYPE_CODE_INDEX(I, E)]
static inline alias_ecs_EntityHandle alias_ecs_construct_entity_handle(uint32_t generation, uint32_t index) {
return ((uint64_t)generation << 32) | (uint64_t)index;
}
static inline alias_ecs_EntityHandle alias_ecs_construct_entity_handle_index_only(alias_ecs_Instance * instance, uint32_t index) {
return alias_ecs_construct_entity_handle(ENTITY_GENERATION(instance, index), index);
}
static inline void * alias_ecs_raw_access(
alias_ecs_Instance * instance
, uint32_t archetype_index
, uint32_t component_index
, uint32_t page
, uint32_t index
) {
alias_ecs_Archetype * archetype = &instance->archetype.data[archetype_index];
uint32_t size, offset;
alias_PagedSOA_decode_column(&archetype->paged_soa, component_index + 1, &size, &offset);
return alias_PagedSOA_raw_write(&archetype->paged_soa, page, index, size, offset);
}
static inline void * alias_ecs_write(
alias_ecs_Instance * instance
, uint32_t entity_index
, uint32_t component_index
) {
uint32_t archetype_index = ENTITY_ARCHETYPE_INDEX(instance, entity_index);
uint32_t page = ENTITY_ARCHETYPE_CODE_PAGE(instance, entity_index);
uint32_t index = ENTITY_ARCHETYPE_CODE_INDEX(instance, entity_index);
return alias_ecs_raw_access(instance, archetype_index, component_index, page, index);
}
#define return_if_ERROR(C) do { alias_ecs_Result __r = C; if(__r < ALIAS_ECS_SUCCESS) return __r; } while(0)
#define return_ERROR_INVALID_ARGUMENT_if(X) do { if(X) { return ALIAS_ECS_ERROR_INVALID_ARGUMENT; } } while(0)
#define ASSERT(X) do { if(!(X)) { return ALIAS_ECS_ERROR_INVALID_ARGUMENT; } } while(0)
#if 0#else
#define TRACE(F, ...)
#endif
alias_ecs_Result alias_ecs_malloc(
alias_ecs_Instance * instance
, size_t size
, size_t alignment
, void * * out_ptr
);
alias_ecs_Result alias_ecs_realloc(
alias_ecs_Instance * instance
, void * ptr
, size_t old_size
, size_t new_size
, size_t alignment
, void * * out_ptr
);
void alias_ecs_free(
alias_ecs_Instance * instance
, void * ptr
, size_t size
, size_t alignment
);
typedef int (*alias_ecs_CompareFn)(void *, const void *, const void *);
typedef alias_Closure(alias_ecs_CompareFn) alias_ecs_CompareCB;
void alias_ecs_quicksort(
void * base
, size_t num
, size_t size
, alias_ecs_CompareCB cb
);
void * alias_ecs_bsearch(
const void * key
, const void * base
, size_t num
, size_t size
, alias_ecs_CompareCB cb
);
#define ALLOC(I, C, P) return_if_ERROR(alias_ecs_malloc(I, (C) * sizeof_alignof(*P), (void **)&P))
#define RELOC(I, oldC, newC, P) return_if_ERROR(alias_ecs_realloc(I, P, (oldC) * sizeof(*P), (newC) * sizeof_alignof(*P), (void **)&P))
#define FREE(I, C, P) alias_ecs_free(I, (void *)P, (C) * sizeof_alignof(*P))
alias_ecs_Result alias_ecs_init_component(alias_ecs_Instance * instance, uint32_t entity_index, uint32_t archetype_index, uint32_t component_index);
alias_ecs_Result alias_ecs_init_components(alias_ecs_Instance * instance, uint32_t entity_index, uint32_t archetype_index);
alias_ecs_Result alias_ecs_cleanup_component(alias_ecs_Instance * instance, uint32_t entity_index, uint32_t archetype_index, uint32_t component_index);
alias_ecs_Result alias_ecs_cleanup_components(alias_ecs_Instance * instance, uint32_t entity_index, uint32_t archetype_index);
alias_ecs_Result alias_ecs_ComponentSet_init(
alias_ecs_Instance * instance
, alias_ecs_ComponentSet * set
, uint32_t count
, const alias_ecs_ComponentHandle * components
);
alias_ecs_Result alias_ecs_ComponentSet_add(
alias_ecs_Instance * instance
, alias_ecs_ComponentSet * dst
, const alias_ecs_ComponentSet * src
, alias_ecs_ComponentHandle component
);
alias_ecs_Result alias_ecs_ComponentSet_remove(
alias_ecs_Instance * instance
, alias_ecs_ComponentSet * dst
, const alias_ecs_ComponentSet * src
, alias_ecs_ComponentHandle component
);
uint32_t alias_ecs_ComponentSet_order_of(
const alias_ecs_ComponentSet * set
, alias_ecs_ComponentHandle component
);
int alias_ecs_ComponentSet_contains(
const alias_ecs_ComponentSet * set
, alias_ecs_ComponentHandle component
);
int alias_ecs_ComponentSet_is_subset(
const alias_ecs_ComponentSet * a
, const alias_ecs_ComponentSet * b
);
int alias_ecs_ComponentSet_intersects(
const alias_ecs_ComponentSet * a
, const alias_ecs_ComponentSet * b
);
alias_ecs_Result alias_ecs_ComponentSet_expand_required(
alias_ecs_Instance * instance
, alias_ecs_ComponentSet * set
);
void alias_ecs_ComponentSet_free(
alias_ecs_Instance * instance
, alias_ecs_ComponentSet * set
);
alias_ecs_Result alias_ecs_validate_layer_handle(
const alias_ecs_Instance * instance
, alias_ecs_LayerHandle layer
, uint32_t * index_ptr
);
alias_ecs_Result alias_ecs_set_entity_layer(
alias_ecs_Instance * instance
, uint32_t entity_index
, uint32_t layer_index
);
void alias_ecs_unset_entity_layer(
alias_ecs_Instance * instance
, uint32_t entity_index
);
alias_ecs_Result alias_ecs_validate_entity_handle(
const alias_ecs_Instance * instance
, alias_ecs_EntityHandle entity
, uint32_t * index_ptr
);
alias_ecs_Result alias_ecs_create_entity(
alias_ecs_Instance * instance
, alias_ecs_EntityHandle * entity_ptr
);
alias_ecs_Result alias_ecs_free_entity(
alias_ecs_Instance * instance
, uint32_t entity_id
);
alias_ecs_Result alias_ecs_resolve_archetype(
alias_ecs_Instance * instance
, alias_ecs_ComponentSet components
, alias_ecs_ArchetypeHandle * out_ptr
);
alias_ecs_Result alias_ecs_unset_entity_archetype(
alias_ecs_Instance * instance
, uint32_t entity_index
);
alias_ecs_Result alias_ecs_set_entity_archetype(
alias_ecs_Instance * instance
, uint32_t entity_index
, uint32_t archetype_index
);
#endif