-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:
parent
f666dfd1d5
commit
16a5696840
4 changed files with 143 additions and 165 deletions
3
dub.json
3
dub.json
|
|
@ -10,9 +10,6 @@
|
|||
"dflags-posix-ldc": [
|
||||
"-defaultlib=phobos2-ldc,druntime-ldc"
|
||||
],
|
||||
"versions": [
|
||||
"UpdateBySystems"
|
||||
],
|
||||
"configurations" : [
|
||||
{
|
||||
"name" : "library",
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -285,6 +285,7 @@ import std.meta;
|
|||
gEM.setJobDispachFunc(&dispatch);
|
||||
assert(gEM !is null);
|
||||
|
||||
gEM.beginRegister();
|
||||
gEM.registerPass("fixed");
|
||||
|
||||
MonoTime time = MonoTime.currTime;
|
||||
|
|
@ -306,6 +307,7 @@ import std.meta;
|
|||
gEM.registerSystem!TestSystem(0);
|
||||
//gEM.registerSystem!TestSystemWithHighPriority(100);
|
||||
//gEM.registerSystem!TestSystem2(0);
|
||||
gEM.endRegister();
|
||||
|
||||
dur = (MonoTime.currTime - time).total!"usecs";
|
||||
writeln("Systems register: ", dur, " usecs");
|
||||
|
|
@ -368,9 +370,11 @@ import std.meta;
|
|||
|
||||
//foreach(j; 0..1_000)gEM.addEntity(tmpl);
|
||||
|
||||
gEM.beginRegister();
|
||||
gEM.registerSystem!TestSystem2(0);
|
||||
gEM.endRegister();
|
||||
|
||||
gEM.generateDependencies();
|
||||
//gEM.generateDependencies();
|
||||
|
||||
//assert(*(cast(EntityID*)(cast(void*)tmpl.info.first_block+24)) == EntityID(1,1));
|
||||
//assert(*(cast(EntityID*)(cast(void*)tmpl.info.first_block+48)) == EntityID(1,1));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue