2014-02-10 02:10:30 +01:00
/*************************************************************************/
2017-01-16 08:04:19 +01:00
/* class_db.cpp */
2014-02-10 02:10:30 +01:00
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 14:16:55 +02:00
/* https://godotengine.org */
2014-02-10 02:10:30 +01:00
/*************************************************************************/
2021-01-01 20:13:46 +01:00
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
2014-02-10 02:10:30 +01:00
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
2018-01-05 00:50:27 +01:00
2017-01-16 08:04:19 +01:00
# include "class_db.h"
2020-11-07 23:33:38 +01:00
# include "core/config/engine.h"
2018-09-11 18:13:45 +02:00
# include "core/os/mutex.h"
# include "core/version.h"
2014-02-10 02:10:30 +01:00
2017-01-07 22:25:37 +01:00
# define OBJTYPE_RLOCK RWLockRead _rw_lockr_(lock);
# define OBJTYPE_WLOCK RWLockWrite _rw_lockw_(lock);
2014-02-10 02:10:30 +01:00
# ifdef DEBUG_METHODS_ENABLED
2017-03-05 16:44:50 +01:00
MethodDefinition D_METHOD ( const char * p_name ) {
2014-02-10 02:10:30 +01:00
MethodDefinition md ;
2017-03-05 16:44:50 +01:00
md . name = StaticCString : : create ( p_name ) ;
2014-02-10 02:10:30 +01:00
return md ;
}
2017-03-05 16:44:50 +01:00
MethodDefinition D_METHOD ( const char * p_name , const char * p_arg1 ) {
2014-02-10 02:10:30 +01:00
MethodDefinition md ;
2017-03-05 16:44:50 +01:00
md . name = StaticCString : : create ( p_name ) ;
2014-02-10 02:10:30 +01:00
md . args . push_back ( StaticCString : : create ( p_arg1 ) ) ;
return md ;
}
2017-03-05 16:44:50 +01:00
MethodDefinition D_METHOD ( const char * p_name , const char * p_arg1 , const char * p_arg2 ) {
2014-02-10 02:10:30 +01:00
MethodDefinition md ;
2017-03-05 16:44:50 +01:00
md . name = StaticCString : : create ( p_name ) ;
2014-02-10 02:10:30 +01:00
md . args . resize ( 2 ) ;
2018-07-25 03:11:03 +02:00
md . args . write [ 0 ] = StaticCString : : create ( p_arg1 ) ;
md . args . write [ 1 ] = StaticCString : : create ( p_arg2 ) ;
2014-02-10 02:10:30 +01:00
return md ;
}
2017-03-05 16:44:50 +01:00
MethodDefinition D_METHOD ( const char * p_name , const char * p_arg1 , const char * p_arg2 , const char * p_arg3 ) {
2014-02-10 02:10:30 +01:00
MethodDefinition md ;
2017-03-05 16:44:50 +01:00
md . name = StaticCString : : create ( p_name ) ;
2014-02-10 02:10:30 +01:00
md . args . resize ( 3 ) ;
2018-07-25 03:11:03 +02:00
md . args . write [ 0 ] = StaticCString : : create ( p_arg1 ) ;
md . args . write [ 1 ] = StaticCString : : create ( p_arg2 ) ;
md . args . write [ 2 ] = StaticCString : : create ( p_arg3 ) ;
2014-02-10 02:10:30 +01:00
return md ;
}
2017-03-05 16:44:50 +01:00
MethodDefinition D_METHOD ( const char * p_name , const char * p_arg1 , const char * p_arg2 , const char * p_arg3 , const char * p_arg4 ) {
2014-02-10 02:10:30 +01:00
MethodDefinition md ;
2017-03-05 16:44:50 +01:00
md . name = StaticCString : : create ( p_name ) ;
2014-02-10 02:10:30 +01:00
md . args . resize ( 4 ) ;
2018-07-25 03:11:03 +02:00
md . args . write [ 0 ] = StaticCString : : create ( p_arg1 ) ;
md . args . write [ 1 ] = StaticCString : : create ( p_arg2 ) ;
md . args . write [ 2 ] = StaticCString : : create ( p_arg3 ) ;
md . args . write [ 3 ] = StaticCString : : create ( p_arg4 ) ;
2014-02-10 02:10:30 +01:00
return md ;
}
2017-03-05 16:44:50 +01:00
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 ) {
2014-02-10 02:10:30 +01:00
MethodDefinition md ;
2017-03-05 16:44:50 +01:00
md . name = StaticCString : : create ( p_name ) ;
2014-02-10 02:10:30 +01:00
md . args . resize ( 5 ) ;
2018-07-25 03:11:03 +02:00
md . args . write [ 0 ] = StaticCString : : create ( p_arg1 ) ;
md . args . write [ 1 ] = StaticCString : : create ( p_arg2 ) ;
md . args . write [ 2 ] = StaticCString : : create ( p_arg3 ) ;
md . args . write [ 3 ] = StaticCString : : create ( p_arg4 ) ;
md . args . write [ 4 ] = StaticCString : : create ( p_arg5 ) ;
2014-02-10 02:10:30 +01:00
return md ;
}
2017-03-05 16:44:50 +01:00
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 ) {
2014-09-17 16:53:29 +02:00
MethodDefinition md ;
2017-03-05 16:44:50 +01:00
md . name = StaticCString : : create ( p_name ) ;
2014-09-17 16:53:29 +02:00
md . args . resize ( 6 ) ;
2018-07-25 03:11:03 +02:00
md . args . write [ 0 ] = StaticCString : : create ( p_arg1 ) ;
md . args . write [ 1 ] = StaticCString : : create ( p_arg2 ) ;
md . args . write [ 2 ] = StaticCString : : create ( p_arg3 ) ;
md . args . write [ 3 ] = StaticCString : : create ( p_arg4 ) ;
md . args . write [ 4 ] = StaticCString : : create ( p_arg5 ) ;
md . args . write [ 5 ] = StaticCString : : create ( p_arg6 ) ;
2014-09-17 16:53:29 +02:00
return md ;
}
2017-03-05 16:44:50 +01:00
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 ) {
2014-09-17 16:53:29 +02:00
MethodDefinition md ;
2017-03-05 16:44:50 +01:00
md . name = StaticCString : : create ( p_name ) ;
2014-09-17 17:24:38 +02:00
md . args . resize ( 7 ) ;
2018-07-25 03:11:03 +02:00
md . args . write [ 0 ] = StaticCString : : create ( p_arg1 ) ;
md . args . write [ 1 ] = StaticCString : : create ( p_arg2 ) ;
md . args . write [ 2 ] = StaticCString : : create ( p_arg3 ) ;
md . args . write [ 3 ] = StaticCString : : create ( p_arg4 ) ;
md . args . write [ 4 ] = StaticCString : : create ( p_arg5 ) ;
md . args . write [ 5 ] = StaticCString : : create ( p_arg6 ) ;
md . args . write [ 6 ] = StaticCString : : create ( p_arg7 ) ;
2014-09-17 16:53:29 +02:00
return md ;
}
2017-03-05 16:44:50 +01:00
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 ) {
2014-09-17 16:53:29 +02:00
MethodDefinition md ;
2017-03-05 16:44:50 +01:00
md . name = StaticCString : : create ( p_name ) ;
2014-09-17 17:21:50 +02:00
md . args . resize ( 8 ) ;
2018-07-25 03:11:03 +02:00
md . args . write [ 0 ] = StaticCString : : create ( p_arg1 ) ;
md . args . write [ 1 ] = StaticCString : : create ( p_arg2 ) ;
md . args . write [ 2 ] = StaticCString : : create ( p_arg3 ) ;
md . args . write [ 3 ] = StaticCString : : create ( p_arg4 ) ;
md . args . write [ 4 ] = StaticCString : : create ( p_arg5 ) ;
md . args . write [ 5 ] = StaticCString : : create ( p_arg6 ) ;
md . args . write [ 6 ] = StaticCString : : create ( p_arg7 ) ;
md . args . write [ 7 ] = StaticCString : : create ( p_arg8 ) ;
2014-09-17 16:53:29 +02:00
return md ;
}
2017-03-05 16:44:50 +01:00
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 ) {
2014-09-17 16:53:29 +02:00
MethodDefinition md ;
2017-03-05 16:44:50 +01:00
md . name = StaticCString : : create ( p_name ) ;
2014-09-17 17:21:50 +02:00
md . args . resize ( 9 ) ;
2018-07-25 03:11:03 +02:00
md . args . write [ 0 ] = StaticCString : : create ( p_arg1 ) ;
md . args . write [ 1 ] = StaticCString : : create ( p_arg2 ) ;
md . args . write [ 2 ] = StaticCString : : create ( p_arg3 ) ;
md . args . write [ 3 ] = StaticCString : : create ( p_arg4 ) ;
md . args . write [ 4 ] = StaticCString : : create ( p_arg5 ) ;
md . args . write [ 5 ] = StaticCString : : create ( p_arg6 ) ;
md . args . write [ 6 ] = StaticCString : : create ( p_arg7 ) ;
md . args . write [ 7 ] = StaticCString : : create ( p_arg8 ) ;
md . args . write [ 8 ] = StaticCString : : create ( p_arg9 ) ;
2014-09-17 16:53:29 +02:00
return md ;
}
2017-03-05 16:44:50 +01:00
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 ) {
2014-09-17 16:53:29 +02:00
MethodDefinition md ;
2017-03-05 16:44:50 +01:00
md . name = StaticCString : : create ( p_name ) ;
2014-09-17 17:21:50 +02:00
md . args . resize ( 10 ) ;
2018-07-25 03:11:03 +02:00
md . args . write [ 0 ] = StaticCString : : create ( p_arg1 ) ;
md . args . write [ 1 ] = StaticCString : : create ( p_arg2 ) ;
md . args . write [ 2 ] = StaticCString : : create ( p_arg3 ) ;
md . args . write [ 3 ] = StaticCString : : create ( p_arg4 ) ;
md . args . write [ 4 ] = StaticCString : : create ( p_arg5 ) ;
md . args . write [ 5 ] = StaticCString : : create ( p_arg6 ) ;
md . args . write [ 6 ] = StaticCString : : create ( p_arg7 ) ;
md . args . write [ 7 ] = StaticCString : : create ( p_arg8 ) ;
md . args . write [ 8 ] = StaticCString : : create ( p_arg9 ) ;
md . args . write [ 9 ] = StaticCString : : create ( p_arg10 ) ;
2014-09-17 16:53:29 +02:00
return md ;
}
2017-10-20 00:24:49 +02:00
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 ) {
MethodDefinition md ;
md . name = StaticCString : : create ( p_name ) ;
md . args . resize ( 11 ) ;
2018-07-25 03:11:03 +02:00
md . args . write [ 0 ] = StaticCString : : create ( p_arg1 ) ;
md . args . write [ 1 ] = StaticCString : : create ( p_arg2 ) ;
md . args . write [ 2 ] = StaticCString : : create ( p_arg3 ) ;
md . args . write [ 3 ] = StaticCString : : create ( p_arg4 ) ;
md . args . write [ 4 ] = StaticCString : : create ( p_arg5 ) ;
md . args . write [ 5 ] = StaticCString : : create ( p_arg6 ) ;
md . args . write [ 6 ] = StaticCString : : create ( p_arg7 ) ;
md . args . write [ 7 ] = StaticCString : : create ( p_arg8 ) ;
md . args . write [ 8 ] = StaticCString : : create ( p_arg9 ) ;
md . args . write [ 9 ] = StaticCString : : create ( p_arg10 ) ;
md . args . write [ 10 ] = StaticCString : : create ( p_arg11 ) ;
2017-10-20 00:24:49 +02:00
return md ;
}
Added all missing VisualServer bindings
- Added bindings for multimesh, immediate, skeleton, light, reflection probe, gi probe, lightmap, particles, camera, environment, scenario, instance
- Removed draw and sync, were duplicates of force_* equivalents
- Bumped binders max arguments from 11 to 13
- Wrote some wrappers as not all methods were variant-friendly
2018-01-20 16:18:51 +01:00
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 ) {
MethodDefinition md ;
md . name = StaticCString : : create ( p_name ) ;
md . args . resize ( 12 ) ;
2018-07-25 03:11:03 +02:00
md . args . write [ 0 ] = StaticCString : : create ( p_arg1 ) ;
md . args . write [ 1 ] = StaticCString : : create ( p_arg2 ) ;
md . args . write [ 2 ] = StaticCString : : create ( p_arg3 ) ;
md . args . write [ 3 ] = StaticCString : : create ( p_arg4 ) ;
md . args . write [ 4 ] = StaticCString : : create ( p_arg5 ) ;
md . args . write [ 5 ] = StaticCString : : create ( p_arg6 ) ;
md . args . write [ 6 ] = StaticCString : : create ( p_arg7 ) ;
md . args . write [ 7 ] = StaticCString : : create ( p_arg8 ) ;
md . args . write [ 8 ] = StaticCString : : create ( p_arg9 ) ;
md . args . write [ 9 ] = StaticCString : : create ( p_arg10 ) ;
md . args . write [ 10 ] = StaticCString : : create ( p_arg11 ) ;
md . args . write [ 11 ] = StaticCString : : create ( p_arg12 ) ;
Added all missing VisualServer bindings
- Added bindings for multimesh, immediate, skeleton, light, reflection probe, gi probe, lightmap, particles, camera, environment, scenario, instance
- Removed draw and sync, were duplicates of force_* equivalents
- Bumped binders max arguments from 11 to 13
- Wrote some wrappers as not all methods were variant-friendly
2018-01-20 16:18:51 +01:00
return md ;
}
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 ) {
MethodDefinition md ;
md . name = StaticCString : : create ( p_name ) ;
md . args . resize ( 13 ) ;
2018-07-25 03:11:03 +02:00
md . args . write [ 0 ] = StaticCString : : create ( p_arg1 ) ;
md . args . write [ 1 ] = StaticCString : : create ( p_arg2 ) ;
md . args . write [ 2 ] = StaticCString : : create ( p_arg3 ) ;
md . args . write [ 3 ] = StaticCString : : create ( p_arg4 ) ;
md . args . write [ 4 ] = StaticCString : : create ( p_arg5 ) ;
md . args . write [ 5 ] = StaticCString : : create ( p_arg6 ) ;
md . args . write [ 6 ] = StaticCString : : create ( p_arg7 ) ;
md . args . write [ 7 ] = StaticCString : : create ( p_arg8 ) ;
md . args . write [ 8 ] = StaticCString : : create ( p_arg9 ) ;
md . args . write [ 9 ] = StaticCString : : create ( p_arg10 ) ;
md . args . write [ 10 ] = StaticCString : : create ( p_arg11 ) ;
md . args . write [ 11 ] = StaticCString : : create ( p_arg12 ) ;
md . args . write [ 12 ] = StaticCString : : create ( p_arg13 ) ;
Added all missing VisualServer bindings
- Added bindings for multimesh, immediate, skeleton, light, reflection probe, gi probe, lightmap, particles, camera, environment, scenario, instance
- Removed draw and sync, were duplicates of force_* equivalents
- Bumped binders max arguments from 11 to 13
- Wrote some wrappers as not all methods were variant-friendly
2018-01-20 16:18:51 +01:00
return md ;
}
2014-02-10 02:10:30 +01:00
# endif
2017-03-05 16:44:50 +01:00
ClassDB : : APIType ClassDB : : current_api = API_CORE ;
2016-09-15 00:37:37 +02:00
2017-01-03 03:03:46 +01:00
void ClassDB : : set_current_api ( APIType p_api ) {
2017-03-05 16:44:50 +01:00
current_api = p_api ;
2016-09-15 00:37:37 +02:00
}
2019-04-06 16:12:59 +02:00
ClassDB : : APIType ClassDB : : get_current_api ( ) {
return current_api ;
}
2018-07-02 20:08:35 +02:00
HashMap < StringName , ClassDB : : ClassInfo > ClassDB : : classes ;
HashMap < StringName , StringName > ClassDB : : resource_base_extensions ;
HashMap < StringName , StringName > ClassDB : : compat_classes ;
2014-02-10 02:10:30 +01:00
2020-11-01 08:44:15 +01:00
bool ClassDB : : _is_parent_class ( const StringName & p_class , const StringName & p_inherits ) {
2020-11-27 21:55:24 +01:00
if ( ! classes . has ( p_class ) ) {
return false ;
}
2016-03-09 00:00:52 +01:00
2020-11-27 21:55:24 +01:00
StringName inherits = p_class ;
2014-02-10 02:10:30 +01:00
while ( inherits . operator String ( ) . length ( ) ) {
2020-05-14 16:41:43 +02:00
if ( inherits = = p_inherits ) {
2014-02-10 02:10:30 +01:00
return true ;
2020-05-14 16:41:43 +02:00
}
2020-11-01 08:44:15 +01:00
inherits = _get_parent_class ( inherits ) ;
2014-02-10 02:10:30 +01:00
}
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
return false ;
}
2020-05-14 14:29:06 +02:00
2020-11-01 08:44:15 +01:00
bool ClassDB : : is_parent_class ( const StringName & p_class , const StringName & p_inherits ) {
OBJTYPE_RLOCK ;
return _is_parent_class ( p_class , p_inherits ) ;
}
2017-03-05 16:44:50 +01:00
void ClassDB : : get_class_list ( List < StringName > * p_classes ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_RLOCK ;
2016-03-09 00:00:52 +01:00
2020-04-02 01:20:12 +02:00
const StringName * k = nullptr ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
while ( ( k = classes . next ( k ) ) ) {
2017-01-03 03:03:46 +01:00
p_classes - > push_back ( * k ) ;
2014-02-10 02:10:30 +01:00
}
2016-03-09 00:00:52 +01:00
2017-01-03 03:03:46 +01:00
p_classes - > sort ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void ClassDB : : get_inheriters_from_class ( const StringName & p_class , List < StringName > * p_classes ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_RLOCK ;
2016-03-09 00:00:52 +01:00
2020-04-02 01:20:12 +02:00
const StringName * k = nullptr ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
while ( ( k = classes . next ( k ) ) ) {
2020-11-01 08:44:15 +01:00
if ( * k ! = p_class & & _is_parent_class ( * k , p_class ) ) {
2017-01-03 03:03:46 +01:00
p_classes - > push_back ( * k ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
}
2019-04-09 00:18:03 +02:00
void ClassDB : : get_direct_inheriters_from_class ( const StringName & p_class , List < StringName > * p_classes ) {
OBJTYPE_RLOCK ;
2020-04-02 01:20:12 +02:00
const StringName * k = nullptr ;
2019-04-09 00:18:03 +02:00
while ( ( k = classes . next ( k ) ) ) {
2020-11-01 08:44:15 +01:00
if ( * k ! = p_class & & _get_parent_class ( * k ) = = p_class ) {
2019-04-09 00:18:03 +02:00
p_classes - > push_back ( * k ) ;
2020-05-14 16:41:43 +02:00
}
2019-04-09 00:18:03 +02:00
}
}
2017-03-05 16:44:50 +01:00
StringName ClassDB : : get_parent_class_nocheck ( const StringName & p_class ) {
2017-01-11 22:29:59 +01:00
OBJTYPE_RLOCK ;
ClassInfo * ti = classes . getptr ( p_class ) ;
2020-05-14 16:41:43 +02:00
if ( ! ti ) {
2017-01-11 22:29:59 +01:00
return StringName ( ) ;
2020-05-14 16:41:43 +02:00
}
2017-01-11 22:29:59 +01:00
return ti - > inherits ;
}
2019-10-03 22:39:08 +02:00
StringName ClassDB : : get_compatibility_remapped_class ( const StringName & p_class ) {
if ( classes . has ( p_class ) ) {
return p_class ;
}
if ( compat_classes . has ( p_class ) ) {
return compat_classes [ p_class ] ;
}
return p_class ;
}
2020-11-01 08:44:15 +01:00
StringName ClassDB : : _get_parent_class ( const StringName & p_class ) {
2017-01-03 03:03:46 +01:00
ClassInfo * ti = classes . getptr ( p_class ) ;
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_V_MSG ( ! ti , StringName ( ) , " Cannot get class ' " + String ( p_class ) + " '. " ) ;
2014-02-10 02:10:30 +01:00
return ti - > inherits ;
}
2020-11-01 08:44:15 +01:00
StringName ClassDB : : get_parent_class ( const StringName & p_class ) {
OBJTYPE_RLOCK ;
return _get_parent_class ( p_class ) ;
}
2017-01-03 03:03:46 +01:00
ClassDB : : APIType ClassDB : : get_api_type ( const StringName & p_class ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_RLOCK ;
2016-09-15 00:37:37 +02:00
2017-01-03 03:03:46 +01:00
ClassInfo * ti = classes . getptr ( p_class ) ;
2017-01-11 22:29:59 +01:00
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_V_MSG ( ! ti , API_NONE , " Cannot get class ' " + String ( p_class ) + " '. " ) ;
2016-09-15 00:37:37 +02:00
return ti - > api ;
}
2017-01-03 03:03:46 +01:00
uint64_t ClassDB : : get_api_hash ( APIType p_api ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_RLOCK ;
2016-09-15 00:37:37 +02:00
# ifdef DEBUG_METHODS_ENABLED
Refactor version macros and fix related bugs
The previous logic with VERSION_MKSTRING was a bit unwieldy, so there were
several places hardcoding their own variant of the version string, potentially
with bugs (e.g. forgetting the patch number when defined).
The new logic defines:
- VERSION_BRANCH, the main 'major.minor' version (e.g. 3.1)
- VERSION_NUMBER, which can be 'major.minor' or 'major.minor.patch',
depending on whether the latter is defined (e.g. 3.1.4)
- VERSION_FULL_CONFIG, which contains the version status (e.g. stable)
and the module-specific suffix (e.g. mono)
- VERSION_FULL_BUILD, same as above but with build/reference name
(e.g. official, custom_build, mageia, etc.)
Note: Slight change here, as the previous format had the build name
*before* the module-specific suffix; now it's after
- VERSION_FULL_NAME, same as before, so VERSION_FULL_BUILD prefixed
with "Godot v" for readability
Bugs fixed thanks to that:
- Export templates version matching now properly takes VERSION_PATCH
into account by relying on VERSION_FULL_CONFIG.
- ClassDB hash no longer takes the build name into account, but limits
itself to VERSION_FULL_CONFIG (build name is cosmetic, not relevant
for the API hash).
- Docs XML no longer hardcode the VERSION_STATUS, this was annoying.
- Small cleanup in Windows .rc file thanks to new macros.
2018-02-23 19:48:49 +01:00
uint64_t hash = hash_djb2_one_64 ( HashMapHasherDefault : : hash ( VERSION_FULL_CONFIG ) ) ;
2016-09-15 00:37:37 +02:00
List < StringName > names ;
2020-04-02 01:20:12 +02:00
const StringName * k = nullptr ;
2016-09-15 00:37:37 +02:00
2017-03-05 16:44:50 +01:00
while ( ( k = classes . next ( k ) ) ) {
2016-09-15 00:37:37 +02:00
names . push_back ( * k ) ;
}
//must be alphabetically sorted for hash to compute
names . sort_custom < StringName : : AlphCompare > ( ) ;
2017-03-05 16:44:50 +01:00
for ( List < StringName > : : Element * E = names . front ( ) ; E ; E = E - > next ( ) ) {
2017-01-03 03:03:46 +01:00
ClassInfo * t = classes . getptr ( E - > get ( ) ) ;
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_V_MSG ( ! t , 0 , " Cannot get class ' " + String ( E - > get ( ) ) + " '. " ) ;
2020-05-14 16:41:43 +02:00
if ( t - > api ! = p_api | | ! t - > exposed ) {
2016-09-15 00:37:37 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
hash = hash_djb2_one_64 ( t - > name . hash ( ) , hash ) ;
hash = hash_djb2_one_64 ( t - > inherits . hash ( ) , hash ) ;
2016-09-15 00:37:37 +02:00
{ //methods
List < StringName > snames ;
2020-04-02 01:20:12 +02:00
k = nullptr ;
2016-09-15 00:37:37 +02:00
2017-03-05 16:44:50 +01:00
while ( ( k = t - > method_map . next ( k ) ) ) {
2020-01-07 00:08:46 +01:00
String name = k - > operator String ( ) ;
2020-12-15 13:04:21 +01:00
ERR_CONTINUE ( name . is_empty ( ) ) ;
2020-01-07 00:08:46 +01:00
2020-05-14 16:41:43 +02:00
if ( name [ 0 ] = = ' _ ' ) {
2020-01-07 00:08:46 +01:00
continue ; // Ignore non-virtual methods that start with an underscore
2020-05-14 16:41:43 +02:00
}
2020-01-07 00:08:46 +01:00
2016-09-15 00:37:37 +02:00
snames . push_back ( * k ) ;
}
snames . sort_custom < StringName : : AlphCompare > ( ) ;
2017-03-05 16:44:50 +01:00
for ( List < StringName > : : Element * F = snames . front ( ) ; F ; F = F - > next ( ) ) {
2016-09-15 00:37:37 +02:00
MethodBind * mb = t - > method_map [ F - > get ( ) ] ;
2017-03-05 16:44:50 +01:00
hash = hash_djb2_one_64 ( mb - > get_name ( ) . hash ( ) , hash ) ;
hash = hash_djb2_one_64 ( mb - > get_argument_count ( ) , hash ) ;
hash = hash_djb2_one_64 ( mb - > get_argument_type ( - 1 ) , hash ) ; //return
for ( int i = 0 ; i < mb - > get_argument_count ( ) ; i + + ) {
2017-12-16 15:47:36 +01:00
const PropertyInfo info = mb - > get_argument_info ( i ) ;
hash = hash_djb2_one_64 ( info . type , hash ) ;
hash = hash_djb2_one_64 ( info . name . hash ( ) , hash ) ;
hash = hash_djb2_one_64 ( info . hint , hash ) ;
hash = hash_djb2_one_64 ( info . hint_string . hash ( ) , hash ) ;
2016-09-15 00:37:37 +02:00
}
2017-03-05 16:44:50 +01:00
hash = hash_djb2_one_64 ( mb - > get_default_argument_count ( ) , hash ) ;
2016-09-15 00:37:37 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < mb - > get_default_argument_count ( ) ; i + + ) {
2016-09-15 00:37:37 +02:00
//hash should not change, i hope for tis
Variant da = mb - > get_default_argument ( i ) ;
2017-03-05 16:44:50 +01:00
hash = hash_djb2_one_64 ( da . hash ( ) , hash ) ;
2016-09-15 00:37:37 +02:00
}
2017-03-05 16:44:50 +01:00
hash = hash_djb2_one_64 ( mb - > get_hint_flags ( ) , hash ) ;
2016-09-15 00:37:37 +02:00
}
}
{ //constants
List < StringName > snames ;
2020-04-02 01:20:12 +02:00
k = nullptr ;
2016-09-15 00:37:37 +02:00
2017-03-05 16:44:50 +01:00
while ( ( k = t - > constant_map . next ( k ) ) ) {
2016-09-15 00:37:37 +02:00
snames . push_back ( * k ) ;
}
snames . sort_custom < StringName : : AlphCompare > ( ) ;
2017-03-05 16:44:50 +01:00
for ( List < StringName > : : Element * F = snames . front ( ) ; F ; F = F - > next ( ) ) {
2016-09-15 00:37:37 +02:00
hash = hash_djb2_one_64 ( F - > get ( ) . hash ( ) , hash ) ;
2017-03-05 16:44:50 +01:00
hash = hash_djb2_one_64 ( t - > constant_map [ F - > get ( ) ] , hash ) ;
2016-09-15 00:37:37 +02:00
}
}
{ //signals
List < StringName > snames ;
2020-04-02 01:20:12 +02:00
k = nullptr ;
2016-09-15 00:37:37 +02:00
2017-03-05 16:44:50 +01:00
while ( ( k = t - > signal_map . next ( k ) ) ) {
2016-09-15 00:37:37 +02:00
snames . push_back ( * k ) ;
}
snames . sort_custom < StringName : : AlphCompare > ( ) ;
2017-03-05 16:44:50 +01:00
for ( List < StringName > : : Element * F = snames . front ( ) ; F ; F = F - > next ( ) ) {
2016-09-15 00:37:37 +02:00
MethodInfo & mi = t - > signal_map [ F - > get ( ) ] ;
2017-03-05 16:44:50 +01:00
hash = hash_djb2_one_64 ( F - > get ( ) . hash ( ) , hash ) ;
for ( int i = 0 ; i < mi . arguments . size ( ) ; i + + ) {
hash = hash_djb2_one_64 ( mi . arguments [ i ] . type , hash ) ;
2016-09-15 00:37:37 +02:00
}
}
}
{ //properties
List < StringName > snames ;
2020-04-02 01:20:12 +02:00
k = nullptr ;
2016-09-15 00:37:37 +02:00
2017-03-05 16:44:50 +01:00
while ( ( k = t - > property_setget . next ( k ) ) ) {
2016-09-15 00:37:37 +02:00
snames . push_back ( * k ) ;
}
snames . sort_custom < StringName : : AlphCompare > ( ) ;
2017-03-05 16:44:50 +01:00
for ( List < StringName > : : Element * F = snames . front ( ) ; F ; F = F - > next ( ) ) {
PropertySetGet * psg = t - > property_setget . getptr ( F - > get ( ) ) ;
2019-07-23 09:14:31 +02:00
ERR_FAIL_COND_V ( ! psg , 0 ) ;
2016-09-15 00:37:37 +02:00
2017-03-05 16:44:50 +01:00
hash = hash_djb2_one_64 ( F - > get ( ) . hash ( ) , hash ) ;
hash = hash_djb2_one_64 ( psg - > setter . hash ( ) , hash ) ;
hash = hash_djb2_one_64 ( psg - > getter . hash ( ) , hash ) ;
2016-09-15 00:37:37 +02:00
}
}
//property list
2017-03-05 16:44:50 +01:00
for ( List < PropertyInfo > : : Element * F = t - > property_list . front ( ) ; F ; F = F - > next ( ) ) {
hash = hash_djb2_one_64 ( F - > get ( ) . name . hash ( ) , hash ) ;
hash = hash_djb2_one_64 ( F - > get ( ) . type , hash ) ;
hash = hash_djb2_one_64 ( F - > get ( ) . hint , hash ) ;
hash = hash_djb2_one_64 ( F - > get ( ) . hint_string . hash ( ) , hash ) ;
hash = hash_djb2_one_64 ( F - > get ( ) . usage , hash ) ;
2016-09-15 00:37:37 +02:00
}
}
return hash ;
# else
return 0 ;
# endif
}
2017-01-03 03:03:46 +01:00
bool ClassDB : : class_exists ( const StringName & p_class ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_RLOCK ;
2017-01-03 03:03:46 +01:00
return classes . has ( p_class ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void ClassDB : : add_compatibility_class ( const StringName & p_class , const StringName & p_fallback ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_WLOCK ;
2017-03-05 16:44:50 +01:00
compat_classes [ p_class ] = p_fallback ;
2015-01-03 20:52:37 +01:00
}
2021-06-04 19:33:48 +02:00
thread_local bool initializing_with_extension = false ;
thread_local ObjectNativeExtension * initializing_extension = nullptr ;
thread_local void * initializing_extension_instance = nullptr ;
void ClassDB : : instance_get_native_extension_data ( ObjectNativeExtension * * r_extension , void * * r_extension_instance ) {
if ( initializing_with_extension ) {
* r_extension = initializing_extension ;
* r_extension_instance = initializing_extension_instance ;
initializing_with_extension = false ;
} else {
* r_extension = nullptr ;
* r_extension_instance = nullptr ;
}
}
2017-01-03 03:03:46 +01:00
Object * ClassDB : : instance ( const StringName & p_class ) {
ClassInfo * ti ;
2014-02-10 02:10:30 +01:00
{
2017-01-07 22:25:37 +01:00
OBJTYPE_RLOCK ;
2017-03-05 16:44:50 +01:00
ti = classes . getptr ( p_class ) ;
2021-06-04 19:33:48 +02:00
if ( ! ti | | ti - > disabled | | ! ti - > creation_func | | ( ti - > native_extension & & ! ti - > native_extension - > create_instance ) ) {
2017-01-03 03:03:46 +01:00
if ( compat_classes . has ( p_class ) ) {
2017-03-05 16:44:50 +01:00
ti = classes . getptr ( compat_classes [ p_class ] ) ;
2015-01-03 20:52:37 +01:00
}
}
2020-04-02 01:20:12 +02:00
ERR_FAIL_COND_V_MSG ( ! ti , nullptr , " Cannot get class ' " + String ( p_class ) + " '. " ) ;
ERR_FAIL_COND_V_MSG ( ti - > disabled , nullptr , " Class ' " + String ( p_class ) + " ' is disabled. " ) ;
ERR_FAIL_COND_V ( ! ti - > creation_func , nullptr ) ;
2014-02-10 02:10:30 +01:00
}
2018-09-07 02:07:46 +02:00
# ifdef TOOLS_ENABLED
if ( ti - > api = = API_EDITOR & & ! Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
2019-11-06 17:03:04 +01:00
ERR_PRINT ( " Class ' " + String ( p_class ) + " ' can only be instantiated by editor. " ) ;
2020-04-02 01:20:12 +02:00
return nullptr ;
2018-09-07 02:07:46 +02:00
}
# endif
2021-06-04 19:33:48 +02:00
if ( ti - > native_extension ) {
initializing_with_extension = true ;
initializing_extension = ti - > native_extension ;
initializing_extension_instance = ti - > native_extension - > create_instance ( ti - > native_extension - > create_instance_userdata ) ;
}
2014-02-10 02:10:30 +01:00
return ti - > creation_func ( ) ;
}
2020-05-14 14:29:06 +02:00
2017-01-03 03:03:46 +01:00
bool ClassDB : : can_instance ( const StringName & p_class ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_RLOCK ;
2016-03-09 00:00:52 +01:00
2017-01-03 03:03:46 +01:00
ClassInfo * ti = classes . getptr ( p_class ) ;
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_V_MSG ( ! ti , false , " Cannot get class ' " + String ( p_class ) + " '. " ) ;
2019-06-01 15:42:22 +02:00
# ifdef TOOLS_ENABLED
if ( ti - > api = = API_EDITOR & & ! Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
return false ;
}
# endif
2021-06-04 19:33:48 +02:00
return ( ! ti - > disabled & & ti - > creation_func ! = nullptr & & ! ( ti - > native_extension & & ! ti - > native_extension - > create_instance ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void ClassDB : : _add_class2 ( const StringName & p_class , const StringName & p_inherits ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_WLOCK ;
2014-02-10 02:10:30 +01:00
2019-06-26 15:08:25 +02:00
const StringName & name = p_class ;
2014-02-10 02:10:30 +01:00
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_MSG ( classes . has ( name ) , " Class ' " + String ( p_class ) + " ' already exists. " ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
classes [ name ] = ClassInfo ( ) ;
ClassInfo & ti = classes [ name ] ;
ti . name = name ;
ti . inherits = p_inherits ;
ti . api = current_api ;
2014-02-10 02:10:30 +01:00
if ( ti . inherits ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( ! classes . has ( ti . inherits ) ) ; //it MUST be registered.
2017-01-03 03:03:46 +01:00
ti . inherits_ptr = & classes [ ti . inherits ] ;
2014-02-10 02:10:30 +01:00
} else {
2020-04-02 01:20:12 +02:00
ti . inherits_ptr = nullptr ;
2014-02-10 02:10:30 +01:00
}
}
2020-06-10 23:13:25 +02:00
# ifdef DEBUG_METHODS_ENABLED
static MethodInfo info_from_bind ( MethodBind * p_method ) {
MethodInfo minfo ;
minfo . name = p_method - > get_name ( ) ;
minfo . id = p_method - > get_method_id ( ) ;
for ( int i = 0 ; i < p_method - > get_argument_count ( ) ; i + + ) {
minfo . arguments . push_back ( p_method - > get_argument_info ( i ) ) ;
}
minfo . return_val = p_method - > get_return_info ( ) ;
minfo . flags = p_method - > get_hint_flags ( ) ;
for ( int i = 0 ; i < p_method - > get_argument_count ( ) ; i + + ) {
if ( p_method - > has_default_argument ( i ) ) {
minfo . default_arguments . push_back ( p_method - > get_default_argument ( i ) ) ;
}
}
return minfo ;
}
# endif
2017-06-23 20:10:46 +02:00
void ClassDB : : get_method_list ( StringName p_class , List < MethodInfo > * p_methods , bool p_no_inheritance , bool p_exclude_from_properties ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_RLOCK ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
ClassInfo * type = classes . getptr ( p_class ) ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
while ( type ) {
2014-02-10 02:10:30 +01:00
if ( type - > disabled ) {
2020-05-14 16:41:43 +02:00
if ( p_no_inheritance ) {
2014-02-10 02:10:30 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
type = type - > inherits_ptr ;
2014-02-10 02:10:30 +01:00
continue ;
}
# ifdef DEBUG_METHODS_ENABLED
2017-03-05 16:44:50 +01:00
for ( List < MethodInfo > : : Element * E = type - > virtual_methods . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 02:10:30 +01:00
p_methods - > push_back ( E - > get ( ) ) ;
}
2017-03-05 16:44:50 +01:00
for ( List < StringName > : : Element * E = type - > method_order . front ( ) ; E ; E = E - > next ( ) ) {
2020-06-10 23:13:25 +02:00
if ( p_exclude_from_properties & & type - > methods_in_properties . has ( E - > get ( ) ) ) {
2017-06-23 20:10:46 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2017-06-23 20:10:46 +02:00
2020-06-10 23:13:25 +02:00
MethodBind * method = type - > method_map . get ( E - > get ( ) ) ;
MethodInfo minfo = info_from_bind ( method ) ;
2017-08-29 18:11:39 +02:00
2014-02-10 02:10:30 +01:00
p_methods - > push_back ( minfo ) ;
}
# else
2020-04-02 01:20:12 +02:00
const StringName * K = nullptr ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
while ( ( K = type - > method_map . next ( K ) ) ) {
MethodBind * m = type - > method_map [ * K ] ;
2014-02-10 02:10:30 +01:00
MethodInfo mi ;
2017-03-05 16:44:50 +01:00
mi . name = m - > get_name ( ) ;
2014-02-10 02:10:30 +01:00
p_methods - > push_back ( mi ) ;
}
# endif
2016-03-09 00:00:52 +01:00
2020-05-14 16:41:43 +02:00
if ( p_no_inheritance ) {
2014-02-10 02:10:30 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
type = type - > inherits_ptr ;
2014-02-10 02:10:30 +01:00
}
}
2020-06-10 23:13:25 +02:00
bool ClassDB : : get_method_info ( StringName p_class , StringName p_method , MethodInfo * r_info , bool p_no_inheritance , bool p_exclude_from_properties ) {
OBJTYPE_RLOCK ;
ClassInfo * type = classes . getptr ( p_class ) ;
while ( type ) {
if ( type - > disabled ) {
if ( p_no_inheritance ) {
break ;
}
type = type - > inherits_ptr ;
continue ;
}
# ifdef DEBUG_METHODS_ENABLED
MethodBind * * method = type - > method_map . getptr ( p_method ) ;
if ( method & & * method ) {
if ( r_info ! = nullptr ) {
MethodInfo minfo = info_from_bind ( * method ) ;
* r_info = minfo ;
}
return true ;
} else if ( type - > virtual_methods_map . has ( p_method ) ) {
if ( r_info ) {
* r_info = type - > virtual_methods_map [ p_method ] ;
}
return true ;
}
# else
if ( type - > method_map . has ( p_method ) ) {
if ( r_info ) {
MethodBind * m = type - > method_map [ p_method ] ;
MethodInfo mi ;
mi . name = m - > get_name ( ) ;
* r_info = mi ;
}
return true ;
}
# endif
if ( p_no_inheritance ) {
break ;
}
type = type - > inherits_ptr ;
}
return false ;
}
2017-01-03 03:03:46 +01:00
MethodBind * ClassDB : : get_method ( StringName p_class , StringName p_name ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_RLOCK ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
ClassInfo * type = classes . getptr ( p_class ) ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
while ( type ) {
MethodBind * * method = type - > method_map . getptr ( p_name ) ;
2020-05-14 16:41:43 +02:00
if ( method & & * method ) {
2014-02-10 02:10:30 +01:00
return * method ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
type = type - > inherits_ptr ;
2014-02-10 02:10:30 +01:00
}
2020-04-02 01:20:12 +02:00
return nullptr ;
2014-02-10 02:10:30 +01:00
}
2017-08-20 17:45:01 +02:00
void ClassDB : : bind_integer_constant ( const StringName & p_class , const StringName & p_enum , const StringName & p_name , int p_constant ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_WLOCK ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
ClassInfo * type = classes . getptr ( p_class ) ;
2014-02-10 02:10:30 +01:00
2019-06-20 16:59:48 +02:00
ERR_FAIL_COND ( ! type ) ;
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
if ( type - > constant_map . has ( p_name ) ) {
ERR_FAIL ( ) ;
}
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
type - > constant_map [ p_name ] = p_constant ;
2017-08-20 17:45:01 +02:00
2017-08-24 05:06:56 +02:00
String enum_name = p_enum ;
2017-08-27 14:16:32 +02:00
if ( enum_name ! = String ( ) ) {
if ( enum_name . find ( " . " ) ! = - 1 ) {
enum_name = enum_name . get_slicec ( ' . ' , 1 ) ;
2017-08-24 05:06:56 +02:00
}
List < StringName > * constants_list = type - > enum_map . getptr ( enum_name ) ;
if ( constants_list ) {
constants_list - > push_back ( p_name ) ;
} else {
List < StringName > new_list ;
new_list . push_back ( p_name ) ;
type - > enum_map [ enum_name ] = new_list ;
}
2017-08-20 17:45:01 +02:00
}
2018-03-30 16:20:24 +02:00
# ifdef DEBUG_METHODS_ENABLED
2014-02-10 02:10:30 +01:00
type - > constant_order . push_back ( p_name ) ;
# endif
}
2017-03-05 16:44:50 +01:00
void ClassDB : : get_integer_constant_list ( const StringName & p_class , List < String > * p_constants , bool p_no_inheritance ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_RLOCK ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
ClassInfo * type = classes . getptr ( p_class ) ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
while ( type ) {
2014-02-10 02:10:30 +01:00
# ifdef DEBUG_METHODS_ENABLED
2020-05-14 16:41:43 +02:00
for ( List < StringName > : : Element * E = type - > constant_order . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 02:10:30 +01:00
p_constants - > push_back ( E - > get ( ) ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
# else
2020-04-02 01:20:12 +02:00
const StringName * K = nullptr ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
while ( ( K = type - > constant_map . next ( K ) ) ) {
2014-02-10 02:10:30 +01:00
p_constants - > push_back ( * K ) ;
}
# endif
2020-05-14 16:41:43 +02:00
if ( p_no_inheritance ) {
2014-02-10 02:10:30 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
type = type - > inherits_ptr ;
2014-02-10 02:10:30 +01:00
}
}
2017-03-05 16:44:50 +01:00
int ClassDB : : get_integer_constant ( const StringName & p_class , const StringName & p_name , bool * p_success ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_RLOCK ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
ClassInfo * type = classes . getptr ( p_class ) ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
while ( type ) {
int * constant = type - > constant_map . getptr ( p_name ) ;
2014-02-10 02:10:30 +01:00
if ( constant ) {
2020-05-14 16:41:43 +02:00
if ( p_success ) {
2017-03-05 16:44:50 +01:00
* p_success = true ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
return * constant ;
}
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
type = type - > inherits_ptr ;
2014-02-10 02:10:30 +01:00
}
2016-03-09 00:00:52 +01:00
2020-05-14 16:41:43 +02:00
if ( p_success ) {
2017-03-05 16:44:50 +01:00
* p_success = false ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2016-03-09 00:00:52 +01:00
return 0 ;
2014-02-10 02:10:30 +01:00
}
2020-06-10 23:13:25 +02:00
bool ClassDB : : has_integer_constant ( const StringName & p_class , const StringName & p_name , bool p_no_inheritance ) {
OBJTYPE_RLOCK ;
ClassInfo * type = classes . getptr ( p_class ) ;
while ( type ) {
if ( type - > constant_map . has ( p_name ) ) {
return true ;
}
if ( p_no_inheritance ) {
return false ;
}
type = type - > inherits_ptr ;
}
return false ;
}
2017-08-20 17:45:01 +02:00
StringName ClassDB : : get_integer_constant_enum ( const StringName & p_class , const StringName & p_name , bool p_no_inheritance ) {
OBJTYPE_RLOCK ;
ClassInfo * type = classes . getptr ( p_class ) ;
while ( type ) {
2020-04-02 01:20:12 +02:00
const StringName * k = nullptr ;
2017-08-20 17:45:01 +02:00
while ( ( k = type - > enum_map . next ( k ) ) ) {
List < StringName > & constants_list = type - > enum_map . get ( * k ) ;
const List < StringName > : : Element * found = constants_list . find ( p_name ) ;
2020-05-14 16:41:43 +02:00
if ( found ) {
2017-08-24 00:10:32 +02:00
return * k ;
2020-05-14 16:41:43 +02:00
}
2017-08-20 17:45:01 +02:00
}
2020-05-14 16:41:43 +02:00
if ( p_no_inheritance ) {
2017-08-20 17:45:01 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2017-08-20 17:45:01 +02:00
type = type - > inherits_ptr ;
}
return StringName ( ) ;
}
void ClassDB : : get_enum_list ( const StringName & p_class , List < StringName > * p_enums , bool p_no_inheritance ) {
OBJTYPE_RLOCK ;
ClassInfo * type = classes . getptr ( p_class ) ;
while ( type ) {
2020-04-02 01:20:12 +02:00
const StringName * k = nullptr ;
2017-08-20 17:45:01 +02:00
while ( ( k = type - > enum_map . next ( k ) ) ) {
p_enums - > push_back ( * k ) ;
}
2020-05-14 16:41:43 +02:00
if ( p_no_inheritance ) {
2017-08-20 17:45:01 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2017-08-20 17:45:01 +02:00
type = type - > inherits_ptr ;
}
}
void ClassDB : : get_enum_constants ( const StringName & p_class , const StringName & p_enum , List < StringName > * p_constants , bool p_no_inheritance ) {
OBJTYPE_RLOCK ;
ClassInfo * type = classes . getptr ( p_class ) ;
while ( type ) {
const List < StringName > * constants = type - > enum_map . getptr ( p_enum ) ;
if ( constants ) {
for ( const List < StringName > : : Element * E = constants - > front ( ) ; E ; E = E - > next ( ) ) {
p_constants - > push_back ( E - > get ( ) ) ;
}
}
2020-05-14 16:41:43 +02:00
if ( p_no_inheritance ) {
2017-08-20 17:45:01 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2017-08-20 17:45:01 +02:00
type = type - > inherits_ptr ;
}
}
2020-06-10 23:13:25 +02:00
bool ClassDB : : has_enum ( const StringName & p_class , const StringName & p_name , bool p_no_inheritance ) {
OBJTYPE_RLOCK ;
ClassInfo * type = classes . getptr ( p_class ) ;
while ( type ) {
if ( type - > enum_map . has ( p_name ) ) {
return true ;
}
if ( p_no_inheritance ) {
return false ;
}
type = type - > inherits_ptr ;
}
return false ;
}
2017-03-05 16:44:50 +01:00
void ClassDB : : add_signal ( StringName p_class , const MethodInfo & p_signal ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_WLOCK ;
2017-03-05 16:44:50 +01:00
ClassInfo * type = classes . getptr ( p_class ) ;
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! type ) ;
StringName sname = p_signal . name ;
2018-10-03 16:13:34 +02:00
# ifdef DEBUG_METHODS_ENABLED
ClassInfo * check = type ;
2017-03-05 16:44:50 +01:00
while ( check ) {
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_MSG ( check - > signal_map . has ( sname ) , " Class ' " + String ( p_class ) + " ' already has signal ' " + String ( sname ) + " '. " ) ;
2017-03-05 16:44:50 +01:00
check = check - > inherits_ptr ;
2014-02-10 02:10:30 +01:00
}
# endif
2017-03-05 16:44:50 +01:00
type - > signal_map [ sname ] = p_signal ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void ClassDB : : get_signal_list ( StringName p_class , List < MethodInfo > * p_signals , bool p_no_inheritance ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_RLOCK ;
2017-03-05 16:44:50 +01:00
ClassInfo * type = classes . getptr ( p_class ) ;
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! type ) ;
2017-03-05 16:44:50 +01:00
ClassInfo * check = type ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
while ( check ) {
2020-04-02 01:20:12 +02:00
const StringName * S = nullptr ;
2017-03-05 16:44:50 +01:00
while ( ( S = check - > signal_map . next ( S ) ) ) {
2014-02-10 02:10:30 +01:00
p_signals - > push_back ( check - > signal_map [ * S ] ) ;
}
2020-05-14 16:41:43 +02:00
if ( p_no_inheritance ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
check = check - > inherits_ptr ;
2014-02-10 02:10:30 +01:00
}
}
2020-06-10 23:13:25 +02:00
bool ClassDB : : has_signal ( StringName p_class , StringName p_signal , bool p_no_inheritance ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_RLOCK ;
2017-03-05 16:44:50 +01:00
ClassInfo * type = classes . getptr ( p_class ) ;
ClassInfo * check = type ;
while ( check ) {
2020-05-14 16:41:43 +02:00
if ( check - > signal_map . has ( p_signal ) ) {
2014-02-10 02:10:30 +01:00
return true ;
2020-05-14 16:41:43 +02:00
}
2020-06-10 23:13:25 +02:00
if ( p_no_inheritance ) {
return false ;
}
2017-03-05 16:44:50 +01:00
check = check - > inherits_ptr ;
2014-02-10 02:10:30 +01:00
}
return false ;
}
2017-03-05 16:44:50 +01:00
bool ClassDB : : get_signal ( StringName p_class , StringName p_signal , MethodInfo * r_signal ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_RLOCK ;
2017-03-05 16:44:50 +01:00
ClassInfo * type = classes . getptr ( p_class ) ;
ClassInfo * check = type ;
while ( check ) {
2016-08-08 00:22:33 +02:00
if ( check - > signal_map . has ( p_signal ) ) {
if ( r_signal ) {
2017-03-05 16:44:50 +01:00
* r_signal = check - > signal_map [ p_signal ] ;
2016-08-08 00:22:33 +02:00
}
return true ;
}
2017-03-05 16:44:50 +01:00
check = check - > inherits_ptr ;
2016-08-08 00:22:33 +02:00
}
return false ;
}
2017-03-05 16:44:50 +01:00
void ClassDB : : add_property_group ( StringName p_class , const String & p_name , const String & p_prefix ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_WLOCK ;
2017-03-05 16:44:50 +01:00
ClassInfo * type = classes . getptr ( p_class ) ;
2017-01-03 04:38:16 +01:00
ERR_FAIL_COND ( ! type ) ;
2017-03-05 16:44:50 +01:00
type - > property_list . push_back ( PropertyInfo ( Variant : : NIL , p_name , PROPERTY_HINT_NONE , p_prefix , PROPERTY_USAGE_GROUP ) ) ;
2017-01-03 04:38:16 +01:00
}
2020-04-08 03:51:52 +02:00
void ClassDB : : add_property_subgroup ( StringName p_class , const String & p_name , const String & p_prefix ) {
OBJTYPE_WLOCK ;
ClassInfo * type = classes . getptr ( p_class ) ;
ERR_FAIL_COND ( ! type ) ;
type - > property_list . push_back ( PropertyInfo ( Variant : : NIL , p_name , PROPERTY_HINT_NONE , p_prefix , PROPERTY_USAGE_SUBGROUP ) ) ;
}
2020-11-28 01:34:13 +01:00
// NOTE: For implementation simplicity reasons, this method doesn't allow setters to have optional arguments at the end.
2017-03-05 16:44:50 +01:00
void ClassDB : : add_property ( StringName p_class , const PropertyInfo & p_pinfo , const StringName & p_setter , const StringName & p_getter , int p_index ) {
2021-01-18 14:01:38 +01:00
lock . read_lock ( ) ;
2017-03-05 16:44:50 +01:00
ClassInfo * type = classes . getptr ( p_class ) ;
2021-01-18 14:01:38 +01:00
lock . read_unlock ( ) ;
2017-01-07 22:25:37 +01:00
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! type ) ;
2020-04-02 01:20:12 +02:00
MethodBind * mb_set = nullptr ;
2014-02-10 02:10:30 +01:00
if ( p_setter ) {
2017-03-05 16:44:50 +01:00
mb_set = get_method ( p_class , p_setter ) ;
2014-02-10 02:10:30 +01:00
# ifdef DEBUG_METHODS_ENABLED
2019-08-15 04:57:49 +02:00
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_MSG ( ! mb_set , " Invalid setter ' " + p_class + " :: " + p_setter + " ' for property ' " + p_pinfo . name + " '. " ) ;
2019-08-15 04:57:49 +02:00
int exp_args = 1 + ( p_index > = 0 ? 1 : 0 ) ;
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_MSG ( mb_set - > get_argument_count ( ) ! = exp_args , " Invalid function for setter ' " + p_class + " :: " + p_setter + " for property ' " + p_pinfo . name + " '. " ) ;
2014-02-10 02:10:30 +01:00
# endif
}
2020-04-02 01:20:12 +02:00
MethodBind * mb_get = nullptr ;
2014-02-10 02:10:30 +01:00
if ( p_getter ) {
2017-08-28 05:03:34 +02:00
mb_get = get_method ( p_class , p_getter ) ;
2014-02-10 02:10:30 +01:00
# ifdef DEBUG_METHODS_ENABLED
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_MSG ( ! mb_get , " Invalid getter ' " + p_class + " :: " + p_getter + " ' for property ' " + p_pinfo . name + " '. " ) ;
2014-02-10 02:10:30 +01:00
2019-08-15 04:57:49 +02:00
int exp_args = 0 + ( p_index > = 0 ? 1 : 0 ) ;
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_MSG ( mb_get - > get_argument_count ( ) ! = exp_args , " Invalid function for getter ' " + p_class + " :: " + p_getter + " ' for property: ' " + p_pinfo . name + " '. " ) ;
2014-02-10 02:10:30 +01:00
# endif
}
# ifdef DEBUG_METHODS_ENABLED
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_MSG ( type - > property_setget . has ( p_pinfo . name ) , " Object ' " + p_class + " ' already has property ' " + p_pinfo . name + " '. " ) ;
2014-02-10 02:10:30 +01:00
# endif
2017-01-07 22:25:37 +01:00
OBJTYPE_WLOCK
2014-02-10 02:10:30 +01:00
type - > property_list . push_back ( p_pinfo ) ;
2020-06-10 23:13:25 +02:00
type - > property_map [ p_pinfo . name ] = p_pinfo ;
2017-06-23 20:10:46 +02:00
# ifdef DEBUG_METHODS_ENABLED
if ( mb_get ) {
type - > methods_in_properties . insert ( p_getter ) ;
}
if ( mb_set ) {
type - > methods_in_properties . insert ( p_setter ) ;
}
# endif
2014-02-10 02:10:30 +01:00
PropertySetGet psg ;
2017-03-05 16:44:50 +01:00
psg . setter = p_setter ;
psg . getter = p_getter ;
psg . _setptr = mb_set ;
psg . _getptr = mb_get ;
psg . index = p_index ;
psg . type = p_pinfo . type ;
type - > property_setget [ p_pinfo . name ] = psg ;
2014-02-10 02:10:30 +01:00
}
2019-06-01 15:42:22 +02:00
void ClassDB : : set_property_default_value ( StringName p_class , const StringName & p_name , const Variant & p_default ) {
if ( ! default_values . has ( p_class ) ) {
default_values [ p_class ] = HashMap < StringName , Variant > ( ) ;
}
default_values [ p_class ] [ p_name ] = p_default ;
}
2017-03-05 16:44:50 +01:00
void ClassDB : : get_property_list ( StringName p_class , List < PropertyInfo > * p_list , bool p_no_inheritance , const Object * p_validator ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_RLOCK ;
2017-03-05 16:44:50 +01:00
ClassInfo * type = classes . getptr ( p_class ) ;
ClassInfo * check = type ;
while ( check ) {
for ( List < PropertyInfo > : : Element * E = check - > property_list . front ( ) ; E ; E = E - > next ( ) ) {
2016-05-15 04:48:23 +02:00
if ( p_validator ) {
PropertyInfo pi = E - > get ( ) ;
p_validator - > _validate_property ( pi ) ;
p_list - > push_back ( pi ) ;
} else {
p_list - > push_back ( E - > get ( ) ) ;
}
2014-02-10 02:10:30 +01:00
}
2020-05-14 16:41:43 +02:00
if ( p_no_inheritance ) {
2017-03-05 16:44:50 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
check = check - > inherits_ptr ;
2014-02-10 02:10:30 +01:00
}
}
2020-05-14 14:29:06 +02:00
2020-06-10 23:13:25 +02:00
bool ClassDB : : get_property_info ( StringName p_class , StringName p_property , PropertyInfo * r_info , bool p_no_inheritance , const Object * p_validator ) {
OBJTYPE_RLOCK ;
ClassInfo * check = classes . getptr ( p_class ) ;
while ( check ) {
if ( check - > property_map . has ( p_property ) ) {
PropertyInfo pinfo = check - > property_map [ p_property ] ;
if ( p_validator ) {
p_validator - > _validate_property ( pinfo ) ;
}
if ( r_info ) {
* r_info = pinfo ;
}
return true ;
}
if ( p_no_inheritance ) {
break ;
}
check = check - > inherits_ptr ;
}
return false ;
}
2017-03-05 16:44:50 +01:00
bool ClassDB : : set_property ( Object * p_object , const StringName & p_property , const Variant & p_value , bool * r_valid ) {
2021-04-02 20:05:01 +02:00
ERR_FAIL_NULL_V ( p_object , false ) ;
2017-03-05 16:44:50 +01:00
ClassInfo * type = classes . getptr ( p_object - > get_class_name ( ) ) ;
ClassInfo * check = type ;
while ( check ) {
2014-02-10 02:10:30 +01:00
const PropertySetGet * psg = check - > property_setget . getptr ( p_property ) ;
if ( psg ) {
2015-12-05 18:18:22 +01:00
if ( ! psg - > setter ) {
2020-05-14 16:41:43 +02:00
if ( r_valid ) {
2017-03-05 16:44:50 +01:00
* r_valid = false ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
return true ; //return true but do nothing
2015-12-05 18:18:22 +01:00
}
2020-02-19 20:27:19 +01:00
Callable : : CallError ce ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( psg - > index > = 0 ) {
Variant index = psg - > index ;
const Variant * arg [ 2 ] = { & index , & p_value } ;
2017-01-14 12:26:56 +01:00
//p_object->call(psg->setter,arg,2,ce);
2015-06-29 05:29:49 +02:00
if ( psg - > _setptr ) {
2017-03-05 16:44:50 +01:00
psg - > _setptr - > call ( p_object , arg , 2 , ce ) ;
2015-06-29 05:29:49 +02:00
} else {
2017-03-05 16:44:50 +01:00
p_object - > call ( psg - > setter , arg , 2 , ce ) ;
2015-06-29 05:29:49 +02:00
}
2014-02-10 02:10:30 +01:00
} else {
2017-03-05 16:44:50 +01:00
const Variant * arg [ 1 ] = { & p_value } ;
2014-02-10 02:10:30 +01:00
if ( psg - > _setptr ) {
2017-03-05 16:44:50 +01:00
psg - > _setptr - > call ( p_object , arg , 1 , ce ) ;
2014-02-10 02:10:30 +01:00
} else {
2017-03-05 16:44:50 +01:00
p_object - > call ( psg - > setter , arg , 1 , ce ) ;
2014-02-10 02:10:30 +01:00
}
}
2015-12-05 18:18:22 +01:00
2020-05-14 16:41:43 +02:00
if ( r_valid ) {
2020-02-19 20:27:19 +01:00
* r_valid = ce . error = = Callable : : CallError : : CALL_OK ;
2020-05-14 16:41:43 +02:00
}
2015-12-05 18:18:22 +01:00
2014-02-10 02:10:30 +01:00
return true ;
}
2017-03-05 16:44:50 +01:00
check = check - > inherits_ptr ;
2014-02-10 02:10:30 +01:00
}
return false ;
}
2020-05-14 14:29:06 +02:00
2017-03-05 16:44:50 +01:00
bool ClassDB : : get_property ( Object * p_object , const StringName & p_property , Variant & r_value ) {
2021-04-02 20:05:01 +02:00
ERR_FAIL_NULL_V ( p_object , false ) ;
2017-03-05 16:44:50 +01:00
ClassInfo * type = classes . getptr ( p_object - > get_class_name ( ) ) ;
ClassInfo * check = type ;
while ( check ) {
2014-02-10 02:10:30 +01:00
const PropertySetGet * psg = check - > property_setget . getptr ( p_property ) ;
if ( psg ) {
2020-05-14 16:41:43 +02:00
if ( ! psg - > getter ) {
2014-02-10 02:10:30 +01:00
return true ; //return true but do nothing
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( psg - > index > = 0 ) {
Variant index = psg - > index ;
const Variant * arg [ 1 ] = { & index } ;
2020-02-19 20:27:19 +01:00
Callable : : CallError ce ;
2017-03-05 16:44:50 +01:00
r_value = p_object - > call ( psg - > getter , arg , 1 , ce ) ;
2014-02-10 02:10:30 +01:00
} else {
2020-02-19 20:27:19 +01:00
Callable : : CallError ce ;
2014-02-10 02:10:30 +01:00
if ( psg - > _getptr ) {
2020-04-02 01:20:12 +02:00
r_value = psg - > _getptr - > call ( p_object , nullptr , 0 , ce ) ;
2014-02-10 02:10:30 +01:00
} else {
2020-04-02 01:20:12 +02:00
r_value = p_object - > call ( psg - > getter , nullptr , 0 , ce ) ;
2014-02-10 02:10:30 +01:00
}
}
return true ;
}
2020-02-19 20:27:19 +01:00
const int * c = check - > constant_map . getptr ( p_property ) ; //constants count
2014-02-10 02:10:30 +01:00
if ( c ) {
2017-03-05 16:44:50 +01:00
r_value = * c ;
2014-02-10 02:10:30 +01:00
return true ;
}
2020-02-19 20:27:19 +01:00
if ( check - > method_map . has ( p_property ) ) { //methods count
r_value = Callable ( p_object , p_property ) ;
return true ;
}
if ( check - > signal_map . has ( p_property ) ) { //signals count
r_value = Signal ( p_object , p_property ) ;
return true ;
}
2017-03-05 16:44:50 +01:00
check = check - > inherits_ptr ;
2014-02-10 02:10:30 +01:00
}
return false ;
}
2017-08-06 02:04:10 +02:00
int ClassDB : : get_property_index ( const StringName & p_class , const StringName & p_property , bool * r_is_valid ) {
ClassInfo * type = classes . getptr ( p_class ) ;
ClassInfo * check = type ;
while ( check ) {
const PropertySetGet * psg = check - > property_setget . getptr ( p_property ) ;
if ( psg ) {
2020-05-14 16:41:43 +02:00
if ( r_is_valid ) {
2017-08-06 02:04:10 +02:00
* r_is_valid = true ;
2020-05-14 16:41:43 +02:00
}
2017-08-06 02:04:10 +02:00
return psg - > index ;
}
check = check - > inherits_ptr ;
}
2020-05-14 16:41:43 +02:00
if ( r_is_valid ) {
2017-08-06 02:04:10 +02:00
* r_is_valid = false ;
2020-05-14 16:41:43 +02:00
}
2017-08-06 02:04:10 +02:00
return - 1 ;
}
2017-03-05 16:44:50 +01:00
Variant : : Type ClassDB : : get_property_type ( const StringName & p_class , const StringName & p_property , bool * r_is_valid ) {
ClassInfo * type = classes . getptr ( p_class ) ;
ClassInfo * check = type ;
while ( check ) {
2015-12-05 18:18:22 +01:00
const PropertySetGet * psg = check - > property_setget . getptr ( p_property ) ;
if ( psg ) {
2020-05-14 16:41:43 +02:00
if ( r_is_valid ) {
2017-03-05 16:44:50 +01:00
* r_is_valid = true ;
2020-05-14 16:41:43 +02:00
}
2015-12-05 18:18:22 +01:00
return psg - > type ;
}
2017-03-05 16:44:50 +01:00
check = check - > inherits_ptr ;
2015-12-05 18:18:22 +01:00
}
2020-05-14 16:41:43 +02:00
if ( r_is_valid ) {
2017-03-05 16:44:50 +01:00
* r_is_valid = false ;
2020-05-14 16:41:43 +02:00
}
2015-12-05 18:18:22 +01:00
return Variant : : NIL ;
}
2019-07-10 11:54:12 +02:00
StringName ClassDB : : get_property_setter ( StringName p_class , const StringName & p_property ) {
2017-03-05 16:44:50 +01:00
ClassInfo * type = classes . getptr ( p_class ) ;
ClassInfo * check = type ;
while ( check ) {
2017-01-04 05:16:14 +01:00
const PropertySetGet * psg = check - > property_setget . getptr ( p_property ) ;
if ( psg ) {
return psg - > setter ;
}
2017-03-05 16:44:50 +01:00
check = check - > inherits_ptr ;
2017-01-04 05:16:14 +01:00
}
return StringName ( ) ;
}
2019-07-10 11:54:12 +02:00
StringName ClassDB : : get_property_getter ( StringName p_class , const StringName & p_property ) {
2017-03-05 16:44:50 +01:00
ClassInfo * type = classes . getptr ( p_class ) ;
ClassInfo * check = type ;
while ( check ) {
2017-01-04 05:16:14 +01:00
const PropertySetGet * psg = check - > property_setget . getptr ( p_property ) ;
if ( psg ) {
return psg - > getter ;
}
2017-03-05 16:44:50 +01:00
check = check - > inherits_ptr ;
2017-01-04 05:16:14 +01:00
}
return StringName ( ) ;
}
2017-03-05 16:44:50 +01:00
bool ClassDB : : has_property ( const StringName & p_class , const StringName & p_property , bool p_no_inheritance ) {
ClassInfo * type = classes . getptr ( p_class ) ;
ClassInfo * check = type ;
while ( check ) {
2020-05-14 16:41:43 +02:00
if ( check - > property_setget . has ( p_property ) ) {
2017-01-04 21:37:45 +01:00
return true ;
2020-05-14 16:41:43 +02:00
}
2017-01-04 21:37:45 +01:00
2020-05-14 16:41:43 +02:00
if ( p_no_inheritance ) {
2017-01-04 21:37:45 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
check = check - > inherits_ptr ;
2017-01-04 21:37:45 +01:00
}
return false ;
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
void ClassDB : : set_method_flags ( StringName p_class , StringName p_method , int p_flags ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_WLOCK ;
2017-03-05 16:44:50 +01:00
ClassInfo * type = classes . getptr ( p_class ) ;
ClassInfo * check = type ;
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! check ) ;
ERR_FAIL_COND ( ! check - > method_map . has ( p_method ) ) ;
check - > method_map [ p_method ] - > set_hint_flags ( p_flags ) ;
}
2017-03-05 16:44:50 +01:00
bool ClassDB : : has_method ( StringName p_class , StringName p_method , bool p_no_inheritance ) {
ClassInfo * type = classes . getptr ( p_class ) ;
ClassInfo * check = type ;
while ( check ) {
2020-05-14 16:41:43 +02:00
if ( check - > method_map . has ( p_method ) ) {
2014-02-10 02:10:30 +01:00
return true ;
2020-05-14 16:41:43 +02:00
}
if ( p_no_inheritance ) {
2014-02-10 02:10:30 +01:00
return false ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
check = check - > inherits_ptr ;
2014-02-10 02:10:30 +01:00
}
return false ;
}
2021-06-04 19:33:48 +02:00
void ClassDB : : bind_method_custom ( const StringName & p_class , MethodBind * p_method ) {
ClassInfo * type = classes . getptr ( p_class ) ;
if ( ! type ) {
ERR_FAIL_MSG ( " Couldn't bind custom method ' " + p_method - > get_name ( ) + " ' for instance ' " + p_class + " '. " ) ;
}
if ( type - > method_map . has ( p_method - > get_name ( ) ) ) {
// overloading not supported
ERR_FAIL_MSG ( " Method already bound ' " + p_class + " :: " + p_method - > get_name ( ) + " '. " ) ;
}
# ifdef DEBUG_METHODS_ENABLED
type - > method_order . push_back ( p_method - > get_name ( ) ) ;
# endif
type - > method_map [ p_method - > get_name ( ) ] = p_method ;
}
2014-02-10 02:10:30 +01:00
# ifdef DEBUG_METHODS_ENABLED
2017-03-05 16:44:50 +01:00
MethodBind * ClassDB : : bind_methodfi ( uint32_t p_flags , MethodBind * p_bind , const MethodDefinition & method_name , const Variant * * p_defs , int p_defcount ) {
StringName mdname = method_name . name ;
2014-02-10 02:10:30 +01:00
# else
2017-03-05 16:44:50 +01:00
MethodBind * ClassDB : : bind_methodfi ( uint32_t p_flags , MethodBind * p_bind , const char * method_name , const Variant * * p_defs , int p_defcount ) {
StringName mdname = StaticCString : : create ( method_name ) ;
2014-02-10 02:10:30 +01:00
# endif
2017-01-07 22:25:37 +01:00
OBJTYPE_WLOCK ;
2020-04-02 01:20:12 +02:00
ERR_FAIL_COND_V ( ! p_bind , nullptr ) ;
2014-02-10 02:10:30 +01:00
p_bind - > set_name ( mdname ) ;
2017-03-05 16:44:50 +01:00
String instance_type = p_bind - > get_instance_class ( ) ;
2014-02-10 02:10:30 +01:00
2017-01-14 15:07:57 +01:00
# ifdef DEBUG_ENABLED
2020-04-02 01:20:12 +02:00
ERR_FAIL_COND_V_MSG ( has_method ( instance_type , mdname ) , nullptr , " Class " + String ( instance_type ) + " already has a method " + String ( mdname ) + " . " ) ;
2017-01-14 15:07:57 +01:00
# endif
2017-03-05 16:44:50 +01:00
ClassInfo * type = classes . getptr ( instance_type ) ;
2014-02-10 02:10:30 +01:00
if ( ! type ) {
memdelete ( p_bind ) ;
2020-04-02 01:20:12 +02:00
ERR_FAIL_V_MSG ( nullptr , " Couldn't bind method ' " + mdname + " ' for instance ' " + instance_type + " '. " ) ;
2014-02-10 02:10:30 +01:00
}
if ( type - > method_map . has ( mdname ) ) {
memdelete ( p_bind ) ;
// overloading not supported
2020-04-02 01:20:12 +02:00
ERR_FAIL_V_MSG ( nullptr , " Method already bound ' " + instance_type + " :: " + mdname + " '. " ) ;
2014-02-10 02:10:30 +01:00
}
2017-08-09 11:54:27 +02:00
2014-02-10 02:10:30 +01:00
# ifdef DEBUG_METHODS_ENABLED
2017-08-09 11:54:27 +02:00
if ( method_name . args . size ( ) > p_bind - > get_argument_count ( ) ) {
memdelete ( p_bind ) ;
2020-04-02 01:20:12 +02:00
ERR_FAIL_V_MSG ( nullptr , " Method definition provides more arguments than the method actually has ' " + instance_type + " :: " + mdname + " '. " ) ;
2017-08-09 11:54:27 +02:00
}
2014-02-10 02:10:30 +01:00
p_bind - > set_argument_names ( method_name . args ) ;
2017-08-09 11:54:27 +02:00
2014-02-10 02:10:30 +01:00
type - > method_order . push_back ( mdname ) ;
# endif
2017-08-09 11:54:27 +02:00
2017-03-05 16:44:50 +01:00
type - > method_map [ mdname ] = p_bind ;
2014-02-10 02:10:30 +01:00
Vector < Variant > defvals ;
defvals . resize ( p_defcount ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < p_defcount ; i + + ) {
2020-10-15 17:29:59 +02:00
defvals . write [ i ] = * p_defs [ i ] ;
2014-02-10 02:10:30 +01:00
}
p_bind - > set_default_arguments ( defvals ) ;
p_bind - > set_hint_flags ( p_flags ) ;
return p_bind ;
}
2017-03-05 16:44:50 +01:00
void ClassDB : : add_virtual_method ( const StringName & p_class , const MethodInfo & p_method , bool p_virtual ) {
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_MSG ( ! classes . has ( p_class ) , " Request for nonexistent class ' " + p_class + " '. " ) ;
2014-02-10 02:10:30 +01:00
2017-01-07 22:25:37 +01:00
OBJTYPE_WLOCK ;
2014-02-10 02:10:30 +01:00
# ifdef DEBUG_METHODS_ENABLED
2017-03-05 16:44:50 +01:00
MethodInfo mi = p_method ;
2020-05-14 16:41:43 +02:00
if ( p_virtual ) {
2017-03-05 16:44:50 +01:00
mi . flags | = METHOD_FLAG_VIRTUAL ;
2020-05-14 16:41:43 +02:00
}
2017-01-03 03:03:46 +01:00
classes [ p_class ] . virtual_methods . push_back ( mi ) ;
2020-06-10 23:13:25 +02:00
classes [ p_class ] . virtual_methods_map [ p_method . name ] = mi ;
2014-02-10 02:10:30 +01:00
# endif
}
2017-03-05 16:44:50 +01:00
void ClassDB : : get_virtual_methods ( const StringName & p_class , List < MethodInfo > * p_methods , bool p_no_inheritance ) {
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_MSG ( ! classes . has ( p_class ) , " Request for nonexistent class ' " + p_class + " '. " ) ;
2014-02-10 02:10:30 +01:00
# ifdef DEBUG_METHODS_ENABLED
2014-12-18 04:56:33 +01:00
2017-03-05 16:44:50 +01:00
ClassInfo * type = classes . getptr ( p_class ) ;
ClassInfo * check = type ;
while ( check ) {
for ( List < MethodInfo > : : Element * E = check - > virtual_methods . front ( ) ; E ; E = E - > next ( ) ) {
2014-12-18 04:56:33 +01:00
p_methods - > push_back ( E - > get ( ) ) ;
}
2020-05-14 16:41:43 +02:00
if ( p_no_inheritance ) {
2014-12-18 04:56:33 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
check = check - > inherits_ptr ;
2014-12-18 04:56:33 +01:00
}
2014-02-10 02:10:30 +01:00
# endif
}
2017-03-05 16:44:50 +01:00
void ClassDB : : set_class_enabled ( StringName p_class , bool p_enable ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_WLOCK ;
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_MSG ( ! classes . has ( p_class ) , " Request for nonexistent class ' " + p_class + " '. " ) ;
2017-03-05 16:44:50 +01:00
classes [ p_class ] . disabled = ! p_enable ;
2014-02-10 02:10:30 +01:00
}
2017-01-03 03:03:46 +01:00
bool ClassDB : : is_class_enabled ( StringName p_class ) {
2017-01-07 22:25:37 +01:00
OBJTYPE_RLOCK ;
2017-03-05 16:44:50 +01:00
ClassInfo * ti = classes . getptr ( p_class ) ;
2015-01-13 15:22:56 +01:00
if ( ! ti | | ! ti - > creation_func ) {
2017-01-03 03:03:46 +01:00
if ( compat_classes . has ( p_class ) ) {
2017-03-05 16:44:50 +01:00
ti = classes . getptr ( compat_classes [ p_class ] ) ;
2015-01-13 15:22:56 +01:00
}
}
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_V_MSG ( ! ti , false , " Cannot get class ' " + String ( p_class ) + " '. " ) ;
2015-01-13 15:22:56 +01:00
return ! ti - > disabled ;
2014-02-10 02:10:30 +01:00
}
2017-10-09 23:49:17 +02:00
bool ClassDB : : is_class_exposed ( StringName p_class ) {
OBJTYPE_RLOCK ;
ClassInfo * ti = classes . getptr ( p_class ) ;
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_V_MSG ( ! ti , false , " Cannot get class ' " + String ( p_class ) + " '. " ) ;
2017-10-09 23:49:17 +02:00
return ti - > exposed ;
}
2017-03-05 16:44:50 +01:00
StringName ClassDB : : get_category ( const StringName & p_node ) {
ERR_FAIL_COND_V ( ! classes . has ( p_node ) , StringName ( ) ) ;
2014-02-10 02:10:30 +01:00
# ifdef DEBUG_ENABLED
2017-01-03 03:03:46 +01:00
return classes [ p_node ] . category ;
2014-02-10 02:10:30 +01:00
# else
return StringName ( ) ;
# endif
}
2017-03-05 16:44:50 +01:00
void ClassDB : : add_resource_base_extension ( const StringName & p_extension , const StringName & p_class ) {
2020-05-14 16:41:43 +02:00
if ( resource_base_extensions . has ( p_extension ) ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
resource_base_extensions [ p_extension ] = p_class ;
2014-02-10 02:10:30 +01:00
}
2017-01-03 03:03:46 +01:00
void ClassDB : : get_resource_base_extensions ( List < String > * p_extensions ) {
2020-04-02 01:20:12 +02:00
const StringName * K = nullptr ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
while ( ( K = resource_base_extensions . next ( K ) ) ) {
2014-02-10 02:10:30 +01:00
p_extensions - > push_back ( * K ) ;
}
}
2017-03-05 16:44:50 +01:00
void ClassDB : : get_extensions_for_type ( const StringName & p_class , List < String > * p_extensions ) {
2020-04-02 01:20:12 +02:00
const StringName * K = nullptr ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
while ( ( K = resource_base_extensions . next ( K ) ) ) {
2014-02-10 02:10:30 +01:00
StringName cmp = resource_base_extensions [ * K ] ;
2020-05-14 16:41:43 +02:00
if ( is_parent_class ( p_class , cmp ) | | is_parent_class ( cmp , p_class ) ) {
2014-02-10 02:10:30 +01:00
p_extensions - > push_back ( * K ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
}
2020-03-17 07:33:00 +01:00
HashMap < StringName , HashMap < StringName , Variant > > ClassDB : : default_values ;
2019-06-01 15:42:22 +02:00
Set < StringName > ClassDB : : default_values_cached ;
2018-11-08 15:30:02 +01:00
2019-06-29 14:51:33 +02:00
Variant ClassDB : : class_get_default_property_value ( const StringName & p_class , const StringName & p_property , bool * r_valid ) {
2019-06-01 15:42:22 +02:00
if ( ! default_values_cached . has ( p_class ) ) {
if ( ! default_values . has ( p_class ) ) {
default_values [ p_class ] = HashMap < StringName , Variant > ( ) ;
}
2018-11-08 15:30:02 +01:00
2020-04-02 01:20:12 +02:00
Object * c = nullptr ;
2019-06-01 15:42:22 +02:00
bool cleanup_c = false ;
if ( Engine : : get_singleton ( ) - > has_singleton ( p_class ) ) {
c = Engine : : get_singleton ( ) - > get_singleton_object ( p_class ) ;
cleanup_c = false ;
} else if ( ClassDB : : can_instance ( p_class ) ) {
c = ClassDB : : instance ( p_class ) ;
2020-02-19 13:14:39 +01:00
cleanup_c = true ;
2019-06-01 15:42:22 +02:00
}
if ( c ) {
2018-11-08 15:30:02 +01:00
List < PropertyInfo > plist ;
c - > get_property_list ( & plist ) ;
for ( List < PropertyInfo > : : Element * E = plist . front ( ) ; E ; E = E - > next ( ) ) {
if ( E - > get ( ) . usage & ( PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR ) ) {
2019-06-01 15:42:22 +02:00
if ( ! default_values [ p_class ] . has ( E - > get ( ) . name ) ) {
Variant v = c - > get ( E - > get ( ) . name ) ;
default_values [ p_class ] [ E - > get ( ) . name ] = v ;
}
2018-11-08 15:30:02 +01:00
}
}
2019-06-01 15:42:22 +02:00
if ( cleanup_c ) {
memdelete ( c ) ;
}
2018-11-08 15:30:02 +01:00
}
2019-06-01 15:42:22 +02:00
default_values_cached . insert ( p_class ) ;
2018-11-08 15:30:02 +01:00
}
if ( ! default_values . has ( p_class ) ) {
2020-05-14 16:41:43 +02:00
if ( r_valid ! = nullptr ) {
2020-05-10 12:56:01 +02:00
* r_valid = false ;
2020-05-14 16:41:43 +02:00
}
2018-11-08 15:30:02 +01:00
return Variant ( ) ;
}
if ( ! default_values [ p_class ] . has ( p_property ) ) {
2020-05-14 16:41:43 +02:00
if ( r_valid ! = nullptr ) {
2020-05-10 12:56:01 +02:00
* r_valid = false ;
2020-05-14 16:41:43 +02:00
}
2018-11-08 15:30:02 +01:00
return Variant ( ) ;
}
2020-05-14 16:41:43 +02:00
if ( r_valid ! = nullptr ) {
2020-05-10 12:56:01 +02:00
* r_valid = true ;
2020-05-14 16:41:43 +02:00
}
2020-06-12 13:16:14 +02:00
Variant var = default_values [ p_class ] [ p_property ] ;
# ifdef DEBUG_ENABLED
// Some properties may have an instantiated Object as default value,
// (like Path2D's `curve` used to have), but that's not a good practice.
// Instead, those properties should use PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT
// to be auto-instantiated when created in the editor.
if ( var . get_type ( ) = = Variant : : OBJECT ) {
Object * obj = var . get_validated_object ( ) ;
if ( obj ) {
WARN_PRINT ( vformat ( " Instantiated %s used as default value for %s's \" %s \" property. " , obj - > get_class ( ) , p_class , p_property ) ) ;
}
}
# endif
return var ;
2018-11-08 15:30:02 +01:00
}
2021-06-04 19:33:48 +02:00
void ClassDB : : register_extension_class ( ObjectNativeExtension * p_extension ) {
GLOBAL_LOCK_FUNCTION ;
ERR_FAIL_COND_MSG ( classes . has ( p_extension - > class_name ) , " Class already registered: " + String ( p_extension - > class_name ) ) ;
ERR_FAIL_COND_MSG ( classes . has ( p_extension - > parent_class_name ) , " Parent class name for extension class not found: " + String ( p_extension - > parent_class_name ) ) ;
ClassInfo * parent = classes . getptr ( p_extension - > parent_class_name ) ;
ClassInfo c ;
c . api = p_extension - > editor_class ? API_EDITOR_EXTENSION : API_EXTENSION ;
c . native_extension = p_extension ;
c . name = p_extension - > class_name ;
c . creation_func = parent - > creation_func ;
c . inherits = parent - > name ;
c . class_ptr = parent - > class_ptr ;
c . inherits_ptr = parent ;
classes [ p_extension - > class_name ] = c ;
}
2021-01-18 14:01:38 +01:00
RWLock ClassDB : : lock ;
2014-02-10 02:10:30 +01:00
2019-06-01 15:42:22 +02:00
void ClassDB : : cleanup_defaults ( ) {
default_values . clear ( ) ;
default_values_cached . clear ( ) ;
}
2017-01-03 03:03:46 +01:00
void ClassDB : : cleanup ( ) {
2014-02-10 02:10:30 +01:00
//OBJTYPE_LOCK; hah not here
2016-03-09 00:00:52 +01:00
2020-04-02 01:20:12 +02:00
const StringName * k = nullptr ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
while ( ( k = classes . next ( k ) ) ) {
ClassInfo & ti = classes [ * k ] ;
2016-03-09 00:00:52 +01:00
2020-04-02 01:20:12 +02:00
const StringName * m = nullptr ;
2017-03-05 16:44:50 +01:00
while ( ( m = ti . method_map . next ( m ) ) ) {
memdelete ( ti . method_map [ * m ] ) ;
2014-02-10 02:10:30 +01:00
}
2016-03-09 00:00:52 +01:00
}
2017-01-03 03:03:46 +01:00
classes . clear ( ) ;
2014-02-10 02:10:30 +01:00
resource_base_extensions . clear ( ) ;
2017-01-03 03:03:46 +01:00
compat_classes . clear ( ) ;
2014-02-10 02:10:30 +01:00
}
//