-documentation
This commit is contained in:
parent
288ad4c6cd
commit
437c672478
5 changed files with 154 additions and 4 deletions
|
|
@ -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";
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue