1 /*************************************************************************/
2 /*  type_info.h                                                          */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 
31 #ifndef GET_TYPE_INFO_H
32 #define GET_TYPE_INFO_H
33 
34 #ifdef DEBUG_METHODS_ENABLED
35 
36 template <bool C, typename T = void>
37 struct EnableIf {
38 
39 	typedef T type;
40 };
41 
42 template <typename T>
43 struct EnableIf<false, T> {
44 };
45 
46 template <typename, typename>
47 struct TypesAreSame {
48 
49 	static bool const value = false;
50 };
51 
52 template <typename A>
53 struct TypesAreSame<A, A> {
54 
55 	static bool const value = true;
56 };
57 
58 template <typename B, typename D>
59 struct TypeInherits {
60 
61 	static D *get_d();
62 
63 	static char (&test(B *))[1];
64 	static char (&test(...))[2];
65 
66 	static bool const value = sizeof(test(get_d())) == sizeof(char) &&
67 							  !TypesAreSame<B volatile const, void volatile const>::value;
68 };
69 
70 namespace GodotTypeInfo {
71 enum Metadata {
72 	METADATA_NONE,
73 	METADATA_INT_IS_INT8,
74 	METADATA_INT_IS_INT16,
75 	METADATA_INT_IS_INT32,
76 	METADATA_INT_IS_INT64,
77 	METADATA_INT_IS_UINT8,
78 	METADATA_INT_IS_UINT16,
79 	METADATA_INT_IS_UINT32,
80 	METADATA_INT_IS_UINT64,
81 	METADATA_REAL_IS_FLOAT,
82 	METADATA_REAL_IS_DOUBLE
83 };
84 }
85 
86 // If the compiler fails because it's trying to instantiate the primary 'GetTypeInfo' template
87 // instead of one of the specializations, it's most likely because the type 'T' is not supported.
88 // If 'T' is a class that inherits 'Object', make sure it can see the actual class declaration
89 // instead of a forward declaration. You can always forward declare 'T' in a header file, and then
90 // include the actual declaration of 'T' in the source file where 'GetTypeInfo<T>' is instantiated.
91 template <class T, typename = void>
92 struct GetTypeInfo;
93 
94 #define MAKE_TYPE_INFO(m_type, m_var_type)                                            \
95 	template <>                                                                       \
96 	struct GetTypeInfo<m_type> {                                                      \
97 		static const Variant::Type VARIANT_TYPE = m_var_type;                         \
98 		static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
99 		static inline PropertyInfo get_class_info() {                                 \
100 			return PropertyInfo(VARIANT_TYPE, String());                              \
101 		}                                                                             \
102 	};                                                                                \
103 	template <>                                                                       \
104 	struct GetTypeInfo<const m_type &> {                                              \
105 		static const Variant::Type VARIANT_TYPE = m_var_type;                         \
106 		static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
107 		static inline PropertyInfo get_class_info() {                                 \
108 			return PropertyInfo(VARIANT_TYPE, String());                              \
109 		}                                                                             \
110 	};
111 
112 #define MAKE_TYPE_INFO_WITH_META(m_type, m_var_type, m_metadata)    \
113 	template <>                                                     \
114 	struct GetTypeInfo<m_type> {                                    \
115 		static const Variant::Type VARIANT_TYPE = m_var_type;       \
116 		static const GodotTypeInfo::Metadata METADATA = m_metadata; \
117 		static inline PropertyInfo get_class_info() {               \
118 			return PropertyInfo(VARIANT_TYPE, String());            \
119 		}                                                           \
120 	};                                                              \
121 	template <>                                                     \
122 	struct GetTypeInfo<const m_type &> {                            \
123 		static const Variant::Type VARIANT_TYPE = m_var_type;       \
124 		static const GodotTypeInfo::Metadata METADATA = m_metadata; \
125 		static inline PropertyInfo get_class_info() {               \
126 			return PropertyInfo(VARIANT_TYPE, String());            \
127 		}                                                           \
128 	};
129 
130 MAKE_TYPE_INFO(bool, Variant::BOOL)
131 MAKE_TYPE_INFO_WITH_META(uint8_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_UINT8)
132 MAKE_TYPE_INFO_WITH_META(int8_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_INT8)
133 MAKE_TYPE_INFO_WITH_META(uint16_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_UINT16)
134 MAKE_TYPE_INFO_WITH_META(int16_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_INT16)
135 MAKE_TYPE_INFO_WITH_META(uint32_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_UINT32)
136 MAKE_TYPE_INFO_WITH_META(int32_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_INT32)
137 MAKE_TYPE_INFO_WITH_META(uint64_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_UINT64)
138 MAKE_TYPE_INFO_WITH_META(int64_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_INT64)
139 MAKE_TYPE_INFO(wchar_t, Variant::INT)
140 MAKE_TYPE_INFO_WITH_META(float, Variant::REAL, GodotTypeInfo::METADATA_REAL_IS_FLOAT)
141 MAKE_TYPE_INFO_WITH_META(double, Variant::REAL, GodotTypeInfo::METADATA_REAL_IS_DOUBLE)
142 
143 MAKE_TYPE_INFO(String, Variant::STRING)
144 MAKE_TYPE_INFO(Vector2, Variant::VECTOR2)
145 MAKE_TYPE_INFO(Rect2, Variant::RECT2)
146 MAKE_TYPE_INFO(Vector3, Variant::VECTOR3)
147 MAKE_TYPE_INFO(Transform2D, Variant::TRANSFORM2D)
148 MAKE_TYPE_INFO(Plane, Variant::PLANE)
149 MAKE_TYPE_INFO(Quat, Variant::QUAT)
150 MAKE_TYPE_INFO(AABB, Variant::AABB)
151 MAKE_TYPE_INFO(Basis, Variant::BASIS)
152 MAKE_TYPE_INFO(Transform, Variant::TRANSFORM)
153 MAKE_TYPE_INFO(Color, Variant::COLOR)
154 MAKE_TYPE_INFO(NodePath, Variant::NODE_PATH)
155 MAKE_TYPE_INFO(RID, Variant::_RID)
156 MAKE_TYPE_INFO(Dictionary, Variant::DICTIONARY)
157 MAKE_TYPE_INFO(Array, Variant::ARRAY)
158 MAKE_TYPE_INFO(PoolByteArray, Variant::POOL_BYTE_ARRAY)
159 MAKE_TYPE_INFO(PoolIntArray, Variant::POOL_INT_ARRAY)
160 MAKE_TYPE_INFO(PoolRealArray, Variant::POOL_REAL_ARRAY)
161 MAKE_TYPE_INFO(PoolStringArray, Variant::POOL_STRING_ARRAY)
162 MAKE_TYPE_INFO(PoolVector2Array, Variant::POOL_VECTOR2_ARRAY)
163 MAKE_TYPE_INFO(PoolVector3Array, Variant::POOL_VECTOR3_ARRAY)
164 MAKE_TYPE_INFO(PoolColorArray, Variant::POOL_COLOR_ARRAY)
165 
166 MAKE_TYPE_INFO(StringName, Variant::STRING)
167 MAKE_TYPE_INFO(IP_Address, Variant::STRING)
168 
169 class BSP_Tree;
170 MAKE_TYPE_INFO(BSP_Tree, Variant::DICTIONARY)
171 
172 //for RefPtr
173 template <>
174 struct GetTypeInfo<RefPtr> {
175 	static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
176 	static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
177 	static inline PropertyInfo get_class_info() {
178 		return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, "Reference");
179 	}
180 };
181 template <>
182 struct GetTypeInfo<const RefPtr &> {
183 	static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
184 	static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
185 	static inline PropertyInfo get_class_info() {
186 		return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, "Reference");
187 	}
188 };
189 
190 //for variant
191 template <>
192 struct GetTypeInfo<Variant> {
193 	static const Variant::Type VARIANT_TYPE = Variant::NIL;
194 	static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
195 	static inline PropertyInfo get_class_info() {
196 		return PropertyInfo(Variant::NIL, String(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
197 	}
198 };
199 
200 template <>
201 struct GetTypeInfo<const Variant &> {
202 	static const Variant::Type VARIANT_TYPE = Variant::NIL;
203 	static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
204 	static inline PropertyInfo get_class_info() {
205 		return PropertyInfo(Variant::NIL, String(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
206 	}
207 };
208 
209 #define MAKE_TEMPLATE_TYPE_INFO(m_template, m_type, m_var_type)                       \
210 	template <>                                                                       \
211 	struct GetTypeInfo<m_template<m_type> > {                                         \
212 		static const Variant::Type VARIANT_TYPE = m_var_type;                         \
213 		static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
214 		static inline PropertyInfo get_class_info() {                                 \
215 			return PropertyInfo(VARIANT_TYPE, String());                              \
216 		}                                                                             \
217 	};                                                                                \
218 	template <>                                                                       \
219 	struct GetTypeInfo<const m_template<m_type> &> {                                  \
220 		static const Variant::Type VARIANT_TYPE = m_var_type;                         \
221 		static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
222 		static inline PropertyInfo get_class_info() {                                 \
223 			return PropertyInfo(VARIANT_TYPE, String());                              \
224 		}                                                                             \
225 	};
226 
227 MAKE_TEMPLATE_TYPE_INFO(Vector, uint8_t, Variant::POOL_BYTE_ARRAY)
228 MAKE_TEMPLATE_TYPE_INFO(Vector, int, Variant::POOL_INT_ARRAY)
229 MAKE_TEMPLATE_TYPE_INFO(Vector, float, Variant::POOL_REAL_ARRAY)
230 MAKE_TEMPLATE_TYPE_INFO(Vector, String, Variant::POOL_STRING_ARRAY)
231 MAKE_TEMPLATE_TYPE_INFO(Vector, Vector2, Variant::POOL_VECTOR2_ARRAY)
232 MAKE_TEMPLATE_TYPE_INFO(Vector, Vector3, Variant::POOL_VECTOR3_ARRAY)
233 MAKE_TEMPLATE_TYPE_INFO(Vector, Color, Variant::POOL_COLOR_ARRAY)
234 
235 MAKE_TEMPLATE_TYPE_INFO(Vector, Variant, Variant::ARRAY)
236 MAKE_TEMPLATE_TYPE_INFO(Vector, RID, Variant::ARRAY)
237 MAKE_TEMPLATE_TYPE_INFO(Vector, Plane, Variant::ARRAY)
238 MAKE_TEMPLATE_TYPE_INFO(Vector, StringName, Variant::POOL_STRING_ARRAY)
239 
240 MAKE_TEMPLATE_TYPE_INFO(PoolVector, Plane, Variant::ARRAY)
241 MAKE_TEMPLATE_TYPE_INFO(PoolVector, Face3, Variant::POOL_VECTOR3_ARRAY)
242 
243 template <typename T>
244 struct GetTypeInfo<T *, typename EnableIf<TypeInherits<Object, T>::value>::type> {
245 	static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
246 	static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
247 	static inline PropertyInfo get_class_info() {
248 		return PropertyInfo(StringName(T::get_class_static()));
249 	}
250 };
251 
252 template <typename T>
253 struct GetTypeInfo<const T *, typename EnableIf<TypeInherits<Object, T>::value>::type> {
254 	static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
255 	static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
256 	static inline PropertyInfo get_class_info() {
257 		return PropertyInfo(StringName(T::get_class_static()));
258 	}
259 };
260 
261 #define TEMPL_MAKE_ENUM_TYPE_INFO(m_enum, m_impl)                                                                                                                                 \
262 	template <>                                                                                                                                                                   \
263 	struct GetTypeInfo<m_impl> {                                                                                                                                                  \
264 		static const Variant::Type VARIANT_TYPE = Variant::INT;                                                                                                                   \
265 		static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;                                                                                             \
266 		static inline PropertyInfo get_class_info() {                                                                                                                             \
267 			return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_ENUM, String(#m_enum).replace("::", ".")); \
268 		}                                                                                                                                                                         \
269 	};
270 
271 #define MAKE_ENUM_TYPE_INFO(m_enum)                 \
272 	TEMPL_MAKE_ENUM_TYPE_INFO(m_enum, m_enum)       \
273 	TEMPL_MAKE_ENUM_TYPE_INFO(m_enum, m_enum const) \
274 	TEMPL_MAKE_ENUM_TYPE_INFO(m_enum, m_enum &)     \
275 	TEMPL_MAKE_ENUM_TYPE_INFO(m_enum, const m_enum &)
276 
277 template <typename T>
278 inline StringName __constant_get_enum_name(T param, const String &p_constant) {
279 	if (GetTypeInfo<T>::VARIANT_TYPE == Variant::NIL)
280 		ERR_PRINTS("Missing VARIANT_ENUM_CAST for constant's enum: " + p_constant);
281 	return GetTypeInfo<T>::get_class_info().class_name;
282 }
283 
284 #define CLASS_INFO(m_type) (GetTypeInfo<m_type *>::get_class_info())
285 
286 #else
287 
288 #define MAKE_ENUM_TYPE_INFO(m_enum)
289 #define CLASS_INFO(m_type)
290 
291 #endif // DEBUG_METHODS_ENABLED
292 
293 #endif // GET_TYPE_INFO_H
294