-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:
parent
c64d621f0e
commit
280d7b8ec4
2 changed files with 148 additions and 11 deletions
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue