From d5780a625209e1351a1828fbb4babb446667b1c9 Mon Sep 17 00:00:00 2001 From: Mergul Date: Sun, 30 Sep 2018 23:12:20 +0200 Subject: [PATCH] -working update() with EntitiesData structure input -added support for 'const' components input (read only, future usage) --- source/ecs/entity.d | 2 +- source/ecs/manager.d | 211 ++++++++++++++++++++++++++++++------------- tests/tests.d | 40 ++++---- 3 files changed, 167 insertions(+), 86 deletions(-) diff --git a/source/ecs/entity.d b/source/ecs/entity.d index 5e85211..d23bab6 100644 --- a/source/ecs/entity.d +++ b/source/ecs/entity.d @@ -17,7 +17,7 @@ struct Entity EntityManager.instance.id_manager.update(this); } - T* getComponent(T)() + T* getComponent(T)() const { EntityManager.EntitiesBlock* block = gEM.getMetaData(&this); EntityManager.EntityInfo* info = block.type_info; diff --git a/source/ecs/manager.d b/source/ecs/manager.d index df77253..5749319 100644 --- a/source/ecs/manager.d +++ b/source/ecs/manager.d @@ -61,6 +61,11 @@ class EntityManager System system; + static if (!(hasMember!(Sys, "system_id")) || !is(typeof(Sys.system_id) == ushort)) + { + static assert(0, "System should have \"__gshared ushort system_id"); + } + version (InputStruct) { static if (!(hasMember!(Sys, "EntitiesData"))) @@ -75,13 +80,13 @@ class EntityManager { static if (isFunction!(__traits(getMember, Sys.EntitiesData, member))) static assert(0, "EntitiesData can't have any function!"); - else static if (isArray!(typeof(__traits(getMember, - Sys.EntitiesData, member)))) + else static if (!(isArray!(typeof(__traits(getMember, + Sys.EntitiesData, member))))) static assert(0, "EntitiesData members should be arrays of elements!"); else static if (is(typeof(__traits(getMember, Sys.EntitiesData, member)) == Entity[])) { - ret ~= "const string entities_name = \"" ~ member ~ "\";"; + //ret ~= "const string entities_name = \"" ~ member ~ "\";"; } else { @@ -111,61 +116,51 @@ class EntityManager ret ~= "system.m_components = Mallocator.instance.makeArray!ushort(req);"; ret ~= "system.m_optional_components = Mallocator.instance.makeArray!ushort(opt);"; + ret ~= "system.m_absen_components = Mallocator.instance.makeArray!ushort(absen);"; ret ~= "opt = 0;req = 0;absen = 0;"; static foreach (member; __traits(allMembers, Sys.EntitiesData)) { - static if (isFunction!(__traits(getMember, Sys.EntitiesData, member))) - static assert(0, "EntitiesData can't have any function!"); - else static if (isArray!(typeof(__traits(getMember, - Sys.EntitiesData, member)))) - static assert(0, "EntitiesData members should be arrays of elements!"); - else static if (is(typeof(__traits(getMember, - Sys.EntitiesData, member)) == Entity[])) + static if (is(typeof(__traits(getMember, Sys.EntitiesData, member)) == Entity[]) + || is(typeof(__traits(getMember, Sys.EntitiesData, member)) == const(Entity)[])) { //ret ~= "const string entities_name = \"" ~ member ~ "\";"; } else { { + + ret ~= "{comp = components_map.get(Unqual!(ForeachType!(typeof( + Sys.EntitiesData." + ~ member ~ "))) + .stringof, ushort.max);\n + if(comp == ushort.max)assert(0,\"Can't register system \\\"" ~ Sys.stringof + ~ "\\\" due to non existing component \" ~ ForeachType!(typeof( + Sys.EntitiesData." + ~ member ~ ")) + .stringof + ~ \".\");"; + bool has_att = false; foreach (att; __traits(getAttributes, __traits(getMember, Sys.EntitiesData, member))) { if (att == "optional") { - ret ~= "{comp = components_map.get(\"" ~ (typeof(__traits(getMember, - Sys.EntitiesData, member))) - .stringof ~ "\", ushort.max);\n - if(comp == ushort.max)assert(0,\"Can't register system \\\"" ~ Sys.stringof - ~ "\\\" due to non existing component " ~ typeof(__traits(getMember, - Sys.EntitiesData, member)).stringof ~ ".\"); - system.m_optional_components[opt++] = comp;}"; + ret ~= "system.m_optional_components[opt++] = comp;}"; has_att = true; break; } else if (att == "absen") { - ret ~= "{comp = components_map.get(\"" ~ (typeof(__traits(getMember, - Sys.EntitiesData, member))) - .stringof ~ "\", ushort.max);\n - if(comp == ushort.max)assert(0,\"Can't register system \\\"" ~ Sys.stringof - ~ "\\\" due to non existing component " ~ typeof(__traits(getMember, - Sys.EntitiesData, member)).stringof - ~ ".\");system.m_absen_components[absen++] = comp;}"; + ret ~= "system.m_absen_components[absen++] = comp;}"; has_att = true; break; } } if (!has_att) { - ret ~= "{comp = components_map.get(\"" ~ (typeof(__traits(getMember, - Sys.EntitiesData, member))) - .stringof ~ "\", ushort.max);\n - if(comp == ushort.max)assert(0,\"Can't register system \\\"" ~ Sys.stringof - ~ "\\\" due to non existing component " ~ typeof(__traits(getMember, - Sys.EntitiesData, member)).stringof ~ ".\"); - system.m_components[req++] = comp;}"; + ret ~= "system.m_components[req++] = comp;}"; } } } @@ -216,11 +211,6 @@ class EntityManager } } - static if (!(hasMember!(Sys, "system_id")) || !is(typeof(Sys.system_id) == ushort)) - { - static assert(0, "System should have \"__gshared ushort system_id"); - } - static if (hasMember!(Sys, "update")) { alias types = Parameters!(Sys.update); @@ -243,11 +233,6 @@ class EntityManager } } - /*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; @@ -301,39 +286,135 @@ class EntityManager return ret; } - static void callUpdate(ref CallData data, void* entity) + version (InputStruct) { - static if (hasMember!(Sys, "update")) + + static string genFillInputData()() { - Sys* s = cast(Sys*) data.system.m_system_pointer; - - void*[] pointers = (cast(void**) alloca(data.system.m_components.length * (void*) - .sizeof))[0 .. data.system.m_components.length]; - void*[] optional_pointers = (cast(void**) alloca( - data.system.m_optional_components.length * (void*).sizeof))[0 - .. data.system.m_optional_components.length]; - - EntitiesBlock* block = data.info.first_block; - while (block !is null) + string ret; + ushort comp; + uint req = 0; + uint opt = 0; + uint absen = 0; + foreach (member; __traits(allMembers, Sys.EntitiesData)) { - EntityInfo* info = block.type_info; - Entity[] id_array = (cast(Entity*) block.dataBegin())[0 - .. block.entities_count]; - mixin(genArrays()); - foreach (i; 0 .. block.entities_count) + if (is(typeof(__traits(getMember, Sys.EntitiesData, member)) == Entity[]) + || is(typeof(__traits(getMember, Sys.EntitiesData, member)) == const(Entity)[])) { - mixin(genCall()); - //data_pointer += EntityID.sizeof; //data.info.size; - /*foreach (ref pointer; pointers) + ret ~= "input_data." ~ member + ~ " = (cast(Entity*) block.dataBegin())[0 .. block.entities_count];"; + } + else + { + { + bool has_att = false; + foreach (att; __traits(getAttributes, + __traits(getMember, Sys.EntitiesData, member))) + { + if (att == "optional") + { + ret ~= "if(data.system.m_optional_components[" + ~ opt.to!string ~ "] < info.deltas.length && info.deltas[ data.system.m_optional_components[" + ~ opt.to!string ~ "]] != 0)input_data." ~ member ~ " = (cast(ForeachType!(typeof(Sys.EntitiesData." + ~ member ~ "))*)(cast(void*) block + info.deltas[ data.system.m_optional_components[" + ~ opt.to!string ~ "]]))[0 .. block.entities_count]; + else input_data." ~ member ~ " = null;"; + opt++; + has_att = true; + break; + } + else if (att == "absen") + { + absen++; + has_att = true; + break; + } + } + if (!has_att) + { + ret ~= "input_data." ~ member ~ " = (cast(ForeachType!(typeof(Sys.EntitiesData." + ~ member ~ "))*)(cast(void*) block + info.deltas[ data.system.m_components[" + ~ req.to!string ~ "]]))[0 .. block.entities_count];"; + req++; + } + } + } + } + return ret; + } + + static void callUpdate(ref CallData data, void* entity) + { + static if (hasMember!(Sys, "update")) + { + Sys* s = cast(Sys*) data.system.m_system_pointer; + + /*void*[] pointers = (cast(void**) alloca(data.system.m_components.length * (void*) + .sizeof))[0 .. data.system.m_components.length]; + void*[] optional_pointers = (cast(void**) alloca( + data.system.m_optional_components.length * (void*).sizeof))[0 + .. data.system.m_optional_components.length];*/ + + Sys.EntitiesData input_data; + + EntitiesBlock* block = data.info.first_block; + while (block !is null) + { + EntityInfo* info = block.type_info; + /*Entity[] id_array = (cast(Entity*) block.dataBegin())[0 + .. block.entities_count];*/ + //mixin(genArrays()); + + mixin(genFillInputData()); + + s.update(input_data); + /*foreach (i; 0 .. block.entities_count) + { + mixin(genCall()); + }*/ + + block = block.next_block; + } + + } + } + } + else + { + static void callUpdate(ref CallData data, void* entity) + { + static if (hasMember!(Sys, "update")) + { + Sys* s = cast(Sys*) data.system.m_system_pointer; + + void*[] pointers = (cast(void**) alloca(data.system.m_components.length * (void*) + .sizeof))[0 .. data.system.m_components.length]; + void*[] optional_pointers = (cast(void**) alloca( + data.system.m_optional_components.length * (void*).sizeof))[0 + .. data.system.m_optional_components.length]; + + EntitiesBlock* block = data.info.first_block; + while (block !is 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;*/ + } + + block = block.next_block; } - block = block.next_block; } - } } @@ -918,7 +999,7 @@ class EntityManager removeEntityNoID(entity, block); } - void addComponents(Components...)(EntityID entity_id, Components comps) + void addComponents(Components...)(const EntityID entity_id, Components comps) { const uint num = Components.length; Entity* entity = id_manager.getEntityPointer(entity_id); @@ -1120,7 +1201,7 @@ class EntityManager *params: *pointer = pointer to any data of entity (i.e. component data pointer) */ - export EntitiesBlock* getMetaData(void* pointer) + export EntitiesBlock* getMetaData(const void* pointer) { return cast(EntitiesBlock*)(cast(size_t) pointer & (~cast(size_t)(page_size - 1))); } diff --git a/tests/tests.d b/tests/tests.d index 11852cb..3e9eee3 100644 --- a/tests/tests.d +++ b/tests/tests.d @@ -127,10 +127,10 @@ int main() static struct EntitiesData { - TestComp* test; - TestComp2* test2; - @optional TestComp3* test3; - @absen TestComp4* test4; + TestComp[] test; + TestComp2[] test2; + @optional TestComp3[] test3; + @absen TestComp4[] test4; } void update(ref Entity entity, ref TestComp test, ref TestComp2 test2)//, TestComp3* test3) //ref TestComp comp) @@ -139,25 +139,21 @@ int main() assert(cast(size_t)&test2 % TestComp2.alignof == 0); import std.stdio; - //writeln("Jakis tekst! ",test.b); test.a += 1000; test.b += 2000; - //writeln("Jakis tekst! ",test.b); test2.b += 2; test2.a = 8; - //writeln("Jakis tekst! ",test2.b); - //writeln("Low priority tekst! "); - /*if (test3) - { - test3.gg = 200; - test3.bg += 1; - }*/ - } void update(ref EntitiesData data) { - + foreach(i;0..data.test.length) + { + data.test[i].a += 1000; + data.test[i].b += 2000; + data.test2[i].b += 2; + data.test2[i].a = 8; + } } void handleEvent(TestEvent event, ref TestComp test, ref TestComp2 test2, TestComp3* test3) @@ -172,7 +168,7 @@ int main() static struct EntitiesData { - TestComp* test; + TestComp[] test; } void initialize(ref Entity entity, ref TestComp comp) @@ -206,8 +202,8 @@ int main() static struct EntitiesData { - Entity* entity; - TestComp3* test; + Entity[] entity; + TestComp3[] test; /*void a() { @@ -244,8 +240,12 @@ int main() void update(ref EntitiesData data) //ref TestComp comp) { //writeln("TestSystem2 update"); - data.test.gg += 14; - gEM.sendSelfEvent!(TestEvent)(data.entity.id, TestEvent()); + foreach(i;0..data.test.length) + { + data.test[i].gg += 14; + gEM.sendSelfEvent!(TestEvent)(data.entity[i].id, TestEvent()); + } + } /*void handleEvent(Event event, ref TestComp comp)