From 16a5696840b634bbd871a2e341442b341aeac99b Mon Sep 17 00:00:00 2001 From: Mergul Date: Sat, 27 Oct 2018 17:34:27 +0200 Subject: [PATCH] -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 --- dub.json | 3 - source/ecs/manager.d | 279 ++++++++++++++++++------------------------- source/ecs/system.d | 20 +++- tests/tests.d | 6 +- 4 files changed, 143 insertions(+), 165 deletions(-) diff --git a/dub.json b/dub.json index c4303f2..bacb5fc 100755 --- a/dub.json +++ b/dub.json @@ -10,9 +10,6 @@ "dflags-posix-ldc": [ "-defaultlib=phobos2-ldc,druntime-ldc" ], - "versions": [ - "UpdateBySystems" - ], "configurations" : [ { "name" : "library", diff --git a/source/ecs/manager.d b/source/ecs/manager.d index cee24f2..fdc2862 100644 --- a/source/ecs/manager.d +++ b/source/ecs/manager.d @@ -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); diff --git a/source/ecs/system.d b/source/ecs/system.d index 2787c68..787c56c 100644 --- a/source/ecs/system.d +++ b/source/ecs/system.d @@ -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; diff --git a/tests/tests.d b/tests/tests.d index a217b91..5366d53 100644 --- a/tests/tests.d +++ b/tests/tests.d @@ -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));