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
/*************************************************************************/
2022-01-03 21:27:34 +01:00
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 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
2022-04-06 01:40:07 +02:00
# ifdef DEBUG_METHODS_ENABLED
2022-04-27 12:52:18 +02:00
MethodDefinition D_METHODP ( const char * p_name , const char * const * * p_args , uint32_t p_argcount ) {
2014-02-10 02:10:30 +01:00
MethodDefinition md ;
2017-03-05 16:44:50 +01:00
md . name = StaticCString : : create ( p_name ) ;
2022-04-27 12:52:18 +02:00
md . args . resize ( p_argcount ) ;
for ( uint32_t i = 0 ; i < p_argcount ; i + + ) {
md . args . write [ i ] = StaticCString : : create ( * p_args [ i ] ) ;
}
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 ;
}
2022-04-06 01:40:07 +02: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
2022-05-08 10:09:19 +02:00
for ( const KeyValue < StringName , ClassInfo > & E : classes ) {
p_classes - > push_back ( E . key ) ;
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
2022-05-08 10:09:19 +02:00
for ( const KeyValue < StringName , ClassInfo > & E : classes ) {
if ( E . key ! = p_class & & _is_parent_class ( E . key , p_class ) ) {
p_classes - > push_back ( E . key ) ;
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 ;
2022-05-08 10:09:19 +02:00
for ( const KeyValue < StringName , ClassInfo > & E : classes ) {
if ( E . key ! = p_class & & _get_parent_class ( E . key ) = = p_class ) {
p_classes - > push_back ( E . key ) ;
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
2022-06-18 16:20:55 +02:00
uint64_t hash = hash_murmur3_one_64 ( HashMapHasherDefault : : hash ( VERSION_FULL_CONFIG ) ) ;
2016-09-15 00:37:37 +02:00
2022-05-08 10:09:19 +02:00
List < StringName > class_list ;
ClassDB : : get_class_list ( & class_list ) ;
// Must be alphabetically sorted for hash to compute.
class_list . sort_custom < StringName : : AlphCompare > ( ) ;
2016-09-15 00:37:37 +02:00
2022-05-08 10:09:19 +02:00
for ( const StringName & E : class_list ) {
2021-07-16 05:45:57 +02:00
ClassInfo * t = classes . getptr ( E ) ;
ERR_FAIL_COND_V_MSG ( ! t , 0 , " Cannot get class ' " + String ( E ) + " '. " ) ;
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
}
2022-06-18 16:20:55 +02:00
hash = hash_murmur3_one_64 ( t - > name . hash ( ) , hash ) ;
hash = hash_murmur3_one_64 ( t - > inherits . hash ( ) , hash ) ;
2016-09-15 00:37:37 +02:00
{ //methods
List < StringName > snames ;
2022-05-08 10:09:19 +02:00
for ( const KeyValue < StringName , MethodBind * > & F : t - > method_map ) {
String name = F . key . operator String ( ) ;
2020-01-07 00:08:46 +01:00
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
2022-05-08 10:09:19 +02:00
snames . push_back ( F . key ) ;
2016-09-15 00:37:37 +02:00
}
snames . sort_custom < StringName : : AlphCompare > ( ) ;
2021-07-24 15:46:25 +02:00
for ( const StringName & F : snames ) {
2021-07-16 05:45:57 +02:00
MethodBind * mb = t - > method_map [ F ] ;
2022-06-18 16:20:55 +02:00
hash = hash_murmur3_one_64 ( mb - > get_name ( ) . hash ( ) , hash ) ;
hash = hash_murmur3_one_64 ( mb - > get_argument_count ( ) , hash ) ;
hash = hash_murmur3_one_64 ( mb - > get_argument_type ( - 1 ) , hash ) ; //return
2017-03-05 16:44:50 +01:00
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 ) ;
2022-06-18 16:20:55 +02:00
hash = hash_murmur3_one_64 ( info . type , hash ) ;
hash = hash_murmur3_one_64 ( info . name . hash ( ) , hash ) ;
hash = hash_murmur3_one_64 ( info . hint , hash ) ;
hash = hash_murmur3_one_64 ( info . hint_string . hash ( ) , hash ) ;
2016-09-15 00:37:37 +02:00
}
2022-06-18 16:20:55 +02:00
hash = hash_murmur3_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 ) ;
2022-06-18 16:20:55 +02:00
hash = hash_murmur3_one_64 ( da . hash ( ) , hash ) ;
2016-09-15 00:37:37 +02:00
}
2022-06-18 16:20:55 +02:00
hash = hash_murmur3_one_64 ( mb - > get_hint_flags ( ) , hash ) ;
2016-09-15 00:37:37 +02:00
}
}
{ //constants
List < StringName > snames ;
2022-05-09 11:47:10 +02:00
for ( const KeyValue < StringName , int64_t > & F : t - > constant_map ) {
2022-05-08 10:09:19 +02:00
snames . push_back ( F . key ) ;
2016-09-15 00:37:37 +02:00
}
snames . sort_custom < StringName : : AlphCompare > ( ) ;
2021-07-24 15:46:25 +02:00
for ( const StringName & F : snames ) {
2022-06-18 16:20:55 +02:00
hash = hash_murmur3_one_64 ( F . hash ( ) , hash ) ;
hash = hash_murmur3_one_64 ( t - > constant_map [ F ] , hash ) ;
2016-09-15 00:37:37 +02:00
}
}
{ //signals
List < StringName > snames ;
2022-05-08 10:09:19 +02:00
for ( const KeyValue < StringName , MethodInfo > & F : t - > signal_map ) {
snames . push_back ( F . key ) ;
2016-09-15 00:37:37 +02:00
}
snames . sort_custom < StringName : : AlphCompare > ( ) ;
2021-07-24 15:46:25 +02:00
for ( const StringName & F : snames ) {
2021-07-16 05:45:57 +02:00
MethodInfo & mi = t - > signal_map [ F ] ;
2022-06-18 16:20:55 +02:00
hash = hash_murmur3_one_64 ( F . hash ( ) , hash ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < mi . arguments . size ( ) ; i + + ) {
2022-06-18 16:20:55 +02:00
hash = hash_murmur3_one_64 ( mi . arguments [ i ] . type , hash ) ;
2016-09-15 00:37:37 +02:00
}
}
}
{ //properties
List < StringName > snames ;
2022-05-08 10:09:19 +02:00
for ( const KeyValue < StringName , PropertySetGet > & F : t - > property_setget ) {
snames . push_back ( F . key ) ;
2016-09-15 00:37:37 +02:00
}
snames . sort_custom < StringName : : AlphCompare > ( ) ;
2021-07-24 15:46:25 +02:00
for ( const StringName & F : snames ) {
2021-07-16 05:45:57 +02:00
PropertySetGet * psg = t - > property_setget . getptr ( F ) ;
2019-07-23 09:14:31 +02:00
ERR_FAIL_COND_V ( ! psg , 0 ) ;
2016-09-15 00:37:37 +02:00
2022-06-18 16:20:55 +02:00
hash = hash_murmur3_one_64 ( F . hash ( ) , hash ) ;
hash = hash_murmur3_one_64 ( psg - > setter . hash ( ) , hash ) ;
hash = hash_murmur3_one_64 ( psg - > getter . hash ( ) , hash ) ;
2016-09-15 00:37:37 +02:00
}
}
//property list
2021-07-24 15:46:25 +02:00
for ( const PropertyInfo & F : t - > property_list ) {
2022-06-18 16:20:55 +02:00
hash = hash_murmur3_one_64 ( F . name . hash ( ) , hash ) ;
hash = hash_murmur3_one_64 ( F . type , hash ) ;
hash = hash_murmur3_one_64 ( F . hint , hash ) ;
hash = hash_murmur3_one_64 ( F . hint_string . hash ( ) , hash ) ;
hash = hash_murmur3_one_64 ( F . usage , hash ) ;
2016-09-15 00:37:37 +02:00
}
}
2022-06-18 16:20:55 +02:00
return hash_fmix32 ( hash ) ;
2016-09-15 00:37:37 +02:00
# 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
}
2022-07-14 14:18:18 +02:00
StringName ClassDB : : get_compatibility_class ( const StringName & p_class ) {
if ( compat_classes . has ( p_class ) ) {
return compat_classes [ p_class ] ;
}
return StringName ( ) ;
}
2021-06-18 00:03:09 +02:00
Object * ClassDB : : instantiate ( const StringName & p_class ) {
2017-01-03 03:03:46 +01:00
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. " ) ;
2021-10-05 14:09:09 +02:00
ERR_FAIL_COND_V_MSG ( ! ti - > creation_func , nullptr , " Class ' " + String ( p_class ) + " ' or its base class cannot be instantiated. " ) ;
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-11-24 10:22:12 +01:00
if ( ti - > native_extension & & ti - > native_extension - > create_instance ) {
return ( Object * ) ti - > native_extension - > create_instance ( ti - > native_extension - > class_userdata ) ;
} else {
return ti - > creation_func ( ) ;
2021-06-04 19:33:48 +02:00
}
2014-02-10 02:10:30 +01:00
}
2020-05-14 14:29:06 +02:00
2021-11-24 10:22:12 +01:00
void ClassDB : : set_object_extension_instance ( Object * p_object , const StringName & p_class , GDExtensionClassInstancePtr p_instance ) {
ERR_FAIL_COND ( ! p_object ) ;
ClassInfo * ti ;
{
OBJTYPE_RLOCK ;
ti = classes . getptr ( p_class ) ;
if ( ! ti | | ti - > disabled | | ! ti - > creation_func | | ( ti - > native_extension & & ! ti - > native_extension - > create_instance ) ) {
if ( compat_classes . has ( p_class ) ) {
ti = classes . getptr ( compat_classes [ p_class ] ) ;
}
}
ERR_FAIL_COND_MSG ( ! ti , " Cannot get class ' " + String ( p_class ) + " '. " ) ;
ERR_FAIL_COND_MSG ( ti - > disabled , " Class ' " + String ( p_class ) + " ' is disabled. " ) ;
ERR_FAIL_COND_MSG ( ! ti - > native_extension , " Class ' " + String ( p_class ) + " ' has no native extension. " ) ;
2021-09-22 18:33:29 +02:00
}
2021-11-24 10:22:12 +01:00
p_object - > _extension = ti - > native_extension ;
p_object - > _extension_instance = p_instance ;
2021-09-21 03:54:50 +02:00
}
2021-06-18 00:03:09 +02:00
bool ClassDB : : can_instantiate ( 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
}
2022-03-10 08:17:38 +01:00
bool ClassDB : : is_virtual ( const StringName & p_class ) {
OBJTYPE_RLOCK ;
ClassInfo * ti = classes . getptr ( p_class ) ;
ERR_FAIL_COND_V_MSG ( ! ti , false , " Cannot get class ' " + String ( p_class ) + " '. " ) ;
# ifdef TOOLS_ENABLED
if ( ti - > api = = API_EDITOR & & ! Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
return false ;
}
# endif
return ( ! ti - > disabled & & ti - > creation_func ! = nullptr & & ! ( ti - > native_extension & & ! ti - > native_extension - > create_instance ) & & ti - > is_virtual ) ;
}
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
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 ;
}
2021-07-19 19:25:15 +02:00
void ClassDB : : get_method_list ( const 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
2021-07-24 15:46:25 +02:00
for ( const MethodInfo & E : type - > virtual_methods ) {
2021-07-16 05:45:57 +02:00
p_methods - > push_back ( E ) ;
2014-02-10 02:10:30 +01:00
}
2021-07-24 15:46:25 +02:00
for ( const StringName & E : type - > method_order ) {
2021-07-16 05:45:57 +02:00
if ( p_exclude_from_properties & & type - > methods_in_properties . has ( E ) ) {
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
2021-07-16 05:45:57 +02:00
MethodBind * method = type - > method_map . get ( E ) ;
2020-06-10 23:13:25 +02:00
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
2022-05-08 10:09:19 +02:00
for ( KeyValue < StringName , MethodBind * > & E : type - > method_map ) {
MethodBind * m = E . value ;
2021-10-07 20:18:52 +02:00
MethodInfo minfo = info_from_bind ( m ) ;
p_methods - > push_back ( minfo ) ;
2014-02-10 02:10:30 +01:00
}
# 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
}
}
2021-07-19 19:25:15 +02:00
bool ClassDB : : get_method_info ( const StringName & p_class , const StringName & p_method , MethodInfo * r_info , bool p_no_inheritance , bool p_exclude_from_properties ) {
2020-06-10 23:13:25 +02:00
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 ] ;
2021-10-07 20:18:52 +02:00
MethodInfo minfo = info_from_bind ( m ) ;
* r_info = minfo ;
2020-06-10 23:13:25 +02:00
}
return true ;
}
# endif
if ( p_no_inheritance ) {
break ;
}
type = type - > inherits_ptr ;
}
return false ;
}
2021-07-19 19:25:15 +02:00
MethodBind * ClassDB : : get_method ( const StringName & p_class , const 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
}
2022-06-24 11:16:37 +02:00
void ClassDB : : bind_integer_constant ( const StringName & p_class , const StringName & p_enum , const StringName & p_name , int64_t p_constant , bool p_is_bitfield ) {
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 ;
2021-12-09 10:42:46 +01:00
if ( ! enum_name . is_empty ( ) ) {
2022-02-03 17:03:38 +01:00
if ( enum_name . contains ( " . " ) ) {
2017-08-27 14:16:32 +02:00
enum_name = enum_name . get_slicec ( ' . ' , 1 ) ;
2017-08-24 05:06:56 +02:00
}
2022-06-24 11:16:37 +02:00
ClassInfo : : EnumInfo * constants_list = type - > enum_map . getptr ( enum_name ) ;
2017-08-24 05:06:56 +02:00
if ( constants_list ) {
2022-06-24 11:16:37 +02:00
constants_list - > constants . push_back ( p_name ) ;
constants_list - > is_bitfield = p_is_bitfield ;
2017-08-24 05:06:56 +02:00
} else {
2022-06-24 11:16:37 +02:00
ClassInfo : : EnumInfo new_list ;
new_list . is_bitfield = p_is_bitfield ;
new_list . constants . push_back ( p_name ) ;
2017-08-24 05:06:56 +02:00
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
2021-07-24 15:46:25 +02:00
for ( const StringName & E : type - > constant_order ) {
2021-07-16 05:45:57 +02:00
p_constants - > push_back ( E ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
# else
2022-05-09 11:47:10 +02:00
for ( const KeyValue < StringName , int64_t > & E : type - > constant_map ) {
2022-05-08 10:09:19 +02:00
p_constants - > push_back ( E . key ) ;
2014-02-10 02:10:30 +01:00
}
# 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
}
}
2022-05-09 11:47:10 +02:00
int64_t 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 ) {
2022-05-09 11:47:10 +02:00
int64_t * 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 ) {
2022-06-24 11:16:37 +02:00
for ( KeyValue < StringName , ClassInfo : : EnumInfo > & E : type - > enum_map ) {
List < StringName > & constants_list = E . value . constants ;
2017-08-20 17:45:01 +02:00
const List < StringName > : : Element * found = constants_list . find ( p_name ) ;
2020-05-14 16:41:43 +02:00
if ( found ) {
2022-05-08 10:09:19 +02:00
return E . key ;
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 ) {
2022-06-24 11:16:37 +02:00
for ( KeyValue < StringName , ClassInfo : : EnumInfo > & E : type - > enum_map ) {
2022-05-08 10:09:19 +02:00
p_enums - > push_back ( E . key ) ;
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 ;
}
}
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 ) {
2022-06-24 11:16:37 +02:00
const ClassInfo : : EnumInfo * constants = type - > enum_map . getptr ( p_enum ) ;
2017-08-20 17:45:01 +02:00
if ( constants ) {
2022-06-24 11:16:37 +02:00
for ( const List < StringName > : : Element * E = constants - > constants . front ( ) ; E ; E = E - > next ( ) ) {
2017-08-20 17:45:01 +02:00
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 ;
}
}
2021-08-24 20:16:25 +02:00
void ClassDB : : set_method_error_return_values ( const StringName & p_class , const StringName & p_method , const Vector < Error > & p_values ) {
OBJTYPE_RLOCK ;
# ifdef DEBUG_METHODS_ENABLED
ClassInfo * type = classes . getptr ( p_class ) ;
ERR_FAIL_COND ( ! type ) ;
type - > method_error_values [ p_method ] = p_values ;
# endif
}
Vector < Error > ClassDB : : get_method_error_return_values ( const StringName & p_class , const StringName & p_method ) {
# ifdef DEBUG_METHODS_ENABLED
ClassInfo * type = classes . getptr ( p_class ) ;
ERR_FAIL_COND_V ( ! type , Vector < Error > ( ) ) ;
if ( ! type - > method_error_values . has ( p_method ) ) {
return Vector < Error > ( ) ;
}
return type - > method_error_values [ p_method ] ;
# else
return Vector < Error > ( ) ;
# endif
}
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 ;
}
2022-06-24 11:16:37 +02:00
bool ClassDB : : is_enum_bitfield ( 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 ) & & type - > enum_map [ p_name ] . is_bitfield ) {
return true ;
}
if ( p_no_inheritance ) {
return false ;
}
type = type - > inherits_ptr ;
}
return false ;
}
2021-07-19 19:25:15 +02:00
void ClassDB : : add_signal ( const 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
}
2021-07-19 19:25:15 +02:00
void ClassDB : : get_signal_list ( const 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 ) {
2022-05-08 10:09:19 +02:00
for ( KeyValue < StringName , MethodInfo > & E : check - > signal_map ) {
p_signals - > push_back ( E . value ) ;
2014-02-10 02:10:30 +01:00
}
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
}
}
2021-07-19 19:25:15 +02:00
bool ClassDB : : has_signal ( const StringName & p_class , const 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 ;
}
2021-07-19 19:25:15 +02:00
bool ClassDB : : get_signal ( const StringName & p_class , const 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 ;
}
2021-11-08 21:53:41 +01:00
void ClassDB : : add_property_group ( const StringName & p_class , const String & p_name , const String & p_prefix , int p_indent_depth ) {
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 ) ;
2021-11-08 21:53:41 +01:00
String prefix = p_prefix ;
if ( p_indent_depth > 0 ) {
prefix = vformat ( " %s,%d " , p_prefix , p_indent_depth ) ;
}
type - > property_list . push_back ( PropertyInfo ( Variant : : NIL , p_name , PROPERTY_HINT_NONE , prefix , PROPERTY_USAGE_GROUP ) ) ;
2017-01-03 04:38:16 +01:00
}
2021-11-08 21:53:41 +01:00
void ClassDB : : add_property_subgroup ( const StringName & p_class , const String & p_name , const String & p_prefix , int p_indent_depth ) {
2020-04-08 03:51:52 +02:00
OBJTYPE_WLOCK ;
ClassInfo * type = classes . getptr ( p_class ) ;
ERR_FAIL_COND ( ! type ) ;
2021-11-08 21:53:41 +01:00
String prefix = p_prefix ;
if ( p_indent_depth > 0 ) {
prefix = vformat ( " %s,%d " , p_prefix , p_indent_depth ) ;
}
type - > property_list . push_back ( PropertyInfo ( Variant : : NIL , p_name , PROPERTY_HINT_NONE , prefix , PROPERTY_USAGE_SUBGROUP ) ) ;
2020-04-08 03:51:52 +02:00
}
2021-08-31 10:48:45 +02:00
void ClassDB : : add_property_array_count ( const StringName & p_class , const String & p_label , const StringName & p_count_property , const StringName & p_count_setter , const StringName & p_count_getter , const String & p_array_element_prefix , uint32_t p_count_usage ) {
add_property ( p_class , PropertyInfo ( Variant : : INT , p_count_property , PROPERTY_HINT_NONE , " " , p_count_usage | PROPERTY_USAGE_ARRAY , vformat ( " %s,%s " , p_label , p_array_element_prefix ) ) , p_count_setter , p_count_getter ) ;
}
void ClassDB : : add_property_array ( const StringName & p_class , const StringName & p_path , const String & p_array_element_prefix ) {
OBJTYPE_WLOCK ;
ClassInfo * type = classes . getptr ( p_class ) ;
ERR_FAIL_COND ( ! type ) ;
type - > property_list . push_back ( PropertyInfo ( Variant : : NIL , p_path , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY , p_array_element_prefix ) ) ;
}
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.
2021-07-19 19:25:15 +02:00
void ClassDB : : add_property ( const 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
}
2021-07-19 19:25:15 +02:00
void ClassDB : : set_property_default_value ( const StringName & p_class , const StringName & p_name , const Variant & p_default ) {
2019-06-01 15:42:22 +02:00
if ( ! default_values . has ( p_class ) ) {
default_values [ p_class ] = HashMap < StringName , Variant > ( ) ;
}
default_values [ p_class ] [ p_name ] = p_default ;
}
2021-08-12 20:26:47 +02:00
void ClassDB : : add_linked_property ( const StringName & p_class , const String & p_property , const String & p_linked_property ) {
# ifdef TOOLS_ENABLED
OBJTYPE_WLOCK ;
ClassInfo * type = classes . getptr ( p_class ) ;
ERR_FAIL_COND ( ! type ) ;
ERR_FAIL_COND ( ! type - > property_map . has ( p_property ) ) ;
ERR_FAIL_COND ( ! type - > property_map . has ( p_linked_property ) ) ;
2022-07-21 01:18:14 +02:00
if ( ! type - > linked_properties . has ( p_property ) ) {
type - > linked_properties . insert ( p_property , List < StringName > ( ) ) ;
}
type - > linked_properties [ p_property ] . push_back ( p_linked_property ) ;
2021-08-12 20:26:47 +02:00
# endif
}
2021-07-19 19:25:15 +02:00
void ClassDB : : get_property_list ( const 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 ) {
2021-07-24 15:46:25 +02:00
for ( const PropertyInfo & pi : check - > property_list ) {
2016-05-15 04:48:23 +02:00
if ( p_validator ) {
2021-07-24 15:46:25 +02:00
// Making a copy as we may modify it.
PropertyInfo pi_mut = pi ;
2022-08-12 22:57:11 +02:00
p_validator - > validate_property ( pi_mut ) ;
2021-07-24 15:46:25 +02:00
p_list - > push_back ( pi_mut ) ;
2016-05-15 04:48:23 +02:00
} else {
2021-07-16 05:45:57 +02:00
p_list - > push_back ( pi ) ;
2016-05-15 04:48:23 +02:00
}
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
2022-07-21 01:18:14 +02:00
void ClassDB : : get_linked_properties_info ( const StringName & p_class , const StringName & p_property , List < StringName > * r_properties , bool p_no_inheritance ) {
# ifdef TOOLS_ENABLED
ClassInfo * check = classes . getptr ( p_class ) ;
while ( check ) {
if ( ! check - > linked_properties . has ( p_property ) ) {
return ;
}
for ( const StringName & E : check - > linked_properties [ p_property ] ) {
r_properties - > push_back ( E ) ;
}
if ( p_no_inheritance ) {
break ;
}
check = check - > inherits_ptr ;
}
# endif
}
2021-07-19 19:25:15 +02:00
bool ClassDB : : get_property_info ( const StringName & p_class , const StringName & p_property , PropertyInfo * r_info , bool p_no_inheritance , const Object * p_validator ) {
2020-06-10 23:13:25 +02:00
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 ) {
2022-08-12 22:57:11 +02:00
p_validator - > validate_property ( pinfo ) ;
2020-06-10 23:13:25 +02:00
}
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 {
2022-03-09 14:58:40 +01:00
p_object - > callp ( 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 {
2022-03-09 14:58:40 +01:00
p_object - > callp ( 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 ;
2022-03-09 14:58:40 +01:00
r_value = p_object - > callp ( 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 {
2022-03-09 14:58:40 +01:00
r_value = p_object - > callp ( psg - > getter , nullptr , 0 , ce ) ;
2014-02-10 02:10:30 +01:00
}
}
return true ;
}
2022-05-09 11:47:10 +02:00
const int64_t * 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 ;
}
2021-07-19 19:25:15 +02:00
StringName ClassDB : : get_property_setter ( const 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 ( ) ;
}
2021-07-19 19:25:15 +02:00
StringName ClassDB : : get_property_getter ( const 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
2021-07-19 19:25:15 +02:00
void ClassDB : : set_method_flags ( const StringName & p_class , const 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 ) ;
}
2021-07-19 19:25:15 +02:00
bool ClassDB : : has_method ( const StringName & p_class , const StringName & p_method , bool p_no_inheritance ) {
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 - > 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 ;
}
2022-04-06 01:40:07 +02: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 ;
2022-04-06 01:40:07 +02:00
# else
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 ) ;
# endif
2014-02-10 02:10:30 +01:00
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 ;
}
2021-08-22 03:52:44 +02:00
void ClassDB : : add_virtual_method ( const StringName & p_class , const MethodInfo & p_method , bool p_virtual , const Vector < String > & p_arg_names , bool p_object_core ) {
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
}
2021-08-22 03:52:44 +02:00
if ( p_object_core ) {
mi . flags | = METHOD_FLAG_OBJECT_CORE ;
}
2022-03-26 16:48:43 +01:00
if ( ! p_object_core ) {
2021-08-22 03:52:44 +02:00
if ( p_arg_names . size ( ) ! = mi . arguments . size ( ) ) {
2022-03-26 16:48:43 +01:00
WARN_PRINT ( " Mismatch argument name count for virtual method: " + String ( p_class ) + " :: " + p_method . name ) ;
2021-08-22 03:52:44 +02:00
} else {
for ( int i = 0 ; i < p_arg_names . size ( ) ; i + + ) {
mi . arguments [ i ] . name = p_arg_names [ i ] ;
}
}
}
2022-03-26 16:48:43 +01:00
if ( classes [ p_class ] . virtual_methods_map . has ( p_method . name ) ) {
// overloading not supported
ERR_FAIL_MSG ( " Virtual method already bound ' " + String ( p_class ) + " :: " + p_method . name + " '. " ) ;
}
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 ) {
2021-07-24 15:46:25 +02:00
for ( const MethodInfo & E : check - > virtual_methods ) {
2021-07-16 05:45:57 +02:00
p_methods - > push_back ( E ) ;
2014-12-18 04:56:33 +01:00
}
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
}
2021-07-19 19:25:15 +02:00
void ClassDB : : set_class_enabled ( const 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
}
2021-07-19 19:25:15 +02:00
bool ClassDB : : is_class_enabled ( const 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
}
2021-07-19 19:25:15 +02:00
bool ClassDB : : is_class_exposed ( const StringName & p_class ) {
2017-10-09 23:49:17 +02:00
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
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 ) {
2022-05-08 10:09:19 +02:00
for ( const KeyValue < StringName , StringName > & E : resource_base_extensions ) {
p_extensions - > push_back ( E . key ) ;
2014-02-10 02:10:30 +01:00
}
}
2021-07-23 21:01:18 +02:00
bool ClassDB : : is_resource_extension ( const StringName & p_extension ) {
return resource_base_extensions . has ( p_extension ) ;
}
2017-03-05 16:44:50 +01:00
void ClassDB : : get_extensions_for_type ( const StringName & p_class , List < String > * p_extensions ) {
2022-05-08 10:09:19 +02:00
for ( const KeyValue < StringName , StringName > & E : resource_base_extensions ) {
if ( is_parent_class ( p_class , E . value ) | | is_parent_class ( E . value , p_class ) ) {
p_extensions - > push_back ( E . key ) ;
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 ;
2022-05-19 17:00:06 +02:00
HashSet < 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 ;
2022-03-14 15:52:03 +01:00
} else if ( ClassDB : : can_instantiate ( p_class ) & & ! ClassDB : : is_virtual ( p_class ) ) {
2021-06-18 00:03:09 +02:00
c = ClassDB : : instantiate ( 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 ) ;
2021-07-24 15:46:25 +02:00
for ( const PropertyInfo & E : plist ) {
2021-07-16 05:45:57 +02:00
if ( E . usage & ( PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR ) ) {
if ( ! default_values [ p_class ] . has ( E . name ) ) {
Variant v = c - > get ( E . name ) ;
default_values [ p_class ] [ E . name ] = v ;
2019-06-01 15:42:22 +02:00
}
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
2020-10-22 21:02:57 +02:00
// to be auto-instantiated when created in the editor with the following method:
// EditorNode::get_editor_data().instantiate_object_properties(obj);
2020-06-12 13:16:14 +02:00
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 ) ) ;
2021-07-29 15:19:28 +02:00
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 ) ) ;
2021-06-04 19:33:48 +02:00
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 ;
2021-07-29 15:19:28 +02:00
c . exposed = true ;
2021-06-04 19:33:48 +02:00
classes [ p_extension - > class_name ] = c ;
}
2021-06-19 17:58:49 +02:00
void ClassDB : : unregister_extension_class ( const StringName & p_class ) {
ERR_FAIL_COND ( ! classes . has ( p_class ) ) ;
classes . erase ( p_class ) ;
}
2022-05-13 15:04:37 +02:00
HashMap < StringName , ClassDB : : NativeStruct > ClassDB : : native_structs ;
2022-03-14 15:52:03 +01:00
void ClassDB : : register_native_struct ( const StringName & p_name , const String & p_code , uint64_t p_current_size ) {
NativeStruct ns ;
ns . ccode = p_code ;
ns . struct_size = p_current_size ;
native_structs [ p_name ] = ns ;
}
void ClassDB : : get_native_struct_list ( List < StringName > * r_names ) {
for ( const KeyValue < StringName , NativeStruct > & E : native_structs ) {
r_names - > push_back ( E . key ) ;
}
}
String ClassDB : : get_native_struct_code ( const StringName & p_name ) {
ERR_FAIL_COND_V ( ! native_structs . has ( p_name ) , String ( ) ) ;
return native_structs [ p_name ] . ccode ;
}
uint64_t ClassDB : : get_native_struct_size ( const StringName & p_name ) {
ERR_FAIL_COND_V ( ! native_structs . has ( p_name ) , 0 ) ;
return native_structs [ p_name ] . struct_size ;
}
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
2022-05-08 10:09:19 +02:00
for ( KeyValue < StringName , ClassInfo > & E : classes ) {
ClassInfo & ti = E . value ;
2016-03-09 00:00:52 +01:00
2022-05-08 10:09:19 +02:00
for ( KeyValue < StringName , MethodBind * > & F : ti . method_map ) {
memdelete ( F . value ) ;
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 ( ) ;
2022-03-14 15:52:03 +01:00
native_structs . clear ( ) ;
2014-02-10 02:10:30 +01:00
}
//