-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)
{
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<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)
{
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);

View file

@ -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;