1 /// Templates for working with Godot's type system 2 module godot.api.types; 3 4 import godot; 5 import godot.abi.core; 6 import godot.abi.types; 7 import godot.api.traits; 8 import godot.api.reference; 9 import godot.script, godot.object; 10 11 import std.meta; 12 13 import std.sumtype; 14 15 /// 16 struct BuiltInClass { 17 String name; 18 } 19 20 /// 21 alias TypeCategories = AliasSeq!(VariantType, BuiltInClass, Ref!Script); 22 23 /++ 24 A specific Godot type in one of these type categories: 25 * A built-in class derived from GodotObject 26 * A Script extending GodotObject (either in D or another Godot scripting language) 27 * A Godot core type from the `godot` modules or a primitive (represented as a Variant.Type) 28 29 These are all the types that can be directly stored in a Godot Variant. D types 30 that are indirectly compatible with Variant are converted to one of these when 31 passed to Godot. 32 +/ 33 alias GodotType = SumType!(TypeCategories); 34 35 /// Returns: `type` as a `T` if it is actually in type category `T`, 36 /// otherwise `defaultValue` 37 @nogc nothrow 38 T get(T)(in GodotType type, T defaultValue = T.init) { 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 return type.match!((T t) => true, _ => false); 46 } 47 48 /// FIXME: GodotType can't currently work with String or Ref!Script at compile 49 /// time, when they're not yet loaded from Godot. That also breaks DTypeOf 50 51 /// GodotType of a compile-time D type. 52 /// If T is indirectly compatible with Godot, this returns the Godot type T would 53 /// be converted to when passed to Godot. 54 template GodotTypeOf(T) { 55 version (none) { 56 static if (extendsGodotBaseClass!T) 57 enum GodotTypeOf = GodotType(NativeScriptTemplate!T.as!Script); 58 else static if (isGodotBaseClass!T) 59 enum GodotTypeOf = GodotType(BuiltInClass(String(T._GODOT_internal_name))); 60 } else 61 enum GodotTypeOf = GodotType(Variant.variantTypeOf!T); 62 } 63 64 // TODO: fix me 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 static if (t.isCategory!(Variant.Type)) { 72 alias DTypeOf = Variant.DType[get!(Variant.Type)(t)]; 73 } else 74 static assert(0, "Class types aren't known at compile time because the Godot API is not yet loaded"); 75 } 76 77 static foreach (alias C; TypeCategories) 78 alias DTypeOf(C t) = DTypeOf!(GodotType(t)); 79 80 // TODO: fix me 81 //static assert(is(DTypeOf!(Variant.Type.int_) == long)); 82 //static assert(is(DTypeOf!(Variant.Type.array) == Array)); 83 84 enum GodotError { 85 ok, 86 failed, 87 unavailable, 88 unconfigured, 89 unauthorized, 90 parameterRangeError, 91 outOfMemory, 92 fileNotFound, 93 fileBadDrive, 94 fileBadPath, 95 fileNoPermission, 96 fileAlreadyInUse, 97 fileCantOpen, 98 fileCantWrite, 99 fileCantRead, 100 fileUnrecognized, 101 fileCorrupt, 102 fileMissingDependencies, 103 fileEof, 104 cantOpen, 105 cantCreate, 106 queryFailed, 107 alreadyInUse, 108 locked, 109 timeout, 110 cantConnect, 111 cantResolve, 112 connectionError, 113 cantAcquireResource, 114 cantFork, 115 invalidData, 116 invalidParameter, 117 alreadyExists, 118 doesNotExist, 119 databaseCantRead, 120 databaseCantWrite, 121 compilationFailed, 122 methodNotFound, 123 linkFailed, 124 scriptFailed, 125 cyclicLink, 126 invalidDeclaration, 127 duplicateSymbol, 128 parseError, 129 busy, 130 skip, 131 help, 132 bug, 133 printerOnFire, 134 omfgThisIsVeryVeryBad, 135 wtf = omfgThisIsVeryVeryBad, 136 } 137 138 // Note that this is only used in struct types such as Vector, Plane, etc... 139 // Plain floats are double by default (see godot.abi.types.godot_float). 140 version(GODOT_REAL_T_DOUBLE) 141 alias real_t = double; 142 else 143 alias real_t = float; 144 145 enum real_t CMP_EPSILON = 0.00001; 146 enum real_t CMP_EPSILON2 = (CMP_EPSILON * CMP_EPSILON); 147 148 enum real_t _PLANE_EQ_DOT_EPSILON = 0.999; 149 enum real_t _PLANE_EQ_D_EPSILON = 0.0001;