diff --git a/.gitignore b/.gitignore
index 3a4254f..280be93 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,5 +3,5 @@
!source/**
!tests/**
!README.md
-!dub.json
+!./dub.json
!.gitignore
\ No newline at end of file
diff --git a/source/ecs/manager.d b/source/ecs/manager.d
index 87491ea..8ca576c 100644
--- a/source/ecs/manager.d
+++ b/source/ecs/manager.d
@@ -84,6 +84,12 @@ class EntityManager
assert(register_state, "beginRegister() should be called before endRegister();");
register_state = false;
+ foreach(ref info; &entities_infos.byValue)
+ {
+ if(info.systems)Mallocator.instance.dispose(info.systems);
+ info.systems = Mallocator.instance.makeArray!bool(systems.length);
+ }
+
foreach (ref system; systems)
{
if (system.m_update is null)
@@ -151,6 +157,11 @@ class EntityManager
}
}
+ foreach(info; &entities_infos.byValue)
+ {
+ generateListeners(info);
+ }
+
generateDependencies();
}
@@ -681,7 +692,6 @@ class EntityManager
static "~RetType.stringof~" call" ~ func
~ "(void* system_pointer)
{
-
Sys* s = cast(Sys*) system_pointer;
"~ret_str~"s." ~ func ~ "();
}
@@ -693,6 +703,32 @@ class EntityManager
//dfmt on
}
+ static string catchEntityFunc(RetType = void)(string member, string func)
+ {
+ //dfmt off
+
+ static if(is(RetType == void))string ret_str = "";
+ else string ret_str = "return ";
+ string ret = "static if (hasMember!(Sys, \"" ~ func ~ "\") &&
+ Parameters!(Sys."~func~").length == 1 &&
+ is(Parameters!(Sys."~func~")[0] == Sys.EntitiesData) &&
+ is(ReturnType!(Sys."~func~") == "~RetType.stringof~"))
+ {
+ static "~RetType.stringof~" call" ~ func
+ ~ "(void* system_pointer)
+ {
+ Sys* s = cast(Sys*) system_pointer;
+ Sys.EntitiesData data;
+ "~ret_str~"s." ~ func ~ "(data);
+ }
+
+ system."
+ ~ member ~ " = &call" ~ func ~ ";
+ }";
+ return ret;
+ //dfmt on
+ }
+
mixin(catchFunc("m_enable", "onEnable"));
mixin(catchFunc("m_disable", "onDisable"));
mixin(catchFunc("m_create", "onCreate"));
@@ -700,6 +736,9 @@ class EntityManager
mixin(catchFunc!(bool)("m_begin", "onBegin"));
mixin(catchFunc("m_end", "onEnd"));
+ mixin(catchEntityFunc("m_entity_added","onAdd"));
+ mixin(catchEntityFunc("m_entity_removed","onRemove"));
+
system.m_system_pointer = cast(void*) Mallocator.instance.make!Sys;
system.m_priority = priority;
(cast(Sys*) system.m_system_pointer).__ecsInitialize();
@@ -1145,6 +1184,8 @@ class EntityManager
current_delta += entites_in_block * components[id].size;
}
+ info.systems = Mallocator.instance.makeArray!bool(systems.length);
+
foreach (i, ref system; systems)
{
if (system.m_update is null)
@@ -1153,10 +1194,52 @@ class EntityManager
}
entities_infos.add(info.components, info);
+
+ generateListeners(info);
}
return info;
}
+ void generateListeners(EntityInfo* info)
+ {
+ if(info.add_listeners)
+ {
+ Mallocator.instance.dispose(info.add_listeners);
+ info.add_listeners = null;
+ }
+ if(info.remove_listeners)
+ {
+ Mallocator.instance.dispose(info.remove_listeners);
+ info.remove_listeners = null;
+ }
+
+ 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;
+ 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;
+ }
+ }
+
+ if(add_len)
+ {
+ info.add_listeners = Mallocator.instance.makeArray!ushort(add_len);
+ memcpy(info.add_listeners.ptr,tmp_add.ptr,add_len*ushort.sizeof);
+ }
+
+ if(rem_len)
+ {
+ info.remove_listeners = Mallocator.instance.makeArray!ushort(rem_len);
+ memcpy(info.remove_listeners.ptr,tmp_add.ptr,rem_len*ushort.sizeof);
+ }
+ }
+
export void addSystemCaller(ref EntityInfo entity, uint system_id) nothrow @nogc
{
System* system = &systems[system_id];
@@ -1193,6 +1276,8 @@ 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;
}
/************************************************************************************************************************
@@ -2084,6 +2169,13 @@ class EntityManager
///max number of entities in block
ushort max_entities;
+ ///array of systems which will update this entity
+ bool[] systems;
+ ///systems which are listening for added entities
+ ushort[] add_listeners;
+ ///systems which are listening for removed entities
+ ushort[] remove_listeners;
+
///pointer to first block/page
EntitiesBlock* first_block;
///pointer to last block
diff --git a/source/ecs/system.d b/source/ecs/system.d
index ba2168e..747f85c 100644
--- a/source/ecs/system.d
+++ b/source/ecs/system.d
@@ -9,12 +9,15 @@ import ecs.manager;
/************************************************************************************************************************
*System contain data required to proper glue EntityManager with Systems.
*System callbacks:
+*
-void update(EntitesData);
*
-void onEnable()
*
-void onDisable();
*
-bool onBegin();
*
-void onEnd();
*
-void onCreate()
*
-void onDestroy();
+*
-void onAdd(EntitesData);
+*
-void onRemove(EntitiesData);
*/
struct System
{
@@ -132,6 +135,9 @@ package:
void* m_begin;
void* m_end;
+ void* m_entity_added;
+ void* m_entity_removed;
+
//void function(ref EntityManager.CallData data) m_initialize;
//void function(ref EntityManager.CallData data) m_deinitilize;
void* m_initialize;
diff --git a/tests/tests.d b/tests/tests.d
index 1d48f4b..dade72a 100644
--- a/tests/tests.d
+++ b/tests/tests.d
@@ -108,6 +108,21 @@ struct TestSystem
writeln("On Test System destroy.");
}
+ void onAdd(EntitiesData data)
+ {
+ writeln("Entity added ID: ",data.entites[0].id);
+ }
+
+ /*void onAdd()
+ {
+
+ }*/
+
+ void onRemove(EntitiesData data)
+ {
+ writeln("Entity destroyed ID: ",data.entites[0].id);
+ }
+
bool onBegin()
{
//writeln("On Test System begin.");
@@ -127,6 +142,7 @@ struct TestSystem
static struct EntitiesData
{
size_t length;
+ const(Entity)[] entites;
TestComp[] test;
TestComp2[] test2;
@readonly @optional const(TestComp3)[] test3;