class_db.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. /*************************************************************************/
  2. /* class_db.h */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2017 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. #ifndef CLASS_DB_H
  31. #define CLASS_DB_H
  32. #include "method_bind.h"
  33. #include "object.h"
  34. #include "print_string.h"
  35. /**
  36. @author Juan Linietsky <[email protected]>
  37. */
  38. struct ParamHint {
  39. String name;
  40. PropertyHint hint;
  41. String hint_text;
  42. Variant default_val;
  43. ParamHint(const String &p_name = "", PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_text = "", const Variant &p_default_val = Variant())
  44. : name(p_name),
  45. hint(p_hint),
  46. hint_text(p_hint_text),
  47. default_val(p_default_val) {
  48. }
  49. };
  50. struct ParamDef {
  51. bool used;
  52. Variant val;
  53. _FORCE_INLINE_ ParamDef() { used = false; }
  54. ParamDef(const Variant &p_variant);
  55. };
  56. //#define DEFVAL( m_defval ) ParamDef(m_defval)
  57. #define DEFVAL(m_defval) (m_defval)
  58. //#define SIMPLE_METHODDEF
  59. #ifdef DEBUG_METHODS_ENABLED
  60. struct MethodDefinition {
  61. StringName name;
  62. Vector<StringName> args;
  63. MethodDefinition() {}
  64. MethodDefinition(const char *p_name)
  65. : name(p_name) {}
  66. MethodDefinition(const StringName &p_name)
  67. : name(p_name) {}
  68. };
  69. MethodDefinition D_METHOD(const char *p_name);
  70. MethodDefinition D_METHOD(const char *p_name, const char *p_arg1);
  71. MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2);
  72. MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3);
  73. MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4);
  74. MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5);
  75. MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6);
  76. MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7);
  77. MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8);
  78. MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9);
  79. MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10);
  80. #else
  81. //#define NO_VARIADIC_MACROS
  82. #ifdef NO_VARIADIC_MACROS
  83. static _FORCE_INLINE_ const char *D_METHOD(const char *m_name, ...) {
  84. return m_name;
  85. }
  86. #else
  87. // When DEBUG_METHODS_ENABLED is set this will let the engine know
  88. // the argument names for easier debugging.
  89. #define D_METHOD(m_c, ...) m_c
  90. #endif
  91. #endif
  92. class ClassDB {
  93. public:
  94. enum APIType {
  95. API_CORE,
  96. API_EDITOR,
  97. API_NONE
  98. };
  99. public:
  100. struct PropertySetGet {
  101. int index;
  102. StringName setter;
  103. StringName getter;
  104. MethodBind *_setptr;
  105. MethodBind *_getptr;
  106. Variant::Type type;
  107. };
  108. struct ClassInfo {
  109. APIType api;
  110. ClassInfo *inherits_ptr;
  111. HashMap<StringName, MethodBind *, StringNameHasher> method_map;
  112. HashMap<StringName, int, StringNameHasher> constant_map;
  113. HashMap<StringName, MethodInfo, StringNameHasher> signal_map;
  114. List<PropertyInfo> property_list;
  115. #ifdef DEBUG_METHODS_ENABLED
  116. HashMap<StringName, List<StringName> > enum_map;
  117. List<StringName> constant_order;
  118. List<StringName> method_order;
  119. Set<StringName> methods_in_properties;
  120. List<MethodInfo> virtual_methods;
  121. StringName category;
  122. #endif
  123. HashMap<StringName, PropertySetGet, StringNameHasher> property_setget;
  124. StringName inherits;
  125. StringName name;
  126. bool disabled;
  127. Object *(*creation_func)();
  128. ClassInfo();
  129. ~ClassInfo();
  130. };
  131. template <class T>
  132. static Object *creator() {
  133. return memnew(T);
  134. }
  135. static RWLock *lock;
  136. static HashMap<StringName, ClassInfo, StringNameHasher> classes;
  137. static HashMap<StringName, StringName, StringNameHasher> resource_base_extensions;
  138. static HashMap<StringName, StringName, StringNameHasher> compat_classes;
  139. #ifdef DEBUG_METHODS_ENABLED
  140. static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount);
  141. #else
  142. static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const char *method_name, const Variant **p_defs, int p_defcount);
  143. #endif
  144. static APIType current_api;
  145. static void _add_class2(const StringName &p_class, const StringName &p_inherits);
  146. public:
  147. // DO NOT USE THIS!!!!!! NEEDS TO BE PUBLIC BUT DO NOT USE NO MATTER WHAT!!!
  148. template <class T>
  149. static void _add_class() {
  150. _add_class2(T::get_class_static(), T::get_parent_class_static());
  151. #if 0
  152. GLOBAL_LOCK_FUNCTION;
  153. StringName name = T::get_class_static();
  154. ERR_FAIL_COND(types.has(name));
  155. types[name]=TypeInfo();
  156. TypeInfo &ti=types[name];
  157. ti.name=name;
  158. ti.inherits=T::get_parent_class_static();
  159. if (ti.inherits) {
  160. ERR_FAIL_COND( !types.has(ti.inherits) ); //it MUST be registered.
  161. ti.inherits_ptr = &types[ti.inherits];
  162. } else {
  163. ti.inherits_ptr=NULL;
  164. }
  165. #endif
  166. }
  167. template <class T>
  168. static void register_class() {
  169. GLOBAL_LOCK_FUNCTION;
  170. T::initialize_class();
  171. ClassInfo *t = classes.getptr(T::get_class_static());
  172. ERR_FAIL_COND(!t);
  173. t->creation_func = &creator<T>;
  174. T::register_custom_data_to_otdb();
  175. }
  176. template <class T>
  177. static void register_virtual_class() {
  178. GLOBAL_LOCK_FUNCTION;
  179. T::initialize_class();
  180. //nothing
  181. }
  182. template <class T>
  183. static Object *_create_ptr_func() {
  184. return T::create();
  185. }
  186. template <class T>
  187. static void register_custom_instance_class() {
  188. GLOBAL_LOCK_FUNCTION;
  189. T::initialize_class();
  190. ClassInfo *t = classes.getptr(T::get_class_static());
  191. ERR_FAIL_COND(!t);
  192. t->creation_func = &_create_ptr_func<T>;
  193. T::register_custom_data_to_otdb();
  194. }
  195. static void get_class_list(List<StringName> *p_classes);
  196. static void get_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes);
  197. static StringName get_parent_class_nocheck(const StringName &p_class);
  198. static StringName get_parent_class(const StringName &p_class);
  199. static bool class_exists(const StringName &p_class);
  200. static bool is_parent_class(const StringName &p_class, const StringName &p_inherits);
  201. static bool can_instance(const StringName &p_class);
  202. static Object *instance(const StringName &p_class);
  203. static APIType get_api_type(const StringName &p_class);
  204. static uint64_t get_api_hash(APIType p_api);
  205. #if 0
  206. template<class N, class M>
  207. static MethodBind* bind_method(N p_method_name, M p_method,
  208. //default arguments
  209. ParamDef d1=ParamDef(),
  210. ParamDef d2=ParamDef(),
  211. ParamDef d3=ParamDef(),
  212. ParamDef d4=ParamDef(),
  213. ParamDef d5=ParamDef()
  214. ) {
  215. return bind_methodf(METHOD_FLAGS_DEFAULT,p_method_name, p_method, d1,d2,d3,d4,d5);
  216. }
  217. template<class N, class M>
  218. static MethodBind* bind_methodf(uint32_t p_flags, N p_method_name, M p_method,
  219. //default arguments
  220. const ParamDef &d1=ParamDef(),
  221. const ParamDef &d2=ParamDef(),
  222. const ParamDef &d3=ParamDef(),
  223. const ParamDef &d4=ParamDef(),
  224. const ParamDef &d5=ParamDef()
  225. ) {
  226. GLOBAL_LOCK_FUNCTION;
  227. MethodDefinition method_name=p_method_name;
  228. MethodBind *bind = create_method_bind(p_method);
  229. bind->set_name(method_name.name);
  230. ERR_FAIL_COND_V(!bind,NULL);
  231. String instance_type=bind->get_instance_type();
  232. TypeInfo *type=types.getptr(instance_type);
  233. if (!type) {
  234. memdelete(bind);
  235. ERR_FAIL_COND_V(!type,NULL);
  236. }
  237. if (type->method_map.has(method_name.name)) {
  238. memdelete(bind);
  239. // overloading not supported
  240. ERR_EXPLAIN("Method already bound: "+instance_type+"::"+method_name.name);
  241. ERR_FAIL_V(NULL);
  242. }
  243. bind->set_argument_names(method_name.args);
  244. type->method_map[method_name.name]=bind;
  245. Vector<Variant> defvals;
  246. #define PARSE_DEFVAL(m_defval) \
  247. if (d##m_defval.used) \
  248. defvals.insert(0, d##m_defval.val); \
  249. else \
  250. goto set_defvals;
  251. PARSE_DEFVAL(1);
  252. PARSE_DEFVAL(2);
  253. PARSE_DEFVAL(3);
  254. PARSE_DEFVAL(4);
  255. PARSE_DEFVAL(5);
  256. set_defvals:
  257. bind->set_default_arguments(defvals);
  258. bind->set_hint_flags(p_flags);
  259. return bind;
  260. #undef PARSE_DEFVAL
  261. }
  262. #else
  263. #if 0
  264. template<class N, class M>
  265. static MethodBind* bind_method(N p_method_name, M p_method,
  266. //default arguments
  267. const ParamDef &d1=ParamDef(),
  268. const ParamDef &d2=ParamDef(),
  269. const ParamDef &d3=ParamDef(),
  270. const ParamDef &d4=ParamDef(),
  271. const ParamDef &d5=ParamDef()
  272. ) {
  273. MethodDefinition method_name=p_method_name;
  274. MethodBind *bind = create_method_bind(p_method);
  275. return bind_methodfi(METHOD_FLAGS_DEFAULT,bind,method_name,d1,d2,d3,d4,d5); //use static function, much smaller binary usage
  276. }
  277. #endif
  278. template <class N, class M>
  279. static MethodBind *bind_method(N p_method_name, M p_method) {
  280. MethodBind *bind = create_method_bind(p_method);
  281. return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, NULL, 0); //use static function, much smaller binary usage
  282. }
  283. template <class N, class M>
  284. static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1) {
  285. MethodBind *bind = create_method_bind(p_method);
  286. const Variant *ptr[1] = { &p_def1 };
  287. return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 1);
  288. }
  289. template <class N, class M>
  290. static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2) {
  291. MethodBind *bind = create_method_bind(p_method);
  292. const Variant *ptr[2] = { &p_def1, &p_def2 };
  293. return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 2);
  294. }
  295. template <class N, class M>
  296. static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3) {
  297. MethodBind *bind = create_method_bind(p_method);
  298. const Variant *ptr[3] = { &p_def1, &p_def2, &p_def3 };
  299. return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 3);
  300. }
  301. template <class N, class M>
  302. static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4) {
  303. MethodBind *bind = create_method_bind(p_method);
  304. const Variant *ptr[4] = { &p_def1, &p_def2, &p_def3, &p_def4 };
  305. return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 4);
  306. }
  307. template <class N, class M>
  308. static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5) {
  309. MethodBind *bind = create_method_bind(p_method);
  310. const Variant *ptr[5] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5 };
  311. return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 5);
  312. }
  313. template <class N, class M>
  314. static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5, const Variant &p_def6) {
  315. MethodBind *bind = create_method_bind(p_method);
  316. const Variant *ptr[6] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5, &p_def6 };
  317. return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 6);
  318. }
  319. #if 0
  320. template<class N, class M>
  321. static MethodBind* bind_methodf(uint32_t p_flags, N p_method_name, M p_method,
  322. const ParamDef& d1=ParamDef(),
  323. const ParamDef& d2=ParamDef(),
  324. const ParamDef& d3=ParamDef(),
  325. const ParamDef& d4=ParamDef(),
  326. const ParamDef& d5=ParamDef()
  327. ) {
  328. MethodDefinition method_name=p_method_name;
  329. MethodBind *bind = create_method_bind(p_method);
  330. return bind_methodfi(p_flags,bind,method_name,d1,d2,d3,d4,d5); //use static function, much smaller binary usage
  331. }
  332. #endif
  333. #endif
  334. template <class M>
  335. static MethodBind *bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const Vector<Variant> &p_default_args = Vector<Variant>()) {
  336. GLOBAL_LOCK_FUNCTION;
  337. MethodBind *bind = create_vararg_method_bind(p_method, p_info);
  338. ERR_FAIL_COND_V(!bind, NULL);
  339. bind->set_name(p_name);
  340. bind->set_default_arguments(p_default_args);
  341. String instance_type = bind->get_instance_class();
  342. ClassInfo *type = classes.getptr(instance_type);
  343. if (!type) {
  344. memdelete(bind);
  345. ERR_FAIL_COND_V(!type, NULL);
  346. }
  347. if (type->method_map.has(p_name)) {
  348. memdelete(bind);
  349. // overloading not supported
  350. ERR_EXPLAIN("Method already bound: " + instance_type + "::" + p_name);
  351. ERR_FAIL_V(NULL);
  352. }
  353. type->method_map[p_name] = bind;
  354. #ifdef DEBUG_METHODS_ENABLED
  355. // FIXME: <reduz> set_return_type is no longer in MethodBind, so I guess it should be moved to vararg method bind
  356. //bind->set_return_type("Variant");
  357. type->method_order.push_back(p_name);
  358. #endif
  359. return bind;
  360. }
  361. static void add_signal(StringName p_class, const MethodInfo &p_signal);
  362. static bool has_signal(StringName p_class, StringName p_signal);
  363. static bool get_signal(StringName p_class, StringName p_signal, MethodInfo *r_signal);
  364. static void get_signal_list(StringName p_class, List<MethodInfo> *p_signals, bool p_no_inheritance = false);
  365. static void add_property_group(StringName p_class, const String &p_name, const String &p_prefix = "");
  366. static void add_property(StringName p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1);
  367. static void get_property_list(StringName p_class, List<PropertyInfo> *p_list, bool p_no_inheritance = false, const Object *p_validator = NULL);
  368. static bool set_property(Object *p_object, const StringName &p_property, const Variant &p_value, bool *r_valid = NULL);
  369. static bool get_property(Object *p_object, const StringName &p_property, Variant &r_value);
  370. static bool has_property(const StringName &p_class, const StringName &p_property, bool p_no_inheritance = false);
  371. static int get_property_index(const StringName &p_class, const StringName &p_property, bool *r_is_valid = NULL);
  372. static Variant::Type get_property_type(const StringName &p_class, const StringName &p_property, bool *r_is_valid = NULL);
  373. static StringName get_property_setter(StringName p_class, const StringName p_property);
  374. static StringName get_property_getter(StringName p_class, const StringName p_property);
  375. static bool has_method(StringName p_class, StringName p_method, bool p_no_inheritance = false);
  376. static void set_method_flags(StringName p_class, StringName p_method, int p_flags);
  377. static void get_method_list(StringName p_class, List<MethodInfo> *p_methods, bool p_no_inheritance = false, bool p_exclude_from_properties = false);
  378. static MethodBind *get_method(StringName p_class, StringName p_name);
  379. static void add_virtual_method(const StringName &p_class, const MethodInfo &p_method, bool p_virtual = true);
  380. static void get_virtual_methods(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance = false);
  381. static void bind_integer_constant(const StringName &p_class, const StringName &p_enum, const StringName &p_name, int p_constant);
  382. static void get_integer_constant_list(const StringName &p_class, List<String> *p_constants, bool p_no_inheritance = false);
  383. static int get_integer_constant(const StringName &p_class, const StringName &p_name, bool *p_success = NULL);
  384. #ifdef DEBUG_METHODS_ENABLED
  385. static StringName get_integer_constant_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false);
  386. static void get_enum_list(const StringName &p_class, List<StringName> *p_enums, bool p_no_inheritance = false);
  387. static void get_enum_constants(const StringName &p_class, const StringName &p_enum, List<StringName> *p_constants, bool p_no_inheritance = false);
  388. #endif
  389. static StringName get_category(const StringName &p_node);
  390. static bool get_setter_and_type_for_property(const StringName &p_class, const StringName &p_prop, StringName &r_class, StringName &r_setter);
  391. static void set_class_enabled(StringName p_class, bool p_enable);
  392. static bool is_class_enabled(StringName p_class);
  393. static void add_resource_base_extension(const StringName &p_extension, const StringName &p_class);
  394. static void get_resource_base_extensions(List<String> *p_extensions);
  395. static void get_extensions_for_type(const StringName &p_class, List<String> *p_extensions);
  396. static void add_compatibility_class(const StringName &p_class, const StringName &p_fallback);
  397. static void init();
  398. static void set_current_api(APIType p_api);
  399. static void cleanup();
  400. };
  401. #ifdef DEBUG_METHODS_ENABLED
  402. #define BIND_CONSTANT(m_constant) \
  403. ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);
  404. #define BIND_ENUM_CONSTANT(m_constant) \
  405. ClassDB::bind_integer_constant(get_class_static(), __constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant);
  406. #else
  407. #define BIND_CONSTANT(m_constant) \
  408. ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);
  409. #define BIND_ENUM_CONSTANT(m_constant) \
  410. ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);
  411. #endif
  412. #ifdef TOOLS_ENABLED
  413. #define BIND_VMETHOD(m_method) \
  414. ClassDB::add_virtual_method(get_class_static(), m_method);
  415. #else
  416. #define BIND_VMETHOD(m_method)
  417. #endif
  418. #endif // CLASS_DB_H