diff --git a/source/ecs/manager.d b/source/ecs/manager.d index 5719f6e..496b6ef 100644 --- a/source/ecs/manager.d +++ b/source/ecs/manager.d @@ -312,7 +312,7 @@ class EntityManager } } - static string genCompList()() + /*static string genCompList()() { static foreach (member; __traits(allMembers, Sys.EntitiesData)) @@ -512,6 +512,195 @@ class EntityManager } } return ret; + }*/ + + static struct ComponentsIndices + { + string[] readonly; + string[] excluded; + string[] optional; + string[] mutable; + string[] req; + + } + + static void allocateSystemComponents(ComponentsIndices componentsInfo)(ref System system) + { + size_t req = componentsInfo.req.length; + size_t opt = componentsInfo.optional.length; + size_t excluded = componentsInfo.excluded.length; + size_t read_only = componentsInfo.readonly.length; + size_t modified = componentsInfo.mutable.length; + + if (req > 0) + system.m_components = Mallocator.instance.makeArray!ushort(req); + if (opt > 0) + system.m_optional_components = Mallocator.instance.makeArray!ushort(opt); + if (excluded > 0) + system.m_excluded_components = Mallocator.instance.makeArray!ushort(excluded); + if (read_only > 0) + system.m_read_only_components = Mallocator.instance.makeArray!ushort(read_only); + if (modified > 0) + system.m_modified_components = Mallocator.instance.makeArray!ushort(modified); + + } + + bool checkExcludedComponentsSomething(Sys)() + { + return __traits(compiles, allSameType!(string, typeof(Sys.ExcludedComponents))) && allSameType!(string, + typeof(Sys.ExcludedComponents)) && isExpressions!(Sys.ExcludedComponents); + } + + static ComponentsIndices getComponentsInfo() + { + ComponentsIndices componentsInfo; + + foreach (member; __traits(allMembers, Sys.EntitiesData)) + { + alias MemberType = typeof(__traits(getMember, Sys.EntitiesData, member)); + if (member == "length" || 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 isOptional; + bool isExcluded; + bool isReadOnly; + + // isMutable!( ForeachType!(MemberType) ); + if (is(CopyConstness!(ForeachType!(MemberType), int) == const(int))) + { + isReadOnly = true; + } + + foreach (att; __traits(getAttributes, __traits(getMember, Sys.EntitiesData, member))) + { + if (att == "optional") + { + isOptional = true; + } + else if (att == "excluded") + { + isExcluded = true; + } + if (att == "readonly") + { + isReadOnly = true; + } + } + if (isReadOnly) + { + componentsInfo.readonly ~= name; + } + else + { + componentsInfo.mutable ~= name; + } + if (isExcluded) + { + componentsInfo.excluded ~= name; + } + if (isOptional) + { + componentsInfo.optional ~= name; + } + if (isReadOnly) + { + componentsInfo.readonly ~= name; + } + if (isExcluded == false && isOptional == false) + { //is Req + componentsInfo.req ~= name; + } + + assert(!(isOptional && isExcluded), + "EntitiesData member can't have both \"@optional\" and \"@excluded\"."); + + } + + static if (__traits(hasMember, Sys, "ExcludedComponents")) + { + static if (is(Sys.ExcludedComponents == enum)) + { + foreach (str; Fields!(Sys.ExcludedComponents)) + { + ComponentInfo info; + info.isExcluded = true; + info.name = str.stringof; + } + } + else static if (checkExcludedComponentsSomething!Sys) + { + foreach (str; Sys.ExcludedComponents) + { + ComponentInfo info; + info.isExcluded = true; + info.name = str; + + } + + } + } + return componentsInfo; + } + + static void genCompList()(ref System system, ref HashMap!(const(char)[], ushort) components_map) + { + + foreach (member; __traits(allMembers, Sys.EntitiesData)) + { + alias MemberType=typeof(__traits(getMember, Sys.EntitiesData, member)); + + static if (isFunction!(__traits(getMember, Sys.EntitiesData, member))) + static assert(0, "EntitiesData can't have any function!"); + else static if (member == "length") + { + static assert(isIntegral!(MemberType), "EntitiesData 'length' member must be integral type."); + static assert(MemberType.sizeof > 1, "EntitiesData 'length' member can't be byte or ubyte."); + } + else static if (!(isArray!(MemberType))) + static assert(0, "EntitiesData members should be arrays of elements!"); + } + + enum ComponentsIndices componentsInfo = getComponentsInfo(); + allocateSystemComponents!(componentsInfo)(system); + + foreach (iii, name; componentsInfo.req) + { + ushort comp = components_map.get(cast(char[]) name, ushort.max); + assert(comp != ushort.max, "Can not register system: component not present"); + system.m_components[iii] = comp; + } + foreach (iii, name; componentsInfo.excluded) + { + ushort comp = components_map.get(cast(char[]) name, ushort.max); + assert(comp != ushort.max, "Can not register system: component not present"); + system.m_excluded_components[iii] = comp; + } + foreach (iii, name; componentsInfo.optional) + { + ushort comp = components_map.get(cast(char[]) name, ushort.max); + assert(comp != ushort.max, "Can not register system: component not present"); + system.m_optional_components[iii] = comp; + } + foreach (iii, name; componentsInfo.readonly) + { + ushort comp = components_map.get(cast(char[]) name, ushort.max); + assert(comp != ushort.max, "Can not register system: component not present"); + system.m_read_only_components[iii] = comp; + } + foreach (iii, name; componentsInfo.mutable) + { + ushort comp = components_map.get(cast(char[]) name, ushort.max); + assert(comp != ushort.max, "Can not register system: component not present"); + system.m_modified_components[iii] = comp; + } + } static string genFillInputData()() @@ -709,7 +898,8 @@ class EntityManager (cast(Sys*) system.m_system_pointer).__ecsInitialize(); system.jobs = (cast(Sys*) system.m_system_pointer)._ecs_jobs; - mixin(genCompList()); + //mixin(genCompList()); + genCompList(system, components_map); ushort sys_id = systems_map.get(Sys.stringof, ushort.max); if (sys_id < systems.length)