1 /// Templates for working with Godot's type system 2 module godot.d.type; 3 4 import godot; 5 import godot.d.traits; 6 import godot.d.reference; 7 import godot.script, godot.object; 8 9 import std.meta; 10 11 import sumtype; 12 13 /// 14 struct BuiltInClass 15 { 16 String name; 17 } 18 19 /// 20 alias TypeCategories = AliasSeq!(Variant.Type, BuiltInClass, Ref!Script); 21 22 /++ 23 A specific Godot type in one of these type categories: 24 * A built-in class derived from GodotObject 25 * A Script extending GodotObject (either in D or another Godot scripting language) 26 * A Godot core type from the `godot.core` modules or a primitive (represented as a Variant.Type) 27 28 These are all the types that can be directly stored in a Godot Variant. D types 29 that are indirectly compatible with Variant are converted to one of these when 30 passed to Godot. 31 +/ 32 alias GodotType = SumType!(TypeCategories); 33 34 /// Returns: `type` as a `T` if it is actually in type category `T`, 35 /// otherwise `defaultValue` 36 @nogc nothrow 37 T get(T)(in GodotType type, T defaultValue = T.init) 38 { 39 return type.match!((T t) => t, _ => defaultValue); 40 } 41 42 /// Is `type` in type category `T`? 43 @nogc nothrow 44 bool isCategory(T)(in GodotType type) 45 { 46 return type.match!((T t) => true, _ => false); 47 } 48 49 /// FIXME: GodotType can't currently work with String or Ref!Script at compile 50 /// time, when they're not yet loaded from Godot. That also breaks DTypeOf 51 52 /// GodotType of a compile-time D type. 53 /// If T is indirectly compatible with Godot, this returns the Godot type T would 54 /// be converted to when passed to Godot. 55 template GodotTypeOf(T) 56 { 57 version(none) 58 { 59 static if(extendsGodotBaseClass!T) enum GodotTypeOf = GodotType(NativeScriptTemplate!T.as!Script); 60 else static if(isGodotBaseClass!T) enum GodotTypeOf = GodotType(BuiltInClass(String(T._GODOT_internal_name))); 61 } 62 else enum GodotTypeOf = GodotType(Variant.variantTypeOf!T); 63 } 64 65 static assert(GodotTypeOf!int == GodotType(Variant.Type.int_)); 66 static assert(GodotTypeOf!(float[]) == GodotType(Variant.Type.array)); 67 static assert(GodotTypeOf!(int[4]) == GodotType(Variant.Type.array)); 68 69 /// D type of a compile-time GodotType 70 template DTypeOf(GodotType t) 71 { 72 static if(t.isCategory!(Variant.Type)) 73 { 74 alias DTypeOf = Variant.DType[get!(Variant.Type)(t)]; 75 } 76 else static assert(0, "Class types aren't known at compile time because the Godot API is not yet loaded"); 77 } 78 static foreach(alias C; TypeCategories) alias DTypeOf(C t) = DTypeOf!(GodotType(t)); 79 80 static assert(is(DTypeOf!(Variant.Type.int_) == long)); 81 static assert(is(DTypeOf!(Variant.Type.array) == Array)); 82