-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_add_entity || system.m_remove_entity)
if (system.m_add_entity || system.m_remove_entity || system.m_change_entity)
{
foreach (info; &entities_infos.byValue)
{
@ -761,6 +761,7 @@ class EntityManager
mixin(catchEntityFunc("m_add_entity", "onAddEntity"));
mixin(catchEntityFunc("m_remove_entity", "onRemoveEntity"));
mixin(catchEntityFunc("m_change_entity", "onChangeEntity"));
system.m_system_pointer = cast(void*) Mallocator.instance.make!Sys;
system.m_priority = priority;
@ -1210,10 +1211,9 @@ class EntityManager
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_add_entity || system.m_remove_entity)
if (system.m_add_entity || system.m_remove_entity || system.m_change_entity)
connectListenerToEntityInfo(*info, cast(uint) i);
continue;
}
@ -1239,13 +1239,21 @@ class EntityManager
Mallocator.instance.dispose(info.remove_listeners);
info.remove_listeners = null;
}
if (info.change_listeners)
{
Mallocator.instance.dispose(info.change_listeners);
info.change_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];
ushort[] tmp_ch = (cast(ushort*) alloca(systems.length * ushort.sizeof))[0 .. systems
.length];
int add_len = 0;
int rem_len = 0;
int ch_len = 0;
//assign listeners to lists
foreach (i; 0 .. systems.length)
{
@ -1290,6 +1298,25 @@ class EntityManager
//assign listener
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);
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
@ -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++;
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++;
removeEntityNoID(entity, block);
}
@ -2026,6 +2083,43 @@ class EntityManager
(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()
{
foreach (ref thread; threads)
@ -2393,6 +2487,8 @@ class EntityManager
ushort[] add_listeners;
///systems which are listening for removed entities
ushort[] remove_listeners;
///systems which are listening for changed entities (changed in term of contained components)
ushort[] change_listeners;
///pointer to first block/page
EntitiesBlock* first_block;

View file

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

View file

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