-added new listener callback: onChangeEntity. Callback is called when entity optional components are changed. There is no info about which components are changed (added/removed), but should be in the future).This is probably slowest callback.

This commit is contained in:
Mergul 2019-03-28 20:25:08 +01:00
parent 7a33e4f94f
commit 0608fe6e89
3 changed files with 175 additions and 42 deletions

View file

@ -95,7 +95,7 @@ class EntityManager
{ {
if (system.m_update is null) if (system.m_update is null)
{ {
if (system.m_add_entity || system.m_remove_entity) if (system.m_add_entity || system.m_remove_entity || system.m_change_entity)
{ {
foreach (info; &entities_infos.byValue) foreach (info; &entities_infos.byValue)
{ {
@ -761,6 +761,7 @@ class EntityManager
mixin(catchEntityFunc("m_add_entity", "onAddEntity")); mixin(catchEntityFunc("m_add_entity", "onAddEntity"));
mixin(catchEntityFunc("m_remove_entity", "onRemoveEntity")); mixin(catchEntityFunc("m_remove_entity", "onRemoveEntity"));
mixin(catchEntityFunc("m_change_entity", "onChangeEntity"));
system.m_system_pointer = cast(void*) Mallocator.instance.make!Sys; system.m_system_pointer = cast(void*) Mallocator.instance.make!Sys;
system.m_priority = priority; system.m_priority = priority;
@ -1210,10 +1211,9 @@ class EntityManager
foreach (i, ref system; systems) foreach (i, ref system; systems)
{ {
//if(system.m_add_entity || system.m_remove_entity)info.systems[system.id] = true;
if (system.m_update is null) if (system.m_update is null)
{ {
if (system.m_add_entity || system.m_remove_entity) if (system.m_add_entity || system.m_remove_entity || system.m_change_entity)
connectListenerToEntityInfo(*info, cast(uint) i); connectListenerToEntityInfo(*info, cast(uint) i);
continue; continue;
} }
@ -1239,13 +1239,21 @@ class EntityManager
Mallocator.instance.dispose(info.remove_listeners); Mallocator.instance.dispose(info.remove_listeners);
info.remove_listeners = null; info.remove_listeners = null;
} }
if (info.change_listeners)
{
Mallocator.instance.dispose(info.change_listeners);
info.change_listeners = null;
}
//allocate local data //allocate local data
ushort[] tmp_add = (cast(ushort*) alloca(systems.length * ushort.sizeof))[0 ushort[] tmp_add = (cast(ushort*) alloca(systems.length * ushort.sizeof))[0
.. systems.length]; .. systems.length];
ushort[] tmp_rem = (cast(ushort*) alloca(systems.length * ushort.sizeof))[0 ushort[] tmp_rem = (cast(ushort*) alloca(systems.length * ushort.sizeof))[0
.. systems.length]; .. systems.length];
ushort[] tmp_ch = (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;
int ch_len = 0;
//assign listeners to lists //assign listeners to lists
foreach (i; 0 .. systems.length) foreach (i; 0 .. systems.length)
{ {
@ -1290,6 +1298,25 @@ class EntityManager
//assign listener //assign listener
tmp_rem[j] = cast(ushort) i; tmp_rem[j] = cast(ushort) i;
} }
//onChangeEntity listener
if (system.m_change_entity)
{
//find listener position by priority
int j;
for (j = 0; j < ch_len; j++)
{
if (systems[i].priority > systems[tmp_ch[j]].priority)
break;
}
ch_len++;
//move elements after new listener
for (int k = ch_len; k > j; k--)
{
tmp_ch[k] = tmp_ch[k - 1];
}
//assign listener
tmp_ch[j] = cast(ushort) i;
}
} }
} }
@ -1304,6 +1331,12 @@ class EntityManager
info.remove_listeners = Mallocator.instance.makeArray!ushort(rem_len); info.remove_listeners = Mallocator.instance.makeArray!ushort(rem_len);
memcpy(info.remove_listeners.ptr, tmp_rem.ptr, rem_len * ushort.sizeof); memcpy(info.remove_listeners.ptr, tmp_rem.ptr, rem_len * ushort.sizeof);
} }
if (ch_len)
{
info.change_listeners = Mallocator.instance.makeArray!ushort(ch_len);
memcpy(info.change_listeners.ptr, tmp_ch.ptr, ch_len * ushort.sizeof);
}
} }
export void connectListenerToEntityInfo(ref EntityInfo entity, uint system_id) nothrow @nogc export void connectListenerToEntityInfo(ref EntityInfo entity, uint system_id) nothrow @nogc
@ -1486,6 +1519,18 @@ class EntityManager
} }
} }
if (new_info.change_listeners)
{
foreach (listener; new_info.change_listeners)
{
if (info.systems[listener])
{
callChangeEntityListener(&systems[listener], new_info, new_block,
new_block.entities_count, new_block.entities_count + 1, del_ids);
}
}
}
new_block.entities_count++; new_block.entities_count++;
removeEntityNoID(entity, block); removeEntityNoID(entity, block);
@ -1660,6 +1705,18 @@ class EntityManager
} }
} }
if (new_info.change_listeners)
{
foreach (listener; new_info.change_listeners)
{
if (info.systems[listener])
{
callChangeEntityListener(&systems[listener], new_info, new_block,
new_block.entities_count, new_block.entities_count + 1, new_ids);
}
}
}
new_block.entities_count++; new_block.entities_count++;
removeEntityNoID(entity, block); removeEntityNoID(entity, block);
} }
@ -2026,6 +2083,43 @@ class EntityManager
(cast(void function(ref ListenerCallData) nothrow @nogc) system.m_remove_entity)(data); (cast(void function(ref ListenerCallData) nothrow @nogc) system.m_remove_entity)(data);
} }
private void callChangeEntityListener(System* system, EntityInfo* info,
EntitiesBlock* block, int begin, int end, ushort[] ch_ids) @nogc nothrow
{
int i = 0;
int j = 0;
bool is_ = false;
while (1)
{
if (ch_ids[i] == system.m_optional_components[j])
{
is_ = true;
break;
}
else if (ch_ids[i] > system.m_optional_components[j])
{
j++;
if (j >= system.m_optional_components.length)
break;
}
else
{
i++;
if (i >= ch_ids.length)
break;
}
}
if (!is_)
return;
ListenerCallData data;
data.system = system;
data.block = block;
data.begin = begin;
data.end = end;
(cast(void function(ref ListenerCallData) nothrow @nogc) system.m_change_entity)(data);
}
private void updateBlocks() private void updateBlocks()
{ {
foreach (ref thread; threads) foreach (ref thread; threads)
@ -2393,6 +2487,8 @@ class EntityManager
ushort[] add_listeners; ushort[] add_listeners;
///systems which are listening for removed entities ///systems which are listening for removed entities
ushort[] remove_listeners; ushort[] remove_listeners;
///systems which are listening for changed entities (changed in term of contained components)
ushort[] change_listeners;
///pointer to first block/page ///pointer to first block/page
EntitiesBlock* first_block; EntitiesBlock* first_block;

View file

@ -137,6 +137,7 @@ package:
void* m_add_entity; void* m_add_entity;
void* m_remove_entity; void* m_remove_entity;
void* m_change_entity;
//void function(ref EntityManager.CallData data) m_initialize; //void function(ref EntityManager.CallData data) m_initialize;
//void function(ref EntityManager.CallData data) m_deinitilize; //void function(ref EntityManager.CallData data) m_deinitilize;

View file

@ -12,19 +12,19 @@ import std.stdio;
struct TestEvent struct TestEvent
{ {
mixin ECS.Event;//__gshared ushort event_id; mixin ECS.Event; //__gshared ushort event_id;
int a; int a;
} }
struct TestEvent2 struct TestEvent2
{ {
mixin ECS.Event;//__gshared ushort event_id; mixin ECS.Event; //__gshared ushort event_id;
float a; float a;
} }
static struct TestComp static struct TestComp
{ {
mixin ECS.Component;//__gshared ushort component_id; mixin ECS.Component; //__gshared ushort component_id;
int a = 1; int a = 1;
ulong b = 2; ulong b = 2;
@ -41,7 +41,7 @@ static struct TestComp
static struct TestComp2 static struct TestComp2
{ {
mixin ECS.Component;//__gshared ushort component_id; mixin ECS.Component; //__gshared ushort component_id;
int b = 3; int b = 3;
int a = 4; int a = 4;
@ -58,7 +58,7 @@ static struct TestComp2
static struct TestComp3 static struct TestComp3
{ {
mixin ECS.Component;//__gshared ushort component_id; mixin ECS.Component; //__gshared ushort component_id;
uint gg = 5; //good game uint gg = 5; //good game
uint bg = 6; //bad game uint bg = 6; //bad game
@ -75,7 +75,28 @@ static struct TestComp3
static struct TestComp4 static struct TestComp4
{ {
mixin ECS.Component;//__gshared ushort component_id; mixin ECS.Component; //__gshared ushort component_id;
uint gg = 7; //good game
uint bg = 8; //bad game
ulong a = 9;
ulong b = 10;
ulong c = 11;
ulong g = 12;
static void serializeComponent(ref TestComp comp, SerializeVector output)
{
}
static void deserializeComponent(ref TestComp comp, ubyte[] data)
{
}
}
static struct TestComp5
{
mixin ECS.Component; //__gshared ushort component_id;
uint gg = 7; //good game uint gg = 7; //good game
uint bg = 8; //bad game uint bg = 8; //bad game
ulong a = 9; ulong a = 9;
@ -96,7 +117,7 @@ static struct TestComp4
struct ChangeTestSystem struct ChangeTestSystem
{ {
mixin ECS.System!16;//__gshared ushort system_id; mixin ECS.System!16; //__gshared ushort system_id;
void onCreate() void onCreate()
{ {
@ -110,13 +131,18 @@ struct ChangeTestSystem
void onAddEntity(EntitiesData data) void onAddEntity(EntitiesData data)
{ {
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 onRemoveEntity(EntitiesData data) void onRemoveEntity(EntitiesData data)
{ {
writeln("Entity removed ID: ",data.entites[0].id); writeln("Entity removed! ID: ", data.entites[0].id);
}
void onChangeEntity(EntitiesData data)
{
writeln("Entity changed! ID: ", data.entites[0].id);
} }
bool onBegin() bool onBegin()
@ -140,20 +166,21 @@ struct ChangeTestSystem
size_t length; size_t length;
const(Entity)[] entites; const(Entity)[] entites;
TestComp4[] test4; TestComp4[] test4;
@optional TestComp5[] test5;
} }
void onUpdate(EntitiesData data) void onUpdate(EntitiesData data)
{ {
foreach(i;0..data.length) foreach (i; 0 .. data.length)
{ {
} }
} }
} }
struct TestSystem struct TestSystem
{ {
mixin ECS.System!16;//__gshared ushort system_id; mixin ECS.System!16; //__gshared ushort system_id;
void onCreate() void onCreate()
{ {
@ -170,7 +197,7 @@ 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 onRemoveEntity(EntitiesData data) void onRemoveEntity(EntitiesData data)
{ {
//writeln("Entity destroyed ID: ",data.entites[0].id); //writeln("Entity destroyed ID: ",data.entites[0].id);
@ -202,7 +229,7 @@ struct TestSystem
//@excluded TestComp4[] test4; //@excluded TestComp4[] test4;
} }
void onUpdate(ref Entity entity, ref TestComp test, ref TestComp2 test2)//, TestComp3* test3) //ref TestComp comp) void onUpdate(ref Entity entity, ref TestComp test, ref TestComp2 test2) //, TestComp3* test3) //ref TestComp comp)
{ {
assert(cast(size_t)&test % TestComp.alignof == 0); assert(cast(size_t)&test % TestComp.alignof == 0);
assert(cast(size_t)&test2 % TestComp2.alignof == 0); assert(cast(size_t)&test2 % TestComp2.alignof == 0);
@ -216,7 +243,7 @@ struct TestSystem
void onUpdate(EntitiesData data) void onUpdate(EntitiesData data)
{ {
foreach(i;0..data.length) foreach (i; 0 .. data.length)
{ {
data.test[i].a += 1000; data.test[i].a += 1000;
data.test[i].b += 2000; data.test[i].b += 2000;
@ -233,7 +260,7 @@ struct TestSystem
struct TestSystemWithHighPriority struct TestSystemWithHighPriority
{ {
mixin ECS.System!16;//__gshared ushort system_id; mixin ECS.System!16; //__gshared ushort system_id;
static struct EntitiesData static struct EntitiesData
{ {
@ -247,7 +274,7 @@ struct TestSystemWithHighPriority
void onUpdate(EntitiesData data) void onUpdate(EntitiesData data)
{ {
} }
/*void handleEvent(Event event, ref TestComp comp) /*void handleEvent(Event event, ref TestComp comp)
@ -282,7 +309,7 @@ struct Sys2
void onAddEntity(EntitiesData data) void onAddEntity(EntitiesData data)
{ {
} }
} }
@ -297,7 +324,7 @@ struct Sys3
void onAddEntity(EntitiesData data) void onAddEntity(EntitiesData data)
{ {
} }
void onUpdate(EntitiesData data) void onUpdate(EntitiesData data)
@ -306,12 +333,11 @@ struct Sys3
} }
} }
import std.meta; import std.meta;
struct TestSystem2 struct TestSystem2
{ {
mixin ECS.System!16;//__gshared ushort system_id; mixin ECS.System!16; //__gshared ushort system_id;
/*enum ExcludedComponents0 /*enum ExcludedComponents0
{ {
@ -326,7 +352,7 @@ struct TestSystem2
static struct EntitiesData static struct EntitiesData
{ {
short length; short length;
const (Entity)[] entity; const(Entity)[] entity;
TestComp3[] test; TestComp3[] test;
//@excluded TestComp[] testt; //@excluded TestComp[] testt;
} }
@ -348,7 +374,7 @@ struct TestSystem2
void handleEvent(EventInput input, ref TestEvent2 event) void handleEvent(EventInput input, ref TestEvent2 event)
{ {
input.test.gg = cast(uint)event.a; input.test.gg = cast(uint) event.a;
} }
void onEnable() void onEnable()
@ -372,12 +398,12 @@ struct TestSystem2
void onUpdate(EntitiesData data) void onUpdate(EntitiesData data)
{ {
foreach(i;0..data.test.length) foreach (i; 0 .. data.test.length)
{ {
data.test[i].gg += 14; data.test[i].gg += 14;
TestEvent event; TestEvent event;
event.a = data.test[i].gg + 4; event.a = data.test[i].gg + 4;
gEM.sendEvent(data.entity[i].id, event);//*/ gEM.sendEvent(data.entity[i].id, event); //*/
/*TestEvent2 event2; /*TestEvent2 event2;
event2.a = data.test[i].gg + 8; event2.a = data.test[i].gg + 8;
gEM.sendEvent(data.entity[i].id, event2);//*/ gEM.sendEvent(data.entity[i].id, event2);//*/
@ -385,10 +411,10 @@ struct TestSystem2
//gEM.sendSelfEvent!(TestEvent)(data.entity[i].id, TestEvent()); //gEM.sendSelfEvent!(TestEvent)(data.entity[i].id, TestEvent());
} }
} }
void lateUpdate(ref EntitiesData data) void lateUpdate(ref EntitiesData data)
{ {
foreach(i;0..data.test.length) foreach (i; 0 .. data.test.length)
{ {
data.test[i].gg -= 1; data.test[i].gg -= 1;
//gEM.sendSelfEvent!(TestEvent)(data.entity[i].id, TestEvent()); //gEM.sendSelfEvent!(TestEvent)(data.entity[i].id, TestEvent());
@ -406,7 +432,7 @@ int main()
void dispatch(EntityManager.JobGroup jobs) nothrow @nogc void dispatch(EntityManager.JobGroup jobs) nothrow @nogc
{ {
foreach(job;jobs.jobs) foreach (job; jobs.jobs)
{ {
//writeln(job); //writeln(job);
job.execute(); job.execute();
@ -417,13 +443,17 @@ int main()
{ {
write(entity.id); write(entity.id);
TestComp* test_comp = entity.getComponent!TestComp; TestComp* test_comp = entity.getComponent!TestComp;
if(test_comp)write(*test_comp); if (test_comp)
write(*test_comp);
TestComp2* test_comp2 = entity.getComponent!TestComp2; TestComp2* test_comp2 = entity.getComponent!TestComp2;
if(test_comp2)write(*test_comp2); if (test_comp2)
write(*test_comp2);
TestComp3* test_comp3 = entity.getComponent!TestComp3; TestComp3* test_comp3 = entity.getComponent!TestComp3;
if(test_comp3)write(*test_comp3); if (test_comp3)
write(*test_comp3);
TestComp4* test_comp4 = entity.getComponent!TestComp4; TestComp4* test_comp4 = entity.getComponent!TestComp4;
if(test_comp4)write(*test_comp4); if (test_comp4)
write(*test_comp4);
writeln(); writeln();
//writeln((cast(uint*) pp)[0 .. 14], " ", pp); //writeln((cast(uint*) pp)[0 .. 14], " ", pp);
} }
@ -441,6 +471,7 @@ int main()
gEM.registerComponent!TestComp4; gEM.registerComponent!TestComp4;
gEM.registerComponent!TestComp; gEM.registerComponent!TestComp;
gEM.registerComponent!TestComp3; gEM.registerComponent!TestComp3;
gEM.registerComponent!TestComp5;
gEM.registerEvent!TestEvent; gEM.registerEvent!TestEvent;
gEM.registerEvent!TestEvent2; gEM.registerEvent!TestEvent2;
@ -450,7 +481,7 @@ int main()
time = MonoTime.currTime; time = MonoTime.currTime;
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!Sys1(10);
@ -483,12 +514,13 @@ 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.EntitiesBlock* block = EntityManager.instance.getMetaData(
gEM.getEntity(entity.id));
EntityManager.EntityInfo* info = block.type_info; EntityManager.EntityInfo* info = block.type_info;
writeln(info.add_listeners); writeln(info.add_listeners);
//if(info)assert(0); //if(info)assert(0);
} }
time = MonoTime.currTime; time = MonoTime.currTime;
//foreach(i; 0..1_000_000)gEM.addEntity(tmpl); //foreach(i; 0..1_000_000)gEM.addEntity(tmpl);
@ -607,13 +639,17 @@ int main()
gEM.removeComponents!(TestComp)(entity.id); gEM.removeComponents!(TestComp)(entity.id);
gEM.addComponents(entity.id, TestComp()); gEM.addComponents(entity.id, TestComp());
gEM.removeComponents!(TestComp4)(entity.id); gEM.addComponents(entity.id, TestComp5());
gEM.begin(); gEM.begin();
gEM.update(); gEM.update();
gEM.update("fixed"); gEM.update("fixed");
gEM.end(); gEM.end();
gEM.removeComponents!(TestComp4)(entity.id);
gEM.commit();
writeEntityComponents(gEM.getEntity(entity.id)); writeEntityComponents(gEM.getEntity(entity.id));
//import std.stdio; //import std.stdio;
//writeln((cast(uint*)tmpl.info.first_block)[0..48]); //writeln((cast(uint*)tmpl.info.first_block)[0..48]);
@ -621,4 +657,4 @@ int main()
EntityManager.destroy(); EntityManager.destroy();
return 0; return 0;
} }