-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
This commit is contained in:
Mergul 2019-03-28 12:19:30 +01:00
parent c64d621f0e
commit 280d7b8ec4
2 changed files with 148 additions and 11 deletions

View file

@ -93,7 +93,16 @@ class EntityManager
foreach (ref system; systems) foreach (ref system; systems)
{ {
if (system.m_update is null) 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; continue;
}
bool added = false; bool added = false;
foreach (i, caller; passes[system.m_pass].system_callers) foreach (i, caller; passes[system.m_pass].system_callers)
@ -119,6 +128,7 @@ class EntityManager
foreach (info; &entities_infos.byValue) foreach (info; &entities_infos.byValue)
{ {
addSystemCaller(*info, system.id); addSystemCaller(*info, system.id);
//info.systems[system.id] = true;
} }
} }
@ -1197,8 +1207,12 @@ class EntityManager
foreach (i, ref system; systems) 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_update is null)
{
if(system.m_entity_added || system.m_entity_removed)connectListenerToEntityInfo(*info,cast(uint)i);
continue; continue;
}
addSystemCaller(*info, cast(uint)i); addSystemCaller(*info, cast(uint)i);
} }
@ -1221,18 +1235,53 @@ class EntityManager
Mallocator.instance.dispose(info.remove_listeners); Mallocator.instance.dispose(info.remove_listeners);
info.remove_listeners = null; info.remove_listeners = null;
} }
//allocate local data
ushort[] tmp_add = (cast(ushort*)alloca(systems.length*ushort.sizeof))[0..systems.length]; 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]; ushort[] tmp_rem = (cast(ushort*)alloca(systems.length*ushort.sizeof))[0..systems.length];
int add_len = 0; int add_len = 0;
int rem_len = 0; int rem_len = 0;
//assign listeners to lists
foreach(i;0..systems.length) foreach(i;0..systems.length)
{ {
if(info.systems[i]) if(info.systems[i])
{ {
System* system = &systems[i]; System* system = &systems[i];
if(system.m_entity_added)tmp_add[add_len++] = cast(ushort)i; //onAddEntity listener
if(system.m_entity_removed)tmp_rem[rem_len++] = cast(ushort)i; if(system.m_entity_added)
{
//find listener position by priority
int j;
for(j=0;j<add_len;j++)
{
if(systems[i].priority > 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<rem_len;j++)
{
if(systems[i].priority > 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) if(rem_len)
{ {
info.remove_listeners = Mallocator.instance.makeArray!ushort(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]; System* system = &systems[system_id];
@ -1276,6 +1325,38 @@ class EntityManager
is_: 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; uint index = 0;
for (; index < passes[system.m_pass].system_callers.length; index++) 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) if (index < passes[system.m_pass].system_callers.length)
{ {
passes[system.m_pass].system_callers[index].infos.add(&entity); passes[system.m_pass].system_callers[index].infos.add(&info);
entity.systems[system_id] = true;
} }
} }
@ -1917,7 +1996,7 @@ class EntityManager
private void callRemoveEntityListeners(EntityInfo* info, EntitiesBlock* block, int begin, int end) @nogc nothrow 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]; System* system = &systems[listener];
callRemoveEntityListener(system,info,block,begin,end); callRemoveEntityListener(system,info,block,begin,end);

View file

@ -170,11 +170,11 @@ struct TestSystem
//foreach(i;0..data.length) //foreach(i;0..data.length)
//writeln("Entity added ID: ",data.entites[i].id.id); //writeln("Entity added ID: ",data.entites[i].id.id);
} }
/*
void onRemove(EntitiesData data) void onRemove(EntitiesData data)
{ {
//writeln("Entity destroyed ID: ",data.entites[0].id); //writeln("Entity destroyed ID: ",data.entites[0].id);
} }*/
bool onBegin() 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; import std.meta;
struct TestSystem2 struct TestSystem2
@ -402,6 +453,9 @@ int main()
gEM.registerSystem!TestSystemWithHighPriority(100,"fixed"); gEM.registerSystem!TestSystemWithHighPriority(100,"fixed");
gEM.registerSystem!TestSystem(0); gEM.registerSystem!TestSystem(0);
gEM.registerSystem!ChangeTestSystem(0); gEM.registerSystem!ChangeTestSystem(0);
gEM.registerSystem!Sys1(10);
gEM.registerSystem!Sys2(-100);
gEM.registerSystem!Sys3(-2);
//gEM.registerSystem!TestSystemWithHighPriority(100); //gEM.registerSystem!TestSystemWithHighPriority(100);
//gEM.registerSystem!TestSystem2(0); //gEM.registerSystem!TestSystem2(0);
gEM.endRegister(); gEM.endRegister();
@ -429,6 +483,10 @@ int main()
{ {
entity = gEM.addEntity(tmpl); entity = gEM.addEntity(tmpl);
writeEntityComponents(gEM.getEntity(entity.id)); 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; time = MonoTime.currTime;