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