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