-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)
{
addEntityCaller(*info, systems[$ - 1]);
addEntityCaller(*info, cast(uint)systems.length - 1);
}
updateEntityCallers();
}
void registerComponent(Comp)()
{
ComponentInfo info;
static if (!(hasMember!(Comp, "component_id")) || !is(typeof(Comp.component_id) == ushort))
{
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.aligment = Comp.alignof; //8;
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);
Comp.component_id = cast(ushort)(components.length - 1);
@ -203,9 +219,10 @@ class EntityManager
temp.info = info;
//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;
@ -233,21 +250,35 @@ class EntityManager
}
alignNum(info.size, info.alignment);
foreach (ref system; systems)
foreach (uint i, ref system; systems)
{
if (system.m_update is null)
continue;
addEntityCaller(*info, system);
addEntityCaller(*info, i);
}
updateEntityCallers();
entities_infos.add(info.components, 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
.. system.m_components.length];
foreach (i, id; system.m_components)
@ -443,10 +474,12 @@ class EntityManager
EntitiesBlock* block = getMetaData(entity);
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
void* data_begin = block.dataBegin();
@ -458,6 +491,18 @@ class EntityManager
if (block.type_data.first_with_free_space.id > block.id)
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)
return;
@ -488,6 +533,7 @@ class EntityManager
ushort size;
ushort aligment;
ubyte[] init_data;
void function(void* pointer) destroy_callback;
}
/************************************************************************************************************************
@ -548,6 +594,8 @@ class EntityManager
*/
struct CallData
{
///system ID. Used to update system pointer after system reload.
uint system_id;
///pointer to used system
System* system;
///poiner to Entity type info