1 /************************************************************************************************************************ 2 Copyright: Copyright © 2018-2023, Dawid Masiukiewicz, Michał Masiukiewicz 3 License: BSD 3-clause, see LICENSE file in project root folder. 4 */ 5 module bubel.ecs.traits; 6 7 import std.traits; 8 9 /************************************************************************************************************************ 10 Return Component/System/Event unique ID 11 */ 12 ref ushort becsID(T)() 13 { 14 /// Embed id in struct so export can be added to variable definition 15 static struct LocalStruct { 16 export __gshared ushort id = ushort.max; 17 } 18 return LocalStruct.id; 19 } 20 21 /************************************************************************************************************************ 22 Return Component/System/Event unique ID 23 */ 24 ref ushort becsID(T)(T obj) 25 { 26 static if(isPointer!T)return becsID!(PointerTarget!T); 27 else return becsID!T; 28 } 29 30 bool isForeachDelegateWithTypes(DG, Types...)() 31 { 32 return is(DG == delegate) && is(ReturnType!DG == int) && is(Parameters!DG == Types); 33 } 34 35 unittest 36 { 37 assert(isForeachDelegateWithTypes!(int delegate(int, int), int, int)); 38 assert(isForeachDelegateWithTypes!(int delegate(ref int, ref int), int, int)); 39 assert(!isForeachDelegateWithTypes!(int delegate(double), int, int)); 40 } 41 42 /************************************************************************************************************************ 43 Returns index of Component/Entity array in System's EntitiesData struct 44 */ 45 static long getIndexOfTypeInEntitiesData(EntitiesData, Type)() 46 { 47 alias EntitiesDataFields = Fields!(EntitiesData); 48 long index = -1; 49 foreach (fieldNum, FieldType; Fields!(EntitiesData)) 50 { 51 52 static if (!isBasicType!(FieldType)) // Not basic type 53 { 54 // FieldType should be something like: 'const(SomeComponent)[]' 55 enum bool entitiesMatches = is(Type == Unqual!(ForeachType!(FieldType))); 56 static if (entitiesMatches) 57 { 58 index = fieldNum; 59 break; 60 } 61 } 62 } 63 return index; 64 } 65 66 static string attachParentName(alias T, string str)() 67 { 68 alias parent = __traits(parent, T); 69 enum parent_str = parent.stringof; 70 static if(parent_str[0..7] == "module ") 71 { 72 static if(__traits(compiles, __traits(parent, parent))) 73 { 74 return attachParentName!(parent, parent_str[7 .. $] ~ '.' ~ str); 75 } 76 else return parent_str[7 .. $] ~ '.' ~ str; 77 } 78 else static if(parent_str[0..8] == "package ") 79 { 80 static if(__traits(compiles, __traits(parent, parent))) 81 { 82 return attachParentName!(parent, parent_str[8 .. $] ~ '.' ~ str); 83 } 84 else return parent_str[8 .. $] ~ '.' ~ str; 85 } 86 else static if(__traits(compiles, __traits(parent, parent))) 87 { 88 return attachParentName!(parent, parent_str ~ '.' ~ str); 89 } 90 else return parent_str ~ '.' ~ str; 91 } 92 93 static string fullName(T)() 94 { 95 return attachParentName!(T, T.stringof); 96 }