-removed UpdateBySystems version switch (it's now default behaviour)

-beginRegister() and endRegister() was added (every register functions must be called between this calls, update calls can't be called there)
-SystemCallers and Systems dependecies is rebuild always in endRegister();
-beginRegister() clear all SystemCallers and Systems dependencies
-possibility to get System ID and execution state
-JobGroup has now pointer to it's parent (SystemCaller)
-SystemCaller clean up destructor
This commit is contained in:
Mergul 2018-10-27 17:34:27 +02:00
parent f666dfd1d5
commit 16a5696840
4 changed files with 143 additions and 165 deletions

View file

@ -20,6 +20,8 @@ import ecs.vector;
import ecs.events;
alias gEM = EntityManager.instance;
alias gEntityManager = EntityManager.instance;
alias gEventManager = EntityManager.instance;
alias SerializeVector = ecs.vector.Vector!ubyte;
class EntityManager
@ -50,6 +52,67 @@ class EntityManager
instance = null;
}
/************************************************************************************************************************
*Begin registering process. Every register function should be called between beginRegister() and endRegister().
*/
void beginRegister()
{
assert(!register_state,"beginRegister() can't be called twice before endRegister();");
register_state = true;
foreach(pass;passes)
{
foreach(caller;pass.system_callers)
{
Mallocator.instance.dispose(caller);
}
pass.system_callers.clear();
}
}
/************************************************************************************************************************
*End registering process. Every register function should be called between beginRegister() and endRegister().
*/
void endRegister()
{
assert(register_state,"beginRegister() should be called before endRegister();");
register_state = false;
foreach(ref system;systems)
{
if (system.m_update is null)
continue;
bool added = false;
foreach (i, caller; passes[system.m_pass].system_callers)
{
if (systems[caller.system_id].priority > system.priority)
{
SystemCaller* sys_caller = Mallocator.instance.make!SystemCaller;
sys_caller.system_id = system.id;
sys_caller.job_group.caller = sys_caller;
passes[system.m_pass].system_callers.add(sys_caller, i);
added = true;
break;
}
}
if (!added)
{
SystemCaller* sys_caller = Mallocator.instance.make!SystemCaller;
sys_caller.system_id = system.id;
sys_caller.job_group.caller = sys_caller;
passes[system.m_pass].system_callers.add(sys_caller);
}
foreach(info;&entities_infos.byValue)
{
addSystemCaller(*info,system.id);
}
}
generateDependencies();
}
/************************************************************************************************************************
*Default constructor.
*/
@ -81,7 +144,7 @@ class EntityManager
void registerSystem(Sys)(int priority, const(char)[] pass_name)
{
ushort pass = passes_map.get(pass_name, ushort.max);
assert(pass != ushort.max);
assert(pass != ushort.max,"Update pass (Name "~pass_name~") doesn't exist.");
registerSystem!(Sys)(priority, pass);
}
@ -97,14 +160,15 @@ class EntityManager
{
alias STC = ParameterStorageClass;
assert(pass < passes.length);
assert(register_state,"asda");
assert(pass < passes.length,"Update pass (ID "~pass.to!string~") doesn't exist.");
System system;
system.m_pass = pass;
static if (!(hasMember!(Sys, "system_id")) || !is(typeof(Sys.system_id) == ushort))
{
static assert(0, "System should have \"__gshared ushort system_id");
static assert(0, "Add \"mixin ECS.System;\" in top of system structure;");//"System should have \"__gshared ushort system_id");
}
static if (!(hasMember!(Sys, "EntitiesData")))
@ -489,55 +553,24 @@ class EntityManager
if (system.m_create)
(cast(void function(void*)) system.m_create)(system.m_system_pointer);
system.m_id = sys_id;
systems[sys_id] = system;
Sys.system_id = sys_id;
}
else
{
system.name = Mallocator.instance.makeArray(Sys.stringof);
systems_map.add(system.name, cast(ushort) systems.length);
system.m_id = cast(ushort)(systems.length);
systems.add(system);
if (system.m_create)
(cast(void function(void*)) system.m_create)(system.m_system_pointer);
systems[$ - 1].enable();
Sys.system_id = cast(ushort)(systems.length - 1);
if (system.m_update !is null)
{
foreach (info; &entities_infos.byValue)
{
addEntityCaller(*info, cast(uint) systems.length - 1);
}
}
version (UpdateBySystems)
{
bool added = false;
foreach (i, ref caller; passes[pass].system_callers)
{
if (systems[caller.system_id].priority > priority)
{
SystemCaller* sys_caller = Mallocator.instance.make!SystemCaller;
sys_caller.system_id = Sys.system_id;
passes[pass].system_callers.add(sys_caller, i);
added = true;
break;
}
}
if (!added)
{
SystemCaller* sys_caller = Mallocator.instance.make!SystemCaller;
sys_caller.system_id = Sys.system_id;
passes[pass].system_callers.add(sys_caller);
}
}
}
updateEntityCallers();
Sys.system_id = system.id;
}
System* getSystem(ushort id)
@ -568,7 +601,7 @@ class EntityManager
static if (!(hasMember!(Comp, "component_id")) || !is(typeof(Comp.component_id) == ushort))
{
static assert(0, "Component should have \"__gshared ushort component_id");
static assert(0, "Add \"mixin ECS.Component;\" in top of component structure;");//"Component should have \"__gshared ushort component_id");
}
static if (hasMember!(Comp, "onDestroy") && isFunction!(Comp.onDestroy)
@ -609,7 +642,7 @@ class EntityManager
static if (!(hasMember!(Ev, "event_id")) || !is(typeof(Ev.event_id) == ushort))
{
static assert(0, "Event should have \"__gshared ushort event_id");
static assert(0, "Add \"mixin ECS.Event;\" in top of event structure;");//"Event should have \"__gshared ushort event_id");
}
static if (hasMember!(Ev, "onDestroy") && isFunction!(Ev.onDestroy)
@ -654,36 +687,17 @@ class EntityManager
*/
export void update(ushort pass = 0)
{
assert(!register_state);
assert(pass < passes.length);
version (UpdateBySystems)
foreach (caller; passes[pass].system_callers)
{
foreach (caller; passes[pass].system_callers)
System* sys = &systems[caller.system_id];
if (sys.enabled && sys.execute)
{
System* sys = &systems[caller.system_id];
if (sys.enabled && sys.execute)
foreach (info; caller.infos)
{
//if (sys.m_begin)
// sys.m_begin(sys.m_system_pointer);
foreach (info; caller.infos)
{
CallData data = CallData(caller.system_id, sys, info);
data.update();
//(cast(SytemFuncType) data.system.m_update)(data);
}
//if (sys.m_end)
// sys.m_end(sys.m_system_pointer);
}
}
}
else
{
foreach (info; &entities_infos.byValue)
{
foreach (data; info.callers)
{
if (data.system.enabled)
data.update();
//(cast(SytemFuncType) data.system.m_update)(data); //caller(call_data,null);
CallData data = CallData(caller.system_id, sys, info);
data.update();
}
}
}
@ -701,6 +715,7 @@ class EntityManager
void updateMT(ushort pass = 0)
{
assert(!register_state);
assert(pass < passes.length);
assert(m_dispatch_jobs,
"Can't update with multithreading without JobDispatch function. Please use setJobDispatchFunc().");
@ -827,28 +842,6 @@ class EntityManager
}
}
struct Job
{
CallData[] callers;
void execute()
{
EntityManager.instance.getThreadID();
foreach (ref caller; callers)
{
caller.update();
}
}
}
struct JobGroup
{
Job[] jobs;
JobGroup*[] dependencies;
uint id;
//uint max_jobs;
}
void setJobDispachFunc(void delegate(JobGroup) func)
{
m_dispatch_jobs = func;
@ -974,41 +967,17 @@ class EntityManager
{
if (system.m_update is null)
continue;
addEntityCaller(*info, i);
addSystemCaller(*info, i);
}
version (UpdateBySystems)
{
foreach (uint i, ref system; systems)
{
if (system.m_update is null)
continue;
addSystemCaller(*info, i);
}
}
updateEntityCallers();
entities_infos.add(info.components, info);
}
return info;
}
export void updateEntityCallers()
{
foreach (entity; &entities_infos.byValue)
{
foreach (ref caller; entity.callers)
{
caller.system = &systems[caller.system_id];
}
}
}
export void addSystemCaller(ref EntityInfo entity, uint system_id)
{
System* system = &systems[system_id];
//CallData call_data = CallData(system_id, system, &entity);
if (system.m_absent_components)
{
@ -1042,51 +1011,6 @@ class EntityManager
if (index < passes[system.m_pass].system_callers.length)
passes[system.m_pass].system_callers[index].infos.add(&entity);
/*for (; index < entity.callers.length; index++)
{
CallData* caller = &entity.callers[index];
if (caller.system.priority >= call_data.system.priority)
break;
}
entity.callers.add(call_data, index);*/
}
export void addEntityCaller(ref EntityInfo entity, uint system_id)
{
System* system = &systems[system_id];
CallData call_data = CallData(system_id, system, &entity);
if (system.m_absent_components)
{
foreach (id; system.m_absent_components)
{
foreach (id2; entity.components)
{
if (id == id2)
return;
}
}
}
foreach (id; system.m_components)
{
foreach (i2, id2; entity.components)
{
if (id2 == id)
goto is_;
}
return;
is_:
}
uint index = 0;
for (; index < entity.callers.length; index++)
{
CallData* caller = &entity.callers[index];
if (caller.system.priority >= call_data.system.priority)
break;
}
entity.callers.add(call_data, index);
}
/************************************************************************************************************************
@ -1677,7 +1601,7 @@ class EntityManager
foreach (ref system; systems)
{
if (system.enabled && system.m_begin)
system.execute = (cast(bool function(void*)) system.m_begin)(system.m_system_pointer);
system.m_execute = (cast(bool function(void*)) system.m_begin)(system.m_system_pointer);
}
}
@ -1927,7 +1851,7 @@ class EntityManager
///pointer to last block
EntitiesBlock* last_block;
///array of CallData. Contain data for System calls.
Vector!(CallData) callers;
//Vector!(CallData) callers;
///Mutex used to managing block new alloction
}
@ -2000,8 +1924,41 @@ class EntityManager
ushort end;
}
struct Job
{
CallData[] callers;
void execute()
{
EntityManager.instance.getThreadID();
foreach (ref caller; callers)
{
caller.update();
}
}
}
struct JobGroup
{
Job[] jobs;
JobGroup*[] dependencies;
uint id;
SystemCaller* caller;
//uint max_jobs;
}
struct SystemCaller
{
~this()
{
if(dependencies)
{
Mallocator.instance.dispose(dependencies);
Mallocator.instance.dispose(exclusion);
}
if(job_group.dependencies)Mallocator.instance.dispose(job_group.dependencies);
}
uint system_id;
System* system;
Vector!(EntityInfo*) infos;
@ -2036,6 +1993,8 @@ class EntityManager
Vector!(UpdatePass*) passes;
bool register_state = false;
//Vector!(SystemCaller*) system_callers;
alias SytemFuncType = void function(ref EntityManager.CallData data);

View file

@ -45,10 +45,28 @@ struct System
return m_priority;
}
/************************************************************************************************************************
*Get system priority.
*/
export bool execute()
{
return m_execute;
}
/************************************************************************************************************************
*Get system priority.
*/
export ushort id()
{
return m_id;
}
package:
///should system be executed in current update?
bool execute = true;
bool m_execute = true;
///system id
ushort m_id;
///should system update and catch events?
bool m_enabled = false;