-added more documentation

-remove update() function from entity
-currently max supported components count is 64 per type
This commit is contained in:
Mergul 2020-03-21 13:27:14 +01:00
parent 546b73c567
commit 845f468d59
10 changed files with 199 additions and 64 deletions

View file

@ -1,5 +1,5 @@
/************************************************************************************************************************
*Most important module.
*Most important module. Almost every function is called from EntityManager.
*/
module ecs.manager;
@ -25,11 +25,35 @@ import ecs.atomic;
export alias gEM = EntityManager.instance;
export alias gEntityManager = EntityManager.instance;
export alias gEventManager = EntityManager.instance;
alias SerializeVector = ecs.vector.Vector!ubyte;
/************************************************************************************************************************
*Entity manager is responsible for everything.
*
*Entity manager can be in three states:
* - registration: time between beginRegister() and endRegister() calls.
* - update: time between being() and end() calls.
* - default: when it's not in registration or update time
*
*Manager can be only in one state simultaneously.
*
*Manager must be initialized before use. There is global instance of EntityManager: EntityManager.instance or gEM as alias.
*
*Registration process consist of registration of passes, systems, entities and events.
*
*Pass is group of system which should be used inside one update() call. Passes are added as name (string) and can be referenced by name or id.<br/>
*System is structure responsible for update of specified group of entities. System consist of EntitiesData structure which contain components used
*by system and some callback. Main callback is onUpdate() which is called by update() entity manager function. Other callbacks are used as listeners for
*adding entites, tracking system lifetime and events handling.<br/>
*Component is basicly small fraction of data which is considered to be used as whole. In best scenario every byte of component is used when it's refered to.
*In practice sometimes it's better to join data into one component even if it's can be accessed separetly.<br/>
*Events are structures with data used to handle events. Event can contain for exmaple one floating point number used as damage dealt to entity.<br/>
*Entity is group of components. In memory entity is only ID which makes it's possible to take it's components. Components are grouped into chunks, and
*grouped by component type so entity can be fracted in big memory chunk.<br/>
*
*There is two types of update:
*<br/> - update(): function used to call update pass.
*<br/> - updateMT(): function used to call update pass multithreaded. This call only generates jobs which must be called by user.
*/
export struct EntityManager
{
@ -353,7 +377,7 @@ export struct EntityManager
static if (!(hasMember!(Sys, "system_id")) || !is(typeof(Sys.system_id) == ushort))
{
static assert(0); //, "Add \"mixin ECS.System;\" in top of system structure;"); //"System should have \"__gshared ushort system_id");
static assert(0); //, "Add \"mixin ECS.System;\" in top of system structure;");
}
static if (!(hasMember!(Sys, "EntitiesData")))
@ -463,11 +487,11 @@ export struct EntityManager
m_req[m_req_counter++] = info;
}
CompInfo[32] m_readonly;
CompInfo[32] m_mutable;
CompInfo[32] m_excluded;
CompInfo[32] m_optional;
CompInfo[32] m_req;
CompInfo[64] m_readonly;
CompInfo[64] m_mutable;
CompInfo[64] m_excluded;
CompInfo[64] m_optional;
CompInfo[64] m_req;
uint m_readonly_counter;
uint m_mutable_counter;
@ -635,7 +659,12 @@ export struct EntityManager
foreach (iii, comp_info; components_info.req)
{
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
assert(comp != ushort.max); //, "Can't register system \""~Sys.stringof~"\" due to non existing component \""~comp_info.type~"\".");
version (betterC)
assert(comp != ushort.max,
"Can't register system due to non existing component.");
else
assert(comp != ushort.max, "Can't register system \"" ~ Sys.stringof
~ "\" due to non existing component \"" ~ comp_info.type ~ "\".");
system.m_components[iii] = comp;
}
foreach (iii, comp_info; components_info.excluded)
@ -1319,7 +1348,7 @@ export struct EntityManager
*Allocate EntityTemplate with all components from entity witch it's data and returns pointer to it.
*
*Params:
*id = ID of entity from which should be created template
*entity_id = ID of entity from which should be created template
*fill_default = if true, components will be filled with default data, instead entity data will be taken
*/
export EntityTemplate* allocateTemplate(EntityID entity_id, bool fill_default = false)
@ -1756,7 +1785,7 @@ export struct EntityManager
Entity* new_entity = cast(Entity*) start;
new_entity.id = entity.id;
new_entity.updateID();
id_manager.update(*new_entity); //new_entity.updateID();
uint ind = block.entityIndex(entity);
@ -1876,7 +1905,7 @@ export struct EntityManager
Entity* new_entity = cast(Entity*) start;
new_entity.id = entity.id;
new_entity.updateID();
id_manager.update(*new_entity); //new_entity.updateID();
uint j = 0;
uint k = 0;
@ -2001,7 +2030,7 @@ export struct EntityManager
*instead of pointer.
*
*Params:
*tmpl = pointer entity template allocated by EntityManager.
*id = ID of entity to be copyied.
*/
export Entity* addEntityCopy(EntityID id)
{
@ -2044,7 +2073,7 @@ export struct EntityManager
//add_mutex.lock_nothrow();
new_entity.id = id_manager.getNewID();
//add_mutex.unlock_nothrow();
new_entity.updateID();
id_manager.update(*new_entity); //new_entity.updateID();
return new_entity;
}
@ -2094,7 +2123,7 @@ export struct EntityManager
//add_mutex.lock_nothrow();
entity.id = id_manager.getNewID();
//add_mutex.unlock_nothrow();
entity.updateID();
id_manager.update(*entity); //entity.updateID();
return entity;
}
@ -2237,7 +2266,7 @@ export struct EntityManager
block = info.last_block;
entity.id = *cast(EntityID*)(block.dataBegin() + block.entities_count * EntityID.sizeof);
entity.updateID();
id_manager.update(*entity); //entity.updateID();
}
block = info.last_block;