-documentation

This commit is contained in:
Mergul 2018-10-01 19:40:24 +02:00
parent 288ad4c6cd
commit 437c672478
5 changed files with 154 additions and 4 deletions

View file

@ -1,4 +1,6 @@
module ecs.attributes; module ecs.attributes;
///Used to mark optional components for system.
enum optional = "optional"; enum optional = "optional";
///Used to mark absen components for system. Enum 'AbsenComponents' should be used instead of it.
enum absen = "absen"; enum absen = "absen";

View file

@ -2,21 +2,36 @@ module ecs.entity;
import ecs.manager; import ecs.manager;
/************************************************************************************************************************
*Entity ID structure.
*/
struct EntityID struct EntityID
{ {
///Index to entity in IDManager.
uint id; uint id;
///Counter required for reusing ID.
uint counter; uint counter;
} }
/************************************************************************************************************************
*Structure of Entity. It's have only ID, but have full konwlege to get to components memory (If pointer to it is proper).
*/
struct Entity struct Entity
{ {
///Entity ID.
EntityID id; EntityID id;
/************************************************************************************************************************
*Update pointer to it in IDManager
*/
void updateID() void updateID()
{ {
EntityManager.instance.id_manager.update(this); EntityManager.instance.id_manager.update(this);
} }
/************************************************************************************************************************
*Get specified component. If component doesn't exist function retun null.
*/
T* getComponent(T)() const T* getComponent(T)() const
{ {
EntityManager.EntitiesBlock* block = gEM.getMetaData(&this); EntityManager.EntitiesBlock* block = gEM.getMetaData(&this);
@ -32,11 +47,19 @@ struct Entity
} }
} }
/************************************************************************************************************************
*Entity template structure.
*/
export struct EntityTemplate export struct EntityTemplate
{ {
///Entity components data
ubyte[] entity_data; ubyte[] entity_data;
///Pointer to entity type info.
EntityManager.EntityInfo* info; EntityManager.EntityInfo* info;
/************************************************************************************************************************
*Get specified component. If component doesn't exist function return null.
*/
T* getComponent(T)() T* getComponent(T)()
{ {
if(T.component_id >= info.tmpl_deltas.length)return null; if(T.component_id >= info.tmpl_deltas.length)return null;

View file

@ -3,8 +3,14 @@ module ecs.id_manager;
import ecs.entity; import ecs.entity;
import ecs.vector; import ecs.vector;
/************************************************************************************************************************
*IDManager is responsible for assignment and removing IDs. IDs are unique throughtout a whole duration of the program.
*/
struct IDManager struct IDManager
{ {
/************************************************************************************************************************
*Get new ID.
*/
EntityID getNewID() EntityID getNewID()
{ {
if (m_next_id >= m_ids_array.length) if (m_next_id >= m_ids_array.length)
@ -18,6 +24,9 @@ struct IDManager
return id; return id;
} }
/************************************************************************************************************************
*Release ID.
*/
void releaseID(EntityID id) void releaseID(EntityID id)
{ {
Data* data = &m_ids_array[id.id]; Data* data = &m_ids_array[id.id];
@ -29,11 +38,17 @@ struct IDManager
m_next_id = id.id; m_next_id = id.id;
} }
/************************************************************************************************************************
*Update pointer to entity. The purpose of this function is to ensure that pointer to entity is always correct.
*/
void update(ref Entity entity) void update(ref Entity entity)
{ {
if(entity.id.counter == m_ids_array[entity.id.id].counter)m_ids_array[entity.id.id].entity = &entity; if(entity.id.counter == m_ids_array[entity.id.id].counter)m_ids_array[entity.id.id].entity = &entity;
} }
/************************************************************************************************************************
*Returns pointer to entity.
*/
export Entity* getEntityPointer(EntityID id) export Entity* getEntityPointer(EntityID id)
{ {
Data* data = &m_ids_array[id.id]; Data* data = &m_ids_array[id.id];
@ -43,20 +58,24 @@ struct IDManager
return data.entity; return data.entity;
} }
/************************************************************************************************************************
*Check if entity with specified ID exist.
*/
export bool isExist(EntityID id) export bool isExist(EntityID id)
{ {
Data* data = &m_ids_array[id.id]; Data* data = &m_ids_array[id.id];
return data.counter == id.counter; return data.counter == id.counter;
} }
struct Data private static struct Data
{ {
uint counter = 0; uint counter = 0;
uint next_id = uint.max; uint next_id = uint.max;
Entity* entity = null; Entity* entity = null;
} }
private uint m_next_id = 0; private:
uint m_next_id;
Vector!Data m_ids_array; Vector!Data m_ids_array;
} }

View file

@ -49,12 +49,23 @@ class EntityManager
instance = null; instance = null;
} }
/************************************************************************************************************************
*Default constructor.
*/
this() this()
{ {
//event_manager = EventManager(this); //event_manager = EventManager(this);
//event_manager.manager = this; //event_manager.manager = this;
} }
/************************************************************************************************************************
*Register new System into EntityManager. This funcion generate glue between EntityManager and System.
*Systems can be registered from external dynamic library, and can be registered after adding entities too.
*System mustn't be registered before components which system want to use, in this case functions call assertion.
*
*params:
*priority = system priority. Priority determines order of execution of systems updates.
*/
void registerSystem(Sys)(int priority) void registerSystem(Sys)(int priority)
{ {
alias STC = ParameterStorageClass; alias STC = ParameterStorageClass;
@ -392,6 +403,9 @@ class EntityManager
return cast(Sys*) systems[Sys.system_id].m_system_pointer; return cast(Sys*) systems[Sys.system_id].m_system_pointer;
} }
/************************************************************************************************************************
*Register component into EntityManager.
*/
void registerComponent(Comp)() void registerComponent(Comp)()
{ {
ComponentInfo info; ComponentInfo info;
@ -469,6 +483,9 @@ class EntityManager
} }
} }
/************************************************************************************************************************
*Update systems. Should be called only between begin() and end().
*/
export void update() export void update()
{ {
foreach (info; &entities_infos.byValue) foreach (info; &entities_infos.byValue)
@ -486,10 +503,10 @@ class EntityManager
num = cast(ushort)((num + alignment - 1) & (-cast(int) alignment)); //num += alignment - (num & (alignment - 1)); num = cast(ushort)((num + alignment - 1) & (-cast(int) alignment)); //num += alignment - (num & (alignment - 1));
} }
static ushort alignedNum(ushort num, ushort alignment) /*static ushort alignedNum(ushort num, ushort alignment)
{ {
return cast(ushort)((num + alignment - 1) & (-cast(int) alignment)); return cast(ushort)((num + alignment - 1) & (-cast(int) alignment));
} }*/
extern (C) static int compareUShorts(const void* a, const void* b) extern (C) static int compareUShorts(const void* a, const void* b)
{ {
@ -503,6 +520,12 @@ class EntityManager
return 1; return 1;
} }
/************************************************************************************************************************
*Allocate EntityTemplate with specifed components and returns pointer to it.
*
*params:
*components_ids = array of components allocated with template
*/
export EntityTemplate* allocateTemplate(ushort[] components_ids) export EntityTemplate* allocateTemplate(ushort[] components_ids)
{ {
@ -541,6 +564,12 @@ class EntityManager
return temp; return temp;
} }
/************************************************************************************************************************
*Returns entity type info.
*
*params:
*ids = array of components
*/
export EntityInfo* getEntityInfo(ushort[] ids) export EntityInfo* getEntityInfo(ushort[] ids)
{ {
EntityInfo* info = entities_infos.get(ids, null); EntityInfo* info = entities_infos.get(ids, null);
@ -651,11 +680,24 @@ class EntityManager
entity.callers.add(call_data, index); entity.callers.add(call_data, index);
} }
/************************************************************************************************************************
*Returns pointer to entity.
*
*params:
*id = ID of entity
*/
export Entity* getEntity(EntityID id) export Entity* getEntity(EntityID id)
{ {
return cast(Entity*) id_manager.getEntityPointer(id); return cast(Entity*) id_manager.getEntityPointer(id);
} }
/************************************************************************************************************************
*Remove components from entity by IDs. Components will be removed on end of frame.
*
*params:
*entity_id = ID of entity
*del_ids = array of components IDs
*/
export void removeComponents(EntityID entity_id, ushort[] del_ids) export void removeComponents(EntityID entity_id, ushort[] del_ids)
{ {
uint num = cast(uint) del_ids.length; uint num = cast(uint) del_ids.length;
@ -725,6 +767,13 @@ class EntityManager
removeEntityNoID(entity, block); removeEntityNoID(entity, block);
} }
/************************************************************************************************************************
*Remove coponents from entity.
*
*params:
*Compoenents = components types to remove
*entity_id = ID of entity
*/
void removeComponents(Components...)(EntityID entity_id) void removeComponents(Components...)(EntityID entity_id)
{ {
const uint num = Components.length; const uint num = Components.length;
@ -861,6 +910,13 @@ class EntityManager
removeEntityNoID(entity, block); removeEntityNoID(entity, block);
} }
/************************************************************************************************************************
*Add components to entity. Components will be added on end of frame.
*
*params:
*entity_id = ID of entity to remove
*tmpl = pointer entity template allocated by EntityManager.
*/
void addComponents(Components...)(const EntityID entity_id, Components comps) void addComponents(Components...)(const EntityID entity_id, Components comps)
{ {
const uint num = Components.length; const uint num = Components.length;
@ -895,12 +951,24 @@ class EntityManager
//__addComponents(entity_id, new_ids, pointers); //__addComponents(entity_id, new_ids, pointers);
} }
/************************************************************************************************************************
*Free template memory.
*
*params:
*tmpl = pointer entity template allocated by EntityManager.
*/
export void freeTemplate(EntityTemplate* template_) export void freeTemplate(EntityTemplate* template_)
{ {
Mallocator.instance.dispose(template_.entity_data); Mallocator.instance.dispose(template_.entity_data);
Mallocator.instance.dispose(template_); Mallocator.instance.dispose(template_);
} }
/************************************************************************************************************************
*Add entity to system.
*
*params:
*tmpl = pointer entity template allocated by EntityManager.
*/
export ref Entity addEntity(EntityTemplate* tmpl) export ref Entity addEntity(EntityTemplate* tmpl)
{ {
EntitiesBlock* block = findBlockWithFreeSpace(tmpl.info); EntitiesBlock* block = findBlockWithFreeSpace(tmpl.info);
@ -969,6 +1037,12 @@ class EntityManager
return block; return block;
} }
/************************************************************************************************************************
*Remove entity by ID. Entity will be removed on frame end.
*
*params:
*id = id of entity to remove
*/
export void removeEntity(EntityID id) export void removeEntity(EntityID id)
{ {
entities_to_remove.add(id); entities_to_remove.add(id);
@ -1125,6 +1199,9 @@ class EntityManager
entities_to_remove.clear(); entities_to_remove.clear();
} }
/************************************************************************************************************************
*Begin of update process. Should be called before any update is called.
*/
export void begin() export void begin()
{ {
updateBlocks(); updateBlocks();
@ -1137,6 +1214,9 @@ class EntityManager
} }
} }
/************************************************************************************************************************
*End of update process. Should be called after every update function.
*/
export void end() export void end()
{ {
foreach (ref system; instance.systems) foreach (ref system; instance.systems)
@ -1151,11 +1231,18 @@ class EntityManager
//clearEvents(); //clearEvents();
} }
/************************************************************************************************************************
*Component info;
*/
struct ComponentInfo struct ComponentInfo
{ {
///Component size
ushort size; ushort size;
///Component data alignment
ushort alignment; ushort alignment;
///Initialization data
ubyte[] init_data; ubyte[] init_data;
///Pointer to component destroy callback
void function(void* pointer) destroy_callback; void function(void* pointer) destroy_callback;
} }

View file

@ -3,13 +3,22 @@ module ecs.system;
import ecs.entity; import ecs.entity;
import ecs.manager; import ecs.manager;
/************************************************************************************************************************
*System contain data required to proper glue EntityManager with Systems.
*/
struct System struct System
{ {
/************************************************************************************************************************
*Check if system is enabled.
*/
export bool enabled() export bool enabled()
{ {
return m_enabled; return m_enabled;
} }
/************************************************************************************************************************
*Enable system. If actually it is enabled function do nothing.
*/
export void enable() export void enable()
{ {
if (!m_enabled && m_enable) if (!m_enabled && m_enable)
@ -17,6 +26,9 @@ struct System
m_enabled = true; m_enabled = true;
} }
/************************************************************************************************************************
*Disable system. If actually it is disabled function do nothing.
*/
export void disable() export void disable()
{ {
if (m_enabled && m_disable) if (m_enabled && m_disable)
@ -24,6 +36,9 @@ struct System
m_enabled = false; m_enabled = false;
} }
/************************************************************************************************************************
*Get system priority.
*/
export int priority() export int priority()
{ {
return m_priority; return m_priority;
@ -38,10 +53,14 @@ package:
///pointer to system implementation ///pointer to system implementation
void* m_system_pointer; void* m_system_pointer;
///system name
const (char)[] name; const (char)[] name;
///required components
ushort[] m_components; ushort[] m_components;
///absen components
ushort[] m_absen_components; ushort[] m_absen_components;
///optional components
ushort[] m_optional_components; ushort[] m_optional_components;
//void function(ref EntityManager.CallData data, void* entity) update; //void function(ref EntityManager.CallData data, void* entity) update;