From a066a97f019276913d35b79cbed3e1bd996a4bf6 Mon Sep 17 00:00:00 2001 From: Mergul Date: Fri, 14 Sep 2018 12:03:27 +0200 Subject: [PATCH] -added removeComponents() function (removing by ids array, or components types) -sorting IDs in addComponents() and removeComponents() --- .gitignore | 1 + source/ecs/manager.d | 131 ++++++++++++++++++++++++++++++++++++------- tests/tests.d | 7 +++ 3 files changed, 118 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index 7cfa996..68b8c91 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ dub.userprefs dub.selections.json .dub /.vscode +LOC perf.data perf.data.old *.o diff --git a/source/ecs/manager.d b/source/ecs/manager.d index 9901332..a42a5c1 100644 --- a/source/ecs/manager.d +++ b/source/ecs/manager.d @@ -126,7 +126,7 @@ class EntityManager foreach (info; &entities_infos.byValue) { - addEntityCaller(*info, cast(uint)systems.length - 1); + addEntityCaller(*info, cast(uint) systems.length - 1); } updateEntityCallers(); @@ -181,19 +181,20 @@ class EntityManager num = cast(ushort)((num + aligment - 1) & (-cast(int) aligment)); //num += aligment - (num & (aligment - 1)); } + extern (C) static int compareUShorts(const void* a, const void* b) + { + ushort _a = *cast(ushort*) a; + ushort _b = *cast(ushort*) b; + if (_a < _b) + return -1; + else if (_a == _b) + return 0; + else + return 1; + } + EntityTemplate* allocateTemplate(ushort[] components_ids) { - extern (C) static int compareUShorts(const void* a, const void* b) - { - ushort _a = *cast(ushort*) a; - ushort _b = *cast(ushort*) b; - if (_a < _b) - return -1; - else if (_a == _b) - return 0; - else - return 1; - } ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * components_ids.length))[0 .. components_ids.length]; @@ -268,9 +269,9 @@ class EntityManager void updateEntityCallers() { - foreach(entity;&entities_infos.byValue) + foreach (entity; &entities_infos.byValue) { - foreach(ref caller;entity.callers) + foreach (ref caller; entity.callers) { caller.system = &systems[caller.system_id]; } @@ -305,12 +306,13 @@ class EntityManager call_data.deltas = Mallocator.instance.makeArray(deltas); //Mallocator.instance.makeArray!ushort(system.m_components.length); uint index = 0; - for(;index= call_data.system.priority)break; + if (caller.system.priority >= call_data.system.priority) + break; } - entity.callers.add(call_data,index); + entity.callers.add(call_data, index); } } @@ -319,6 +321,69 @@ class EntityManager return cast(Entity*) id_manager.getEntityPointer(id); } + void removeComponents(EntityID entity_id, ushort[] del_ids) + { + Entity* entity = id_manager.getEntityPointer(entity_id); + EntitiesBlock* block = getMetaData(entity); + EntityInfo* info = block.type_data; + + qsort(del_ids.ptr, del_ids.length, ushort.sizeof, &compareUShorts); + + ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length)))[0 + .. info.components.length]; + + uint j = 0; + uint k = 0; + foreach (id;info.components) + { + while (k < del_ids.length && del_ids[k] < id) + k++; + if (k >= del_ids.length) + { + ids[j++] = id; + } + else if (del_ids[k] == info.components[j]) + { + k++; + } + else + ids[j++] = id; + } + + if (j == info.components.length) + return; + + EntityInfo* new_info = getEntityInfo(ids[0 .. j]); + + EntitiesBlock* new_block = findBlockWithFreeSpace(new_info); + + void* start = new_block.dataBegin() + new_block.entities_count * new_info.size; + + Entity* new_entity = cast(Entity*) start; + new_entity.id = entity.id; + new_entity.updateID(); + + foreach (comp; new_info.components) + { + memcpy(cast(void*) new_entity + new_info.deltas[comp], + cast(void*) entity + info.deltas[comp], components[comp].size); + } + + removeEntityNoID(entity, block); + } + + void removeComponents(Components...)(EntityID entity_id) + { + const uint num = Components.length; + ushort[num] del_ids; + static foreach (i, comp; Components) + { + del_ids[i] = comp.component_id; + } + + removeComponents(entity_id,del_ids); + } + void addComponents(Components...)(EntityID entity_id, Components comps) { const uint num = Components.length; @@ -341,6 +406,30 @@ class EntityManager pointers[i] = ∁ } + foreach(int i;0..new_ids.length) + { + ushort min = new_ids[i]; + int pos = i; + foreach(int j;0..new_ids.length) + { + if(new_ids[j] < min) + { + min = new_ids[j]; + pos = j; + } + } + if(pos != i) + { + ushort id = new_ids[i]; + new_ids[i] = new_ids[pos]; + new_ids[pos] = id; + void* ptr = pointers[i]; + pointers[i] = pointers[pos]; + pointers[pos] = ptr; + } + } + + uint j = 0; uint k = 0; foreach (ref id; ids) @@ -442,7 +531,7 @@ class EntityManager { if (block is null) { - block = cast(EntitiesBlock*) allocator.getBlock();//AlignedMallocator.instance.alignedAllocate(page_size, page_size); + block = cast(EntitiesBlock*) allocator.getBlock(); //AlignedMallocator.instance.alignedAllocate(page_size, page_size); *block = EntitiesBlock(info); if (previous_block is null) { @@ -498,12 +587,12 @@ class EntityManager if (block.type_data.first_with_free_space.id > block.id) block.type_data.first_with_free_space = block; - if(call_destructors) + if (call_destructors) { void* data = data_begin + pos * block.type_data.size; - foreach(comp;block.type_data.components) + foreach (comp; block.type_data.components) { - if(components[comp].destroy_callback) + if (components[comp].destroy_callback) { components[comp].destroy_callback(data + block.type_data.deltas[comp]); } diff --git a/tests/tests.d b/tests/tests.d index b71b9a9..541ea91 100644 --- a/tests/tests.d +++ b/tests/tests.d @@ -263,6 +263,13 @@ int main() writeln((cast(uint*) pp)[0 .. 14], " ", pp); + gEM.removeComponents!(TestComp)(entity.id); + pp = gEM.getEntity(entity.id); + + gEM.update(); + + writeln((cast(uint*) pp)[0 .. 14], " ", pp); + //import std.stdio; //writeln((cast(uint*)tmpl.info.first_block)[0..48]); gEM.freeTemplate(tmpl);