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 }