diff --git a/dub.json b/dub.json index 23114c3..b96cc11 100755 --- a/dub.json +++ b/dub.json @@ -10,6 +10,9 @@ "versions": [ "LinearLayout" ], + "dflags-posix-ldc": [ + "-defaultlib=phobos2-ldc,druntime-ldc" + ], "configurations" : [ { "name" : "library", diff --git a/source/ecs/block_allocator.d b/source/ecs/block_allocator.d index cfb1d13..30afcc8 100644 --- a/source/ecs/block_allocator.d +++ b/source/ecs/block_allocator.d @@ -7,7 +7,7 @@ import std.experimental.allocator.mallocator : AlignedMallocator, Mallocator; struct BlockAllocator(uint block_size, uint blocks_in_allocation) { - void* next_block; + void* next_block = null; void* getBlock() { diff --git a/source/ecs/entity.d b/source/ecs/entity.d index 3b8f59c..11f7354 100644 --- a/source/ecs/entity.d +++ b/source/ecs/entity.d @@ -20,9 +20,21 @@ struct Entity T* getComponent(T)() { EntityManager.EntitiesBlock* block = gEM.getMetaData(&this); - EntityManager.EntityInfo* info = block.type_data; - if(T.component_id >= info.deltas.length || info.deltas[T.component_id] == 0)return null; - return cast(T*)(cast(void*)&this + info.deltas[T.component_id]); + EntityManager.EntityInfo* info = block.type_info; + if (T.component_id >= info.deltas.length || info.deltas[T.component_id] == 0) + return null; + version (LinearLayout) + { + static if (EntityID.sizeof == 8) + uint ind = cast(uint)((cast(void*)&this - block.dataBegin()) >> 3); + else + uint ind = cast(uint)((cast(void*)&this - block.dataBegin()) / EntityID.sizeof()); + return cast(T*)(cast(void*)block + info.deltas[T.component_id] + ind * T.sizeof); + } + else + { + return cast(T*)(cast(void*)&this + info.deltas[T.component_id]); + } } } diff --git a/source/ecs/manager.d b/source/ecs/manager.d index 9b4c724..3b89943 100644 --- a/source/ecs/manager.d +++ b/source/ecs/manager.d @@ -72,12 +72,75 @@ class EntityManager alias storages = ParameterStorageClassTuple!(Sys.update); static string genCall()() { - string ret = "s.update(*cast(Entity*)data_pointer,"; + string ret; + version (LinearLayout) + { + { + uint i = 0; + uint opt = 0; + static foreach (param; (Parameters!(Sys.update))[1 .. $]) + { + i++; + if (isPointer!param) + { + ret ~= "if(opt_ptr" ~ opt.to!string ~ " !is null)opt_ptr" + ~ opt.to!string ~ " = &opt_array" ~ opt.to!string ~ "[i];"; + opt++; + } + } + } + } /*foreach (i; 1 .. (Parameters!(Sys.update)).length) { ret ~= "*cast(types[" ~ i.to!string ~ "]*)(pointers[" ~ (i - 1) .to!string ~ "]),"; }*/ + uint i = 0; + uint req = 0; + uint opt = 0; + version (LinearLayout) + { + ret ~= "s.update(id_array[i],"; + static foreach (param; (Parameters!(Sys.update))[1 .. $]) + { + i++; + if (isPointer!param) + { + ret ~= "opt_ptr" ~ (opt++).to!string ~ ","; + } + else + { + ret ~= "array" ~ (req++).to!string ~ "[i],"; + } + } + } + else + { + ret ~= "s.update(*cast(Entity*)data_pointer,"; + static foreach (param; (Parameters!(Sys.update))[1 .. $]) + { + i++; + if (isPointer!param) + { + ret ~= "cast(types[" ~ i.to!string ~ "])(optional_pointers[" ~ (opt++) + .to!string ~ "]),"; + } + else + { + ret ~= "*cast(types[" ~ i.to!string ~ "]*)(pointers[" ~ (req++) + .to!string ~ "]),"; + } + } + } + + ret ~= ");"; + return ret; + } + + static string genArrays()() + { + string ret; + uint i = 0; uint req = 0; uint opt = 0; @@ -86,16 +149,17 @@ class EntityManager i++; if (isPointer!param) { - ret ~= "cast(types[" ~ i.to!string ~ "])(optional_pointers[" ~ (opt++) - .to!string ~ "]),"; + ret ~= "PointerTarget!(types[" ~ i.to!string + ~ "])[] opt_array" ~ opt.to!string ~ ";"; + ret ~= "types[" ~ i.to!string ~ "] opt_ptr" ~ opt.to!string ~ ";"; + opt++; } else { - ret ~= "*cast(types[" ~ i.to!string ~ "]*)(pointers[" ~ (req++) - .to!string ~ "]),"; + ret ~= "types[" ~ i.to!string ~ "][] array" ~ req.to!string ~ " = (cast(types[" ~ i.to!string ~ "]*)(cast(void*)block + info.deltas[types[" ~ i.to!string ~ "].component_id]))[0..block.entities_count];"; + req++; } } - ret ~= ");"; return ret; } @@ -154,29 +218,62 @@ class EntityManager EntitiesBlock* block = data.info.first_block; while (block !is null) { - uint size = block.type_data.size; - void* data_pointer = block.dataBegin(); - foreach (i, ref pointer; pointers) + version (LinearLayout) { - pointer = data_pointer + data.deltas[i]; - } - foreach (i, ref pointer; optional_pointers) - { - uint ind = cast(uint)(i + pointers.length); - if (data.deltas[ind] != uint.max) - pointer = data_pointer + data.deltas[ind]; - else - pointer = null; - } - foreach (i; 0 .. block.entities_count) - { - mixin(genCall()); - data_pointer += size; //data.info.size; - foreach (ref pointer; pointers) - pointer += size; - foreach (ref pointer; optional_pointers) - if (pointer != null) + //uint size = block.type_info.size; + /*void* data_pointer = block.dataBegin(); + foreach (i, ref pointer; pointers) + { + pointer = cast(void*) block + data.deltas[i]; + } + foreach (i, ref pointer; optional_pointers) + { + uint ind = cast(uint)(i + pointers.length); + if (data.deltas[ind] != uint.max) + pointer = cast(void*) block + data.deltas[ind]; + else + pointer = null; + }*/ + EntityInfo* info = block.type_info; + Entity[] id_array = (cast(Entity*)block.dataBegin())[0..block.entities_count]; + mixin(genArrays()); + foreach (i; 0 .. block.entities_count) + { + mixin(genCall()); + //data_pointer += EntityID.sizeof; //data.info.size; + /*foreach (ref pointer; pointers) pointer += size; + foreach (ref pointer; optional_pointers) + if (pointer != null) + pointer += size;*/ + } + } + else + { + uint size = block.type_info.size; + void* data_pointer = block.dataBegin(); + foreach (i, ref pointer; pointers) + { + pointer = data_pointer + data.deltas[i]; + } + foreach (i, ref pointer; optional_pointers) + { + uint ind = cast(uint)(i + pointers.length); + if (data.deltas[ind] != uint.max) + pointer = data_pointer + data.deltas[ind]; + else + pointer = null; + } + foreach (i; 0 .. block.entities_count) + { + mixin(genCall()); + data_pointer += size; //data.info.size; + foreach (ref pointer; pointers) + pointer += size; + foreach (ref pointer; optional_pointers) + if (pointer != null) + pointer += size; + } } block = block.next_block; } @@ -393,10 +490,21 @@ class EntityManager temp.info = info; //fill components with default data - foreach (comp; info.components) + version (LinearLayout) { - temp.entity_data[info.deltas[comp] .. info.deltas[comp] + components[comp].size] - = components[comp].init_data; + foreach (comp; info.components) + { + temp.entity_data[info.tmpl_deltas[comp] .. info.tmpl_deltas[comp] + components[comp].size] + = components[comp].init_data; + } + } + else + { + foreach (comp; info.components) + { + temp.entity_data[info.deltas[comp] .. info.deltas[comp] + components[comp].size] + = components[comp].init_data; + } } return temp; @@ -412,6 +520,23 @@ class EntityManager info.components = Mallocator.instance.makeArray(ids); info.deltas = Mallocator.instance.makeArray!ushort(ids[$ - 1] + 1); + version (LinearLayout) + { + info.tmpl_deltas = Mallocator.instance.makeArray!ushort(ids[$ - 1] + 1); + uint block_memory = page_size - EntitiesBlock.sizeof; + uint entity_comps_size = EntityID.sizeof; + uint mem_begin = EntitiesBlock.sizeof; + + foreach (id; ids) + { + entity_comps_size += components[id].size; + } + + uint entites_in_block = block_memory / entity_comps_size; + info.max_entities = cast(ushort) entites_in_block; + uint current_delta = cast(uint)(mem_begin + entites_in_block * EntityID.sizeof); + } + info.size = EntityID.sizeof; info.alignment = EntityID.alignof; @@ -419,11 +544,29 @@ class EntityManager { info.alignment = max(info.alignment, components[id].alignment); alignNum(info.size, components[id].alignment); - info.deltas[id] = info.size; + + version (LinearLayout) + { + info.tmpl_deltas[id] = info.size; + + info.deltas[id] = cast(ushort) current_delta; + current_delta += entites_in_block * components[id].size; + } + else + { + info.deltas[id] = info.size; + } + info.size += components[id].size; } alignNum(info.size, info.alignment); + version (LinearLayout) + { + } + else + info.max_entities = (page_size - EntitiesBlock.sizeof) / info.size; + foreach (uint i, ref system; systems) { if (system.m_update is null) @@ -497,7 +640,6 @@ class EntityManager delta_id++; } - call_data.deltas = Mallocator.instance.makeArray(deltas); //Mallocator.instance.makeArray!ushort(system.m_components.length); uint index = 0; @@ -527,9 +669,10 @@ class EntityManager private void __removeComponents(EntityID entity_id, ushort[] del_ids) { Entity* entity = id_manager.getEntityPointer(entity_id); - if(!entity)return; + if (!entity) + return; EntitiesBlock* block = getMetaData(entity); - EntityInfo* info = block.type_data; + EntityInfo* info = block.type_info; qsort(del_ids.ptr, del_ids.length, ushort.sizeof, &compareUShorts); @@ -598,9 +741,10 @@ class EntityManager { uint num = cast(uint) new_ids.length; Entity* entity = id_manager.getEntityPointer(entity_id); - if(!entity)return; + if (!entity) + return; EntitiesBlock* block = getMetaData(entity); - EntityInfo* info = block.type_data; + EntityInfo* info = block.type_info; ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length + num)))[0 .. info.components.length + num]; /*ushort[num] new_ids; @@ -717,7 +861,7 @@ class EntityManager const uint num = Components.length; Entity* entity = id_manager.getEntityPointer(entity_id); EntitiesBlock* block = getMetaData(entity); - EntityInfo* info = block.type_data; + EntityInfo* info = block.type_info; ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length + num)))[0 .. info.components.length + num]; ushort[num] new_ids; @@ -755,10 +899,25 @@ class EntityManager export ref Entity addEntity(EntityTemplate* tmpl) { EntitiesBlock* block = findBlockWithFreeSpace(tmpl.info); + uint id = (block.entities_count + block.added_count); + EntityInfo* info = tmpl.info; - void* start = block.dataBegin() + (block.entities_count + block.added_count) - * tmpl.info.size; - memcpy(start, tmpl.entity_data.ptr, tmpl.info.size); + version (LinearLayout) + { + void* data_begin = block.dataBegin(); + void* start = data_begin + EntityID.sizeof * id; + //memcpy(data_begin + EntityID.sizeof * id, tmpl.entity_data.ptr, EntityID.sizeof); + foreach (i, comp; info.components) + { + memcpy(cast(void*) block + info.deltas[comp] + components[comp].size * id, + tmpl.entity_data.ptr + info.tmpl_deltas[comp], components[comp].size); + } + } + else + { + void* start = block.dataBegin() + id * info.size; + memcpy(start, tmpl.entity_data.ptr, info.size); + } if (!block.added_count) blocks_to_update.add(block); @@ -791,14 +950,15 @@ class EntityManager { previous_block.next_block = block; block.prev_block = previous_block; - block.id = previous_block.id + 1; + block.id = cast(ushort)(previous_block.id + 1); } info.first_with_free_space = block; break; // new block certainly has free space } // check if there is enought space - if (block.dataDelta() + ( - block.entities_count + block.added_count + 1) * info.size > page_size) + /*if (block.dataDelta() + ( + block.entities_count + block.added_count + 1) * info.size > page_size)*/ + if (block.entities_count + block.added_count >= block.type_info.max_entities) { previous_block = block; block = block.next_block; @@ -834,41 +994,66 @@ class EntityManager { //pos is Entity number in block void* data_begin = block.dataBegin(); - uint pos = cast(int)(cast(void*) entity - data_begin) / block.type_data.size; + EntityInfo* info = block.type_info; block.entities_count--; //set "first_with_free_space" if should it be - if (block.type_data.first_with_free_space.id > block.id) - block.type_data.first_with_free_space = block; + if (info.first_with_free_space.id > block.id) + info.first_with_free_space = block; - if (call_destructors) + version (LinearLayout) { - void* data = data_begin + pos * block.type_data.size; - foreach (comp; block.type_data.components) + static if (EntityID.sizeof == 8) + uint pos = cast(uint)((cast(void*) entity - data_begin) >> 3); + else + uint pos = cast(uint)((cast(void*) entity - data_begin) / EntityID.sizeof()); + + if (call_destructors) { - if (components[comp].destroy_callback) + //void* data = data_begin + pos * info.size; + foreach (comp; info.components) { - components[comp].destroy_callback(data + block.type_data.deltas[comp]); + if (components[comp].destroy_callback) + { + //components[comp].destroy_callback(data + info.deltas[comp]); + components[comp].destroy_callback(cast( + void*) block + info.deltas[comp] + pos * components[comp].size); + } + } + } + } + else + { + uint pos = cast(int)(cast(void*) entity - data_begin) / info.size; + if (call_destructors) + { + void* data = data_begin + pos * info.size; + foreach (comp; info.components) + { + if (components[comp].destroy_callback) + { + components[comp].destroy_callback(data + info.deltas[comp]); + } } } } if (block.entities_count == 0) { - if (block.type_data.first_block is block) + if (info.first_block is block) { - block.type_data.first_block = block.next_block; + info.first_block = block.next_block; } - if (block.type_data.first_with_free_space is block) + if (info.first_with_free_space is block) { - block.type_data.first_with_free_space = block.next_block;//block.type_data.first_block; + info.first_with_free_space = block.next_block; //info.first_block; } if (block.prev_block) { block.prev_block.next_block = block.next_block; } - if(block.next_block) + if (block.next_block) { block.next_block.prev_block = block.prev_block; } @@ -879,14 +1064,27 @@ class EntityManager if (pos == block.entities_count) return; - //copy memory of last entity to position of removed entity - void* src = data_begin + block.entities_count * block.type_data.size; - void* dst = data_begin + pos * block.type_data.size; + version (LinearLayout) + { + foreach (comp; info.components) + { + void* ptr = cast(void*) block + info.deltas[comp]; + uint size = components[comp].size; + memcpy(ptr + pos * size, ptr + block.entities_count * size, size); + } - memcpy(dst, src, block.type_data.size); + entity.id = *cast(EntityID*)(data_begin + block.entities_count * EntityID.sizeof); + } + else + { + //copy memory of last entity to position of removed entity + void* src = data_begin + block.entities_count * info.size; + void* dst = data_begin + pos * info.size; + memcpy(dst, src, info.size); + } //update pointer for moved entity ID - entity = cast(Entity*) dst; + //entity = cast(Entity*) dst; entity.updateID(); } @@ -981,7 +1179,7 @@ class EntityManager removeEntities(); changeEntites(); - clearEvents(); + //clearEvents(); } struct ComponentInfo @@ -1006,12 +1204,27 @@ class EntityManager { ///entity components ushort[] components; - ///deltas in memory for components - ushort[] deltas; + + version (LinearLayout) + { + ///deltas in memory for components in EntitiesBlock + ushort[] deltas; + ///deltas in memory for components in EntityTemplate + ushort[] tmpl_deltas; + } + else + { + ///deltas in memory for components + ushort[] deltas; + } + ///alignment of whole entity - ushort alignment; + ushort alignment; //unused in linear-layout ///size of entity (with alignment respect) ushort size; + ///max number of entities in block + ushort max_entities; + ///pointer to first block/page EntitiesBlock* first_block; ///a hint for allocations @@ -1029,7 +1242,7 @@ class EntityManager uint dataDelta() { ushort dif = EntitiesBlock.sizeof; - alignNum(dif, type_data.alignment); + alignNum(dif, type_info.alignment); return dif; } @@ -1037,23 +1250,29 @@ class EntityManager export void* dataBegin() { ushort dif = EntitiesBlock.sizeof; - alignNum(dif, type_data.alignment); + version (LinearLayout) + { + } + else + alignNum(dif, type_info.alignment); return cast(void*)&this + dif; } ///pointer to Entity type info - EntityInfo* type_data = null; + EntityInfo* type_info = null; ///number of entities in block ushort entities_count = 0; ///number of new entities in block ushort added_count = 0; ///block id - uint id = 0; + ushort id = 0; + ///maximum number of entities in block + //ushort max_entities = 0; ///pointer to next block/page EntitiesBlock* next_block = null; ///pointer to next block/page EntitiesBlock* prev_block = null; - //there is a loooot of data (4kB, pure magic) + //there is a loooot of data (some kB of memory, pure magic) } /************************************************************************************************************************ @@ -1068,7 +1287,7 @@ class EntityManager ///poiner to Entity type info EntityManager.EntityInfo* info; ///deltas for components - ushort[] deltas; + ushort[] deltas; //unused in linear-layout } alias SytemFuncType = void function(ref EntityManager.CallData data, void* entity); @@ -1078,7 +1297,7 @@ class EntityManager //alias event_manager this; ///Single page size. Must be power of two. - enum page_size = 4096; + enum page_size = 32768; //4096; ///Number of pages in block. enum pages_in_block = 128; diff --git a/tests/tests.d b/tests/tests.d index c4840ba..8a21d9d 100644 --- a/tests/tests.d +++ b/tests/tests.d @@ -23,11 +23,11 @@ int main() float a; } - struct TestComp + static struct TestComp { __gshared ushort component_id; - int a; - ulong b; + int a = 1; + ulong b = 2; static void serializeComponent(SerializeVector output) { @@ -40,11 +40,11 @@ int main() } } - struct TestComp2 + static struct TestComp2 { __gshared ushort component_id; - int b; - int a; + int b = 3; + int a = 4; static void serializeComponent(ref TestComp comp, SerializeVector output) { @@ -57,11 +57,11 @@ int main() } } - struct TestComp3 + static struct TestComp3 { __gshared ushort component_id; - uint gg; //good game - uint bg; //bad game + uint gg = 5; //good game + uint bg = 6; //bad game void serializeComponent(SerializeVector output) { @@ -74,11 +74,15 @@ int main() } } - struct TestComp4 + static struct TestComp4 { __gshared ushort component_id; - uint gg; //good game - uint bg; //bad game + uint gg = 7; //good game + uint bg = 8; //bad game + ulong a; + ulong b; + ulong c; + ulong g; static void serializeComponent(ref TestComp comp, SerializeVector output) { @@ -107,12 +111,12 @@ int main() void onBegin() { - writeln("On Test System begin."); + //writeln("On Test System begin."); } void onEnd() { - writeln("On Test System end."); + //writeln("On Test System end."); } void initialize(ref Entity entity, ref TestComp comp) @@ -127,7 +131,7 @@ int main() @("optional") TestComp3* test3; } - void update(ref Entity entity, ref TestComp test, ref TestComp2 test2, TestComp3* test3) //ref TestComp comp) + void update(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); @@ -141,8 +145,12 @@ int main() test2.a = 8; //writeln("Jakis tekst! ",test2.b); //writeln("Low priority tekst! "); - if (test3) + /*if (test3) + { test3.gg = 200; + test3.bg += 1; + }*/ + } void handleEvent(TestEvent event, ref TestComp test, ref TestComp2 test2, TestComp3* test3) @@ -209,6 +217,21 @@ int main() }*/ } + void writeEntityComponents(Entity* entity) + { + write(entity.id); + TestComp* test_comp = entity.getComponent!TestComp; + if(test_comp)write(*test_comp); + TestComp2* test_comp2 = entity.getComponent!TestComp2; + if(test_comp2)write(*test_comp2); + TestComp3* test_comp3 = entity.getComponent!TestComp3; + if(test_comp3)write(*test_comp3); + TestComp4* test_comp4 = entity.getComponent!TestComp4; + if(test_comp4)write(*test_comp4); + writeln(); + //writeln((cast(uint*) pp)[0 .. 14], " ", pp); + } + EntityManager.initialize(); assert(gEM !is null); @@ -237,14 +260,24 @@ int main() time = MonoTime.currTime; - ushort[2] ids = [TestComp2.component_id, TestComp.component_id]; + ushort[3] ids = [TestComp2.component_id, TestComp.component_id, TestComp4.component_id]; EntityTemplate* tmpl = gEM.allocateTemplate(ids); + + ushort[3] ids2 = [TestComp3.component_id, TestComp.component_id, TestComp4.component_id]; + EntityTemplate* tmpl2 = gEM.allocateTemplate(ids2); //writeln(tmpl.info.components[]); - *cast(EntityID*) tmpl.entity_data.ptr = EntityID(1, 1); + //*cast(EntityID*) tmpl.entity_data.ptr = EntityID(1, 1); dur = (MonoTime.currTime - time).total!"usecs"; writeln("Template allocating: ", dur, " usecs"); + Entity entity; + + { + entity = gEM.addEntity(tmpl); + writeEntityComponents(gEM.getEntity(entity.id)); + } + time = MonoTime.currTime; //foreach(i; 0..1_000_000)gEM.addEntity(tmpl); @@ -253,13 +286,18 @@ int main() EntityID[1000] idss; - foreach (i; 0 .. 1_000) + /*foreach (i; 0 .. 1_000) { + gEM.begin(); foreach (j; 0 .. 1_000) idss[j] = gEM.addEntity(tmpl).id; foreach (j; 0 .. 1_000) gEM.removeEntity(idss[j]); - } + gEM.end(); + }*/ + + dur = (MonoTime.currTime - time).total!"usecs"; + writeln("Entities adding: ", dur, " usecs"); uint blocks = 0; foreach (info; &gEM.entities_infos.byValue) @@ -273,13 +311,6 @@ int main() } writeln("Entities blocks: ", blocks); - /*Entity entity = gEM.addEntity(tmpl); - gEM.removeEntity(entity.id); - gEM.addEntity(tmpl);*/ - - dur = (MonoTime.currTime - time).total!"usecs"; - writeln("Entities adding: ", dur, " usecs"); - //foreach(j; 0..1_000)gEM.addEntity(tmpl); gEM.registerSystem!TestSystem2(0); @@ -287,43 +318,69 @@ int main() //assert(*(cast(EntityID*)(cast(void*)tmpl.info.first_block+24)) == EntityID(1,1)); //assert(*(cast(EntityID*)(cast(void*)tmpl.info.first_block+48)) == EntityID(1,1)); + foreach (i; 0 .. 500_000) + { + gEM.addEntity(tmpl); + gEM.addEntity(tmpl2); + } + time = MonoTime.currTime; - //gEM.update(); - - dur = (MonoTime.currTime - time).total!"usecs"; - writeln("Update: ", dur, " usecs"); - - Entity entity = gEM.addEntity(tmpl); - gEM.begin(); gEM.update(); gEM.end(); - Entity* pp = gEM.getEntity(entity.id); - writeln((cast(uint*) pp)[0 .. 14], " ", pp); + dur = (MonoTime.currTime - time).total!"usecs"; + writeln("Update: ", dur, " usecs"); + + time = MonoTime.currTime; + + gEM.begin(); + gEM.update(); + gEM.end(); + + dur = (MonoTime.currTime - time).total!"usecs"; + writeln("Update: ", dur, " usecs"); + + time = MonoTime.currTime; + + gEM.begin(); + gEM.update(); + gEM.end(); + + dur = (MonoTime.currTime - time).total!"usecs"; + writeln("Update: ", dur, " usecs"); + + writeEntityComponents(gEM.getEntity(entity.id)); + + entity = gEM.addEntity(tmpl); + + gEM.begin(); + gEM.update(); + gEM.end(); + + //Entity* pp;// = gEM.getEntity(entity.id); + //writeln((cast(uint*) pp)[0 .. 14], " ", pp); + writeEntityComponents(gEM.getEntity(entity.id)); gEM.addEntity(tmpl); + gEM.addComponents(entity.id, TestComp4()); gEM.addComponents(entity.id, TestComp3()); gEM.begin(); gEM.update(); gEM.end(); - pp = gEM.getEntity(entity.id); + writeEntityComponents(gEM.getEntity(entity.id)); - writeln((cast(uint*) pp)[0 .. 14], " ", pp); - - //gEM.removeComponents!(TestComp)(entity.id); + gEM.removeComponents!(TestComp)(entity.id); gEM.begin(); gEM.update(); gEM.end(); - pp = gEM.getEntity(entity.id); - - writeln((cast(uint*) pp)[0 .. 14], " ", pp); + writeEntityComponents(gEM.getEntity(entity.id)); //import std.stdio; //writeln((cast(uint*)tmpl.info.first_block)[0..48]); @@ -331,4 +388,4 @@ int main() EntityManager.destroy(); return 0; -} +} \ No newline at end of file