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;