2017-12-06 21:36:34 +01:00
/**************************************************************************/
2014-02-10 02:10:30 +01:00
/* object.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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
2014-02-10 02:10:30 +01:00
# ifndef OBJECT_H
# define OBJECT_H
2022-12-07 12:11:28 +01:00
# include "core/extension/gdextension_interface.h"
2022-03-09 14:58:40 +01:00
# include "core/object/message_queue.h"
2020-11-07 23:33:38 +01:00
# include "core/object/object_id.h"
2018-09-11 18:13:45 +02:00
# include "core/os/rw_lock.h"
2020-11-07 23:33:38 +01:00
# include "core/os/spin_lock.h"
# include "core/templates/hash_map.h"
2022-05-19 17:00:06 +02:00
# include "core/templates/hash_set.h"
2020-11-07 23:33:38 +01:00
# include "core/templates/list.h"
2022-05-13 15:04:37 +02:00
# include "core/templates/rb_map.h"
2021-02-10 19:22:13 +01:00
# include "core/templates/safe_refcount.h"
2020-11-07 23:33:38 +01:00
# include "core/variant/callable_bind.h"
# include "core/variant/variant.h"
2014-02-10 02:10:30 +01:00
2022-08-05 20:35:08 +02:00
template < typename T >
class TypedArray ;
2014-02-10 02:10:30 +01:00
enum PropertyHint {
PROPERTY_HINT_NONE , ///< no hint provided.
2023-09-23 16:27:01 +02:00
PROPERTY_HINT_RANGE , ///< hint_text = "min,max[,step][,or_greater][,or_less][,hide_slider][,radians_as_degrees][,degrees][,exp][,suffix:<keyword>] range.
2014-02-10 02:10:30 +01:00
PROPERTY_HINT_ENUM , ///< hint_text= "val1,val2,val3,etc"
2021-07-04 22:42:23 +02:00
PROPERTY_HINT_ENUM_SUGGESTION , ///< hint_text= "val1,val2,val3,etc"
2021-10-07 18:17:25 +02:00
PROPERTY_HINT_EXP_EASING , /// exponential easing function (Math::ease) use "attenuation" hint string to revert (flip h), "positive_only" to exclude in-out and out-in. (ie: "attenuation,positive_only")
2022-04-05 02:58:21 +02:00
PROPERTY_HINT_LINK ,
2014-02-10 02:10:30 +01:00
PROPERTY_HINT_FLAGS , ///< hint_text= "flag1,flag2,etc" (as bit flags)
2017-01-11 02:20:57 +01:00
PROPERTY_HINT_LAYERS_2D_RENDER ,
PROPERTY_HINT_LAYERS_2D_PHYSICS ,
2021-03-08 20:56:33 +01:00
PROPERTY_HINT_LAYERS_2D_NAVIGATION ,
2017-01-11 02:20:57 +01:00
PROPERTY_HINT_LAYERS_3D_RENDER ,
PROPERTY_HINT_LAYERS_3D_PHYSICS ,
2021-03-08 20:56:33 +01:00
PROPERTY_HINT_LAYERS_3D_NAVIGATION ,
2015-08-30 02:09:11 +02:00
PROPERTY_HINT_FILE , ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
2017-09-22 05:58:29 +02:00
PROPERTY_HINT_DIR , ///< a directory path must be passed
2014-02-10 02:10:30 +01:00
PROPERTY_HINT_GLOBAL_FILE , ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
2017-09-22 05:58:29 +02:00
PROPERTY_HINT_GLOBAL_DIR , ///< a directory path must be passed
2014-02-10 02:10:30 +01:00
PROPERTY_HINT_RESOURCE_TYPE , ///< a resource object type
2015-08-30 02:09:11 +02:00
PROPERTY_HINT_MULTILINE_TEXT , ///< used for string properties that can contain multiple lines
2022-06-27 22:10:04 +02:00
PROPERTY_HINT_EXPRESSION , ///< used for string properties that can contain multiple lines
2018-08-17 03:50:12 +02:00
PROPERTY_HINT_PLACEHOLDER_TEXT , ///< used to set a placeholder text for string properties
2014-02-10 02:10:30 +01:00
PROPERTY_HINT_COLOR_NO_ALPHA , ///< used for ignoring alpha component when editing a color
2016-05-23 00:28:37 +02:00
PROPERTY_HINT_OBJECT_ID ,
2016-08-03 00:11:05 +02:00
PROPERTY_HINT_TYPE_STRING , ///< a type string, the hint is the base type to choose
2023-10-20 02:39:06 +02:00
PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE , // Deprecated.
2017-08-18 15:59:31 +02:00
PROPERTY_HINT_OBJECT_TOO_BIG , ///< object is too big to send
2018-06-28 01:50:25 +02:00
PROPERTY_HINT_NODE_PATH_VALID_TYPES ,
2019-04-19 20:54:33 +02:00
PROPERTY_HINT_SAVE_FILE , ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,". This opens a save dialog
Implement Running Godot as Movie Writer
* Allows running the game in "movie writer" mode.
* It ensures entirely stable framerate, so your run can be saved stable and with proper sound (which is impossible if your CPU/GPU can't sustain doing this in real-time).
* If disabling vsync, it can save movies faster than the game is run, but if you want to control the interaction it can get difficult.
* Implements a simple, default MJPEG writer.
This new features has two main use cases, which have high demand:
* Saving game videos in high quality and ensuring the frame rate is *completely* stable, always.
* Using Godot as a tool to make movies and animations (which is ideal if you want interaction, or creating them procedurally. No other software is as good for this).
**Note**: This feature **IS NOT** for capturing real-time footage. Use something like OBS, SimpleScreenRecorder or FRAPS to achieve that, as they do a much better job at intercepting the compositor than Godot can probably do using Vulkan or OpenGL natively. If your game runs near real-time when capturing, you can still use this feature but it will play no sound (sound will be saved directly).
Usage:
$ godot --write-movie movie.avi [scene_file.tscn]
Missing:
* Options for configuring video writing via GLOBAL_DEF
* UI Menu for launching with this mode from the editor.
* Add to list of command line options.
* Add a feature tag to override configurations when movie writing (fantastic for saving videos with highest quality settings).
2022-06-17 00:55:19 +02:00
PROPERTY_HINT_GLOBAL_SAVE_FILE , ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,". This opens a save dialog
2023-10-20 02:39:06 +02:00
PROPERTY_HINT_INT_IS_OBJECTID , // Deprecated.
2021-08-23 19:53:27 +02:00
PROPERTY_HINT_INT_IS_POINTER ,
2022-10-21 01:02:29 +02:00
PROPERTY_HINT_ARRAY_TYPE ,
2021-09-23 13:08:50 +02:00
PROPERTY_HINT_LOCALE_ID ,
2022-03-04 14:04:59 +01:00
PROPERTY_HINT_LOCALIZABLE_STRING ,
2022-06-19 00:42:02 +02:00
PROPERTY_HINT_NODE_TYPE , ///< a node object type
2022-08-21 09:03:38 +02:00
PROPERTY_HINT_HIDE_QUATERNION_EDIT , /// Only Node3D::transform should hide the quaternion editor.
2022-08-09 17:51:43 +02:00
PROPERTY_HINT_PASSWORD ,
2023-05-12 01:37:59 +02:00
PROPERTY_HINT_LAYERS_AVOIDANCE ,
2014-02-10 02:10:30 +01:00
PROPERTY_HINT_MAX ,
} ;
enum PropertyUsageFlags {
2021-06-18 01:10:18 +02:00
PROPERTY_USAGE_NONE = 0 ,
2022-04-23 02:54:57 +02:00
PROPERTY_USAGE_STORAGE = 1 < < 1 ,
PROPERTY_USAGE_EDITOR = 1 < < 2 ,
2023-01-09 15:31:44 +01:00
PROPERTY_USAGE_INTERNAL = 1 < < 3 ,
PROPERTY_USAGE_CHECKABLE = 1 < < 4 , // Used for editing global variables.
PROPERTY_USAGE_CHECKED = 1 < < 5 , // Used for editing global variables.
2022-04-23 02:54:57 +02:00
PROPERTY_USAGE_GROUP = 1 < < 6 , // Used for grouping props in the editor.
PROPERTY_USAGE_CATEGORY = 1 < < 7 ,
PROPERTY_USAGE_SUBGROUP = 1 < < 8 ,
PROPERTY_USAGE_CLASS_IS_BITFIELD = 1 < < 9 ,
PROPERTY_USAGE_NO_INSTANCE_STATE = 1 < < 10 ,
PROPERTY_USAGE_RESTART_IF_CHANGED = 1 < < 11 ,
PROPERTY_USAGE_SCRIPT_VARIABLE = 1 < < 12 ,
PROPERTY_USAGE_STORE_IF_NULL = 1 < < 13 ,
2022-11-29 10:51:45 +01:00
PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED = 1 < < 14 ,
2023-10-20 02:39:06 +02:00
PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE = 1 < < 15 , // Deprecated.
2022-11-29 10:51:45 +01:00
PROPERTY_USAGE_CLASS_IS_ENUM = 1 < < 16 ,
PROPERTY_USAGE_NIL_IS_VARIANT = 1 < < 17 ,
2023-01-09 15:31:44 +01:00
PROPERTY_USAGE_ARRAY = 1 < < 18 , // Used in the inspector to group properties as elements of an array.
2023-01-10 07:04:35 +01:00
PROPERTY_USAGE_ALWAYS_DUPLICATE = 1 < < 19 , // When duplicating a resource, always duplicate, even with subresource duplication disabled.
2023-01-10 21:42:05 +01:00
PROPERTY_USAGE_NEVER_DUPLICATE = 1 < < 20 , // When duplicating a resource, never duplicate, even with subresource duplication enabled.
PROPERTY_USAGE_HIGH_END_GFX = 1 < < 21 ,
PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT = 1 < < 22 ,
PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT = 1 < < 23 ,
PROPERTY_USAGE_KEYING_INCREMENTS = 1 < < 24 , // Used in inspector to increment property when keyed in animation player.
2023-10-20 02:39:06 +02:00
PROPERTY_USAGE_DEFERRED_SET_RESOURCE = 1 < < 25 , // Deprecated.
2023-01-10 21:42:05 +01:00
PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT = 1 < < 26 , // For Object properties, instantiate them when creating in editor.
PROPERTY_USAGE_EDITOR_BASIC_SETTING = 1 < < 27 , //for project or editor settings, show when basic settings are selected.
PROPERTY_USAGE_READ_ONLY = 1 < < 28 , // Mark a property as read-only in the inspector.
2023-05-10 11:40:17 +02:00
PROPERTY_USAGE_SECRET = 1 < < 29 , // Export preset credentials that should be stored separately from the rest of the export config.
2022-04-23 02:54:57 +02:00
PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR ,
PROPERTY_USAGE_NO_EDITOR = PROPERTY_USAGE_STORAGE ,
2014-02-10 02:10:30 +01:00
} ;
2021-08-13 16:46:14 +02:00
# define ADD_SIGNAL(m_signal) ::ClassDB::add_signal(get_class_static(), m_signal)
# define ADD_PROPERTY(m_property, m_setter, m_getter) ::ClassDB::add_property(get_class_static(), m_property, _scs_create(m_setter), _scs_create(m_getter))
# define ADD_PROPERTYI(m_property, m_setter, m_getter, m_index) ::ClassDB::add_property(get_class_static(), m_property, _scs_create(m_setter), _scs_create(m_getter), m_index)
# define ADD_PROPERTY_DEFAULT(m_property, m_default) ::ClassDB::set_property_default_value(get_class_static(), m_property, m_default)
# define ADD_GROUP(m_name, m_prefix) ::ClassDB::add_property_group(get_class_static(), m_name, m_prefix)
2021-11-08 21:53:41 +01:00
# define ADD_GROUP_INDENT(m_name, m_prefix, m_depth) ::ClassDB::add_property_group(get_class_static(), m_name, m_prefix, m_depth)
2021-08-13 16:46:14 +02:00
# define ADD_SUBGROUP(m_name, m_prefix) ::ClassDB::add_property_subgroup(get_class_static(), m_name, m_prefix)
2021-11-08 21:53:41 +01:00
# define ADD_SUBGROUP_INDENT(m_name, m_prefix, m_depth) ::ClassDB::add_property_subgroup(get_class_static(), m_name, m_prefix, m_depth)
2021-08-12 20:26:47 +02:00
# define ADD_LINKED_PROPERTY(m_property, m_linked_property) ::ClassDB::add_linked_property(get_class_static(), m_property, m_linked_property)
2014-02-10 02:10:30 +01:00
2021-08-31 10:48:45 +02:00
# define ADD_ARRAY_COUNT(m_label, m_count_property, m_count_property_setter, m_count_property_getter, m_prefix) ClassDB::add_property_array_count(get_class_static(), m_label, m_count_property, _scs_create(m_count_property_setter), _scs_create(m_count_property_getter), m_prefix)
# define ADD_ARRAY_COUNT_WITH_USAGE_FLAGS(m_label, m_count_property, m_count_property_setter, m_count_property_getter, m_prefix, m_property_usage_flags) ClassDB::add_property_array_count(get_class_static(), m_label, m_count_property, _scs_create(m_count_property_setter), _scs_create(m_count_property_getter), m_prefix, m_property_usage_flags)
# define ADD_ARRAY(m_array_path, m_prefix) ClassDB::add_property_array(get_class_static(), m_array_path, m_prefix)
2022-11-22 16:10:41 +01:00
// Helper macro to use with PROPERTY_HINT_ARRAY_TYPE for arrays of specific resources:
// PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, MAKE_RESOURCE_TYPE_HINT("Font")
# define MAKE_RESOURCE_TYPE_HINT(m_type) vformat("%s / %s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, m_type)
2014-02-10 02:10:30 +01:00
struct PropertyInfo {
2020-05-12 17:01:17 +02:00
Variant : : Type type = Variant : : NIL ;
2014-02-10 02:10:30 +01:00
String name ;
2021-08-13 16:46:14 +02:00
StringName class_name ; // For classes
2020-05-12 17:01:17 +02:00
PropertyHint hint = PROPERTY_HINT_NONE ;
2015-08-30 02:09:11 +02:00
String hint_string ;
2020-05-12 17:01:17 +02:00
uint32_t usage = PROPERTY_USAGE_DEFAULT ;
2014-02-10 02:10:30 +01:00
2022-07-21 01:18:14 +02:00
// If you are thinking about adding another member to this class, ask the maintainer (Juan) first.
2021-08-12 20:26:47 +02:00
2021-07-01 03:24:34 +02:00
_FORCE_INLINE_ PropertyInfo added_usage ( uint32_t p_fl ) const {
2014-02-10 02:10:30 +01:00
PropertyInfo pi = * this ;
pi . usage | = p_fl ;
return pi ;
}
2016-08-25 22:45:20 +02:00
operator Dictionary ( ) const ;
static PropertyInfo from_dict ( const Dictionary & p_dict ) ;
2020-05-12 17:01:17 +02:00
PropertyInfo ( ) { }
2017-09-14 18:54:37 +02:00
2024-01-09 02:36:19 +01:00
PropertyInfo ( const Variant : : Type p_type , const String & p_name , const PropertyHint p_hint = PROPERTY_HINT_NONE , const String & p_hint_string = " " , const uint32_t p_usage = PROPERTY_USAGE_DEFAULT , const StringName & p_class_name = StringName ( ) ) :
2017-12-06 21:36:34 +01:00
type ( p_type ) ,
name ( p_name ) ,
hint ( p_hint ) ,
hint_string ( p_hint_string ) ,
usage ( p_usage ) {
2017-08-24 00:10:32 +02:00
if ( hint = = PROPERTY_HINT_RESOURCE_TYPE ) {
class_name = hint_string ;
} else {
class_name = p_class_name ;
}
}
2017-09-14 18:54:37 +02:00
2017-12-06 21:36:34 +01:00
PropertyInfo ( const StringName & p_class_name ) :
type ( Variant : : OBJECT ) ,
2020-05-12 17:01:17 +02:00
class_name ( p_class_name ) { }
2017-08-24 00:10:32 +02:00
2022-12-07 12:11:28 +01:00
explicit PropertyInfo ( const GDExtensionPropertyInfo & pinfo ) :
2022-06-06 22:24:13 +02:00
type ( ( Variant : : Type ) pinfo . type ) ,
2022-10-23 10:43:09 +02:00
name ( * reinterpret_cast < StringName * > ( pinfo . name ) ) ,
class_name ( * reinterpret_cast < StringName * > ( pinfo . class_name ) ) ,
2022-06-06 22:24:13 +02:00
hint ( ( PropertyHint ) pinfo . hint ) ,
2022-10-23 10:43:09 +02:00
hint_string ( * reinterpret_cast < String * > ( pinfo . hint_string ) ) ,
2022-06-06 22:24:13 +02:00
usage ( pinfo . usage ) { }
2019-07-05 22:30:01 +02:00
bool operator = = ( const PropertyInfo & p_info ) const {
return ( ( type = = p_info . type ) & &
( name = = p_info . name ) & &
( class_name = = p_info . class_name ) & &
( hint = = p_info . hint ) & &
( hint_string = = p_info . hint_string ) & &
( usage = = p_info . usage ) ) ;
}
2015-05-01 02:53:41 +02:00
bool operator < ( const PropertyInfo & p_info ) const {
return name < p_info . name ;
}
2014-02-10 02:10:30 +01:00
} ;
2022-08-05 20:35:08 +02:00
TypedArray < Dictionary > convert_property_list ( const List < PropertyInfo > * p_list ) ;
2014-02-10 02:10:30 +01:00
2022-06-23 12:21:07 +02:00
enum MethodFlags {
METHOD_FLAG_NORMAL = 1 ,
METHOD_FLAG_EDITOR = 2 ,
2022-04-23 02:54:57 +02:00
METHOD_FLAG_CONST = 4 ,
METHOD_FLAG_VIRTUAL = 8 ,
METHOD_FLAG_VARARG = 16 ,
METHOD_FLAG_STATIC = 32 ,
METHOD_FLAG_OBJECT_CORE = 64 ,
2022-06-23 12:21:07 +02:00
METHOD_FLAGS_DEFAULT = METHOD_FLAG_NORMAL ,
} ;
2014-02-10 02:10:30 +01:00
struct MethodInfo {
String name ;
PropertyInfo return_val ;
2022-06-23 12:21:07 +02:00
uint32_t flags = METHOD_FLAGS_DEFAULT ;
2020-05-12 17:01:17 +02:00
int id = 0 ;
2018-09-28 17:17:38 +02:00
List < PropertyInfo > arguments ;
Vector < Variant > default_arguments ;
2023-01-25 03:51:32 +01:00
int return_val_metadata = 0 ;
Vector < int > arguments_metadata ;
int get_argument_meta ( int p_arg ) const {
ERR_FAIL_COND_V ( p_arg < - 1 | | p_arg > arguments . size ( ) , 0 ) ;
if ( p_arg = = - 1 ) {
return return_val_metadata ;
}
return arguments_metadata . size ( ) > p_arg ? arguments_metadata [ p_arg ] : 0 ;
}
2015-08-30 02:09:11 +02:00
2023-12-17 12:42:14 +01:00
inline bool operator = = ( const MethodInfo & p_method ) const { return id = = p_method . id & & name = = p_method . name ; }
2014-02-10 02:10:30 +01:00
inline bool operator < ( const MethodInfo & p_method ) const { return id = = p_method . id ? ( name < p_method . name ) : ( id < p_method . id ) ; }
2015-08-30 02:09:11 +02:00
2016-08-25 22:45:20 +02:00
operator Dictionary ( ) const ;
static MethodInfo from_dict ( const Dictionary & p_dict ) ;
2020-05-12 17:01:17 +02:00
2022-06-23 12:21:07 +02:00
MethodInfo ( ) { }
2022-12-07 12:11:28 +01:00
explicit MethodInfo ( const GDExtensionMethodInfo & pinfo ) :
2022-10-23 10:43:09 +02:00
name ( * reinterpret_cast < StringName * > ( pinfo . name ) ) ,
return_val ( PropertyInfo ( pinfo . return_value ) ) ,
flags ( pinfo . flags ) ,
id ( pinfo . id ) {
for ( uint32_t j = 0 ; j < pinfo . argument_count ; j + + ) {
arguments . push_back ( PropertyInfo ( pinfo . arguments [ j ] ) ) ;
}
const Variant * def_values = ( const Variant * ) pinfo . default_arguments ;
for ( uint32_t j = 0 ; j < pinfo . default_argument_count ; j + + ) {
default_arguments . push_back ( def_values [ j ] ) ;
}
}
2022-06-23 12:21:07 +02:00
void _push_params ( const PropertyInfo & p_param ) {
arguments . push_back ( p_param ) ;
}
template < typename . . . VarArgs >
void _push_params ( const PropertyInfo & p_param , VarArgs . . . p_params ) {
arguments . push_back ( p_param ) ;
_push_params ( p_params . . . ) ;
}
MethodInfo ( const String & p_name ) { name = p_name ; }
template < typename . . . VarArgs >
MethodInfo ( const String & p_name , VarArgs . . . p_params ) {
name = p_name ;
_push_params ( p_params . . . ) ;
}
MethodInfo ( Variant : : Type ret ) { return_val . type = ret ; }
MethodInfo ( Variant : : Type ret , const String & p_name ) {
return_val . type = ret ;
name = p_name ;
}
template < typename . . . VarArgs >
MethodInfo ( Variant : : Type ret , const String & p_name , VarArgs . . . p_params ) {
name = p_name ;
return_val . type = ret ;
_push_params ( p_params . . . ) ;
}
MethodInfo ( const PropertyInfo & p_ret , const String & p_name ) {
return_val = p_ret ;
name = p_name ;
}
template < typename . . . VarArgs >
MethodInfo ( const PropertyInfo & p_ret , const String & p_name , VarArgs . . . p_params ) {
return_val = p_ret ;
name = p_name ;
_push_params ( p_params . . . ) ;
}
2014-02-10 02:10:30 +01:00
} ;
2022-12-07 12:11:28 +01:00
// API used to extend in GDExtension and other C compatible compiled languages.
2021-06-04 19:33:48 +02:00
class MethodBind ;
2023-02-16 16:38:57 +01:00
class GDExtension ;
2021-06-04 19:33:48 +02:00
2022-12-07 12:11:28 +01:00
struct ObjectGDExtension {
2023-02-16 16:38:57 +01:00
GDExtension * library = nullptr ;
2022-12-07 12:11:28 +01:00
ObjectGDExtension * parent = nullptr ;
List < ObjectGDExtension * > children ;
2021-06-04 19:33:48 +02:00
StringName parent_class_name ;
StringName class_name ;
bool editor_class = false ;
2023-08-05 03:34:14 +02:00
bool reloadable = false ;
2022-10-15 12:01:04 +02:00
bool is_virtual = false ;
bool is_abstract = false ;
2022-12-20 04:36:25 +01:00
bool is_exposed = true ;
2022-12-07 12:11:28 +01:00
GDExtensionClassSet set ;
GDExtensionClassGet get ;
GDExtensionClassGetPropertyList get_property_list ;
GDExtensionClassFreePropertyList free_property_list ;
GDExtensionClassPropertyCanRevert property_can_revert ;
GDExtensionClassPropertyGetRevert property_get_revert ;
2023-09-09 20:05:16 +02:00
GDExtensionClassValidateProperty validate_property ;
2023-06-24 03:07:22 +02:00
# ifndef DISABLE_DEPRECATED
2022-12-07 12:11:28 +01:00
GDExtensionClassNotification notification ;
2023-06-24 03:07:22 +02:00
# endif // DISABLE_DEPRECATED
GDExtensionClassNotification2 notification2 ;
2022-12-07 12:11:28 +01:00
GDExtensionClassToString to_string ;
GDExtensionClassReference reference ;
GDExtensionClassReference unreference ;
GDExtensionClassGetRID get_rid ;
2021-06-04 19:33:48 +02:00
_FORCE_INLINE_ bool is_class ( const String & p_class ) const {
2022-12-07 12:11:28 +01:00
const ObjectGDExtension * e = this ;
2021-06-04 19:33:48 +02:00
while ( e ) {
if ( p_class = = e - > class_name . operator String ( ) ) {
return true ;
}
e = e - > parent ;
}
return false ;
}
2021-06-19 17:58:49 +02:00
void * class_userdata = nullptr ;
2022-12-07 12:11:28 +01:00
GDExtensionClassCreateInstance create_instance ;
GDExtensionClassFreeInstance free_instance ;
GDExtensionClassGetVirtual get_virtual ;
2023-08-16 02:03:49 +02:00
GDExtensionClassGetVirtualCallData get_virtual_call_data ;
GDExtensionClassCallVirtualWithData call_virtual_with_data ;
2023-08-05 03:34:14 +02:00
GDExtensionClassRecreateInstance recreate_instance ;
# ifdef TOOLS_ENABLED
void * tracking_userdata = nullptr ;
void ( * track_instance ) ( void * p_userdata , void * p_instance ) ;
void ( * untrack_instance ) ( void * p_userdata , void * p_instance ) ;
# endif
2021-06-04 19:33:48 +02:00
} ;
2022-03-10 08:17:38 +01:00
# define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call<false>(__VA_ARGS__)
# define GDVIRTUAL_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call<false>(__VA_ARGS__)
# define GDVIRTUAL_REQUIRED_CALL(m_name, ...) _gdvirtual_##m_name##_call<true>(__VA_ARGS__)
# define GDVIRTUAL_REQUIRED_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call<true>(__VA_ARGS__)
2021-08-22 03:52:44 +02:00
# ifdef DEBUG_METHODS_ENABLED
# define GDVIRTUAL_BIND(m_name, ...) ::ClassDB::add_virtual_method(get_class_static(), _gdvirtual_##m_name##_get_method_info(), true, sarray(__VA_ARGS__));
# else
# define GDVIRTUAL_BIND(m_name, ...)
# endif
2021-08-25 19:44:01 +02:00
# define GDVIRTUAL_IS_OVERRIDDEN(m_name) _gdvirtual_##m_name##_overridden()
# define GDVIRTUAL_IS_OVERRIDDEN_PTR(m_obj, m_name) m_obj->_gdvirtual_##m_name##_overridden()
2021-06-19 17:58:49 +02:00
2014-02-10 02:10:30 +01:00
/*
2022-02-16 13:56:32 +01:00
* The following is an incomprehensible blob of hacks and workarounds to
* compensate for many of the fallacies in C + + . As a plus , this macro pretty
* much alone defines the object model .
*/
2014-02-10 02:10:30 +01:00
# define REVERSE_GET_PROPERTY_LIST \
public : \
_FORCE_INLINE_ bool _is_gpl_reversed ( ) const { return true ; } ; \
2017-03-05 16:44:50 +01:00
\
2014-02-10 02:10:30 +01:00
private :
# define UNREVERSE_GET_PROPERTY_LIST \
public : \
_FORCE_INLINE_ bool _is_gpl_reversed ( ) const { return false ; } ; \
2017-03-05 16:44:50 +01:00
\
2014-02-10 02:10:30 +01:00
private :
2020-07-10 12:34:39 +02:00
# define GDCLASS(m_class, m_inherits) \
private : \
void operator = ( const m_class & p_rval ) { } \
2021-08-13 16:46:14 +02:00
friend class : : ClassDB ; \
2020-07-10 12:34:39 +02:00
\
public : \
2023-08-26 17:39:43 +02:00
typedef m_class self_type ; \
2022-07-14 14:18:18 +02:00
static constexpr bool _class_is_enabled = ! bool ( GD_IS_DEFINED ( ClassDB_Disable_ # # m_class ) ) & & m_inherits : : _class_is_enabled ; \
2020-07-10 12:34:39 +02:00
virtual String get_class ( ) const override { \
2021-06-04 19:33:48 +02:00
if ( _get_extension ( ) ) { \
return _get_extension ( ) - > class_name . operator String ( ) ; \
} \
2020-07-10 12:34:39 +02:00
return String ( # m_class ) ; \
} \
virtual const StringName * _get_class_namev ( ) const override { \
2023-04-07 23:32:37 +02:00
static StringName _class_name_static ; \
if ( unlikely ( ! _class_name_static ) ) { \
StringName : : assign_static_unique_class_name ( & _class_name_static , # m_class ) ; \
2020-07-10 12:34:39 +02:00
} \
2023-04-07 23:32:37 +02:00
return & _class_name_static ; \
2020-07-10 12:34:39 +02:00
} \
static _FORCE_INLINE_ void * get_class_ptr_static ( ) { \
static int ptr ; \
return & ptr ; \
} \
static _FORCE_INLINE_ String get_class_static ( ) { \
return String ( # m_class ) ; \
} \
static _FORCE_INLINE_ String get_parent_class_static ( ) { \
return m_inherits : : get_class_static ( ) ; \
} \
static void get_inheritance_list_static ( List < String > * p_inheritance_list ) { \
m_inherits : : get_inheritance_list_static ( p_inheritance_list ) ; \
p_inheritance_list - > push_back ( String ( # m_class ) ) ; \
} \
2021-06-04 19:33:48 +02:00
virtual bool is_class ( const String & p_class ) const override { \
if ( _get_extension ( ) & & _get_extension ( ) - > is_class ( p_class ) ) { \
return true ; \
} \
return ( p_class = = ( # m_class ) ) ? true : m_inherits : : is_class ( p_class ) ; \
} \
2020-07-10 12:34:39 +02:00
virtual bool is_class_ptr ( void * p_ptr ) const override { return ( p_ptr = = get_class_ptr_static ( ) ) ? true : m_inherits : : is_class_ptr ( p_ptr ) ; } \
\
static void get_valid_parents_static ( List < String > * p_parents ) { \
if ( m_class : : _get_valid_parents_static ! = m_inherits : : _get_valid_parents_static ) { \
m_class : : _get_valid_parents_static ( p_parents ) ; \
} \
\
m_inherits : : get_valid_parents_static ( p_parents ) ; \
} \
\
protected : \
_FORCE_INLINE_ static void ( * _get_bind_methods ( ) ) ( ) { \
return & m_class : : _bind_methods ; \
2023-07-20 12:53:10 +02:00
} \
_FORCE_INLINE_ static void ( * _get_bind_compatibility_methods ( ) ) ( ) { \
return & m_class : : _bind_compatibility_methods ; \
2020-07-10 12:34:39 +02:00
} \
\
public : \
static void initialize_class ( ) { \
static bool initialized = false ; \
if ( initialized ) { \
return ; \
} \
m_inherits : : initialize_class ( ) ; \
2021-08-13 16:46:14 +02:00
: : ClassDB : : _add_class < m_class > ( ) ; \
2020-07-10 12:34:39 +02:00
if ( m_class : : _get_bind_methods ( ) ! = m_inherits : : _get_bind_methods ( ) ) { \
_bind_methods ( ) ; \
} \
2023-07-20 12:53:10 +02:00
if ( m_class : : _get_bind_compatibility_methods ( ) ! = m_inherits : : _get_bind_compatibility_methods ( ) ) { \
_bind_compatibility_methods ( ) ; \
} \
2020-07-10 12:34:39 +02:00
initialized = true ; \
} \
\
protected : \
virtual void _initialize_classv ( ) override { \
initialize_class ( ) ; \
} \
_FORCE_INLINE_ bool ( Object : : * _get_get ( ) const ) ( const StringName & p_name , Variant & ) const { \
2021-10-28 16:01:30 +02:00
return ( bool ( Object : : * ) ( const StringName & , Variant & ) const ) & m_class : : _get ; \
2020-07-10 12:34:39 +02:00
} \
virtual bool _getv ( const StringName & p_name , Variant & r_ret ) const override { \
if ( m_class : : _get_get ( ) ! = m_inherits : : _get_get ( ) ) { \
if ( _get ( p_name , r_ret ) ) { \
return true ; \
} \
} \
return m_inherits : : _getv ( p_name , r_ret ) ; \
} \
_FORCE_INLINE_ bool ( Object : : * _get_set ( ) const ) ( const StringName & p_name , const Variant & p_property ) { \
2021-10-28 16:01:30 +02:00
return ( bool ( Object : : * ) ( const StringName & , const Variant & ) ) & m_class : : _set ; \
2020-07-10 12:34:39 +02:00
} \
virtual bool _setv ( const StringName & p_name , const Variant & p_property ) override { \
if ( m_inherits : : _setv ( p_name , p_property ) ) { \
return true ; \
} \
if ( m_class : : _get_set ( ) ! = m_inherits : : _get_set ( ) ) { \
return _set ( p_name , p_property ) ; \
} \
return false ; \
} \
_FORCE_INLINE_ void ( Object : : * _get_get_property_list ( ) const ) ( List < PropertyInfo > * p_list ) const { \
2021-10-28 16:01:30 +02:00
return ( void ( Object : : * ) ( List < PropertyInfo > * ) const ) & m_class : : _get_property_list ; \
2020-07-10 12:34:39 +02:00
} \
virtual void _get_property_listv ( List < PropertyInfo > * p_list , bool p_reversed ) const override { \
if ( ! p_reversed ) { \
m_inherits : : _get_property_listv ( p_list , p_reversed ) ; \
} \
2023-08-31 21:20:39 +02:00
p_list - > push_back ( PropertyInfo ( Variant : : NIL , get_class_static ( ) , PROPERTY_HINT_NONE , get_class_static ( ) , PROPERTY_USAGE_CATEGORY ) ) ; \
2020-07-10 12:34:39 +02:00
if ( ! _is_gpl_reversed ( ) ) { \
2021-08-13 16:46:14 +02:00
: : ClassDB : : get_property_list ( # m_class , p_list , true , this ) ; \
2020-07-10 12:34:39 +02:00
} \
if ( m_class : : _get_get_property_list ( ) ! = m_inherits : : _get_get_property_list ( ) ) { \
_get_property_list ( p_list ) ; \
} \
if ( _is_gpl_reversed ( ) ) { \
2021-08-13 16:46:14 +02:00
: : ClassDB : : get_property_list ( # m_class , p_list , true , this ) ; \
2020-07-10 12:34:39 +02:00
} \
if ( p_reversed ) { \
m_inherits : : _get_property_listv ( p_list , p_reversed ) ; \
} \
} \
2022-08-12 22:57:11 +02:00
_FORCE_INLINE_ void ( Object : : * _get_validate_property ( ) const ) ( PropertyInfo & p_property ) const { \
return ( void ( Object : : * ) ( PropertyInfo & ) const ) & m_class : : _validate_property ; \
} \
virtual void _validate_propertyv ( PropertyInfo & p_property ) const override { \
m_inherits : : _validate_propertyv ( p_property ) ; \
if ( m_class : : _get_validate_property ( ) ! = m_inherits : : _get_validate_property ( ) ) { \
_validate_property ( p_property ) ; \
} \
} \
2022-08-12 20:43:14 +02:00
_FORCE_INLINE_ bool ( Object : : * _get_property_can_revert ( ) const ) ( const StringName & p_name ) const { \
return ( bool ( Object : : * ) ( const StringName & ) const ) & m_class : : _property_can_revert ; \
} \
virtual bool _property_can_revertv ( const StringName & p_name ) const override { \
if ( m_class : : _get_property_can_revert ( ) ! = m_inherits : : _get_property_can_revert ( ) ) { \
if ( _property_can_revert ( p_name ) ) { \
return true ; \
} \
} \
return m_inherits : : _property_can_revertv ( p_name ) ; \
} \
_FORCE_INLINE_ bool ( Object : : * _get_property_get_revert ( ) const ) ( const StringName & p_name , Variant & ) const { \
return ( bool ( Object : : * ) ( const StringName & , Variant & ) const ) & m_class : : _property_get_revert ; \
} \
virtual bool _property_get_revertv ( const StringName & p_name , Variant & r_ret ) const override { \
if ( m_class : : _get_property_get_revert ( ) ! = m_inherits : : _get_property_get_revert ( ) ) { \
if ( _property_get_revert ( p_name , r_ret ) ) { \
return true ; \
} \
} \
return m_inherits : : _property_get_revertv ( p_name , r_ret ) ; \
} \
2020-07-10 12:34:39 +02:00
_FORCE_INLINE_ void ( Object : : * _get_notification ( ) const ) ( int ) { \
2021-10-28 16:01:30 +02:00
return ( void ( Object : : * ) ( int ) ) & m_class : : _notification ; \
2020-07-10 12:34:39 +02:00
} \
virtual void _notificationv ( int p_notification , bool p_reversed ) override { \
if ( ! p_reversed ) { \
m_inherits : : _notificationv ( p_notification , p_reversed ) ; \
} \
if ( m_class : : _get_notification ( ) ! = m_inherits : : _get_notification ( ) ) { \
_notification ( p_notification ) ; \
} \
if ( p_reversed ) { \
m_inherits : : _notificationv ( p_notification , p_reversed ) ; \
} \
} \
\
2014-02-10 02:10:30 +01:00
private :
2020-07-10 12:34:39 +02:00
# define OBJ_SAVE_TYPE(m_class) \
public : \
virtual String get_save_class ( ) const override { return # m_class ; } \
\
2014-02-10 02:10:30 +01:00
private :
class ScriptInstance ;
2015-08-30 02:09:11 +02:00
class Object {
2014-02-10 02:10:30 +01:00
public :
2023-08-26 17:39:43 +02:00
typedef Object self_type ;
2014-02-10 02:10:30 +01:00
enum ConnectFlags {
CONNECT_DEFERRED = 1 ,
CONNECT_PERSIST = 2 , // hint for scene to save this connection
2022-09-01 15:44:42 +02:00
CONNECT_ONE_SHOT = 4 ,
2018-08-20 18:38:18 +02:00
CONNECT_REFERENCE_COUNTED = 8 ,
2022-12-06 13:50:54 +01:00
CONNECT_INHERITED = 16 , // Used in editor builds.
2014-02-10 02:10:30 +01:00
} ;
struct Connection {
2020-02-19 20:27:19 +01:00
: : Signal signal ;
Callable callable ;
2020-05-12 17:01:17 +02:00
uint32_t flags = 0 ;
2014-02-10 02:10:30 +01:00
bool operator < ( const Connection & p_conn ) const ;
operator Variant ( ) const ;
2020-05-12 17:01:17 +02:00
Connection ( ) { }
2014-02-10 02:10:30 +01:00
Connection ( const Variant & p_variant ) ;
} ;
2017-03-05 16:44:50 +01:00
2014-02-10 02:10:30 +01:00
private :
2014-04-05 17:39:30 +02:00
# ifdef DEBUG_ENABLED
2018-10-01 16:46:50 +02:00
friend struct _ObjectDebugLock ;
2014-04-05 17:39:30 +02:00
# endif
2014-02-10 02:10:30 +01:00
friend bool predelete_handler ( Object * ) ;
friend void postinitialize_handler ( Object * ) ;
2022-12-07 12:11:28 +01:00
ObjectGDExtension * _extension = nullptr ;
2021-06-19 17:58:49 +02:00
GDExtensionClassInstancePtr _extension_instance = nullptr ;
2021-06-04 19:33:48 +02:00
2020-02-19 20:27:19 +01:00
struct SignalData {
2014-02-10 02:10:30 +01:00
struct Slot {
2020-05-12 17:01:17 +02:00
int reference_count = 0 ;
2014-02-10 02:10:30 +01:00
Connection conn ;
2020-05-12 17:01:17 +02:00
List < Connection > : : Element * cE = nullptr ;
2014-02-10 02:10:30 +01:00
} ;
MethodInfo user ;
2023-01-30 17:46:56 +01:00
HashMap < Callable , Slot , HashableHasher < Callable > > slot_map ;
2014-02-10 02:10:30 +01:00
} ;
2020-02-19 20:27:19 +01:00
HashMap < StringName , SignalData > signal_map ;
2014-02-10 02:10:30 +01:00
List < Connection > connections ;
2014-04-05 17:39:30 +02:00
# ifdef DEBUG_ENABLED
SafeRefCount _lock_index ;
# endif
2020-05-12 17:01:17 +02:00
bool _block_signals = false ;
int _predelete_ok = 0 ;
2019-05-09 11:21:49 +02:00
ObjectID _instance_id ;
2014-02-10 02:10:30 +01:00
bool _predelete ( ) ;
void _postinitialize ( ) ;
2020-05-12 17:01:17 +02:00
bool _can_translate = true ;
bool _emitting = false ;
2014-02-10 02:10:30 +01:00
# ifdef TOOLS_ENABLED
2020-05-12 17:01:17 +02:00
bool _edited = false ;
uint32_t _edited_version = 0 ;
2022-05-19 17:00:06 +02:00
HashSet < String > editor_section_folding ;
2014-02-10 02:10:30 +01:00
# endif
2020-05-12 17:01:17 +02:00
ScriptInstance * script_instance = nullptr ;
2022-02-16 13:56:32 +01:00
Variant script ; // Reference does not exist yet, store it in a Variant.
2022-05-08 10:09:19 +02:00
HashMap < StringName , Variant > metadata ;
HashMap < StringName , Variant * > metadata_properties ;
2023-04-07 23:32:37 +02:00
mutable const StringName * _class_name_ptr = nullptr ;
2014-02-10 02:10:30 +01:00
2017-08-11 21:10:05 +02:00
void _add_user_signal ( const String & p_name , const Array & p_args = Array ( ) ) ;
2015-03-03 18:39:13 +01:00
bool _has_user_signal ( const StringName & p_name ) const ;
2022-02-22 12:15:43 +01:00
Error _emit_signal ( const Variant * * p_args , int p_argcount , Callable : : CallError & r_error ) ;
2022-08-05 20:35:08 +02:00
TypedArray < Dictionary > _get_signal_list ( ) const ;
TypedArray < Dictionary > _get_signal_connection_list ( const StringName & p_signal ) const ;
TypedArray < Dictionary > _get_incoming_connections ( ) const ;
2022-06-14 15:28:59 +02:00
void _set_bind ( const StringName & p_set , const Variant & p_value ) ;
Variant _get_bind ( const StringName & p_name ) const ;
2017-05-30 22:20:15 +02:00
void _set_indexed_bind ( const NodePath & p_name , const Variant & p_value ) ;
Variant _get_indexed_bind ( const NodePath & p_name ) const ;
2014-02-10 02:10:30 +01:00
2020-02-13 20:03:10 +01:00
_FORCE_INLINE_ void _construct_object ( bool p_reference ) ;
2021-06-04 18:03:15 +02:00
friend class RefCounted ;
2020-02-13 20:03:10 +01:00
bool type_is_reference = false ;
2021-07-08 21:16:02 +02:00
2023-11-17 20:44:38 +01:00
BinaryMutex _instance_binding_mutex ;
2021-07-08 21:16:02 +02:00
struct InstanceBinding {
2022-04-04 15:06:57 +02:00
void * binding = nullptr ;
void * token = nullptr ;
2022-12-07 12:11:28 +01:00
GDExtensionInstanceBindingFreeCallback free_callback = nullptr ;
GDExtensionInstanceBindingReferenceCallback reference_callback = nullptr ;
2021-07-08 21:16:02 +02:00
} ;
InstanceBinding * _instance_bindings = nullptr ;
uint32_t _instance_binding_count = 0 ;
2020-05-12 17:01:17 +02:00
2020-02-13 20:03:10 +01:00
Object ( bool p_reference ) ;
2018-02-22 15:34:08 +01:00
2015-08-30 02:09:11 +02:00
protected :
2021-07-08 21:16:02 +02:00
_FORCE_INLINE_ bool _instance_binding_reference ( bool p_reference ) {
bool can_die = true ;
if ( _instance_bindings ) {
_instance_binding_mutex . lock ( ) ;
for ( uint32_t i = 0 ; i < _instance_binding_count ; i + + ) {
if ( _instance_bindings [ i ] . reference_callback ) {
if ( ! _instance_bindings [ i ] . reference_callback ( _instance_bindings [ i ] . token , _instance_bindings [ i ] . binding , p_reference ) ) {
can_die = false ;
}
}
}
_instance_binding_mutex . unlock ( ) ;
}
return can_die ;
}
2022-02-16 13:56:32 +01:00
2022-12-07 12:11:28 +01:00
friend class GDExtensionMethodBind ;
_ALWAYS_INLINE_ const ObjectGDExtension * _get_extension ( ) const { return _extension ; }
2021-06-19 17:58:49 +02:00
_ALWAYS_INLINE_ GDExtensionClassInstancePtr _get_extension_instance ( ) const { return _extension_instance ; }
2017-01-03 03:03:46 +01:00
virtual void _initialize_classv ( ) { initialize_class ( ) ; }
2014-02-10 02:10:30 +01:00
virtual bool _setv ( const StringName & p_name , const Variant & p_property ) { return false ; } ;
virtual bool _getv ( const StringName & p_name , Variant & r_property ) const { return false ; } ;
virtual void _get_property_listv ( List < PropertyInfo > * p_list , bool p_reversed ) const { } ;
2022-08-12 22:57:11 +02:00
virtual void _validate_propertyv ( PropertyInfo & p_property ) const { } ;
2022-08-12 20:43:14 +02:00
virtual bool _property_can_revertv ( const StringName & p_name ) const { return false ; } ;
virtual bool _property_get_revertv ( const StringName & p_name , Variant & r_property ) const { return false ; } ;
2020-05-12 17:01:17 +02:00
virtual void _notificationv ( int p_notification , bool p_reversed ) { }
2015-08-30 02:09:11 +02:00
2014-02-10 02:10:30 +01:00
static void _bind_methods ( ) ;
2023-07-20 12:53:10 +02:00
static void _bind_compatibility_methods ( ) { }
2014-02-10 02:10:30 +01:00
bool _set ( const StringName & p_name , const Variant & p_property ) { return false ; } ;
bool _get ( const StringName & p_name , Variant & r_property ) const { return false ; } ;
void _get_property_list ( List < PropertyInfo > * p_list ) const { } ;
2022-08-12 22:57:11 +02:00
void _validate_property ( PropertyInfo & p_property ) const { } ;
2022-08-12 20:43:14 +02:00
bool _property_can_revert ( const StringName & p_name ) const { return false ; } ;
bool _property_get_revert ( const StringName & p_name , Variant & r_property ) const { return false ; } ;
2020-05-12 17:01:17 +02:00
void _notification ( int p_notification ) { }
2015-08-30 02:09:11 +02:00
2014-02-10 02:10:30 +01:00
_FORCE_INLINE_ static void ( * _get_bind_methods ( ) ) ( ) {
return & Object : : _bind_methods ;
}
2023-07-20 12:53:10 +02:00
_FORCE_INLINE_ static void ( * _get_bind_compatibility_methods ( ) ) ( ) {
return & Object : : _bind_compatibility_methods ;
}
2018-09-30 22:25:55 +02:00
_FORCE_INLINE_ bool ( Object : : * _get_get ( ) const ) ( const StringName & p_name , Variant & r_ret ) const {
2014-02-10 02:10:30 +01:00
return & Object : : _get ;
}
2018-09-30 22:25:55 +02:00
_FORCE_INLINE_ bool ( Object : : * _get_set ( ) const ) ( const StringName & p_name , const Variant & p_property ) {
2014-02-10 02:10:30 +01:00
return & Object : : _set ;
}
2018-09-30 22:25:55 +02:00
_FORCE_INLINE_ void ( Object : : * _get_get_property_list ( ) const ) ( List < PropertyInfo > * p_list ) const {
2014-02-10 02:10:30 +01:00
return & Object : : _get_property_list ;
2015-08-30 02:09:11 +02:00
}
2022-08-12 22:57:11 +02:00
_FORCE_INLINE_ void ( Object : : * _get_validate_property ( ) const ) ( PropertyInfo & p_property ) const {
return & Object : : _validate_property ;
}
2022-08-12 20:43:14 +02:00
_FORCE_INLINE_ bool ( Object : : * _get_property_can_revert ( ) const ) ( const StringName & p_name ) const {
return & Object : : _property_can_revert ;
}
_FORCE_INLINE_ bool ( Object : : * _get_property_get_revert ( ) const ) ( const StringName & p_name , Variant & ) const {
return & Object : : _property_get_revert ;
}
2018-09-30 22:25:55 +02:00
_FORCE_INLINE_ void ( Object : : * _get_notification ( ) const ) ( int ) {
2014-02-10 02:10:30 +01:00
return & Object : : _notification ;
2015-08-30 02:09:11 +02:00
}
2014-02-10 02:10:30 +01:00
static void get_valid_parents_static ( List < String > * p_parents ) ;
static void _get_valid_parents_static ( List < String > * p_parents ) ;
2015-08-30 02:09:11 +02:00
2020-02-19 20:27:19 +01:00
Variant _call_bind ( const Variant * * p_args , int p_argcount , Callable : : CallError & r_error ) ;
Variant _call_deferred_bind ( const Variant * * p_args , int p_argcount , Callable : : CallError & r_error ) ;
2014-02-10 02:10:30 +01:00
2017-01-03 03:03:46 +01:00
virtual const StringName * _get_class_namev ( ) const {
2023-04-07 23:32:37 +02:00
static StringName _class_name_static ;
if ( unlikely ( ! _class_name_static ) ) {
StringName : : assign_static_unique_class_name ( & _class_name_static , " Object " ) ;
2020-05-14 16:41:43 +02:00
}
2023-04-07 23:32:37 +02:00
return & _class_name_static ;
2015-06-29 05:29:49 +02:00
}
2014-02-10 02:10:30 +01:00
2023-04-25 00:21:32 +02:00
TypedArray < StringName > _get_meta_list_bind ( ) const ;
2022-08-05 20:35:08 +02:00
TypedArray < Dictionary > _get_property_list_bind ( ) const ;
TypedArray < Dictionary > _get_method_list_bind ( ) const ;
2014-02-10 02:10:30 +01:00
2015-06-22 05:03:19 +02:00
void _clear_internal_resource_paths ( const Variant & p_var ) ;
2017-01-03 03:03:46 +01:00
friend class ClassDB ;
2016-05-15 04:48:23 +02:00
2023-05-04 01:20:15 +02:00
bool _disconnect ( const StringName & p_signal , const Callable & p_callable , bool p_force = false ) ;
2018-08-20 21:35:36 +02:00
2023-08-05 03:34:14 +02:00
# ifdef TOOLS_ENABLED
struct VirtualMethodTracker {
void * * method ;
bool * initialized ;
VirtualMethodTracker * next ;
} ;
mutable VirtualMethodTracker * virtual_method_list = nullptr ;
# endif
2022-02-16 13:56:32 +01:00
public : // Should be protected, but bug in clang++.
2017-01-03 03:03:46 +01:00
static void initialize_class ( ) ;
2020-05-12 17:01:17 +02:00
_FORCE_INLINE_ static void register_custom_data_to_otdb ( ) { }
2014-02-10 02:10:30 +01:00
public :
2022-07-14 14:18:18 +02:00
static constexpr bool _class_is_enabled = true ;
2021-02-10 21:18:45 +01:00
void notify_property_list_changed ( ) ;
2017-01-03 03:03:46 +01:00
static void * get_class_ptr_static ( ) {
2014-02-10 02:10:30 +01:00
static int ptr ;
return & ptr ;
}
bool _is_gpl_reversed ( ) const { return false ; }
2022-03-23 10:08:58 +01:00
void detach_from_objectdb ( ) ;
2019-05-09 11:21:49 +02:00
_FORCE_INLINE_ ObjectID get_instance_id ( ) const { return _instance_id ; }
2014-02-10 02:10:30 +01:00
2017-08-24 21:58:13 +02:00
template < class T >
static T * cast_to ( Object * p_object ) {
return dynamic_cast < T * > ( p_object ) ;
}
template < class T >
static const T * cast_to ( const Object * p_object ) {
return dynamic_cast < const T * > ( p_object ) ;
}
2014-02-10 02:10:30 +01:00
enum {
NOTIFICATION_POSTINITIALIZE = 0 ,
2023-08-05 03:34:14 +02:00
NOTIFICATION_PREDELETE = 1 ,
NOTIFICATION_EXTENSION_RELOADED = 2 ,
2023-10-20 13:43:42 +02:00
// Internal notification to send after NOTIFICATION_PREDELETE, not bound to scripting.
NOTIFICATION_PREDELETE_CLEANUP = 3 ,
2014-02-10 02:10:30 +01:00
} ;
2015-08-30 02:09:11 +02:00
2014-02-10 02:10:30 +01:00
/* TYPE API */
static void get_inheritance_list_static ( List < String > * p_inheritance_list ) { p_inheritance_list - > push_back ( " Object " ) ; }
2017-01-03 03:03:46 +01:00
static String get_class_static ( ) { return " Object " ; }
static String get_parent_class_static ( ) { return String ( ) ; }
2014-02-10 02:10:30 +01:00
2021-06-04 19:33:48 +02:00
virtual String get_class ( ) const {
2022-01-27 17:34:33 +01:00
if ( _extension ) {
2021-06-04 19:33:48 +02:00
return _extension - > class_name . operator String ( ) ;
2022-01-27 17:34:33 +01:00
}
2021-06-04 19:33:48 +02:00
return " Object " ;
}
2017-01-03 03:03:46 +01:00
virtual String get_save_class ( ) const { return get_class ( ) ; } //class stored when saving
2015-06-29 05:29:49 +02:00
2021-06-04 19:33:48 +02:00
virtual bool is_class ( const String & p_class ) const {
if ( _extension & & _extension - > is_class ( p_class ) ) {
return true ;
}
return ( p_class = = " Object " ) ;
}
2017-01-03 03:03:46 +01:00
virtual bool is_class_ptr ( void * p_ptr ) const { return get_class_ptr_static ( ) = = p_ptr ; }
2015-06-29 05:29:49 +02:00
2017-01-03 03:03:46 +01:00
_FORCE_INLINE_ const StringName & get_class_name ( ) const {
2021-06-04 19:33:48 +02:00
if ( _extension ) {
2023-04-07 23:32:37 +02:00
// Can't put inside the unlikely as constructor can run it
2021-06-04 19:33:48 +02:00
return _extension - > class_name ;
}
2023-04-07 23:32:37 +02:00
if ( unlikely ( ! _class_name_ptr ) ) {
// While class is initializing / deinitializing, constructors and destructurs
// need access to the proper class at the proper stage.
2017-01-03 03:03:46 +01:00
return * _get_class_namev ( ) ;
2015-06-29 05:29:49 +02:00
}
2023-04-07 23:32:37 +02:00
return * _class_name_ptr ;
2015-06-29 05:29:49 +02:00
}
2015-08-30 02:09:11 +02:00
2023-06-09 19:30:39 +02:00
StringName get_class_name_for_extension ( const GDExtension * p_library ) const ;
2023-02-16 16:38:57 +01:00
2014-02-10 02:10:30 +01:00
/* IAPI */
2020-04-02 01:20:12 +02:00
void set ( const StringName & p_name , const Variant & p_value , bool * r_valid = nullptr ) ;
Variant get ( const StringName & p_name , bool * r_valid = nullptr ) const ;
void set_indexed ( const Vector < StringName > & p_names , const Variant & p_value , bool * r_valid = nullptr ) ;
Variant get_indexed ( const Vector < StringName > & p_names , bool * r_valid = nullptr ) const ;
2014-02-10 02:10:30 +01:00
void get_property_list ( List < PropertyInfo > * p_list , bool p_reversed = false ) const ;
2022-08-12 22:57:11 +02:00
void validate_property ( PropertyInfo & p_property ) const ;
2022-08-22 11:43:14 +02:00
bool property_can_revert ( const StringName & p_name ) const ;
Variant property_get_revert ( const StringName & p_name ) const ;
2015-08-30 02:09:11 +02:00
2014-02-10 02:10:30 +01:00
bool has_method ( const StringName & p_method ) const ;
void get_method_list ( List < MethodInfo > * p_list ) const ;
Variant callv ( const StringName & p_method , const Array & p_args ) ;
2022-03-09 14:58:40 +01:00
virtual Variant callp ( const StringName & p_method , const Variant * * p_args , int p_argcount , Callable : : CallError & r_error ) ;
2022-06-27 22:10:04 +02:00
virtual Variant call_const ( const StringName & p_method , const Variant * * p_args , int p_argcount , Callable : : CallError & r_error ) ;
2022-03-09 14:58:40 +01:00
template < typename . . . VarArgs >
Variant call ( const StringName & p_method , VarArgs . . . p_args ) {
Variant args [ sizeof . . . ( p_args ) + 1 ] = { p_args . . . , Variant ( ) } ; // +1 makes sure zero sized arrays are also supported.
const Variant * argptrs [ sizeof . . . ( p_args ) + 1 ] ;
for ( uint32_t i = 0 ; i < sizeof . . . ( p_args ) ; i + + ) {
argptrs [ i ] = & args [ i ] ;
}
Callable : : CallError cerr ;
return callp ( p_method , sizeof . . . ( p_args ) = = 0 ? nullptr : ( const Variant * * ) argptrs , sizeof . . . ( p_args ) , cerr ) ;
}
2014-02-10 02:10:30 +01:00
2015-08-30 02:09:11 +02:00
void notification ( int p_notification , bool p_reversed = false ) ;
2020-09-15 17:14:45 +02:00
virtual String to_string ( ) ;
2014-02-10 02:10:30 +01:00
2022-02-16 13:56:32 +01:00
// Used mainly by script, get and set all INCLUDING string.
2020-04-02 01:20:12 +02:00
virtual Variant getvar ( const Variant & p_key , bool * r_valid = nullptr ) const ;
virtual void setvar ( const Variant & p_key , const Variant & p_value , bool * r_valid = nullptr ) ;
2014-02-10 02:10:30 +01:00
/* SCRIPT */
2015-08-30 02:09:11 +02:00
2023-05-12 13:53:15 +02:00
// When in debug, some non-virtual functions can be overridden for multithreaded guards.
# ifdef DEBUG_ENABLED
# define MTVIRTUAL virtual
# else
# define MTVIRTUAL
# endif
MTVIRTUAL void set_script ( const Variant & p_script ) ;
MTVIRTUAL Variant get_script ( ) const ;
2014-02-10 02:10:30 +01:00
2023-05-12 13:53:15 +02:00
MTVIRTUAL bool has_meta ( const StringName & p_name ) const ;
MTVIRTUAL void set_meta ( const StringName & p_name , const Variant & p_value ) ;
MTVIRTUAL void remove_meta ( const StringName & p_name ) ;
MTVIRTUAL Variant get_meta ( const StringName & p_name , const Variant & p_default = Variant ( ) ) const ;
MTVIRTUAL void get_meta_list ( List < StringName > * p_list ) const ;
2014-02-10 02:10:30 +01:00
# ifdef TOOLS_ENABLED
void set_edited ( bool p_edited ) ;
bool is_edited ( ) const ;
2022-02-16 13:56:32 +01:00
// This function is used to check when something changed beyond a point, it's used mainly for generating previews.
uint32_t get_edited_version ( ) const ;
2014-02-10 02:10:30 +01:00
# endif
void set_script_instance ( ScriptInstance * p_instance ) ;
_FORCE_INLINE_ ScriptInstance * get_script_instance ( ) const { return script_instance ; }
2022-02-16 13:56:32 +01:00
// Some script languages can't control instance creation, so this function eases the process.
void set_script_and_instance ( const Variant & p_script , ScriptInstance * p_instance ) ;
2017-07-22 21:57:56 +02:00
2014-02-10 02:10:30 +01:00
void add_user_signal ( const MethodInfo & p_signal ) ;
2022-03-09 14:58:40 +01:00
template < typename . . . VarArgs >
Error emit_signal ( const StringName & p_name , VarArgs . . . p_args ) {
Variant args [ sizeof . . . ( p_args ) + 1 ] = { p_args . . . , Variant ( ) } ; // +1 makes sure zero sized arrays are also supported.
const Variant * argptrs [ sizeof . . . ( p_args ) + 1 ] ;
for ( uint32_t i = 0 ; i < sizeof . . . ( p_args ) ; i + + ) {
argptrs [ i ] = & args [ i ] ;
}
return emit_signalp ( p_name , sizeof . . . ( p_args ) = = 0 ? nullptr : ( const Variant * * ) argptrs , sizeof . . . ( p_args ) ) ;
}
2023-05-12 13:53:15 +02:00
MTVIRTUAL Error emit_signalp ( const StringName & p_name , const Variant * * p_args , int p_argcount ) ;
MTVIRTUAL bool has_signal ( const StringName & p_name ) const ;
MTVIRTUAL void get_signal_list ( List < MethodInfo > * p_signals ) const ;
MTVIRTUAL void get_signal_connection_list ( const StringName & p_signal , List < Connection > * p_connections ) const ;
MTVIRTUAL void get_all_signal_connections ( List < Connection > * p_connections ) const ;
MTVIRTUAL int get_persistent_signal_connection_count ( ) const ;
MTVIRTUAL void get_signals_connected_to_this ( List < Connection > * p_connections ) const ;
2014-02-10 02:10:30 +01:00
2023-05-12 13:53:15 +02:00
MTVIRTUAL Error connect ( const StringName & p_signal , const Callable & p_callable , uint32_t p_flags = 0 ) ;
MTVIRTUAL void disconnect ( const StringName & p_signal , const Callable & p_callable ) ;
MTVIRTUAL bool is_connected ( const StringName & p_signal , const Callable & p_callable ) const ;
2014-02-10 02:10:30 +01:00
2022-03-09 14:58:40 +01:00
template < typename . . . VarArgs >
void call_deferred ( const StringName & p_name , VarArgs . . . p_args ) {
MessageQueue : : get_singleton ( ) - > push_call ( this , p_name , p_args . . . ) ;
}
2018-11-16 12:49:26 +01:00
void set_deferred ( const StringName & p_property , const Variant & p_value ) ;
2014-02-10 02:10:30 +01:00
void set_block_signals ( bool p_block ) ;
bool is_blocking_signals ( ) const ;
2020-04-02 01:20:12 +02:00
Variant : : Type get_static_property_type ( const StringName & p_property , bool * r_valid = nullptr ) const ;
Variant : : Type get_static_property_type_indexed ( const Vector < StringName > & p_path , bool * r_valid = nullptr ) const ;
2015-12-05 18:18:22 +01:00
2014-12-17 02:31:57 +01:00
virtual void get_argument_options ( const StringName & p_function , int p_idx , List < String > * r_options ) const ;
2014-02-10 02:10:30 +01:00
2022-02-16 13:56:32 +01:00
// Translate message (internationalization).
String tr ( const StringName & p_message , const StringName & p_context = " " ) const ;
2020-07-16 10:52:06 +02:00
String tr_n ( const StringName & p_message , const StringName & p_message_plural , int p_n , const StringName & p_context = " " ) const ;
2014-02-10 02:10:30 +01:00
2022-02-16 13:56:32 +01:00
bool _is_queued_for_deletion = false ; // Set to true by SceneTree::queue_delete().
2015-08-30 02:09:11 +02:00
bool is_queued_for_deletion ( ) const ;
2015-03-28 18:34:28 +01:00
2017-08-18 22:29:15 +02:00
_FORCE_INLINE_ void set_message_translation ( bool p_enable ) { _can_translate = p_enable ; }
2014-02-10 02:10:30 +01:00
_FORCE_INLINE_ bool can_translate_messages ( ) const { return _can_translate ; }
2015-06-22 05:03:19 +02:00
2017-06-25 22:30:28 +02:00
# ifdef TOOLS_ENABLED
void editor_set_section_unfold ( const String & p_section , bool p_unfolded ) ;
bool editor_is_section_unfolded ( const String & p_section ) ;
2022-05-19 17:00:06 +02:00
const HashSet < String > & editor_get_section_folding ( ) const { return editor_section_folding ; }
2018-10-29 20:36:31 +01:00
void editor_clear_section_folding ( ) { editor_section_folding . clear ( ) ; }
2017-06-25 22:30:28 +02:00
# endif
2021-07-15 16:41:57 +02:00
// Used by script languages to store binding data.
2022-12-07 12:11:28 +01:00
void * get_instance_binding ( void * p_token , const GDExtensionInstanceBindingCallbacks * p_callbacks ) ;
2021-07-15 16:41:57 +02:00
// Used on creation by binding only.
2022-12-07 12:11:28 +01:00
void set_instance_binding ( void * p_token , void * p_binding , const GDExtensionInstanceBindingCallbacks * p_callbacks ) ;
2021-08-16 17:16:36 +02:00
bool has_instance_binding ( void * p_token ) ;
2023-10-04 19:13:07 +02:00
void free_instance_binding ( void * p_token ) ;
2017-07-16 17:39:23 +02:00
2023-08-05 03:34:14 +02:00
# ifdef TOOLS_ENABLED
void clear_internal_extension ( ) ;
void reset_internal_extension ( ObjectGDExtension * p_extension ) ;
# endif
2015-06-22 05:03:19 +02:00
void clear_internal_resource_paths ( ) ;
2021-06-04 18:03:15 +02:00
_ALWAYS_INLINE_ bool is_ref_counted ( ) const { return type_is_reference ; }
2020-05-12 17:01:17 +02:00
2023-04-10 18:45:53 +02:00
void cancel_free ( ) ;
2015-08-30 02:09:11 +02:00
Object ( ) ;
2014-02-10 02:10:30 +01:00
virtual ~ Object ( ) ;
} ;
bool predelete_handler ( Object * p_object ) ;
void postinitialize_handler ( Object * p_object ) ;
class ObjectDB {
2022-02-16 13:56:32 +01:00
// This needs to add up to 63, 1 bit is for reference.
2020-02-13 20:03:10 +01:00
# define OBJECTDB_VALIDATOR_BITS 39
# define OBJECTDB_VALIDATOR_MASK ((uint64_t(1) << OBJECTDB_VALIDATOR_BITS) - 1)
# define OBJECTDB_SLOT_MAX_COUNT_BITS 24
# define OBJECTDB_SLOT_MAX_COUNT_MASK ((uint64_t(1) << OBJECTDB_SLOT_MAX_COUNT_BITS) - 1)
# define OBJECTDB_REFERENCE_BIT (uint64_t(1) << (OBJECTDB_SLOT_MAX_COUNT_BITS + OBJECTDB_VALIDATOR_BITS))
2022-02-16 13:56:32 +01:00
struct ObjectSlot { // 128 bits per slot.
2020-02-13 20:03:10 +01:00
uint64_t validator : OBJECTDB_VALIDATOR_BITS ;
uint64_t next_free : OBJECTDB_SLOT_MAX_COUNT_BITS ;
2021-06-04 18:03:15 +02:00
uint64_t is_ref_counted : 1 ;
2022-04-04 15:06:57 +02:00
Object * object = nullptr ;
2014-02-10 02:10:30 +01:00
} ;
2020-02-13 20:03:10 +01:00
static SpinLock spin_lock ;
static uint32_t slot_count ;
static uint32_t slot_max ;
static ObjectSlot * object_slots ;
static uint64_t validator_counter ;
2014-02-10 02:10:30 +01:00
2015-08-30 02:09:11 +02:00
friend class Object ;
2014-02-10 02:10:30 +01:00
friend void unregister_core_types ( ) ;
static void cleanup ( ) ;
2020-02-13 20:03:10 +01:00
2017-06-09 05:23:50 +02:00
static ObjectID add_instance ( Object * p_object ) ;
2014-02-10 02:10:30 +01:00
static void remove_instance ( Object * p_object ) ;
2020-02-13 20:03:10 +01:00
2017-01-07 22:25:37 +01:00
friend void register_core_types ( ) ;
static void setup ( ) ;
2015-08-30 02:09:11 +02:00
public :
2014-02-10 02:10:30 +01:00
typedef void ( * DebugFunc ) ( Object * p_obj ) ;
2020-02-13 20:03:10 +01:00
_ALWAYS_INLINE_ static Object * get_instance ( ObjectID p_instance_id ) {
uint64_t id = p_instance_id ;
uint32_t slot = id & OBJECTDB_SLOT_MAX_COUNT_MASK ;
2022-02-16 13:56:32 +01:00
ERR_FAIL_COND_V ( slot > = slot_max , nullptr ) ; // This should never happen unless RID is corrupted.
2020-02-13 20:03:10 +01:00
spin_lock . lock ( ) ;
2014-02-10 02:10:30 +01:00
2020-02-13 20:03:10 +01:00
uint64_t validator = ( id > > OBJECTDB_SLOT_MAX_COUNT_BITS ) & OBJECTDB_VALIDATOR_MASK ;
2014-02-10 02:10:30 +01:00
2020-02-13 20:03:10 +01:00
if ( unlikely ( object_slots [ slot ] . validator ! = validator ) ) {
spin_lock . unlock ( ) ;
return nullptr ;
}
Object * object = object_slots [ slot ] . object ;
2019-07-28 22:19:44 +02:00
2020-02-13 20:03:10 +01:00
spin_lock . unlock ( ) ;
2019-07-28 22:19:44 +02:00
2020-02-13 20:03:10 +01:00
return object ;
2014-02-10 02:10:30 +01:00
}
2020-02-13 20:03:10 +01:00
static void debug_objects ( DebugFunc p_func ) ;
static int get_object_count ( ) ;
2014-02-10 02:10:30 +01:00
} ;
2020-03-25 11:10:34 +01:00
# endif // OBJECT_H