bubel-ecs/source/bubel/ecs/traits.d

96 lines
No EOL
2.8 KiB
D

/************************************************************************************************************************
Copyright: Copyright © 2018-2019, Dawid Masiukiewicz, Michał Masiukiewicz
License: BSD 3-clause, see LICENSE file in project root folder.
*/
module bubel.ecs.traits;
import std.traits;
/************************************************************************************************************************
Return Component/System/Event unique ID
*/
ref ushort becsID(T)()
{
/// Embed id in struct so export can be added to variable definition
static struct LocalStruct {
export __gshared ushort id = ushort.max;
}
return LocalStruct.id;
}
/************************************************************************************************************************
Return Component/System/Event unique ID
*/
ref ushort becsID(T)(T obj)
{
static if(isPointer!T)return becsID!(PointerTarget!T);
else return becsID!T;
}
bool isForeachDelegateWithTypes(DG, Types...)()
{
return is(DG == delegate) && is(ReturnType!DG == int) && is(Parameters!DG == Types);
}
unittest
{
assert(isForeachDelegateWithTypes!(int delegate(int, int), int, int));
assert(isForeachDelegateWithTypes!(int delegate(ref int, ref int), int, int));
assert(!isForeachDelegateWithTypes!(int delegate(double), int, int));
}
/************************************************************************************************************************
Returns index of Component/Entity array in System's EntitiesData struct
*/
static long getIndexOfTypeInEntitiesData(EntitiesData, Type)()
{
alias EntitiesDataFields = Fields!(EntitiesData);
long index = -1;
foreach (fieldNum, FieldType; Fields!(EntitiesData))
{
static if (!isBasicType!(FieldType)) // Not basic type
{
// FieldType should be something like: 'const(SomeComponent)[]'
enum bool entitiesMatches = is(Type == Unqual!(ForeachType!(FieldType)));
static if (entitiesMatches)
{
index = fieldNum;
break;
}
}
}
return index;
}
static string attachParentName(alias T, string str)()
{
alias parent = __traits(parent, T);
enum parent_str = parent.stringof;
static if(parent_str[0..7] == "module ")
{
static if(__traits(compiles, __traits(parent, parent)))
{
return attachParentName!(parent, parent_str[7 .. $] ~ '.' ~ str);
}
else return parent_str[7 .. $] ~ '.' ~ str;
}
else static if(parent_str[0..8] == "package ")
{
static if(__traits(compiles, __traits(parent, parent)))
{
return attachParentName!(parent, parent_str[8 .. $] ~ '.' ~ str);
}
else return parent_str[8 .. $] ~ '.' ~ str;
}
else static if(__traits(compiles, __traits(parent, parent)))
{
return attachParentName!(parent, parent_str ~ '.' ~ str);
}
else return parent_str ~ '.' ~ str;
}
static string fullName(T)()
{
return attachParentName!(T, T.stringof);
}