diff --git a/source/ecs/manager.d b/source/ecs/manager.d index b6071be..d75b0f3 100644 --- a/source/ecs/manager.d +++ b/source/ecs/manager.d @@ -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