godot/core/object/object.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

1059 lines
58 KiB
C++
Raw Normal View History

/**************************************************************************/
2014-02-09 22:10:30 -03: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. */
/**************************************************************************/
2014-02-09 22:10:30 -03:00
#ifndef OBJECT_H
#define OBJECT_H
#include "core/extension/gdextension_interface.h"
#include "core/object/message_queue.h"
#include "core/object/object_id.h"
#include "core/os/rw_lock.h"
#include "core/os/spin_lock.h"
#include "core/templates/hash_map.h"
#include "core/templates/hash_set.h"
#include "core/templates/list.h"
#include "core/templates/rb_map.h"
#include "core/templates/safe_refcount.h"
#include "core/variant/callable_bind.h"
#include "core/variant/variant.h"
2014-02-09 22:10:30 -03:00
template <typename T>
class TypedArray;
2014-02-09 22:10:30 -03:00
enum PropertyHint {
PROPERTY_HINT_NONE, ///< no hint provided.
PROPERTY_HINT_RANGE, ///< hint_text = "min,max[,step][,or_greater][,or_less][,hide_slider][,radians_as_degrees][,degrees][,exp][,suffix:<keyword>] range.
2014-02-09 22:10:30 -03:00
PROPERTY_HINT_ENUM, ///< hint_text= "val1,val2,val3,etc"
2021-07-04 23:42:23 +03:00
PROPERTY_HINT_ENUM_SUGGESTION, ///< hint_text= "val1,val2,val3,etc"
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")
PROPERTY_HINT_LINK,
2014-02-09 22:10:30 -03:00
PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags)
PROPERTY_HINT_LAYERS_2D_RENDER,
PROPERTY_HINT_LAYERS_2D_PHYSICS,
2021-03-08 20:56:33 +01:00
PROPERTY_HINT_LAYERS_2D_NAVIGATION,
PROPERTY_HINT_LAYERS_3D_RENDER,
PROPERTY_HINT_LAYERS_3D_PHYSICS,
2021-03-08 20:56:33 +01:00
PROPERTY_HINT_LAYERS_3D_NAVIGATION,
PROPERTY_HINT_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
PROPERTY_HINT_DIR, ///< a directory path must be passed
2014-02-09 22:10:30 -03:00
PROPERTY_HINT_GLOBAL_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
PROPERTY_HINT_GLOBAL_DIR, ///< a directory path must be passed
2014-02-09 22:10:30 -03:00
PROPERTY_HINT_RESOURCE_TYPE, ///< a resource object type
PROPERTY_HINT_MULTILINE_TEXT, ///< used for string properties that can contain multiple lines
PROPERTY_HINT_EXPRESSION, ///< used for string properties that can contain multiple lines
PROPERTY_HINT_PLACEHOLDER_TEXT, ///< used to set a placeholder text for string properties
2014-02-09 22:10:30 -03:00
PROPERTY_HINT_COLOR_NO_ALPHA, ///< used for ignoring alpha component when editing a color
2016-05-22 19:28:37 -03:00
PROPERTY_HINT_OBJECT_ID,
PROPERTY_HINT_TYPE_STRING, ///< a type string, the hint is the base type to choose
PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE, // Deprecated.
PROPERTY_HINT_OBJECT_TOO_BIG, ///< object is too big to send
PROPERTY_HINT_NODE_PATH_VALID_TYPES,
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
PROPERTY_HINT_INT_IS_OBJECTID, // Deprecated.
PROPERTY_HINT_INT_IS_POINTER,
PROPERTY_HINT_ARRAY_TYPE,
PROPERTY_HINT_LOCALE_ID,
PROPERTY_HINT_LOCALIZABLE_STRING,
PROPERTY_HINT_NODE_TYPE, ///< a node object type
2022-08-21 16:03:38 +09:00
PROPERTY_HINT_HIDE_QUATERNION_EDIT, /// Only Node3D::transform should hide the quaternion editor.
PROPERTY_HINT_PASSWORD,
PROPERTY_HINT_LAYERS_AVOIDANCE,
2023-06-24 13:03:28 -05:00
PROPERTY_HINT_DICTIONARY_TYPE,
PROPERTY_HINT_TOOL_BUTTON,
PROPERTY_HINT_ONESHOT, ///< the property will be changed by self after setting, such as AudioStreamPlayer.playing, Particles.emitting.
Improve Scene Tree editor performance We now cache the Node*<>TreeItem* mapping in the SceneTreeEditor. This allows us to make targeted updates to the Tree used to display the scene tree in the editor. Previously on almost all changes to the scene tree the editor would rebuild the entire widget, causing a large number of deallocations an allocations. We now carefully manipulate the Tree widget in-situ saving a large number of these allocations. In order to know what Nodes need to be updated we add a editor_state_changed signal to Node, this is a TOOLS_ENABLED, editor-only signal fired when changes to Node happen that are relevant to editor state. We also now make sure that when nodes are moved/renamed we don't check expensive properties that cannot contain NodePaths. This saves a lot of time when SceneTreeDock renames a node in a scene with a lot of MeshInstances. This makes renaming nodes go from ~27 seconds to ~2 seconds on large scenes. SceneTreeEditor instances will now also not do all of the potentially expensive update work if they are invisible. This behavior is turned off by default so it won't affect existing users. This change allows the editor to only update SceneTreeEditors that actually in view. In practice this means that for most changes instead of updating 6 SceneTreeEditors we only update 1 instantly, and the others only when they become visible. There is definitely more that could be done, but this is already a massive improvement. In complex scenes we see an improvement of 10x, things that used to take ~30 seconds now only take 2. This fixes #83460 I want to thank KoBeWi, TokisanGames, a-johnston, aniel080400 for their tireless testing. And AeioMuch for their testing and providing a fix for the hover issue.
2024-11-26 00:04:25 +01:00
PROPERTY_HINT_NO_NODEPATH, /// < this property will not contain a NodePath, regardless of type (Array, Dictionary, List, etc.). Needed for SceneTreeDock.
2014-02-09 22:10:30 -03:00
PROPERTY_HINT_MAX,
};
enum PropertyUsageFlags {
2021-06-17 19:10:18 -04:00
PROPERTY_USAGE_NONE = 0,
2022-04-23 02:54:57 +02:00
PROPERTY_USAGE_STORAGE = 1 << 1,
PROPERTY_USAGE_EDITOR = 1 << 2,
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,
PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED = 1 << 14,
PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE = 1 << 15, // Deprecated.
PROPERTY_USAGE_CLASS_IS_ENUM = 1 << 16,
PROPERTY_USAGE_NIL_IS_VARIANT = 1 << 17,
PROPERTY_USAGE_ARRAY = 1 << 18, // Used in the inspector to group properties as elements of an array.
PROPERTY_USAGE_ALWAYS_DUPLICATE = 1 << 19, // When duplicating a resource, always duplicate, even with subresource duplication disabled.
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.
PROPERTY_USAGE_DEFERRED_SET_RESOURCE = 1 << 25, // Deprecated.
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.
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-09 22:10:30 -03: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)
#define ADD_GROUP_INDENT(m_name, m_prefix, m_depth) ::ClassDB::add_property_group(get_class_static(), m_name, m_prefix, m_depth)
#define ADD_SUBGROUP(m_name, m_prefix) ::ClassDB::add_property_subgroup(get_class_static(), m_name, m_prefix)
#define ADD_SUBGROUP_INDENT(m_name, m_prefix, m_depth) ::ClassDB::add_property_subgroup(get_class_static(), m_name, m_prefix, m_depth)
#define ADD_LINKED_PROPERTY(m_property, m_linked_property) ::ClassDB::add_linked_property(get_class_static(), m_property, m_linked_property)
2014-02-09 22:10:30 -03: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)
// 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-09 22:10:30 -03:00
struct PropertyInfo {
Variant::Type type = Variant::NIL;
2014-02-09 22:10:30 -03:00
String name;
StringName class_name; // For classes
PropertyHint hint = PROPERTY_HINT_NONE;
String hint_string;
uint32_t usage = PROPERTY_USAGE_DEFAULT;
2014-02-09 22:10:30 -03: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.
_FORCE_INLINE_ PropertyInfo added_usage(uint32_t p_fl) const {
2014-02-09 22:10:30 -03:00
PropertyInfo pi = *this;
pi.usage |= p_fl;
return pi;
}
operator Dictionary() const;
static PropertyInfo from_dict(const Dictionary &p_dict);
PropertyInfo() {}
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()) :
type(p_type),
name(p_name),
hint(p_hint),
hint_string(p_hint_string),
usage(p_usage) {
if (hint == PROPERTY_HINT_RESOURCE_TYPE) {
class_name = hint_string;
} else {
class_name = p_class_name;
}
}
PropertyInfo(const StringName &p_class_name) :
type(Variant::OBJECT),
class_name(p_class_name) {}
explicit PropertyInfo(const GDExtensionPropertyInfo &pinfo) :
type((Variant::Type)pinfo.type),
name(*reinterpret_cast<StringName *>(pinfo.name)),
class_name(*reinterpret_cast<StringName *>(pinfo.class_name)),
hint((PropertyHint)pinfo.hint),
hint_string(*reinterpret_cast<String *>(pinfo.hint_string)),
usage(pinfo.usage) {}
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));
}
bool operator<(const PropertyInfo &p_info) const {
return name < p_info.name;
}
2014-02-09 22:10:30 -03:00
};
TypedArray<Dictionary> convert_property_list(const List<PropertyInfo> *p_list);
2014-02-09 22:10:30 -03: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,
METHOD_FLAG_VIRTUAL_REQUIRED = 128,
METHOD_FLAGS_DEFAULT = METHOD_FLAG_NORMAL,
};
2014-02-09 22:10:30 -03:00
struct MethodInfo {
String name;
PropertyInfo return_val;
uint32_t flags = METHOD_FLAGS_DEFAULT;
int id = 0;
Fix warnings about wrong member initialization order [-Wreorder] Fixes the following GCC 5 warnings: ``` core/object.h:193:11: warning: 'MethodInfo::flags' will be initialized after [-Wreorder] core/object.h:192:15: warning: 'PropertyInfo MethodInfo::return_val' [-Wreorder] core/object.cpp:278:1: warning: when initialized here [-Wreorder] core/script_debugger_remote.h:97:6: warning: 'ScriptDebuggerRemote::max_cps' will be initialized after [-Wreorder] core/script_debugger_remote.h:91:6: warning: 'int ScriptDebuggerRemote::max_messages_per_frame' [-Wreorder] core/script_debugger_remote.cpp:1086:1: warning: when initialized here [-Wreorder] core/script_debugger_remote.h:98:6: warning: 'ScriptDebuggerRemote::char_count' will be initialized after [-Wreorder] core/script_debugger_remote.h:92:6: warning: 'int ScriptDebuggerRemote::n_messages_dropped' [-Wreorder] core/script_debugger_remote.cpp:1086:1: warning: when initialized here [-Wreorder] modules/bullet/area_bullet.h:102:7: warning: 'AreaBullet::isScratched' will be initialized after [-Wreorder] modules/bullet/area_bullet.h:92:39: warning: 'PhysicsServer::AreaSpaceOverrideMode AreaBullet::spOv_mode' [-Wreorder] modules/bullet/area_bullet.cpp:46:1: warning: when initialized here [-Wreorder] modules/bullet/collision_object_bullet.h:127:15: warning: 'CollisionObjectBullet::space' will be initialized after [-Wreorder] modules/bullet/collision_object_bullet.h:117:7: warning: 'CollisionObjectBullet::Type CollisionObjectBullet::type' [-Wreorder] modules/bullet/collision_object_bullet.cpp:67:1: warning: when initialized here [-Wreorder] modules/bullet/godot_ray_world_algorithm.h:48:7: warning: 'GodotRayWorldAlgorithm::m_ownManifol1d' will be initialized after [-Wreorder] modules/bullet/godot_ray_world_algorithm.h:46:33: warning: 'const btDiscreteDynamicsWorld* GodotRayWorldAlgorithm::m_world' [-Wreorder] modules/bullet/godot_ray_world_algorithm.cpp:50:1: warning: when initialized here [-Wreorder] modules/bullet/godot_result_callbacks.h:91:18: warning: 'GodotAllConvexResultCallback::m_exclude' will be initialized after [-Wreorder] modules/bullet/godot_result_callbacks.h:89:6: warning: 'int GodotAllConvexResultCallback::m_resultMax' [-Wreorder] modules/bullet/godot_result_callbacks.h:93:2: warning: when initialized here [-Wreorder] modules/bullet/godot_result_callbacks.h:142:18: warning: 'GodotAllContactResultCallback::m_exclude' will be initialized after [-Wreorder] modules/bullet/godot_result_callbacks.h:140:6: warning: 'int GodotAllContactResultCallback::m_resultMax' [-Wreorder] modules/bullet/godot_result_callbacks.h:147:2: warning: when initialized here [-Wreorder] modules/bullet/godot_result_callbacks.h:168:18: warning: 'GodotContactPairContactResultCallback::m_exclude' will be initialized after [-Wreorder] modules/bullet/godot_result_callbacks.h:166:6: warning: 'int GodotContactPairContactResultCallback::m_resultMax' [-Wreorder] modules/bullet/godot_result_callbacks.h:173:2: warning: when initialized here [-Wreorder] modules/bullet/godot_result_callbacks.h:195:18: warning: 'GodotRestInfoContactResultCallback::m_exclude' will be initialized after [-Wreorder] modules/bullet/godot_result_callbacks.h:191:7: warning: 'bool GodotRestInfoContactResultCallback::m_collided' [-Wreorder] modules/bullet/godot_result_callbacks.h:199:2: warning: when initialized here [-Wreorder] modules/bullet/rigid_body_bullet.h:200:9: warning: 'RigidBodyBullet::gravity_scale' will be initialized after [-Wreorder] modules/bullet/rigid_body_bullet.h:199:9: warning: 'real_t RigidBodyBullet::mass' [-Wreorder] modules/bullet/rigid_body_bullet.cpp:258:1: warning: when initialized here [-Wreorder] modules/bullet/rigid_body_bullet.h:222:28: warning: 'RigidBodyBullet::force_integration_callback' will be initialized after [-Wreorder] modules/bullet/rigid_body_bullet.h:219:7: warning: 'bool RigidBodyBullet::isTransformChanged' [-Wreorder] modules/bullet/rigid_body_bullet.cpp:258:1: warning: when initialized here [-Wreorder] modules/bullet/rigid_body_bullet.h:220:7: warning: 'RigidBodyBullet::previousActiveState' will be initialized after [-Wreorder] modules/bullet/rigid_body_bullet.h:208:6: warning: 'int RigidBodyBullet::maxCollisionsDetection' [-Wreorder] modules/bullet/rigid_body_bullet.cpp:258:1: warning: when initialized here [-Wreorder] modules/bullet/soft_body_bullet.h:69:9: warning: 'SoftBodyBullet::total_mass' will be initialized after [-Wreorder] modules/bullet/soft_body_bullet.h:68:6: warning: 'int SoftBodyBullet::simulation_precision' [-Wreorder] modules/bullet/soft_body_bullet.cpp:38:1: warning: when initialized here [-Wreorder] modules/bullet/soft_body_bullet.h:76:9: warning: 'SoftBodyBullet::drag_coefficient' will be initialized after [-Wreorder] modules/bullet/soft_body_bullet.h:61:14: warning: 'btSoftBody* SoftBodyBullet::bt_soft_body' [-Wreorder] modules/bullet/soft_body_bullet.cpp:38:1: warning: when initialized here [-Wreorder] modules/bullet/space_bullet.h:97:22: warning: 'SpaceBullet::solver' will be initialized after [-Wreorder] modules/bullet/space_bullet.h:95:35: warning: 'btDefaultCollisionConfiguration* SpaceBullet::collisionConfiguration' [-Wreorder] modules/bullet/space_bullet.cpp:333:1: warning: when initialized here [-Wreorder] modules/bullet/space_bullet.h:101:23: warning: 'SpaceBullet::soft_body_world_info' will be initialized after [-Wreorder] modules/bullet/space_bullet.h:99:23: warning: 'btGhostPairCallback* SpaceBullet::ghostPairCallback' [-Wreorder] modules/bullet/space_bullet.cpp:333:1: warning: when initialized here [-Wreorder] modules/gdnative/nativescript/nativescript.h:79:13: warning: 'NativeScriptDesc::base_native_type' will be initialized after [-Wreorder] modules/gdnative/nativescript/nativescript.h:73:9: warning: 'String NativeScriptDesc::documentation' [-Wreorder] modules/gdnative/nativescript/nativescript.h:88:9: warning: when initialized here [-Wreorder] modules/gdscript/gdscript.h:296:6: warning: 'GDScriptWarning::line' will be initialized after [-Wreorder] modules/gdscript/gdscript.h:294:4: warning: 'GDScriptWarning::Code GDScriptWarning::code' [-Wreorder] modules/gdscript/gdscript.h:303:2: warning: when initialized here [-Wreorder] scene/3d/physics_body.h:544:7: warning: 'PhysicalBone::simulate_physics' will be initialized after [-Wreorder] scene/3d/physics_body.h:543:7: warning: 'bool PhysicalBone::_internal_static_body' [-Wreorder] scene/3d/physics_body.cpp:2502:1: warning: when initialized here [-Wreorder] scene/3d/physics_body.h:546:6: warning: 'PhysicalBone::bone_id' will be initialized after [-Wreorder] scene/3d/physics_body.h:539:12: warning: 'Skeleton* PhysicalBone::parent_skeleton' [-Wreorder] scene/3d/physics_body.cpp:2502:1: warning: when initialized here [-Wreorder] scene/3d/spring_arm.h:44:11: warning: 'SpringArm::mask' will be initialized after [-Wreorder] scene/3d/spring_arm.h:43:8: warning: 'float SpringArm::current_spring_length' [-Wreorder] scene/3d/spring_arm.cpp:37:1: warning: when initialized here [-Wreorder] scene/animation/skeleton_ik.h:159:11: warning: 'SkeletonIK::target_node_override' will be initialized after [-Wreorder] scene/animation/skeleton_ik.h:152:7: warning: 'bool SkeletonIK::use_magnet' [-Wreorder] scene/animation/skeleton_ik.cpp:418:1: warning: when initialized here [-Wreorder] scene/resources/tile_set.h:84:9: warning: 'TileSet::AutotileData::size' will be initialized after [-Wreorder] scene/resources/tile_set.h:83:7: warning: 'int TileSet::AutotileData::spacing' [-Wreorder] scene/resources/tile_set.h:92:12: warning: when initialized here [-Wreorder] scene/resources/tile_set.h:115:12: warning: 'TileSet::TileData::tile_mode' will be initialized after [-Wreorder] scene/resources/tile_set.h:114:9: warning: 'Color TileSet::TileData::modulate' [-Wreorder] scene/resources/tile_set.h:120:12: warning: when initialized here [-Wreorder] servers/physics/body_sw.h:84:19: warning: 'BodySW::direct_state_query_list' will be initialized after [-Wreorder] servers/physics/body_sw.h:57:11: warning: 'uint16_t BodySW::locked_axis' [-Wreorder] servers/physics/body_sw.cpp:756:1: warning: when initialized here [-Wreorder] ``` Nothing really relevant for us, but it's not a bad consistency improvement anyway so worth taking.
2018-09-28 17:17:38 +02:00
List<PropertyInfo> arguments;
Vector<Variant> default_arguments;
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;
}
inline bool operator==(const MethodInfo &p_method) const { return id == p_method.id && name == p_method.name; }
2014-02-09 22:10:30 -03:00
inline bool operator<(const MethodInfo &p_method) const { return id == p_method.id ? (name < p_method.name) : (id < p_method.id); }
operator Dictionary() const;
static MethodInfo from_dict(const Dictionary &p_dict);
MethodInfo() {}
explicit MethodInfo(const GDExtensionMethodInfo &pinfo) :
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]);
}
}
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-09 22:10:30 -03:00
};
// API used to extend in GDExtension and other C compatible compiled languages.
class MethodBind;
class GDExtension;
struct ObjectGDExtension {
GDExtension *library = nullptr;
ObjectGDExtension *parent = nullptr;
List<ObjectGDExtension *> children;
StringName parent_class_name;
StringName class_name;
bool editor_class = false;
2023-08-04 20:34:14 -05:00
bool reloadable = false;
bool is_virtual = false;
bool is_abstract = false;
bool is_exposed = true;
2024-01-02 14:10:54 -06:00
#ifdef TOOLS_ENABLED
bool is_runtime = false;
bool is_placeholder = false;
#endif
GDExtensionClassSet set;
GDExtensionClassGet get;
GDExtensionClassGetPropertyList get_property_list;
GDExtensionClassFreePropertyList2 free_property_list2;
GDExtensionClassPropertyCanRevert property_can_revert;
GDExtensionClassPropertyGetRevert property_get_revert;
GDExtensionClassValidateProperty validate_property;
#ifndef DISABLE_DEPRECATED
GDExtensionClassNotification notification;
GDExtensionClassFreePropertyList free_property_list;
#endif // DISABLE_DEPRECATED
GDExtensionClassNotification2 notification2;
GDExtensionClassToString to_string;
GDExtensionClassReference reference;
GDExtensionClassReference unreference;
GDExtensionClassGetRID get_rid;
_FORCE_INLINE_ bool is_class(const String &p_class) const {
const ObjectGDExtension *e = this;
while (e) {
if (p_class == e->class_name.operator String()) {
return true;
}
e = e->parent;
}
return false;
}
void *class_userdata = nullptr;
#ifndef DISABLE_DEPRECATED
GDExtensionClassCreateInstance create_instance;
#endif // DISABLE_DEPRECATED
GDExtensionClassCreateInstance2 create_instance2;
GDExtensionClassFreeInstance free_instance;
GDExtensionClassGetVirtual get_virtual;
GDExtensionClassGetVirtualCallData get_virtual_call_data;
GDExtensionClassCallVirtualWithData call_virtual_with_data;
2023-08-04 20:34:14 -05:00
GDExtensionClassRecreateInstance recreate_instance;
#ifdef TOOLS_ENABLED
void *tracking_userdata = nullptr;
void (*track_instance)(void *p_userdata, void *p_instance) = nullptr;
void (*untrack_instance)(void *p_userdata, void *p_instance) = nullptr;
2023-08-04 20:34:14 -05:00
#endif
};
#define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call(__VA_ARGS__)
#define GDVIRTUAL_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call(__VA_ARGS__)
#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
#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()
2014-02-09 22:10:30 -03: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-09 22:10:30 -03:00
2020-07-10 11:34:39 +01:00
#define GDCLASS(m_class, m_inherits) \
private: \
void operator=(const m_class &p_rval) {} \
friend class ::ClassDB; \
2020-07-10 11:34:39 +01:00
\
public: \
typedef m_class self_type; \
static constexpr bool _class_is_enabled = !bool(GD_IS_DEFINED(ClassDB_Disable_##m_class)) && m_inherits::_class_is_enabled; \
2020-07-10 11:34:39 +01:00
virtual String get_class() const override { \
if (_get_extension()) { \
return _get_extension()->class_name.operator String(); \
} \
2020-07-10 11:34:39 +01:00
return String(#m_class); \
} \
virtual const StringName *_get_class_namev() const override { \
static StringName _class_name_static; \
if (unlikely(!_class_name_static)) { \
StringName::assign_static_unique_class_name(&_class_name_static, #m_class); \
2020-07-10 11:34:39 +01:00
} \
return &_class_name_static; \
2020-07-10 11:34:39 +01: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)); \
} \
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 11:34:39 +01: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; \
} \
_FORCE_INLINE_ static void (*_get_bind_compatibility_methods())() { \
return &m_class::_bind_compatibility_methods; \
2020-07-10 11:34:39 +01:00
} \
\
public: \
static void initialize_class() { \
static bool initialized = false; \
if (initialized) { \
return; \
} \
m_inherits::initialize_class(); \
::ClassDB::_add_class<m_class>(); \
2020-07-10 11:34:39 +01:00
if (m_class::_get_bind_methods() != m_inherits::_get_bind_methods()) { \
_bind_methods(); \
} \
if (m_class::_get_bind_compatibility_methods() != m_inherits::_get_bind_compatibility_methods()) { \
_bind_compatibility_methods(); \
} \
2020-07-10 11:34:39 +01:00
initialized = true; \
} \
\
protected: \
virtual void _initialize_classv() override { \
initialize_class(); \
} \
_FORCE_INLINE_ bool (Object::*_get_get() const)(const StringName &p_name, Variant &) const { \
return (bool(Object::*)(const StringName &, Variant &) const) & m_class::_get; \
2020-07-10 11:34:39 +01: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) { \
return (bool(Object::*)(const StringName &, const Variant &)) & m_class::_set; \
2020-07-10 11:34:39 +01: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 { \
return (void(Object::*)(List<PropertyInfo> *) const) & m_class::_get_property_list; \
2020-07-10 11:34:39 +01: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); \
} \
p_list->push_back(PropertyInfo(Variant::NIL, get_class_static(), PROPERTY_HINT_NONE, get_class_static(), PROPERTY_USAGE_CATEGORY)); \
::ClassDB::get_property_list(#m_class, p_list, true, this); \
2020-07-10 11:34:39 +01:00
if (m_class::_get_get_property_list() != m_inherits::_get_get_property_list()) { \
_get_property_list(p_list); \
} \
if (p_reversed) { \
m_inherits::_get_property_listv(p_list, p_reversed); \
} \
} \
_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); \
} \
} \
_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 11:34:39 +01:00
_FORCE_INLINE_ void (Object::*_get_notification() const)(int) { \
return (void(Object::*)(int)) & m_class::_notification; \
2020-07-10 11:34:39 +01: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-09 22:10:30 -03:00
private:
2020-07-10 11:34:39 +01:00
#define OBJ_SAVE_TYPE(m_class) \
public: \
virtual String get_save_class() const override { return #m_class; } \
\
2014-02-09 22:10:30 -03:00
private:
class ScriptInstance;
class Object {
2014-02-09 22:10:30 -03:00
public:
typedef Object self_type;
2014-02-09 22:10:30 -03:00
enum ConnectFlags {
CONNECT_DEFERRED = 1,
CONNECT_PERSIST = 2, // hint for scene to save this connection
CONNECT_ONE_SHOT = 4,
CONNECT_REFERENCE_COUNTED = 8,
CONNECT_INHERITED = 16, // Used in editor builds.
2014-02-09 22:10:30 -03:00
};
struct Connection {
::Signal signal;
Callable callable;
uint32_t flags = 0;
2014-02-09 22:10:30 -03:00
bool operator<(const Connection &p_conn) const;
operator Variant() const;
Connection() {}
2014-02-09 22:10:30 -03:00
Connection(const Variant &p_variant);
};
2014-02-09 22:10:30 -03:00
private:
#ifdef DEBUG_ENABLED
Fix mismatched class/struct definition warnings [-Wmismatched-tags] Fixes the following Clang 7 warnings: ``` core/object.cpp:44:1: warning: '_ObjectDebugLock' defined as a struct here but previously declared as a class [-Wmismatched-tags] core/variant_call.cpp:43:1: warning: '_VariantCall' defined as a struct here but previously declared as a class [-Wmismatched-tags] drivers/gles3/rasterizer_storage_gles3.h:765:2: warning: 'MultiMesh' defined as a struct here but previously declared as a class [-Wmismatched-tags] editor/editor_node.h:794:1: warning: 'EditorProgress' defined as a struct here but previously declared as a class [-Wmismatched-tags] modules/bullet/rigid_body_bullet.h:230:17: warning: class 'KinematicUtilities' was previously declared as a struct [-Wmismatched-tags] modules/bullet/space_bullet.h:60:1: warning: class 'btSoftBodyWorldInfo' was previously declared as a struct [-Wmismatched-tags] scene/resources/world_2d.cpp:40:1: warning: 'SpatialIndexer2D' defined as a struct here but previously declared as a class [-Wmismatched-tags] scene/resources/world.cpp:39:1: warning: 'SpatialIndexer' defined as a struct here but previously declared as a class [-Wmismatched-tags] servers/audio/reverb_sw.cpp:60:1: warning: 'ReverbParamsSW' defined as a struct here but previously declared as a class [-Wmismatched-tags] thirdparty/bullet/BulletSoftBody/btSoftBody.h:43:1: warning: 'btSoftBodyWorldInfo' defined as a struct here but previously declared as a class [-Wmismatched-tags] ```
2018-10-01 16:46:50 +02:00
friend struct _ObjectDebugLock;
#endif
2014-02-09 22:10:30 -03:00
friend bool predelete_handler(Object *);
friend void postinitialize_handler(Object *);
ObjectGDExtension *_extension = nullptr;
GDExtensionClassInstancePtr _extension_instance = nullptr;
struct SignalData {
2014-02-09 22:10:30 -03:00
struct Slot {
int reference_count = 0;
2014-02-09 22:10:30 -03:00
Connection conn;
List<Connection>::Element *cE = nullptr;
2014-02-09 22:10:30 -03:00
};
MethodInfo user;
HashMap<Callable, Slot, HashableHasher<Callable>> slot_map;
bool removable = false;
2014-02-09 22:10:30 -03:00
};
HashMap<StringName, SignalData> signal_map;
2014-02-09 22:10:30 -03:00
List<Connection> connections;
#ifdef DEBUG_ENABLED
SafeRefCount _lock_index;
#endif
bool _block_signals = false;
int _predelete_ok = 0;
ObjectID _instance_id;
2014-02-09 22:10:30 -03:00
bool _predelete();
void _initialize();
2014-02-09 22:10:30 -03:00
void _postinitialize();
bool _can_translate = true;
bool _emitting = false;
2014-02-09 22:10:30 -03:00
#ifdef TOOLS_ENABLED
bool _edited = false;
uint32_t _edited_version = 0;
HashSet<String> editor_section_folding;
2014-02-09 22:10:30 -03:00
#endif
ScriptInstance *script_instance = nullptr;
Variant script; // Reference does not exist yet, store it in a Variant.
HashMap<StringName, Variant> metadata;
HashMap<StringName, Variant *> metadata_properties;
mutable const StringName *_class_name_ptr = nullptr;
2014-02-09 22:10:30 -03:00
void _add_user_signal(const String &p_name, const Array &p_args = Array());
2015-03-03 14:39:13 -03:00
bool _has_user_signal(const StringName &p_name) const;
void _remove_user_signal(const StringName &p_name);
Error _emit_signal(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
TypedArray<Dictionary> _get_signal_list() const;
TypedArray<Dictionary> _get_signal_connection_list(const StringName &p_signal) const;
TypedArray<Dictionary> _get_incoming_connections() const;
void _set_bind(const StringName &p_set, const Variant &p_value);
Variant _get_bind(const StringName &p_name) const;
void _set_indexed_bind(const NodePath &p_name, const Variant &p_value);
Variant _get_indexed_bind(const NodePath &p_name) const;
int _get_method_argument_count_bind(const StringName &p_name) const;
2014-02-09 22:10:30 -03:00
_FORCE_INLINE_ void _construct_object(bool p_reference);
2021-06-04 18:03:15 +02:00
friend class RefCounted;
bool type_is_reference = false;
2023-11-17 20:44:38 +01:00
BinaryMutex _instance_binding_mutex;
struct InstanceBinding {
void *binding = nullptr;
void *token = nullptr;
GDExtensionInstanceBindingFreeCallback free_callback = nullptr;
GDExtensionInstanceBindingReferenceCallback reference_callback = nullptr;
};
InstanceBinding *_instance_bindings = nullptr;
uint32_t _instance_binding_count = 0;
Object(bool p_reference);
protected:
StringName _translation_domain;
_FORCE_INLINE_ bool _instance_binding_reference(bool p_reference) {
bool can_die = true;
if (_instance_bindings) {
2024-08-28 11:27:01 +02:00
MutexLock instance_binding_lock(_instance_binding_mutex);
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;
}
}
}
}
return can_die;
}
friend class GDExtensionMethodBind;
_ALWAYS_INLINE_ const ObjectGDExtension *_get_extension() const { return _extension; }
_ALWAYS_INLINE_ GDExtensionClassInstancePtr _get_extension_instance() const { return _extension_instance; }
virtual void _initialize_classv() { initialize_class(); }
2014-02-09 22:10:30 -03: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 {}
virtual void _validate_propertyv(PropertyInfo &p_property) const {}
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; }
virtual void _notificationv(int p_notification, bool p_reversed) {}
2014-02-09 22:10:30 -03:00
static void _bind_methods();
static void _bind_compatibility_methods() {}
2014-02-09 22:10:30 -03: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 {}
void _validate_property(PropertyInfo &p_property) const {}
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; }
void _notification(int p_notification) {}
2014-02-09 22:10:30 -03:00
_FORCE_INLINE_ static void (*_get_bind_methods())() {
return &Object::_bind_methods;
}
_FORCE_INLINE_ static void (*_get_bind_compatibility_methods())() {
return &Object::_bind_compatibility_methods;
}
_FORCE_INLINE_ bool (Object::*_get_get() const)(const StringName &p_name, Variant &r_ret) const {
2014-02-09 22:10:30 -03:00
return &Object::_get;
}
_FORCE_INLINE_ bool (Object::*_get_set() const)(const StringName &p_name, const Variant &p_property) {
2014-02-09 22:10:30 -03:00
return &Object::_set;
}
_FORCE_INLINE_ void (Object::*_get_get_property_list() const)(List<PropertyInfo> *p_list) const {
2014-02-09 22:10:30 -03:00
return &Object::_get_property_list;
}
_FORCE_INLINE_ void (Object::*_get_validate_property() const)(PropertyInfo &p_property) const {
return &Object::_validate_property;
}
_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;
}
_FORCE_INLINE_ void (Object::*_get_notification() const)(int) {
2014-02-09 22:10:30 -03:00
return &Object::_notification;
}
2014-02-09 22:10:30 -03:00
static void get_valid_parents_static(List<String> *p_parents);
static void _get_valid_parents_static(List<String> *p_parents);
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-09 22:10:30 -03:00
virtual const StringName *_get_class_namev() const {
static StringName _class_name_static;
if (unlikely(!_class_name_static)) {
StringName::assign_static_unique_class_name(&_class_name_static, "Object");
}
return &_class_name_static;
}
2014-02-09 22:10:30 -03:00
TypedArray<StringName> _get_meta_list_bind() const;
TypedArray<Dictionary> _get_property_list_bind() const;
TypedArray<Dictionary> _get_method_list_bind() const;
2014-02-09 22:10:30 -03:00
void _clear_internal_resource_paths(const Variant &p_var);
friend class ClassDB;
2024-01-02 14:10:54 -06:00
friend class PlaceholderExtensionInstance;
bool _disconnect(const StringName &p_signal, const Callable &p_callable, bool p_force = false);
2018-08-20 16:35:36 -03:00
2023-08-04 20:34:14 -05:00
#ifdef TOOLS_ENABLED
struct VirtualMethodTracker {
void **method;
bool *initialized;
VirtualMethodTracker *next;
};
mutable VirtualMethodTracker *virtual_method_list = nullptr;
#endif
public: // Should be protected, but bug in clang++.
static void initialize_class();
_FORCE_INLINE_ static void register_custom_data_to_otdb() {}
2014-02-09 22:10:30 -03:00
public:
static constexpr bool _class_is_enabled = true;
void notify_property_list_changed();
static void *get_class_ptr_static() {
2014-02-09 22:10:30 -03:00
static int ptr;
return &ptr;
}
void detach_from_objectdb();
_FORCE_INLINE_ ObjectID get_instance_id() const { return _instance_id; }
2014-02-09 22:10:30 -03:00
template <typename T>
static T *cast_to(Object *p_object) {
return p_object ? dynamic_cast<T *>(p_object) : nullptr;
}
template <typename T>
static const T *cast_to(const Object *p_object) {
return p_object ? dynamic_cast<const T *>(p_object) : nullptr;
}
2014-02-09 22:10:30 -03:00
enum {
NOTIFICATION_POSTINITIALIZE = 0,
2023-08-04 20:34:14 -05:00
NOTIFICATION_PREDELETE = 1,
NOTIFICATION_EXTENSION_RELOADED = 2,
// Internal notification to send after NOTIFICATION_PREDELETE, not bound to scripting.
NOTIFICATION_PREDELETE_CLEANUP = 3,
2014-02-09 22:10:30 -03:00
};
2014-02-09 22:10:30 -03:00
/* TYPE API */
static void get_inheritance_list_static(List<String> *p_inheritance_list) { p_inheritance_list->push_back("Object"); }
static String get_class_static() { return "Object"; }
static String get_parent_class_static() { return String(); }
2014-02-09 22:10:30 -03:00
virtual String get_class() const {
if (_extension) {
return _extension->class_name.operator String();
}
return "Object";
}
virtual String get_save_class() const { return get_class(); } //class stored when saving
virtual bool is_class(const String &p_class) const {
if (_extension && _extension->is_class(p_class)) {
return true;
}
return (p_class == "Object");
}
virtual bool is_class_ptr(void *p_ptr) const { return get_class_ptr_static() == p_ptr; }
_FORCE_INLINE_ const StringName &get_class_name() const {
if (_extension) {
// Can't put inside the unlikely as constructor can run it
return _extension->class_name;
}
if (unlikely(!_class_name_ptr)) {
// While class is initializing / deinitializing, constructors and destructurs
// need access to the proper class at the proper stage.
return *_get_class_namev();
}
return *_class_name_ptr;
}
StringName get_class_name_for_extension(const GDExtension *p_library) const;
2014-02-09 22:10:30 -03: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-09 22:10:30 -03:00
void get_property_list(List<PropertyInfo> *p_list, bool p_reversed = false) const;
void validate_property(PropertyInfo &p_property) const;
bool property_can_revert(const StringName &p_name) const;
Variant property_get_revert(const StringName &p_name) const;
2014-02-09 22:10:30 -03:00
bool has_method(const StringName &p_method) const;
int get_method_argument_count(const StringName &p_method, bool *r_is_valid = nullptr) const;
2014-02-09 22:10:30 -03:00
void get_method_list(List<MethodInfo> *p_list) const;
Variant callv(const StringName &p_method, const Array &p_args);
virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
virtual Variant call_const(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
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;
const Variant ret = callp(p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args), cerr);
return (cerr.error == Callable::CallError::CALL_OK) ? ret : Variant();
}
2014-02-09 22:10:30 -03:00
void notification(int p_notification, bool p_reversed = false);
virtual String to_string();
2014-02-09 22:10:30 -03: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-09 22:10:30 -03:00
/* SCRIPT */
// 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-09 22:10:30 -03: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;
MTVIRTUAL void merge_meta_from(const Object *p_src);
2014-02-09 22:10:30 -03:00
#ifdef TOOLS_ENABLED
void set_edited(bool p_edited);
bool is_edited() const;
// 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-09 22:10:30 -03:00
#endif
void set_script_instance(ScriptInstance *p_instance);
_FORCE_INLINE_ ScriptInstance *get_script_instance() const { return script_instance; }
// 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);
2014-02-09 22:10:30 -03:00
void add_user_signal(const MethodInfo &p_signal);
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));
}
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-09 22:10:30 -03: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;
MTVIRTUAL bool has_connections(const StringName &p_signal) const;
2014-02-09 22:10:30 -03:00
template <typename... VarArgs>
void call_deferred(const StringName &p_name, VarArgs... p_args) {
MessageQueue::get_singleton()->push_call(this, p_name, p_args...);
}
void set_deferred(const StringName &p_property, const Variant &p_value);
2014-02-09 22:10:30 -03: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;
// Translate message (internationalization).
String tr(const StringName &p_message, const StringName &p_context = "") const;
String tr_n(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context = "") const;
2014-02-09 22:10:30 -03:00
bool _is_queued_for_deletion = false; // Set to true by SceneTree::queue_delete().
bool is_queued_for_deletion() const;
_FORCE_INLINE_ void set_message_translation(bool p_enable) { _can_translate = p_enable; }
2014-02-09 22:10:30 -03:00
_FORCE_INLINE_ bool can_translate_messages() const { return _can_translate; }
virtual StringName get_translation_domain() const;
virtual void set_translation_domain(const StringName &p_domain);
#ifdef TOOLS_ENABLED
virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const;
void editor_set_section_unfold(const String &p_section, bool p_unfolded);
bool editor_is_section_unfolded(const String &p_section);
const HashSet<String> &editor_get_section_folding() const { return editor_section_folding; }
void editor_clear_section_folding() { editor_section_folding.clear(); }
#endif
// Used by script languages to store binding data.
void *get_instance_binding(void *p_token, const GDExtensionInstanceBindingCallbacks *p_callbacks);
// Used on creation by binding only.
void set_instance_binding(void *p_token, void *p_binding, const GDExtensionInstanceBindingCallbacks *p_callbacks);
bool has_instance_binding(void *p_token);
void free_instance_binding(void *p_token);
2023-08-04 20:34:14 -05:00
#ifdef TOOLS_ENABLED
void clear_internal_extension();
void reset_internal_extension(ObjectGDExtension *p_extension);
2024-01-02 14:10:54 -06:00
bool is_extension_placeholder() const { return _extension && _extension->is_placeholder; }
2023-08-04 20:34:14 -05:00
#endif
void clear_internal_resource_paths();
2021-06-04 18:03:15 +02:00
_ALWAYS_INLINE_ bool is_ref_counted() const { return type_is_reference; }
void cancel_free();
Object();
2014-02-09 22:10:30 -03:00
virtual ~Object();
};
bool predelete_handler(Object *p_object);
void postinitialize_handler(Object *p_object);
class ObjectDB {
// This needs to add up to 63, 1 bit is for reference.
#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))
struct ObjectSlot { // 128 bits per slot.
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;
Object *object = nullptr;
2014-02-09 22:10:30 -03: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-09 22:10:30 -03:00
friend class Object;
2014-02-09 22:10:30 -03:00
friend void unregister_core_types();
static void cleanup();
static ObjectID add_instance(Object *p_object);
2014-02-09 22:10:30 -03:00
static void remove_instance(Object *p_object);
friend void register_core_types();
static void setup();
public:
2014-02-09 22:10:30 -03:00
typedef void (*DebugFunc)(Object *p_obj);
_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;
ERR_FAIL_COND_V(slot >= slot_max, nullptr); // This should never happen unless RID is corrupted.
spin_lock.lock();
2014-02-09 22:10:30 -03:00
uint64_t validator = (id >> OBJECTDB_SLOT_MAX_COUNT_BITS) & OBJECTDB_VALIDATOR_MASK;
2014-02-09 22:10:30 -03:00
if (unlikely(object_slots[slot].validator != validator)) {
spin_lock.unlock();
return nullptr;
}
Object *object = object_slots[slot].object;
spin_lock.unlock();
return object;
2014-02-09 22:10:30 -03:00
}
static void debug_objects(DebugFunc p_func);
static int get_object_count();
2014-02-09 22:10:30 -03:00
};
#endif // OBJECT_H