From 0670aed50629c4304c3afa7f9d1b5de792af0476 Mon Sep 17 00:00:00 2001 From: Mergul Date: Tue, 14 Apr 2020 17:29:49 +0200 Subject: [PATCH] BetterC improvement -fixed some bugs -non betterC code has better assertion messages -fixed limited count of components in system -small dub.json fix --- dub.json | 2 +- source/ecs/manager.d | 157 +++++++++++++++++++++++++++++++++---------- tests/runner.d | 2 +- 3 files changed, 124 insertions(+), 37 deletions(-) diff --git a/dub.json b/dub.json index 31ef8f9..dd0933c 100755 --- a/dub.json +++ b/dub.json @@ -97,7 +97,7 @@ { "name" : "tests-betterC", "targetType" : "executable", - "sourcePaths" : ["source\/","tests\/"], + "sourceFiles" : ["tests/tests.d"], "excludedSourceFiles":[ "source\/win_dll.d" ], diff --git a/source/ecs/manager.d b/source/ecs/manager.d index 9f26584..f95027c 100644 --- a/source/ecs/manager.d +++ b/source/ecs/manager.d @@ -351,7 +351,8 @@ export struct EntityManager void registerSystem(Sys)(int priority, const(char)[] pass_name) { ushort pass = passes_map.get(pass_name, ushort.max); - assert(pass != ushort.max); //, "Update pass (Name " ~ pass_name ~ ") doesn't exist."); + version(D_BetterC)assert(pass != ushort.max, "Update pass doesn't exist."); + else assert(pass != ushort.max, "Update pass (Name " ~ pass_name ~ ") doesn't exist."); registerSystem!(Sys)(priority, pass); } @@ -370,19 +371,20 @@ export struct EntityManager assert(register_state, "registerSystem must be called between beginRegister() and endRegister()."); - assert(pass < passes.length); //, "Update pass (ID " ~ pass.to!string ~ ") doesn't exist."); + version(D_BetterC)assert(pass < passes.length, "Update pass doesn't exist."); + else assert(pass < passes.length, "Update pass (ID " ~ pass.to!string ~ ") doesn't exist."); System system; system.m_pass = pass; static if (!(hasMember!(Sys, "system_id")) || !is(typeof(Sys.system_id) == ushort)) { - static assert(0); //, "Add \"mixin ECS.System;\" in top of system structure;"); + static assert(0, "Add \"mixin ECS.System;\" in top of system structure;"); } static if (!(hasMember!(Sys, "EntitiesData"))) { - static assert(0); //, "System should gave \"EntitiesData\" struct for input components"); + static assert(0, "System should gave \"EntitiesData\" struct for input components"); } static if (hasMember!(Sys, "handleEvent")) @@ -434,9 +436,104 @@ export struct EntityManager string type; } - static struct ComponentsIndices + static struct ComponentsCounts { + uint readonly; + uint mutable; + uint excluded; + uint optional; + uint req; + } + static ComponentsCounts getComponentsCounts()() + { + ComponentsCounts components_counts; + + bool checkExcludedComponentsSomething(Sys)() + { + return __traits(compiles, allSameType!(string, typeof(Sys.ExcludedComponents))) && allSameType!(string, + typeof(Sys.ExcludedComponents)) && isExpressions!(Sys.ExcludedComponents); + } + + foreach (member; __traits(allMembers, Sys.EntitiesData)) + { + alias MemberType = typeof(__traits(getMember, Sys.EntitiesData, member)); + if (member == "length" || member == "thread_id" + || is(MemberType == Entity[]) || is(MemberType == const(Entity)[])) + { + continue; + } + + string name; + static if (isArray!MemberType) + { // Workaround. This code is never called with: not an array type, but compiler prints an error + name = Unqual!(ForeachType!MemberType).stringof; + } + + bool is_optional; + bool is_read_only; + + if (is(CopyConstness!(ForeachType!(MemberType), int) == const(int))) + { + is_read_only = true; + } + + foreach (att; __traits(getAttributes, __traits(getMember, + Sys.EntitiesData, member))) + { + if (att == "optional") + { + is_optional = true; + } + if (att == "readonly") + { + is_read_only = true; + } + } + if (is_read_only) + { + components_counts.readonly++; + } + else + { + components_counts.mutable++; + } + if (is_optional) + { + components_counts.optional++; + } + else + { + components_counts.req++; + } + } + + static if (__traits(hasMember, Sys, "ExcludedComponents")) + { + static if (is(Sys.ExcludedComponents == enum)) + { + foreach (str; __traits(allMembers, Sys.ExcludedComponents)) + { + components_counts.excluded++; + } + } + else //static if (checkExcludedComponentsSomething!Sys) + { + foreach (str; Sys.ExcludedComponents) + { + components_counts.excluded++; + } + + } + } + + return components_counts; + } + + enum ComponentsCounts component_counts = getComponentsCounts(); + + static struct ComponentsIndices(ComponentsCounts counts) + { CompInfo[] readonly() { return m_readonly[0 .. m_readonly_counter]; @@ -487,11 +584,11 @@ export struct EntityManager m_req[m_req_counter++] = info; } - CompInfo[64] m_readonly; - CompInfo[64] m_mutable; - CompInfo[64] m_excluded; - CompInfo[64] m_optional; - CompInfo[64] m_req; + CompInfo[counts.readonly] m_readonly; + CompInfo[counts.mutable] m_mutable; + CompInfo[counts.excluded] m_excluded; + CompInfo[counts.optional] m_optional; + CompInfo[counts.req] m_req; uint m_readonly_counter; uint m_mutable_counter; @@ -502,7 +599,7 @@ export struct EntityManager string entites_array; } - static void allocateSystemComponents(ComponentsIndices components_info)(ref System system) + static void allocateSystemComponents(ComponentsIndices!component_counts components_info)(ref System system) { size_t req = components_info.req.length; size_t opt = components_info.optional.length; @@ -523,9 +620,9 @@ export struct EntityManager } - static ComponentsIndices getComponentsInfo()() + static ComponentsIndices!component_counts getComponentsInfo()() { - ComponentsIndices components_info; + ComponentsIndices!component_counts components_info; bool checkExcludedComponentsSomething(Sys)() { @@ -573,31 +670,19 @@ export struct EntityManager if (is_read_only) { components_info.addReadonly(CompInfo(member, name)); - //components_info.readonly ~= CompInfo(member,name); } else { components_info.addMutable(CompInfo(member, name)); - //components_info.mutable ~= CompInfo(member,name); } if (is_optional) { components_info.addOptional(CompInfo(member, name)); - //components_info.optional ~= CompInfo(member,name); } else { components_info.addReq(CompInfo(member, name)); - //components_info.req ~= CompInfo(member,name); } - /*if (is_read_only) - { - //components_info.readonly ~= CompInfo(member,name); - } - if (is_optional == false) - { //is Req - //components_info.req ~= CompInfo(member,name); - }*/ } static if (__traits(hasMember, Sys, "ExcludedComponents")) @@ -607,7 +692,6 @@ export struct EntityManager foreach (str; __traits(allMembers, Sys.ExcludedComponents)) { components_info.addExcluded(CompInfo(str, str)); - //components_info.excluded ~= CompInfo(str,str); } } else //static if (checkExcludedComponentsSomething!Sys) @@ -615,7 +699,6 @@ export struct EntityManager foreach (str; Sys.ExcludedComponents) { components_info.addExcluded(CompInfo(str.stringof, str.stringof)); - //components_info.excluded ~= CompInfo(str,str); } } @@ -624,7 +707,7 @@ export struct EntityManager return components_info; } - enum ComponentsIndices components_info = getComponentsInfo(); + enum ComponentsIndices!component_counts components_info = getComponentsInfo(); static void genCompList()(ref System system, ref HashMap!(char[], ushort) components_map) { @@ -659,7 +742,7 @@ export struct EntityManager foreach (iii, comp_info; components_info.req) { ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max); - version (betterC) + version (D_BetterC) assert(comp != ushort.max, "Can't register system due to non existing component."); else @@ -670,25 +753,29 @@ export struct EntityManager foreach (iii, comp_info; components_info.excluded) { ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max); - assert(comp != ushort.max); //, "Can't register system \""~Sys.stringof~"\" due to non existing component \""~comp_info.type~"\"."); + version (D_BetterC)assert(comp != ushort.max, "Can't register system due to non existing component."); + else assert(comp != ushort.max, "Can't register system \""~Sys.stringof~"\" due to non existing component \""~comp_info.type~"\"."); system.m_excluded_components[iii] = comp; } foreach (iii, comp_info; components_info.optional) { ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max); - assert(comp != ushort.max); //, "Can't register system \""~Sys.stringof~"\" due to non existing component \""~comp_info.type~"\"."); + version (D_BetterC)assert(comp != ushort.max, "Can't register system due to non existing component."); + else assert(comp != ushort.max, "Can't register system \""~Sys.stringof~"\" due to non existing component \""~comp_info.type~"\"."); system.m_optional_components[iii] = comp; } foreach (iii, comp_info; components_info.readonly) { ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max); - assert(comp != ushort.max); //, "Can't register system \""~Sys.stringof~"\" due to non existing component \""~comp_info.type~"\"."); + version (D_BetterC)assert(comp != ushort.max, "Can't register system due to non existing component."); + else assert(comp != ushort.max, "Can't register system \""~Sys.stringof~"\" due to non existing component \""~comp_info.type~"\"."); system.m_read_only_components[iii] = comp; } foreach (iii, comp_info; components_info.mutable) { ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max); - assert(comp != ushort.max); //, "Can't register system \""~Sys.stringof~"\" due to non existing component \""~comp_info.type~"\"."); + version (D_BetterC)assert(comp != ushort.max, "Can't register system due to non existing component."); + else assert(comp != ushort.max, "Can't register system \""~Sys.stringof~"\" due to non existing component \""~comp_info.type~"\"."); system.m_modified_components[iii] = comp; } @@ -1009,7 +1096,7 @@ export struct EntityManager static if (!(hasMember!(Comp, "component_id")) || !is(typeof(Comp.component_id) == ushort)) { - static assert(0, "Add \"mixin ECS.Component;\" in top of component structure;"); //"Component should have \"__gshared ushort component_id"); + static assert(0, "Add \"mixin ECS.Component;\" in top of component structure;"); } static if (hasMember!(Comp, "onDestroy") && isFunction!(Comp.onDestroy) @@ -1063,7 +1150,7 @@ export struct EntityManager static if (!(hasMember!(Ev, "event_id")) || !is(typeof(Ev.event_id) == ushort)) { - static assert(0, "Add \"mixin ECS.Event;\" in top of event structure;"); //"Event should have \"__gshared ushort event_id"); + static assert(0, "Add \"mixin ECS.Event;\" in top of event structure;"); } static if (hasMember!(Ev, "onDestroy") && isFunction!(Ev.onDestroy) diff --git a/tests/runner.d b/tests/runner.d index d2f9210..98c024d 100644 --- a/tests/runner.d +++ b/tests/runner.d @@ -15,7 +15,7 @@ enum string OUT_FILE = "test_report.xml"; static jmp_buf gEnvBuffer; static AssertInfo gAssertInfo; -version(betterC){} +version(D_BetterC){} else version = notBetterC; struct AssertInfo