From 280d7b8ec4b0ad4287c3be184527b02160f0e978 Mon Sep 17 00:00:00 2001 From: Mergul Date: Thu, 28 Mar 2019 12:19:30 +0100 Subject: [PATCH] -onAdd/onRemove order is determined by system priority -fixed many bug with onAdd/onRemove -onAdd/onRemove now works even when system haven't update callback --- source/ecs/manager.d | 97 ++++++++++++++++++++++++++++++++++++++++---- tests/tests.d | 62 +++++++++++++++++++++++++++- 2 files changed, 148 insertions(+), 11 deletions(-) diff --git a/source/ecs/manager.d b/source/ecs/manager.d index 0c6d0aa..cd3c00f 100644 --- a/source/ecs/manager.d +++ b/source/ecs/manager.d @@ -93,7 +93,16 @@ class EntityManager foreach (ref system; systems) { if (system.m_update is null) + { + if(system.m_entity_added || system.m_entity_removed) + { + foreach (info; &entities_infos.byValue) + { + connectListenerToEntityInfo(*info,system.id); + } + } continue; + } bool added = false; foreach (i, caller; passes[system.m_pass].system_callers) @@ -119,6 +128,7 @@ class EntityManager foreach (info; &entities_infos.byValue) { addSystemCaller(*info, system.id); + //info.systems[system.id] = true; } } @@ -1197,8 +1207,12 @@ class EntityManager foreach (i, ref system; systems) { + //if(system.m_entity_added || system.m_entity_removed)info.systems[system.id] = true; if (system.m_update is null) + { + if(system.m_entity_added || system.m_entity_removed)connectListenerToEntityInfo(*info,cast(uint)i); continue; + } addSystemCaller(*info, cast(uint)i); } @@ -1221,18 +1235,53 @@ class EntityManager Mallocator.instance.dispose(info.remove_listeners); info.remove_listeners = null; } - + //allocate local data ushort[] tmp_add = (cast(ushort*)alloca(systems.length*ushort.sizeof))[0..systems.length]; ushort[] tmp_rem = (cast(ushort*)alloca(systems.length*ushort.sizeof))[0..systems.length]; int add_len = 0; int rem_len = 0; + //assign listeners to lists foreach(i;0..systems.length) { if(info.systems[i]) { System* system = &systems[i]; - if(system.m_entity_added)tmp_add[add_len++] = cast(ushort)i; - if(system.m_entity_removed)tmp_rem[rem_len++] = cast(ushort)i; + //onAddEntity listener + if(system.m_entity_added) + { + //find listener position by priority + int j; + for(j=0;j systems[tmp_add[j]].priority)break; + } + add_len++; + //move elements after new listener + for(int k=add_len;k>j;k--) + { + tmp_add[k] = tmp_add[k-1]; + } + //assign listener + tmp_add[j] = cast(ushort)i; + } + //onRemoveEntity listener + if(system.m_entity_removed) + { + //find listener position by priority + int j; + for(j=0;j systems[tmp_rem[j]].priority)break; + } + rem_len++; + //move elements after new listener + for(int k=rem_len;k>j;k--) + { + tmp_rem[k] = tmp_rem[k-1]; + } + //assign listener + tmp_rem[j] = cast(ushort)i; + } } } @@ -1245,11 +1294,11 @@ class EntityManager if(rem_len) { info.remove_listeners = Mallocator.instance.makeArray!ushort(rem_len); - memcpy(info.remove_listeners.ptr,tmp_add.ptr,rem_len*ushort.sizeof); + memcpy(info.remove_listeners.ptr,tmp_rem.ptr,rem_len*ushort.sizeof); } } - export void addSystemCaller(ref EntityInfo entity, uint system_id) nothrow @nogc + export void connectListenerToEntityInfo(ref EntityInfo entity, uint system_id) nothrow @nogc { System* system = &systems[system_id]; @@ -1276,6 +1325,38 @@ class EntityManager is_: } + entity.systems[system_id] = true; + } + + export void addSystemCaller(ref EntityInfo info, uint system_id) nothrow @nogc + { + System* system = &systems[system_id]; + + if (system.m_excluded_components) + { + foreach (id; system.m_excluded_components) + { + foreach (id2; info.components) + { + if (id == id2) + return; + } + } + } + + foreach (id; system.m_components) + { + foreach (i2, id2; info.components) + { + if (id2 == id) + goto is_; + } + return; + is_: + } + + info.systems[system_id] = true; + uint index = 0; for (; index < passes[system.m_pass].system_callers.length; index++) { @@ -1285,9 +1366,7 @@ class EntityManager if (index < passes[system.m_pass].system_callers.length) { - passes[system.m_pass].system_callers[index].infos.add(&entity); - - entity.systems[system_id] = true; + passes[system.m_pass].system_callers[index].infos.add(&info); } } @@ -1917,7 +1996,7 @@ class EntityManager private void callRemoveEntityListeners(EntityInfo* info, EntitiesBlock* block, int begin, int end) @nogc nothrow { - foreach(listener;info.add_listeners) + foreach(listener;info.remove_listeners) { System* system = &systems[listener]; callRemoveEntityListener(system,info,block,begin,end); diff --git a/tests/tests.d b/tests/tests.d index 9e74e6e..4fa8515 100644 --- a/tests/tests.d +++ b/tests/tests.d @@ -170,11 +170,11 @@ struct TestSystem //foreach(i;0..data.length) //writeln("Entity added ID: ",data.entites[i].id.id); } - +/* void onRemove(EntitiesData data) { //writeln("Entity destroyed ID: ",data.entites[0].id); - } + }*/ bool onBegin() { @@ -256,6 +256,57 @@ struct TestSystemWithHighPriority }*/ } +struct Sys1 +{ + mixin ECS.System; + + struct EntitiesData + { + TestComp[] comp; + } + + void onAdd(EntitiesData data) + { + + } +} + +struct Sys2 +{ + mixin ECS.System; + + struct EntitiesData + { + TestComp[] comp; + } + + void onAdd(EntitiesData data) + { + + } +} + +struct Sys3 +{ + mixin ECS.System; + + struct EntitiesData + { + TestComp[] comp; + } + + void onAdd(EntitiesData data) + { + + } + + void update(EntitiesData data) + { + + } +} + + import std.meta; struct TestSystem2 @@ -402,6 +453,9 @@ int main() gEM.registerSystem!TestSystemWithHighPriority(100,"fixed"); gEM.registerSystem!TestSystem(0); gEM.registerSystem!ChangeTestSystem(0); + gEM.registerSystem!Sys1(10); + gEM.registerSystem!Sys2(-100); + gEM.registerSystem!Sys3(-2); //gEM.registerSystem!TestSystemWithHighPriority(100); //gEM.registerSystem!TestSystem2(0); gEM.endRegister(); @@ -429,6 +483,10 @@ int main() { entity = gEM.addEntity(tmpl); writeEntityComponents(gEM.getEntity(entity.id)); + EntityManager.EntitiesBlock* block = EntityManager.instance.getMetaData(gEM.getEntity(entity.id)); + EntityManager.EntityInfo* info = block.type_info; + writeln(info.add_listeners); + //if(info)assert(0); } time = MonoTime.currTime;