1 /*************************************************************************/
2 /*  class_db.cpp                                                         */
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 #include "class_db.h"
32 
33 #include "core/engine.h"
34 #include "core/os/mutex.h"
35 #include "core/version.h"
36 
37 #define OBJTYPE_RLOCK RWLockRead _rw_lockr_(lock);
38 #define OBJTYPE_WLOCK RWLockWrite _rw_lockw_(lock);
39 
40 #ifdef DEBUG_METHODS_ENABLED
41 
D_METHOD(const char * p_name)42 MethodDefinition D_METHOD(const char *p_name) {
43 
44 	MethodDefinition md;
45 	md.name = StaticCString::create(p_name);
46 	return md;
47 }
48 
D_METHOD(const char * p_name,const char * p_arg1)49 MethodDefinition D_METHOD(const char *p_name, const char *p_arg1) {
50 
51 	MethodDefinition md;
52 	md.name = StaticCString::create(p_name);
53 	md.args.push_back(StaticCString::create(p_arg1));
54 	return md;
55 }
56 
D_METHOD(const char * p_name,const char * p_arg1,const char * p_arg2)57 MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2) {
58 
59 	MethodDefinition md;
60 	md.name = StaticCString::create(p_name);
61 	md.args.resize(2);
62 	md.args.write[0] = StaticCString::create(p_arg1);
63 	md.args.write[1] = StaticCString::create(p_arg2);
64 	return md;
65 }
66 
D_METHOD(const char * p_name,const char * p_arg1,const char * p_arg2,const char * p_arg3)67 MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3) {
68 
69 	MethodDefinition md;
70 	md.name = StaticCString::create(p_name);
71 	md.args.resize(3);
72 	md.args.write[0] = StaticCString::create(p_arg1);
73 	md.args.write[1] = StaticCString::create(p_arg2);
74 	md.args.write[2] = StaticCString::create(p_arg3);
75 	return md;
76 }
77 
D_METHOD(const char * p_name,const char * p_arg1,const char * p_arg2,const char * p_arg3,const char * p_arg4)78 MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4) {
79 
80 	MethodDefinition md;
81 	md.name = StaticCString::create(p_name);
82 	md.args.resize(4);
83 	md.args.write[0] = StaticCString::create(p_arg1);
84 	md.args.write[1] = StaticCString::create(p_arg2);
85 	md.args.write[2] = StaticCString::create(p_arg3);
86 	md.args.write[3] = StaticCString::create(p_arg4);
87 	return md;
88 }
89 
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)90 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) {
91 
92 	MethodDefinition md;
93 	md.name = StaticCString::create(p_name);
94 	md.args.resize(5);
95 	md.args.write[0] = StaticCString::create(p_arg1);
96 	md.args.write[1] = StaticCString::create(p_arg2);
97 	md.args.write[2] = StaticCString::create(p_arg3);
98 	md.args.write[3] = StaticCString::create(p_arg4);
99 	md.args.write[4] = StaticCString::create(p_arg5);
100 	return md;
101 }
102 
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)103 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) {
104 
105 	MethodDefinition md;
106 	md.name = StaticCString::create(p_name);
107 	md.args.resize(6);
108 	md.args.write[0] = StaticCString::create(p_arg1);
109 	md.args.write[1] = StaticCString::create(p_arg2);
110 	md.args.write[2] = StaticCString::create(p_arg3);
111 	md.args.write[3] = StaticCString::create(p_arg4);
112 	md.args.write[4] = StaticCString::create(p_arg5);
113 	md.args.write[5] = StaticCString::create(p_arg6);
114 	return md;
115 }
116 
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)117 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) {
118 
119 	MethodDefinition md;
120 	md.name = StaticCString::create(p_name);
121 	md.args.resize(7);
122 	md.args.write[0] = StaticCString::create(p_arg1);
123 	md.args.write[1] = StaticCString::create(p_arg2);
124 	md.args.write[2] = StaticCString::create(p_arg3);
125 	md.args.write[3] = StaticCString::create(p_arg4);
126 	md.args.write[4] = StaticCString::create(p_arg5);
127 	md.args.write[5] = StaticCString::create(p_arg6);
128 	md.args.write[6] = StaticCString::create(p_arg7);
129 	return md;
130 }
131 
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)132 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) {
133 
134 	MethodDefinition md;
135 	md.name = StaticCString::create(p_name);
136 	md.args.resize(8);
137 	md.args.write[0] = StaticCString::create(p_arg1);
138 	md.args.write[1] = StaticCString::create(p_arg2);
139 	md.args.write[2] = StaticCString::create(p_arg3);
140 	md.args.write[3] = StaticCString::create(p_arg4);
141 	md.args.write[4] = StaticCString::create(p_arg5);
142 	md.args.write[5] = StaticCString::create(p_arg6);
143 	md.args.write[6] = StaticCString::create(p_arg7);
144 	md.args.write[7] = StaticCString::create(p_arg8);
145 	return md;
146 }
147 
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)148 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) {
149 
150 	MethodDefinition md;
151 	md.name = StaticCString::create(p_name);
152 	md.args.resize(9);
153 	md.args.write[0] = StaticCString::create(p_arg1);
154 	md.args.write[1] = StaticCString::create(p_arg2);
155 	md.args.write[2] = StaticCString::create(p_arg3);
156 	md.args.write[3] = StaticCString::create(p_arg4);
157 	md.args.write[4] = StaticCString::create(p_arg5);
158 	md.args.write[5] = StaticCString::create(p_arg6);
159 	md.args.write[6] = StaticCString::create(p_arg7);
160 	md.args.write[7] = StaticCString::create(p_arg8);
161 	md.args.write[8] = StaticCString::create(p_arg9);
162 	return md;
163 }
164 
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)165 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) {
166 
167 	MethodDefinition md;
168 	md.name = StaticCString::create(p_name);
169 	md.args.resize(10);
170 	md.args.write[0] = StaticCString::create(p_arg1);
171 	md.args.write[1] = StaticCString::create(p_arg2);
172 	md.args.write[2] = StaticCString::create(p_arg3);
173 	md.args.write[3] = StaticCString::create(p_arg4);
174 	md.args.write[4] = StaticCString::create(p_arg5);
175 	md.args.write[5] = StaticCString::create(p_arg6);
176 	md.args.write[6] = StaticCString::create(p_arg7);
177 	md.args.write[7] = StaticCString::create(p_arg8);
178 	md.args.write[8] = StaticCString::create(p_arg9);
179 	md.args.write[9] = StaticCString::create(p_arg10);
180 	return md;
181 }
182 
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,const char * p_arg11)183 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, const char *p_arg11) {
184 
185 	MethodDefinition md;
186 	md.name = StaticCString::create(p_name);
187 	md.args.resize(11);
188 	md.args.write[0] = StaticCString::create(p_arg1);
189 	md.args.write[1] = StaticCString::create(p_arg2);
190 	md.args.write[2] = StaticCString::create(p_arg3);
191 	md.args.write[3] = StaticCString::create(p_arg4);
192 	md.args.write[4] = StaticCString::create(p_arg5);
193 	md.args.write[5] = StaticCString::create(p_arg6);
194 	md.args.write[6] = StaticCString::create(p_arg7);
195 	md.args.write[7] = StaticCString::create(p_arg8);
196 	md.args.write[8] = StaticCString::create(p_arg9);
197 	md.args.write[9] = StaticCString::create(p_arg10);
198 	md.args.write[10] = StaticCString::create(p_arg11);
199 	return md;
200 }
201 
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,const char * p_arg11,const char * p_arg12)202 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, const char *p_arg11, const char *p_arg12) {
203 
204 	MethodDefinition md;
205 	md.name = StaticCString::create(p_name);
206 	md.args.resize(12);
207 	md.args.write[0] = StaticCString::create(p_arg1);
208 	md.args.write[1] = StaticCString::create(p_arg2);
209 	md.args.write[2] = StaticCString::create(p_arg3);
210 	md.args.write[3] = StaticCString::create(p_arg4);
211 	md.args.write[4] = StaticCString::create(p_arg5);
212 	md.args.write[5] = StaticCString::create(p_arg6);
213 	md.args.write[6] = StaticCString::create(p_arg7);
214 	md.args.write[7] = StaticCString::create(p_arg8);
215 	md.args.write[8] = StaticCString::create(p_arg9);
216 	md.args.write[9] = StaticCString::create(p_arg10);
217 	md.args.write[10] = StaticCString::create(p_arg11);
218 	md.args.write[11] = StaticCString::create(p_arg12);
219 	return md;
220 }
221 
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,const char * p_arg11,const char * p_arg12,const char * p_arg13)222 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, const char *p_arg11, const char *p_arg12, const char *p_arg13) {
223 
224 	MethodDefinition md;
225 	md.name = StaticCString::create(p_name);
226 	md.args.resize(13);
227 	md.args.write[0] = StaticCString::create(p_arg1);
228 	md.args.write[1] = StaticCString::create(p_arg2);
229 	md.args.write[2] = StaticCString::create(p_arg3);
230 	md.args.write[3] = StaticCString::create(p_arg4);
231 	md.args.write[4] = StaticCString::create(p_arg5);
232 	md.args.write[5] = StaticCString::create(p_arg6);
233 	md.args.write[6] = StaticCString::create(p_arg7);
234 	md.args.write[7] = StaticCString::create(p_arg8);
235 	md.args.write[8] = StaticCString::create(p_arg9);
236 	md.args.write[9] = StaticCString::create(p_arg10);
237 	md.args.write[10] = StaticCString::create(p_arg11);
238 	md.args.write[11] = StaticCString::create(p_arg12);
239 	md.args.write[12] = StaticCString::create(p_arg13);
240 	return md;
241 }
242 
243 #endif
244 
245 ClassDB::APIType ClassDB::current_api = API_CORE;
246 
set_current_api(APIType p_api)247 void ClassDB::set_current_api(APIType p_api) {
248 
249 	current_api = p_api;
250 }
251 
get_current_api()252 ClassDB::APIType ClassDB::get_current_api() {
253 
254 	return current_api;
255 }
256 
257 HashMap<StringName, ClassDB::ClassInfo> ClassDB::classes;
258 HashMap<StringName, StringName> ClassDB::resource_base_extensions;
259 HashMap<StringName, StringName> ClassDB::compat_classes;
260 
ClassInfo()261 ClassDB::ClassInfo::ClassInfo() {
262 
263 	api = API_NONE;
264 	creation_func = NULL;
265 	inherits_ptr = NULL;
266 	disabled = false;
267 	exposed = false;
268 }
269 
~ClassInfo()270 ClassDB::ClassInfo::~ClassInfo() {
271 }
272 
is_parent_class(const StringName & p_class,const StringName & p_inherits)273 bool ClassDB::is_parent_class(const StringName &p_class, const StringName &p_inherits) {
274 
275 	OBJTYPE_RLOCK;
276 
277 	StringName inherits = p_class;
278 
279 	while (inherits.operator String().length()) {
280 
281 		if (inherits == p_inherits)
282 			return true;
283 		inherits = get_parent_class(inherits);
284 	}
285 
286 	return false;
287 }
get_class_list(List<StringName> * p_classes)288 void ClassDB::get_class_list(List<StringName> *p_classes) {
289 
290 	OBJTYPE_RLOCK;
291 
292 	const StringName *k = NULL;
293 
294 	while ((k = classes.next(k))) {
295 
296 		p_classes->push_back(*k);
297 	}
298 
299 	p_classes->sort();
300 }
301 
get_inheriters_from_class(const StringName & p_class,List<StringName> * p_classes)302 void ClassDB::get_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes) {
303 
304 	OBJTYPE_RLOCK;
305 
306 	const StringName *k = NULL;
307 
308 	while ((k = classes.next(k))) {
309 
310 		if (*k != p_class && is_parent_class(*k, p_class))
311 			p_classes->push_back(*k);
312 	}
313 }
314 
get_direct_inheriters_from_class(const StringName & p_class,List<StringName> * p_classes)315 void ClassDB::get_direct_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes) {
316 
317 	OBJTYPE_RLOCK;
318 
319 	const StringName *k = NULL;
320 
321 	while ((k = classes.next(k))) {
322 
323 		if (*k != p_class && get_parent_class(*k) == p_class)
324 			p_classes->push_back(*k);
325 	}
326 }
327 
get_parent_class_nocheck(const StringName & p_class)328 StringName ClassDB::get_parent_class_nocheck(const StringName &p_class) {
329 
330 	OBJTYPE_RLOCK;
331 
332 	ClassInfo *ti = classes.getptr(p_class);
333 	if (!ti)
334 		return StringName();
335 	return ti->inherits;
336 }
337 
get_parent_class(const StringName & p_class)338 StringName ClassDB::get_parent_class(const StringName &p_class) {
339 
340 	OBJTYPE_RLOCK;
341 
342 	ClassInfo *ti = classes.getptr(p_class);
343 	ERR_FAIL_COND_V_MSG(!ti, StringName(), "Cannot get class '" + String(p_class) + "'.");
344 	return ti->inherits;
345 }
346 
get_api_type(const StringName & p_class)347 ClassDB::APIType ClassDB::get_api_type(const StringName &p_class) {
348 
349 	OBJTYPE_RLOCK;
350 
351 	ClassInfo *ti = classes.getptr(p_class);
352 
353 	ERR_FAIL_COND_V_MSG(!ti, API_NONE, "Cannot get class '" + String(p_class) + "'.");
354 	return ti->api;
355 }
356 
get_api_hash(APIType p_api)357 uint64_t ClassDB::get_api_hash(APIType p_api) {
358 
359 	OBJTYPE_RLOCK;
360 #ifdef DEBUG_METHODS_ENABLED
361 
362 	uint64_t hash = hash_djb2_one_64(HashMapHasherDefault::hash(VERSION_FULL_CONFIG));
363 
364 	List<StringName> names;
365 
366 	const StringName *k = NULL;
367 
368 	while ((k = classes.next(k))) {
369 
370 		names.push_back(*k);
371 	}
372 	//must be alphabetically sorted for hash to compute
373 	names.sort_custom<StringName::AlphCompare>();
374 
375 	for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
376 
377 		ClassInfo *t = classes.getptr(E->get());
378 		ERR_FAIL_COND_V_MSG(!t, 0, "Cannot get class '" + String(E->get()) + "'.");
379 		if (t->api != p_api || !t->exposed)
380 			continue;
381 		hash = hash_djb2_one_64(t->name.hash(), hash);
382 		hash = hash_djb2_one_64(t->inherits.hash(), hash);
383 
384 		{ //methods
385 
386 			List<StringName> snames;
387 
388 			k = NULL;
389 
390 			while ((k = t->method_map.next(k))) {
391 
392 				String name = k->operator String();
393 
394 				ERR_CONTINUE(name.empty());
395 
396 				if (name[0] == '_')
397 					continue; // Ignore non-virtual methods that start with an underscore
398 
399 				snames.push_back(*k);
400 			}
401 
402 			snames.sort_custom<StringName::AlphCompare>();
403 
404 			for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
405 
406 				MethodBind *mb = t->method_map[F->get()];
407 				hash = hash_djb2_one_64(mb->get_name().hash(), hash);
408 				hash = hash_djb2_one_64(mb->get_argument_count(), hash);
409 				hash = hash_djb2_one_64(mb->get_argument_type(-1), hash); //return
410 
411 				for (int i = 0; i < mb->get_argument_count(); i++) {
412 					const PropertyInfo info = mb->get_argument_info(i);
413 					hash = hash_djb2_one_64(info.type, hash);
414 					hash = hash_djb2_one_64(info.name.hash(), hash);
415 					hash = hash_djb2_one_64(info.hint, hash);
416 					hash = hash_djb2_one_64(info.hint_string.hash(), hash);
417 				}
418 
419 				hash = hash_djb2_one_64(mb->get_default_argument_count(), hash);
420 
421 				for (int i = 0; i < mb->get_default_argument_count(); i++) {
422 					//hash should not change, i hope for tis
423 					Variant da = mb->get_default_argument(i);
424 					hash = hash_djb2_one_64(da.hash(), hash);
425 				}
426 
427 				hash = hash_djb2_one_64(mb->get_hint_flags(), hash);
428 			}
429 		}
430 
431 		{ //constants
432 
433 			List<StringName> snames;
434 
435 			k = NULL;
436 
437 			while ((k = t->constant_map.next(k))) {
438 
439 				snames.push_back(*k);
440 			}
441 
442 			snames.sort_custom<StringName::AlphCompare>();
443 
444 			for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
445 
446 				hash = hash_djb2_one_64(F->get().hash(), hash);
447 				hash = hash_djb2_one_64(t->constant_map[F->get()], hash);
448 			}
449 		}
450 
451 		{ //signals
452 
453 			List<StringName> snames;
454 
455 			k = NULL;
456 
457 			while ((k = t->signal_map.next(k))) {
458 
459 				snames.push_back(*k);
460 			}
461 
462 			snames.sort_custom<StringName::AlphCompare>();
463 
464 			for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
465 
466 				MethodInfo &mi = t->signal_map[F->get()];
467 				hash = hash_djb2_one_64(F->get().hash(), hash);
468 				for (int i = 0; i < mi.arguments.size(); i++) {
469 					hash = hash_djb2_one_64(mi.arguments[i].type, hash);
470 				}
471 			}
472 		}
473 
474 		{ //properties
475 
476 			List<StringName> snames;
477 
478 			k = NULL;
479 
480 			while ((k = t->property_setget.next(k))) {
481 
482 				snames.push_back(*k);
483 			}
484 
485 			snames.sort_custom<StringName::AlphCompare>();
486 
487 			for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
488 
489 				PropertySetGet *psg = t->property_setget.getptr(F->get());
490 				ERR_FAIL_COND_V(!psg, 0);
491 
492 				hash = hash_djb2_one_64(F->get().hash(), hash);
493 				hash = hash_djb2_one_64(psg->setter.hash(), hash);
494 				hash = hash_djb2_one_64(psg->getter.hash(), hash);
495 			}
496 		}
497 
498 		//property list
499 		for (List<PropertyInfo>::Element *F = t->property_list.front(); F; F = F->next()) {
500 
501 			hash = hash_djb2_one_64(F->get().name.hash(), hash);
502 			hash = hash_djb2_one_64(F->get().type, hash);
503 			hash = hash_djb2_one_64(F->get().hint, hash);
504 			hash = hash_djb2_one_64(F->get().hint_string.hash(), hash);
505 			hash = hash_djb2_one_64(F->get().usage, hash);
506 		}
507 	}
508 
509 	return hash;
510 #else
511 	return 0;
512 #endif
513 }
514 
class_exists(const StringName & p_class)515 bool ClassDB::class_exists(const StringName &p_class) {
516 
517 	OBJTYPE_RLOCK;
518 	return classes.has(p_class);
519 }
520 
add_compatibility_class(const StringName & p_class,const StringName & p_fallback)521 void ClassDB::add_compatibility_class(const StringName &p_class, const StringName &p_fallback) {
522 
523 	OBJTYPE_WLOCK;
524 	compat_classes[p_class] = p_fallback;
525 }
526 
instance(const StringName & p_class)527 Object *ClassDB::instance(const StringName &p_class) {
528 
529 	ClassInfo *ti;
530 	{
531 		OBJTYPE_RLOCK;
532 		ti = classes.getptr(p_class);
533 		if (!ti || ti->disabled || !ti->creation_func) {
534 			if (compat_classes.has(p_class)) {
535 				ti = classes.getptr(compat_classes[p_class]);
536 			}
537 		}
538 		ERR_FAIL_COND_V_MSG(!ti, NULL, "Cannot get class '" + String(p_class) + "'.");
539 		ERR_FAIL_COND_V_MSG(ti->disabled, NULL, "Class '" + String(p_class) + "' is disabled.");
540 		ERR_FAIL_COND_V(!ti->creation_func, NULL);
541 	}
542 #ifdef TOOLS_ENABLED
543 	if (ti->api == API_EDITOR && !Engine::get_singleton()->is_editor_hint()) {
544 		ERR_PRINTS("Class '" + String(p_class) + "' can only be instantiated by editor.");
545 		return NULL;
546 	}
547 #endif
548 	return ti->creation_func();
549 }
can_instance(const StringName & p_class)550 bool ClassDB::can_instance(const StringName &p_class) {
551 
552 	OBJTYPE_RLOCK;
553 
554 	ClassInfo *ti = classes.getptr(p_class);
555 	ERR_FAIL_COND_V_MSG(!ti, false, "Cannot get class '" + String(p_class) + "'.");
556 #ifdef TOOLS_ENABLED
557 	if (ti->api == API_EDITOR && !Engine::get_singleton()->is_editor_hint()) {
558 		return false;
559 	}
560 #endif
561 	return (!ti->disabled && ti->creation_func != NULL);
562 }
563 
_add_class2(const StringName & p_class,const StringName & p_inherits)564 void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherits) {
565 
566 	OBJTYPE_WLOCK;
567 
568 	const StringName &name = p_class;
569 
570 	ERR_FAIL_COND_MSG(classes.has(name), "Class '" + String(p_class) + "' already exists.");
571 
572 	classes[name] = ClassInfo();
573 	ClassInfo &ti = classes[name];
574 	ti.name = name;
575 	ti.inherits = p_inherits;
576 	ti.api = current_api;
577 
578 	if (ti.inherits) {
579 
580 		ERR_FAIL_COND(!classes.has(ti.inherits)); //it MUST be registered.
581 		ti.inherits_ptr = &classes[ti.inherits];
582 
583 	} else {
584 		ti.inherits_ptr = NULL;
585 	}
586 }
587 
get_method_list(StringName p_class,List<MethodInfo> * p_methods,bool p_no_inheritance,bool p_exclude_from_properties)588 void ClassDB::get_method_list(StringName p_class, List<MethodInfo> *p_methods, bool p_no_inheritance, bool p_exclude_from_properties) {
589 
590 	OBJTYPE_RLOCK;
591 
592 	ClassInfo *type = classes.getptr(p_class);
593 
594 	while (type) {
595 
596 		if (type->disabled) {
597 
598 			if (p_no_inheritance)
599 				break;
600 
601 			type = type->inherits_ptr;
602 			continue;
603 		}
604 
605 #ifdef DEBUG_METHODS_ENABLED
606 
607 		for (List<MethodInfo>::Element *E = type->virtual_methods.front(); E; E = E->next()) {
608 
609 			p_methods->push_back(E->get());
610 		}
611 
612 		for (List<StringName>::Element *E = type->method_order.front(); E; E = E->next()) {
613 
614 			MethodBind *method = type->method_map.get(E->get());
615 			MethodInfo minfo;
616 			minfo.name = E->get();
617 			minfo.id = method->get_method_id();
618 
619 			if (p_exclude_from_properties && type->methods_in_properties.has(minfo.name))
620 				continue;
621 
622 			for (int i = 0; i < method->get_argument_count(); i++) {
623 
624 				//Variant::Type t=method->get_argument_type(i);
625 
626 				minfo.arguments.push_back(method->get_argument_info(i));
627 			}
628 
629 			minfo.return_val = method->get_return_info();
630 			minfo.flags = method->get_hint_flags();
631 
632 			for (int i = 0; i < method->get_argument_count(); i++) {
633 				if (method->has_default_argument(i))
634 					minfo.default_arguments.push_back(method->get_default_argument(i));
635 			}
636 
637 			p_methods->push_back(minfo);
638 		}
639 
640 #else
641 
642 		const StringName *K = NULL;
643 
644 		while ((K = type->method_map.next(K))) {
645 
646 			MethodBind *m = type->method_map[*K];
647 			MethodInfo mi;
648 			mi.name = m->get_name();
649 			p_methods->push_back(mi);
650 		}
651 
652 #endif
653 
654 		if (p_no_inheritance)
655 			break;
656 
657 		type = type->inherits_ptr;
658 	}
659 }
660 
get_method(StringName p_class,StringName p_name)661 MethodBind *ClassDB::get_method(StringName p_class, StringName p_name) {
662 
663 	OBJTYPE_RLOCK;
664 
665 	ClassInfo *type = classes.getptr(p_class);
666 
667 	while (type) {
668 
669 		MethodBind **method = type->method_map.getptr(p_name);
670 		if (method && *method)
671 			return *method;
672 		type = type->inherits_ptr;
673 	}
674 	return NULL;
675 }
676 
bind_integer_constant(const StringName & p_class,const StringName & p_enum,const StringName & p_name,int p_constant)677 void ClassDB::bind_integer_constant(const StringName &p_class, const StringName &p_enum, const StringName &p_name, int p_constant) {
678 
679 	OBJTYPE_WLOCK;
680 
681 	ClassInfo *type = classes.getptr(p_class);
682 
683 	ERR_FAIL_COND(!type);
684 
685 	if (type->constant_map.has(p_name)) {
686 
687 		ERR_FAIL();
688 	}
689 
690 	type->constant_map[p_name] = p_constant;
691 
692 	String enum_name = p_enum;
693 	if (enum_name != String()) {
694 		if (enum_name.find(".") != -1) {
695 			enum_name = enum_name.get_slicec('.', 1);
696 		}
697 
698 		List<StringName> *constants_list = type->enum_map.getptr(enum_name);
699 
700 		if (constants_list) {
701 			constants_list->push_back(p_name);
702 		} else {
703 			List<StringName> new_list;
704 			new_list.push_back(p_name);
705 			type->enum_map[enum_name] = new_list;
706 		}
707 	}
708 
709 #ifdef DEBUG_METHODS_ENABLED
710 	type->constant_order.push_back(p_name);
711 #endif
712 }
713 
get_integer_constant_list(const StringName & p_class,List<String> * p_constants,bool p_no_inheritance)714 void ClassDB::get_integer_constant_list(const StringName &p_class, List<String> *p_constants, bool p_no_inheritance) {
715 
716 	OBJTYPE_RLOCK;
717 
718 	ClassInfo *type = classes.getptr(p_class);
719 
720 	while (type) {
721 
722 #ifdef DEBUG_METHODS_ENABLED
723 		for (List<StringName>::Element *E = type->constant_order.front(); E; E = E->next())
724 			p_constants->push_back(E->get());
725 #else
726 		const StringName *K = NULL;
727 
728 		while ((K = type->constant_map.next(K))) {
729 			p_constants->push_back(*K);
730 		}
731 
732 #endif
733 		if (p_no_inheritance)
734 			break;
735 
736 		type = type->inherits_ptr;
737 	}
738 }
739 
get_integer_constant(const StringName & p_class,const StringName & p_name,bool * p_success)740 int ClassDB::get_integer_constant(const StringName &p_class, const StringName &p_name, bool *p_success) {
741 
742 	OBJTYPE_RLOCK;
743 
744 	ClassInfo *type = classes.getptr(p_class);
745 
746 	while (type) {
747 
748 		int *constant = type->constant_map.getptr(p_name);
749 		if (constant) {
750 
751 			if (p_success)
752 				*p_success = true;
753 			return *constant;
754 		}
755 
756 		type = type->inherits_ptr;
757 	}
758 
759 	if (p_success)
760 		*p_success = false;
761 
762 	return 0;
763 }
764 
get_integer_constant_enum(const StringName & p_class,const StringName & p_name,bool p_no_inheritance)765 StringName ClassDB::get_integer_constant_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) {
766 
767 	OBJTYPE_RLOCK;
768 
769 	ClassInfo *type = classes.getptr(p_class);
770 
771 	while (type) {
772 
773 		const StringName *k = NULL;
774 		while ((k = type->enum_map.next(k))) {
775 
776 			List<StringName> &constants_list = type->enum_map.get(*k);
777 			const List<StringName>::Element *found = constants_list.find(p_name);
778 			if (found)
779 				return *k;
780 		}
781 
782 		if (p_no_inheritance)
783 			break;
784 
785 		type = type->inherits_ptr;
786 	}
787 
788 	return StringName();
789 }
790 
get_enum_list(const StringName & p_class,List<StringName> * p_enums,bool p_no_inheritance)791 void ClassDB::get_enum_list(const StringName &p_class, List<StringName> *p_enums, bool p_no_inheritance) {
792 
793 	OBJTYPE_RLOCK;
794 
795 	ClassInfo *type = classes.getptr(p_class);
796 
797 	while (type) {
798 
799 		const StringName *k = NULL;
800 		while ((k = type->enum_map.next(k))) {
801 			p_enums->push_back(*k);
802 		}
803 
804 		if (p_no_inheritance)
805 			break;
806 
807 		type = type->inherits_ptr;
808 	}
809 }
810 
get_enum_constants(const StringName & p_class,const StringName & p_enum,List<StringName> * p_constants,bool p_no_inheritance)811 void ClassDB::get_enum_constants(const StringName &p_class, const StringName &p_enum, List<StringName> *p_constants, bool p_no_inheritance) {
812 
813 	OBJTYPE_RLOCK;
814 
815 	ClassInfo *type = classes.getptr(p_class);
816 
817 	while (type) {
818 
819 		const List<StringName> *constants = type->enum_map.getptr(p_enum);
820 
821 		if (constants) {
822 			for (const List<StringName>::Element *E = constants->front(); E; E = E->next()) {
823 				p_constants->push_back(E->get());
824 			}
825 		}
826 
827 		if (p_no_inheritance)
828 			break;
829 
830 		type = type->inherits_ptr;
831 	}
832 }
833 
add_signal(StringName p_class,const MethodInfo & p_signal)834 void ClassDB::add_signal(StringName p_class, const MethodInfo &p_signal) {
835 
836 	OBJTYPE_WLOCK;
837 
838 	ClassInfo *type = classes.getptr(p_class);
839 	ERR_FAIL_COND(!type);
840 
841 	StringName sname = p_signal.name;
842 
843 #ifdef DEBUG_METHODS_ENABLED
844 	ClassInfo *check = type;
845 	while (check) {
846 		ERR_FAIL_COND_MSG(check->signal_map.has(sname), "Class '" + String(p_class) + "' already has signal '" + String(sname) + "'.");
847 		check = check->inherits_ptr;
848 	}
849 #endif
850 
851 	type->signal_map[sname] = p_signal;
852 }
853 
get_signal_list(StringName p_class,List<MethodInfo> * p_signals,bool p_no_inheritance)854 void ClassDB::get_signal_list(StringName p_class, List<MethodInfo> *p_signals, bool p_no_inheritance) {
855 
856 	OBJTYPE_RLOCK;
857 
858 	ClassInfo *type = classes.getptr(p_class);
859 	ERR_FAIL_COND(!type);
860 
861 	ClassInfo *check = type;
862 
863 	while (check) {
864 
865 		const StringName *S = NULL;
866 		while ((S = check->signal_map.next(S))) {
867 
868 			p_signals->push_back(check->signal_map[*S]);
869 		}
870 
871 		if (p_no_inheritance)
872 			return;
873 
874 		check = check->inherits_ptr;
875 	}
876 }
877 
has_signal(StringName p_class,StringName p_signal)878 bool ClassDB::has_signal(StringName p_class, StringName p_signal) {
879 
880 	OBJTYPE_RLOCK;
881 	ClassInfo *type = classes.getptr(p_class);
882 	ClassInfo *check = type;
883 	while (check) {
884 		if (check->signal_map.has(p_signal))
885 			return true;
886 		check = check->inherits_ptr;
887 	}
888 
889 	return false;
890 }
891 
get_signal(StringName p_class,StringName p_signal,MethodInfo * r_signal)892 bool ClassDB::get_signal(StringName p_class, StringName p_signal, MethodInfo *r_signal) {
893 
894 	OBJTYPE_RLOCK;
895 	ClassInfo *type = classes.getptr(p_class);
896 	ClassInfo *check = type;
897 	while (check) {
898 		if (check->signal_map.has(p_signal)) {
899 			if (r_signal) {
900 				*r_signal = check->signal_map[p_signal];
901 			}
902 			return true;
903 		}
904 		check = check->inherits_ptr;
905 	}
906 
907 	return false;
908 }
909 
add_property_group(StringName p_class,const String & p_name,const String & p_prefix)910 void ClassDB::add_property_group(StringName p_class, const String &p_name, const String &p_prefix) {
911 
912 	OBJTYPE_WLOCK;
913 	ClassInfo *type = classes.getptr(p_class);
914 	ERR_FAIL_COND(!type);
915 
916 	type->property_list.push_back(PropertyInfo(Variant::NIL, p_name, PROPERTY_HINT_NONE, p_prefix, PROPERTY_USAGE_GROUP));
917 }
918 
add_property(StringName p_class,const PropertyInfo & p_pinfo,const StringName & p_setter,const StringName & p_getter,int p_index)919 void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index) {
920 
921 	lock->read_lock();
922 	ClassInfo *type = classes.getptr(p_class);
923 	lock->read_unlock();
924 
925 	ERR_FAIL_COND(!type);
926 
927 	MethodBind *mb_set = NULL;
928 	if (p_setter) {
929 		mb_set = get_method(p_class, p_setter);
930 #ifdef DEBUG_METHODS_ENABLED
931 
932 		ERR_FAIL_COND_MSG(!mb_set, "Invalid setter '" + p_class + "::" + p_setter + "' for property '" + p_pinfo.name + "'.");
933 
934 		int exp_args = 1 + (p_index >= 0 ? 1 : 0);
935 		ERR_FAIL_COND_MSG(mb_set->get_argument_count() != exp_args, "Invalid function for setter '" + p_class + "::" + p_setter + " for property '" + p_pinfo.name + "'.");
936 #endif
937 	}
938 
939 	MethodBind *mb_get = NULL;
940 	if (p_getter) {
941 
942 		mb_get = get_method(p_class, p_getter);
943 #ifdef DEBUG_METHODS_ENABLED
944 
945 		ERR_FAIL_COND_MSG(!mb_get, "Invalid getter '" + p_class + "::" + p_getter + "' for property '" + p_pinfo.name + "'.");
946 
947 		int exp_args = 0 + (p_index >= 0 ? 1 : 0);
948 		ERR_FAIL_COND_MSG(mb_get->get_argument_count() != exp_args, "Invalid function for getter '" + p_class + "::" + p_getter + "' for property: '" + p_pinfo.name + "'.");
949 #endif
950 	}
951 
952 #ifdef DEBUG_METHODS_ENABLED
953 	ERR_FAIL_COND_MSG(type->property_setget.has(p_pinfo.name), "Object '" + p_class + "' already has property '" + p_pinfo.name + "'.");
954 #endif
955 
956 	OBJTYPE_WLOCK
957 
958 	type->property_list.push_back(p_pinfo);
959 #ifdef DEBUG_METHODS_ENABLED
960 	if (mb_get) {
961 		type->methods_in_properties.insert(p_getter);
962 	}
963 	if (mb_set) {
964 		type->methods_in_properties.insert(p_setter);
965 	}
966 #endif
967 	PropertySetGet psg;
968 	psg.setter = p_setter;
969 	psg.getter = p_getter;
970 	psg._setptr = mb_set;
971 	psg._getptr = mb_get;
972 	psg.index = p_index;
973 	psg.type = p_pinfo.type;
974 
975 	type->property_setget[p_pinfo.name] = psg;
976 }
977 
set_property_default_value(StringName p_class,const StringName & p_name,const Variant & p_default)978 void ClassDB::set_property_default_value(StringName p_class, const StringName &p_name, const Variant &p_default) {
979 	if (!default_values.has(p_class)) {
980 		default_values[p_class] = HashMap<StringName, Variant>();
981 	}
982 	default_values[p_class][p_name] = p_default;
983 }
984 
get_property_list(StringName p_class,List<PropertyInfo> * p_list,bool p_no_inheritance,const Object * p_validator)985 void ClassDB::get_property_list(StringName p_class, List<PropertyInfo> *p_list, bool p_no_inheritance, const Object *p_validator) {
986 
987 	OBJTYPE_RLOCK;
988 
989 	ClassInfo *type = classes.getptr(p_class);
990 	ClassInfo *check = type;
991 	while (check) {
992 
993 		for (List<PropertyInfo>::Element *E = check->property_list.front(); E; E = E->next()) {
994 
995 			if (p_validator) {
996 				PropertyInfo pi = E->get();
997 				p_validator->_validate_property(pi);
998 				p_list->push_back(pi);
999 			} else {
1000 				p_list->push_back(E->get());
1001 			}
1002 		}
1003 
1004 		if (p_no_inheritance)
1005 			return;
1006 		check = check->inherits_ptr;
1007 	}
1008 }
set_property(Object * p_object,const StringName & p_property,const Variant & p_value,bool * r_valid)1009 bool ClassDB::set_property(Object *p_object, const StringName &p_property, const Variant &p_value, bool *r_valid) {
1010 
1011 	ClassInfo *type = classes.getptr(p_object->get_class_name());
1012 	ClassInfo *check = type;
1013 	while (check) {
1014 		const PropertySetGet *psg = check->property_setget.getptr(p_property);
1015 		if (psg) {
1016 
1017 			if (!psg->setter) {
1018 				if (r_valid)
1019 					*r_valid = false;
1020 				return true; //return true but do nothing
1021 			}
1022 
1023 			Variant::CallError ce;
1024 
1025 			if (psg->index >= 0) {
1026 				Variant index = psg->index;
1027 				const Variant *arg[2] = { &index, &p_value };
1028 				//p_object->call(psg->setter,arg,2,ce);
1029 				if (psg->_setptr) {
1030 					psg->_setptr->call(p_object, arg, 2, ce);
1031 				} else {
1032 					p_object->call(psg->setter, arg, 2, ce);
1033 				}
1034 
1035 			} else {
1036 				const Variant *arg[1] = { &p_value };
1037 				if (psg->_setptr) {
1038 					psg->_setptr->call(p_object, arg, 1, ce);
1039 				} else {
1040 					p_object->call(psg->setter, arg, 1, ce);
1041 				}
1042 			}
1043 
1044 			if (r_valid)
1045 				*r_valid = ce.error == Variant::CallError::CALL_OK;
1046 
1047 			return true;
1048 		}
1049 
1050 		check = check->inherits_ptr;
1051 	}
1052 
1053 	return false;
1054 }
get_property(Object * p_object,const StringName & p_property,Variant & r_value)1055 bool ClassDB::get_property(Object *p_object, const StringName &p_property, Variant &r_value) {
1056 
1057 	ClassInfo *type = classes.getptr(p_object->get_class_name());
1058 	ClassInfo *check = type;
1059 	while (check) {
1060 		const PropertySetGet *psg = check->property_setget.getptr(p_property);
1061 		if (psg) {
1062 			if (!psg->getter)
1063 				return true; //return true but do nothing
1064 
1065 			if (psg->index >= 0) {
1066 				Variant index = psg->index;
1067 				const Variant *arg[1] = { &index };
1068 				Variant::CallError ce;
1069 				r_value = p_object->call(psg->getter, arg, 1, ce);
1070 
1071 			} else {
1072 
1073 				Variant::CallError ce;
1074 				if (psg->_getptr) {
1075 
1076 					r_value = psg->_getptr->call(p_object, NULL, 0, ce);
1077 				} else {
1078 					r_value = p_object->call(psg->getter, NULL, 0, ce);
1079 				}
1080 			}
1081 			return true;
1082 		}
1083 
1084 		const int *c = check->constant_map.getptr(p_property);
1085 		if (c) {
1086 
1087 			r_value = *c;
1088 			return true;
1089 		}
1090 
1091 		check = check->inherits_ptr;
1092 	}
1093 
1094 	return false;
1095 }
1096 
get_property_index(const StringName & p_class,const StringName & p_property,bool * r_is_valid)1097 int ClassDB::get_property_index(const StringName &p_class, const StringName &p_property, bool *r_is_valid) {
1098 
1099 	ClassInfo *type = classes.getptr(p_class);
1100 	ClassInfo *check = type;
1101 	while (check) {
1102 		const PropertySetGet *psg = check->property_setget.getptr(p_property);
1103 		if (psg) {
1104 
1105 			if (r_is_valid)
1106 				*r_is_valid = true;
1107 
1108 			return psg->index;
1109 		}
1110 
1111 		check = check->inherits_ptr;
1112 	}
1113 	if (r_is_valid)
1114 		*r_is_valid = false;
1115 
1116 	return -1;
1117 }
1118 
get_property_type(const StringName & p_class,const StringName & p_property,bool * r_is_valid)1119 Variant::Type ClassDB::get_property_type(const StringName &p_class, const StringName &p_property, bool *r_is_valid) {
1120 
1121 	ClassInfo *type = classes.getptr(p_class);
1122 	ClassInfo *check = type;
1123 	while (check) {
1124 		const PropertySetGet *psg = check->property_setget.getptr(p_property);
1125 		if (psg) {
1126 
1127 			if (r_is_valid)
1128 				*r_is_valid = true;
1129 
1130 			return psg->type;
1131 		}
1132 
1133 		check = check->inherits_ptr;
1134 	}
1135 	if (r_is_valid)
1136 		*r_is_valid = false;
1137 
1138 	return Variant::NIL;
1139 }
1140 
get_property_setter(StringName p_class,const StringName & p_property)1141 StringName ClassDB::get_property_setter(StringName p_class, const StringName &p_property) {
1142 
1143 	ClassInfo *type = classes.getptr(p_class);
1144 	ClassInfo *check = type;
1145 	while (check) {
1146 		const PropertySetGet *psg = check->property_setget.getptr(p_property);
1147 		if (psg) {
1148 
1149 			return psg->setter;
1150 		}
1151 
1152 		check = check->inherits_ptr;
1153 	}
1154 
1155 	return StringName();
1156 }
1157 
get_property_getter(StringName p_class,const StringName & p_property)1158 StringName ClassDB::get_property_getter(StringName p_class, const StringName &p_property) {
1159 
1160 	ClassInfo *type = classes.getptr(p_class);
1161 	ClassInfo *check = type;
1162 	while (check) {
1163 		const PropertySetGet *psg = check->property_setget.getptr(p_property);
1164 		if (psg) {
1165 
1166 			return psg->getter;
1167 		}
1168 
1169 		check = check->inherits_ptr;
1170 	}
1171 
1172 	return StringName();
1173 }
1174 
has_property(const StringName & p_class,const StringName & p_property,bool p_no_inheritance)1175 bool ClassDB::has_property(const StringName &p_class, const StringName &p_property, bool p_no_inheritance) {
1176 
1177 	ClassInfo *type = classes.getptr(p_class);
1178 	ClassInfo *check = type;
1179 	while (check) {
1180 		if (check->property_setget.has(p_property))
1181 			return true;
1182 
1183 		if (p_no_inheritance)
1184 			break;
1185 		check = check->inherits_ptr;
1186 	}
1187 
1188 	return false;
1189 }
1190 
set_method_flags(StringName p_class,StringName p_method,int p_flags)1191 void ClassDB::set_method_flags(StringName p_class, StringName p_method, int p_flags) {
1192 
1193 	OBJTYPE_WLOCK;
1194 	ClassInfo *type = classes.getptr(p_class);
1195 	ClassInfo *check = type;
1196 	ERR_FAIL_COND(!check);
1197 	ERR_FAIL_COND(!check->method_map.has(p_method));
1198 	check->method_map[p_method]->set_hint_flags(p_flags);
1199 }
1200 
has_method(StringName p_class,StringName p_method,bool p_no_inheritance)1201 bool ClassDB::has_method(StringName p_class, StringName p_method, bool p_no_inheritance) {
1202 
1203 	ClassInfo *type = classes.getptr(p_class);
1204 	ClassInfo *check = type;
1205 	while (check) {
1206 		if (check->method_map.has(p_method))
1207 			return true;
1208 		if (p_no_inheritance)
1209 			return false;
1210 		check = check->inherits_ptr;
1211 	}
1212 
1213 	return false;
1214 }
1215 
1216 #ifdef DEBUG_METHODS_ENABLED
bind_methodfi(uint32_t p_flags,MethodBind * p_bind,const MethodDefinition & method_name,const Variant ** p_defs,int p_defcount)1217 MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount) {
1218 	StringName mdname = method_name.name;
1219 #else
1220 MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const char *method_name, const Variant **p_defs, int p_defcount) {
1221 	StringName mdname = StaticCString::create(method_name);
1222 #endif
1223 
1224 	OBJTYPE_WLOCK;
1225 	ERR_FAIL_COND_V(!p_bind, NULL);
1226 	p_bind->set_name(mdname);
1227 
1228 	String instance_type = p_bind->get_instance_class();
1229 
1230 #ifdef DEBUG_ENABLED
1231 
1232 	ERR_FAIL_COND_V_MSG(has_method(instance_type, mdname), NULL, "Class " + String(instance_type) + " already has a method " + String(mdname) + ".");
1233 #endif
1234 
1235 	ClassInfo *type = classes.getptr(instance_type);
1236 	if (!type) {
1237 		memdelete(p_bind);
1238 		ERR_FAIL_V_MSG(NULL, "Couldn't bind method '" + mdname + "' for instance '" + instance_type + "'.");
1239 	}
1240 
1241 	if (type->method_map.has(mdname)) {
1242 		memdelete(p_bind);
1243 		// overloading not supported
1244 		ERR_FAIL_V_MSG(NULL, "Method already bound '" + instance_type + "::" + mdname + "'.");
1245 	}
1246 
1247 #ifdef DEBUG_METHODS_ENABLED
1248 
1249 	if (method_name.args.size() > p_bind->get_argument_count()) {
1250 		memdelete(p_bind);
1251 		ERR_FAIL_V_MSG(NULL, "Method definition provides more arguments than the method actually has '" + instance_type + "::" + mdname + "'.");
1252 	}
1253 
1254 	p_bind->set_argument_names(method_name.args);
1255 
1256 	type->method_order.push_back(mdname);
1257 #endif
1258 
1259 	type->method_map[mdname] = p_bind;
1260 
1261 	Vector<Variant> defvals;
1262 
1263 	defvals.resize(p_defcount);
1264 	for (int i = 0; i < p_defcount; i++) {
1265 
1266 		defvals.write[i] = *p_defs[p_defcount - i - 1];
1267 	}
1268 
1269 	p_bind->set_default_arguments(defvals);
1270 	p_bind->set_hint_flags(p_flags);
1271 	return p_bind;
1272 }
1273 
1274 void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_method, bool p_virtual) {
1275 	ERR_FAIL_COND_MSG(!classes.has(p_class), "Request for nonexistent class '" + p_class + "'.");
1276 
1277 	OBJTYPE_WLOCK;
1278 
1279 #ifdef DEBUG_METHODS_ENABLED
1280 	MethodInfo mi = p_method;
1281 	if (p_virtual)
1282 		mi.flags |= METHOD_FLAG_VIRTUAL;
1283 	classes[p_class].virtual_methods.push_back(mi);
1284 
1285 #endif
1286 }
1287 
1288 void ClassDB::get_virtual_methods(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance) {
1289 
1290 	ERR_FAIL_COND_MSG(!classes.has(p_class), "Request for nonexistent class '" + p_class + "'.");
1291 
1292 #ifdef DEBUG_METHODS_ENABLED
1293 
1294 	ClassInfo *type = classes.getptr(p_class);
1295 	ClassInfo *check = type;
1296 	while (check) {
1297 
1298 		for (List<MethodInfo>::Element *E = check->virtual_methods.front(); E; E = E->next()) {
1299 			p_methods->push_back(E->get());
1300 		}
1301 
1302 		if (p_no_inheritance)
1303 			return;
1304 		check = check->inherits_ptr;
1305 	}
1306 
1307 #endif
1308 }
1309 
1310 void ClassDB::set_class_enabled(StringName p_class, bool p_enable) {
1311 
1312 	OBJTYPE_WLOCK;
1313 
1314 	ERR_FAIL_COND_MSG(!classes.has(p_class), "Request for nonexistent class '" + p_class + "'.");
1315 	classes[p_class].disabled = !p_enable;
1316 }
1317 
1318 bool ClassDB::is_class_enabled(StringName p_class) {
1319 
1320 	OBJTYPE_RLOCK;
1321 
1322 	ClassInfo *ti = classes.getptr(p_class);
1323 	if (!ti || !ti->creation_func) {
1324 		if (compat_classes.has(p_class)) {
1325 			ti = classes.getptr(compat_classes[p_class]);
1326 		}
1327 	}
1328 
1329 	ERR_FAIL_COND_V_MSG(!ti, false, "Cannot get class '" + String(p_class) + "'.");
1330 	return !ti->disabled;
1331 }
1332 
1333 bool ClassDB::is_class_exposed(StringName p_class) {
1334 
1335 	OBJTYPE_RLOCK;
1336 
1337 	ClassInfo *ti = classes.getptr(p_class);
1338 	ERR_FAIL_COND_V_MSG(!ti, false, "Cannot get class '" + String(p_class) + "'.");
1339 	return ti->exposed;
1340 }
1341 
1342 StringName ClassDB::get_category(const StringName &p_node) {
1343 
1344 	ERR_FAIL_COND_V(!classes.has(p_node), StringName());
1345 #ifdef DEBUG_ENABLED
1346 	return classes[p_node].category;
1347 #else
1348 	return StringName();
1349 #endif
1350 }
1351 
1352 void ClassDB::add_resource_base_extension(const StringName &p_extension, const StringName &p_class) {
1353 
1354 	if (resource_base_extensions.has(p_extension))
1355 		return;
1356 
1357 	resource_base_extensions[p_extension] = p_class;
1358 }
1359 
1360 void ClassDB::get_resource_base_extensions(List<String> *p_extensions) {
1361 
1362 	const StringName *K = NULL;
1363 
1364 	while ((K = resource_base_extensions.next(K))) {
1365 
1366 		p_extensions->push_back(*K);
1367 	}
1368 }
1369 
1370 void ClassDB::get_extensions_for_type(const StringName &p_class, List<String> *p_extensions) {
1371 
1372 	const StringName *K = NULL;
1373 
1374 	while ((K = resource_base_extensions.next(K))) {
1375 		StringName cmp = resource_base_extensions[*K];
1376 		if (is_parent_class(p_class, cmp) || is_parent_class(cmp, p_class))
1377 			p_extensions->push_back(*K);
1378 	}
1379 }
1380 
1381 HashMap<StringName, HashMap<StringName, Variant> > ClassDB::default_values;
1382 Set<StringName> ClassDB::default_values_cached;
1383 
1384 Variant ClassDB::class_get_default_property_value(const StringName &p_class, const StringName &p_property, bool *r_valid) {
1385 
1386 	if (!default_values_cached.has(p_class)) {
1387 
1388 		if (!default_values.has(p_class)) {
1389 			default_values[p_class] = HashMap<StringName, Variant>();
1390 		}
1391 
1392 		Object *c = NULL;
1393 		bool cleanup_c = false;
1394 
1395 		if (Engine::get_singleton()->has_singleton(p_class)) {
1396 			c = Engine::get_singleton()->get_singleton_object(p_class);
1397 			cleanup_c = false;
1398 		} else if (ClassDB::can_instance(p_class)) {
1399 			c = ClassDB::instance(p_class);
1400 			cleanup_c = true;
1401 		}
1402 
1403 		if (c) {
1404 
1405 			List<PropertyInfo> plist;
1406 			c->get_property_list(&plist);
1407 			for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
1408 				if (E->get().usage & (PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR)) {
1409 
1410 					if (!default_values[p_class].has(E->get().name)) {
1411 						Variant v = c->get(E->get().name);
1412 						default_values[p_class][E->get().name] = v;
1413 					}
1414 				}
1415 			}
1416 
1417 			if (cleanup_c) {
1418 				memdelete(c);
1419 			}
1420 		}
1421 
1422 		default_values_cached.insert(p_class);
1423 	}
1424 
1425 	if (!default_values.has(p_class)) {
1426 		if (r_valid != NULL) *r_valid = false;
1427 		return Variant();
1428 	}
1429 
1430 	if (!default_values[p_class].has(p_property)) {
1431 		if (r_valid != NULL) *r_valid = false;
1432 		return Variant();
1433 	}
1434 
1435 	if (r_valid != NULL) *r_valid = true;
1436 	return default_values[p_class][p_property];
1437 }
1438 
1439 RWLock *ClassDB::lock = NULL;
1440 
1441 void ClassDB::init() {
1442 
1443 	lock = RWLock::create();
1444 }
1445 
1446 void ClassDB::cleanup_defaults() {
1447 
1448 	default_values.clear();
1449 	default_values_cached.clear();
1450 }
1451 
1452 void ClassDB::cleanup() {
1453 
1454 	//OBJTYPE_LOCK; hah not here
1455 
1456 	const StringName *k = NULL;
1457 
1458 	while ((k = classes.next(k))) {
1459 
1460 		ClassInfo &ti = classes[*k];
1461 
1462 		const StringName *m = NULL;
1463 		while ((m = ti.method_map.next(m))) {
1464 
1465 			memdelete(ti.method_map[*m]);
1466 		}
1467 	}
1468 	classes.clear();
1469 	resource_base_extensions.clear();
1470 	compat_classes.clear();
1471 
1472 	memdelete(lock);
1473 }
1474 
1475 //
1476