-Components onDestroy() support (called when component is destoryed)

-EntityCallers pointers to systems now are updated after adding new system (or in future system reloading)
-fixed compilation issue referenced to filling components with default values
This commit is contained in:
Mergul 2018-09-13 21:32:13 +02:00
parent 624c899c8c
commit 0eaff0adad

View file

@ -124,22 +124,38 @@ class EntityManager
foreach (info; &entities_infos.byValue) foreach (info; &entities_infos.byValue)
{ {
addEntityCaller(*info, systems[$ - 1]); addEntityCaller(*info, cast(uint)systems.length - 1);
} }
updateEntityCallers();
} }
void registerComponent(Comp)() void registerComponent(Comp)()
{ {
ComponentInfo info;
static if (!(hasMember!(Comp, "component_id")) || !is(typeof(Comp.component_id) == ushort)) static if (!(hasMember!(Comp, "component_id")) || !is(typeof(Comp.component_id) == ushort))
{ {
static assert(0, "Component should have \"__gshared ushort component_id"); static assert(0, "Component should have \"__gshared ushort component_id");
} }
ComponentInfo info; static if (hasMember!(Comp, "onDestroy") && isFunction!(Comp.onDestroy)
&& is(ReturnType!(Comp.onDestroy) == void)
&& Parameters!(Comp.onDestroy).length == 0)
{
static void callDestroy(void* pointer)
{
(cast(Comp*) pointer).onDestroy();
}
info.destroy_callback = &callDestroy;
}
info.size = Comp.sizeof; info.size = Comp.sizeof;
info.aligment = Comp.alignof; //8; info.aligment = Comp.alignof; //8;
info.init_data = Mallocator.instance.makeArray!ubyte(Comp.sizeof); info.init_data = Mallocator.instance.makeArray!ubyte(Comp.sizeof);
*cast(Comp*)info.init_data.ptr = Comp(); *cast(Comp*) info.init_data.ptr = Comp.init; // = Comp();
components.add(info); components.add(info);
Comp.component_id = cast(ushort)(components.length - 1); Comp.component_id = cast(ushort)(components.length - 1);
@ -205,7 +221,8 @@ class EntityManager
//fill components with default data //fill components with default data
foreach (comp; info.components) foreach (comp; info.components)
{ {
temp.entity_data[info.deltas[comp]..info.deltas[comp]+components[comp].size] = components[comp].init_data; temp.entity_data[info.deltas[comp] .. info.deltas[comp] + components[comp].size]
= components[comp].init_data;
} }
return temp; return temp;
@ -233,21 +250,35 @@ class EntityManager
} }
alignNum(info.size, info.alignment); alignNum(info.size, info.alignment);
foreach (ref system; systems) foreach (uint i, ref system; systems)
{ {
if (system.m_update is null) if (system.m_update is null)
continue; continue;
addEntityCaller(*info, system); addEntityCaller(*info, i);
} }
updateEntityCallers();
entities_infos.add(info.components, info); entities_infos.add(info.components, info);
} }
return info; return info;
} }
void addEntityCaller(ref EntityInfo entity, ref System system) void updateEntityCallers()
{ {
CallData call_data = CallData(&system, &entity, null); foreach(entity;&entities_infos.byValue)
{
foreach(caller;entity.callers)
{
caller.system = &systems[caller.system_id];
}
}
}
void addEntityCaller(ref EntityInfo entity, uint system_id)
{
System* system = &systems[system_id];
CallData call_data = CallData(system_id, system, &entity, null);
ushort[] deltas = (cast(ushort*) alloca(system.m_components.length * ushort.sizeof))[0 ushort[] deltas = (cast(ushort*) alloca(system.m_components.length * ushort.sizeof))[0
.. system.m_components.length]; .. system.m_components.length];
foreach (i, id; system.m_components) foreach (i, id; system.m_components)
@ -443,10 +474,12 @@ class EntityManager
EntitiesBlock* block = getMetaData(entity); EntitiesBlock* block = getMetaData(entity);
id_manager.releaseID(id); //release id from manager id_manager.releaseID(id); //release id from manager
removeEntityNoID(entity, block); removeEntityNoID(entity, block, true);
} }
private void removeEntityNoID(Entity* entity, EntitiesBlock* block) private void removeEntityNoID(Entity* entity, EntitiesBlock* block,
bool call_destructors = false)
{ {
//pos is Entity number in block //pos is Entity number in block
void* data_begin = block.dataBegin(); void* data_begin = block.dataBegin();
@ -458,6 +491,18 @@ class EntityManager
if (block.type_data.first_with_free_space.id > block.id) if (block.type_data.first_with_free_space.id > block.id)
block.type_data.first_with_free_space = block; block.type_data.first_with_free_space = block;
if(call_destructors)
{
void* data = data_begin + pos * block.type_data.size;
foreach(comp;block.type_data.components)
{
if(components[comp].destroy_callback)
{
components[comp].destroy_callback(data + block.type_data.deltas[comp]);
}
}
}
if (pos == block.entities_count) if (pos == block.entities_count)
return; return;
@ -488,6 +533,7 @@ class EntityManager
ushort size; ushort size;
ushort aligment; ushort aligment;
ubyte[] init_data; ubyte[] init_data;
void function(void* pointer) destroy_callback;
} }
/************************************************************************************************************************ /************************************************************************************************************************
@ -548,6 +594,8 @@ class EntityManager
*/ */
struct CallData struct CallData
{ {
///system ID. Used to update system pointer after system reload.
uint system_id;
///pointer to used system ///pointer to used system
System* system; System* system;
///poiner to Entity type info ///poiner to Entity type info