| 1 | /**************************************************************************/ |
| 2 | /* node.h */ |
| 3 | /**************************************************************************/ |
| 4 | /* This file is part of: */ |
| 5 | /* GODOT ENGINE */ |
| 6 | /* https://godotengine.org */ |
| 7 | /**************************************************************************/ |
| 8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
| 9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
| 10 | /* */ |
| 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
| 12 | /* a copy of this software and associated documentation files (the */ |
| 13 | /* "Software"), to deal in the Software without restriction, including */ |
| 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
| 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
| 16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
| 17 | /* the following conditions: */ |
| 18 | /* */ |
| 19 | /* The above copyright notice and this permission notice shall be */ |
| 20 | /* included in all copies or substantial portions of the Software. */ |
| 21 | /* */ |
| 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
| 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
| 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
| 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
| 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
| 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
| 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
| 29 | /**************************************************************************/ |
| 30 | |
| 31 | #ifndef NODE_H |
| 32 | #define NODE_H |
| 33 | |
| 34 | #include "core/string/node_path.h" |
| 35 | #include "core/templates/rb_map.h" |
| 36 | #include "core/variant/typed_array.h" |
| 37 | #include "scene/main/scene_tree.h" |
| 38 | |
| 39 | class Viewport; |
| 40 | class Window; |
| 41 | class SceneState; |
| 42 | class Tween; |
| 43 | class PropertyTweener; |
| 44 | |
| 45 | SAFE_FLAG_TYPE_PUN_GUARANTEES |
| 46 | SAFE_NUMERIC_TYPE_PUN_GUARANTEES(uint32_t) |
| 47 | |
| 48 | class Node : public Object { |
| 49 | GDCLASS(Node, Object); |
| 50 | |
| 51 | protected: |
| 52 | // During group processing, these are thread-safe. |
| 53 | // Outside group processing, these avoid the cost of sync by working as plain primitive types. |
| 54 | union MTFlag { |
| 55 | SafeFlag mt; |
| 56 | bool st; |
| 57 | MTFlag() : |
| 58 | mt{} {} |
| 59 | }; |
| 60 | template <class T> |
| 61 | union MTNumeric { |
| 62 | SafeNumeric<T> mt; |
| 63 | T st; |
| 64 | MTNumeric() : |
| 65 | mt{} {} |
| 66 | }; |
| 67 | |
| 68 | public: |
| 69 | enum ProcessMode { |
| 70 | PROCESS_MODE_INHERIT, // same as parent node |
| 71 | PROCESS_MODE_PAUSABLE, // process only if not paused |
| 72 | PROCESS_MODE_WHEN_PAUSED, // process only if paused |
| 73 | PROCESS_MODE_ALWAYS, // process always |
| 74 | PROCESS_MODE_DISABLED, // never process |
| 75 | }; |
| 76 | |
| 77 | enum ProcessThreadGroup { |
| 78 | PROCESS_THREAD_GROUP_INHERIT, |
| 79 | PROCESS_THREAD_GROUP_MAIN_THREAD, |
| 80 | PROCESS_THREAD_GROUP_SUB_THREAD, |
| 81 | }; |
| 82 | |
| 83 | enum ProcessThreadMessages { |
| 84 | FLAG_PROCESS_THREAD_MESSAGES = 1, |
| 85 | FLAG_PROCESS_THREAD_MESSAGES_PHYSICS = 2, |
| 86 | FLAG_PROCESS_THREAD_MESSAGES_ALL = 3, |
| 87 | }; |
| 88 | |
| 89 | enum DuplicateFlags { |
| 90 | DUPLICATE_SIGNALS = 1, |
| 91 | DUPLICATE_GROUPS = 2, |
| 92 | DUPLICATE_SCRIPTS = 4, |
| 93 | DUPLICATE_USE_INSTANTIATION = 8, |
| 94 | #ifdef TOOLS_ENABLED |
| 95 | DUPLICATE_FROM_EDITOR = 16, |
| 96 | #endif |
| 97 | }; |
| 98 | |
| 99 | enum NameCasing { |
| 100 | NAME_CASING_PASCAL_CASE, |
| 101 | NAME_CASING_CAMEL_CASE, |
| 102 | NAME_CASING_SNAKE_CASE |
| 103 | }; |
| 104 | |
| 105 | enum InternalMode { |
| 106 | INTERNAL_MODE_DISABLED, |
| 107 | INTERNAL_MODE_FRONT, |
| 108 | INTERNAL_MODE_BACK, |
| 109 | }; |
| 110 | |
| 111 | struct Comparator { |
| 112 | bool operator()(const Node *p_a, const Node *p_b) const { return p_b->is_greater_than(p_a); } |
| 113 | }; |
| 114 | |
| 115 | static int orphan_node_count; |
| 116 | |
| 117 | void _update_process(bool p_enable, bool p_for_children); |
| 118 | |
| 119 | private: |
| 120 | struct GroupData { |
| 121 | bool persistent = false; |
| 122 | SceneTree::Group *group = nullptr; |
| 123 | }; |
| 124 | |
| 125 | struct ComparatorByIndex { |
| 126 | bool operator()(const Node *p_left, const Node *p_right) const { |
| 127 | static const uint32_t order[3] = { 1, 0, 2 }; |
| 128 | uint32_t order_left = order[p_left->data.internal_mode]; |
| 129 | uint32_t order_right = order[p_right->data.internal_mode]; |
| 130 | if (order_left == order_right) { |
| 131 | return p_left->data.index < p_right->data.index; |
| 132 | } |
| 133 | return order_left < order_right; |
| 134 | } |
| 135 | }; |
| 136 | |
| 137 | struct ComparatorWithPriority { |
| 138 | bool operator()(const Node *p_a, const Node *p_b) const { return p_b->data.process_priority == p_a->data.process_priority ? p_b->is_greater_than(p_a) : p_b->data.process_priority > p_a->data.process_priority; } |
| 139 | }; |
| 140 | |
| 141 | struct ComparatorWithPhysicsPriority { |
| 142 | bool operator()(const Node *p_a, const Node *p_b) const { return p_b->data.physics_process_priority == p_a->data.physics_process_priority ? p_b->is_greater_than(p_a) : p_b->data.physics_process_priority > p_a->data.physics_process_priority; } |
| 143 | }; |
| 144 | |
| 145 | // This Data struct is to avoid namespace pollution in derived classes. |
| 146 | struct Data { |
| 147 | String scene_file_path; |
| 148 | Ref<SceneState> instance_state; |
| 149 | Ref<SceneState> inherited_state; |
| 150 | |
| 151 | Node *parent = nullptr; |
| 152 | Node *owner = nullptr; |
| 153 | HashMap<StringName, Node *> children; |
| 154 | mutable bool children_cache_dirty = true; |
| 155 | mutable LocalVector<Node *> children_cache; |
| 156 | HashMap<StringName, Node *> owned_unique_nodes; |
| 157 | bool unique_name_in_owner = false; |
| 158 | InternalMode internal_mode = INTERNAL_MODE_DISABLED; |
| 159 | mutable int internal_children_front_count_cache = 0; |
| 160 | mutable int internal_children_back_count_cache = 0; |
| 161 | mutable int external_children_count_cache = 0; |
| 162 | mutable int index = -1; // relative to front, normal or back. |
| 163 | int depth = -1; |
| 164 | int blocked = 0; // Safeguard that throws an error when attempting to modify the tree in a harmful way while being traversed. |
| 165 | StringName name; |
| 166 | SceneTree *tree = nullptr; |
| 167 | bool inside_tree = false; |
| 168 | bool ready_notified = false; // This is a small hack, so if a node is added during _ready() to the tree, it correctly gets the _ready() notification. |
| 169 | bool ready_first = true; |
| 170 | #ifdef TOOLS_ENABLED |
| 171 | NodePath import_path; // Path used when imported, used by scene editors to keep tracking. |
| 172 | #endif |
| 173 | String editor_description; |
| 174 | |
| 175 | Viewport *viewport = nullptr; |
| 176 | |
| 177 | HashMap<StringName, GroupData> grouped; |
| 178 | List<Node *>::Element *OW = nullptr; // Owned element. |
| 179 | List<Node *> owned; |
| 180 | |
| 181 | ProcessMode process_mode = PROCESS_MODE_INHERIT; |
| 182 | Node *process_owner = nullptr; |
| 183 | ProcessThreadGroup process_thread_group = PROCESS_THREAD_GROUP_INHERIT; |
| 184 | Node *process_thread_group_owner = nullptr; |
| 185 | int process_thread_group_order = 0; |
| 186 | BitField<ProcessThreadMessages> process_thread_messages; |
| 187 | void *process_group = nullptr; // to avoid cyclic dependency |
| 188 | |
| 189 | int multiplayer_authority = 1; // Server by default. |
| 190 | Variant rpc_config; |
| 191 | |
| 192 | // Variables used to properly sort the node when processing, ignored otherwise. |
| 193 | // TODO: Should move all the stuff below to bits. |
| 194 | bool physics_process = false; |
| 195 | bool process = false; |
| 196 | int process_priority = 0; |
| 197 | int physics_process_priority = 0; |
| 198 | |
| 199 | bool physics_process_internal = false; |
| 200 | bool process_internal = false; |
| 201 | |
| 202 | bool input = false; |
| 203 | bool shortcut_input = false; |
| 204 | bool unhandled_input = false; |
| 205 | bool unhandled_key_input = false; |
| 206 | |
| 207 | bool parent_owned = false; |
| 208 | bool in_constructor = true; |
| 209 | bool use_placeholder = false; |
| 210 | |
| 211 | bool display_folded = false; |
| 212 | bool editable_instance = false; |
| 213 | |
| 214 | mutable NodePath *path_cache = nullptr; |
| 215 | |
| 216 | } data; |
| 217 | |
| 218 | Ref<MultiplayerAPI> multiplayer; |
| 219 | |
| 220 | void _print_tree_pretty(const String &prefix, const bool last); |
| 221 | void _print_tree(const Node *p_node); |
| 222 | |
| 223 | Node *_get_child_by_name(const StringName &p_name) const; |
| 224 | |
| 225 | void _replace_connections_target(Node *p_new_target); |
| 226 | |
| 227 | void _validate_child_name(Node *p_child, bool p_force_human_readable = false); |
| 228 | void _generate_serial_child_name(const Node *p_child, StringName &name) const; |
| 229 | |
| 230 | void _propagate_reverse_notification(int p_notification); |
| 231 | void _propagate_deferred_notification(int p_notification, bool p_reverse); |
| 232 | void _propagate_enter_tree(); |
| 233 | void _propagate_ready(); |
| 234 | void _propagate_exit_tree(); |
| 235 | void _propagate_after_exit_tree(); |
| 236 | void _propagate_process_owner(Node *p_owner, int p_pause_notification, int p_enabled_notification); |
| 237 | void _propagate_groups_dirty(); |
| 238 | Array _get_node_and_resource(const NodePath &p_path); |
| 239 | |
| 240 | void _duplicate_signals(const Node *p_original, Node *p_copy) const; |
| 241 | Node *_duplicate(int p_flags, HashMap<const Node *, Node *> *r_duplimap = nullptr) const; |
| 242 | |
| 243 | TypedArray<StringName> _get_groups() const; |
| 244 | |
| 245 | Error _rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error); |
| 246 | Error _rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error); |
| 247 | |
| 248 | friend class SceneTree; |
| 249 | |
| 250 | void _set_tree(SceneTree *p_tree); |
| 251 | void _propagate_pause_notification(bool p_enable); |
| 252 | |
| 253 | _FORCE_INLINE_ bool _can_process(bool p_paused) const; |
| 254 | _FORCE_INLINE_ bool _is_enabled() const; |
| 255 | |
| 256 | void _release_unique_name_in_owner(); |
| 257 | void _acquire_unique_name_in_owner(); |
| 258 | |
| 259 | void _clean_up_owner(); |
| 260 | |
| 261 | _FORCE_INLINE_ void _update_children_cache() const { |
| 262 | if (unlikely(data.children_cache_dirty)) { |
| 263 | _update_children_cache_impl(); |
| 264 | } |
| 265 | } |
| 266 | |
| 267 | void _update_children_cache_impl() const; |
| 268 | |
| 269 | // Process group management |
| 270 | void _add_process_group(); |
| 271 | void _remove_process_group(); |
| 272 | void _add_to_process_thread_group(); |
| 273 | void _remove_from_process_thread_group(); |
| 274 | void _remove_tree_from_process_thread_group(); |
| 275 | void _add_tree_to_process_thread_group(Node *p_owner); |
| 276 | |
| 277 | static thread_local Node *current_process_thread_group; |
| 278 | |
| 279 | Variant _call_deferred_thread_group_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error); |
| 280 | Variant _call_thread_safe_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error); |
| 281 | |
| 282 | protected: |
| 283 | void _block() { data.blocked++; } |
| 284 | void _unblock() { data.blocked--; } |
| 285 | |
| 286 | void _notification(int p_notification); |
| 287 | |
| 288 | virtual void add_child_notify(Node *p_child); |
| 289 | virtual void remove_child_notify(Node *p_child); |
| 290 | virtual void move_child_notify(Node *p_child); |
| 291 | virtual void owner_changed_notify(); |
| 292 | |
| 293 | void _propagate_replace_owner(Node *p_owner, Node *p_by_owner); |
| 294 | |
| 295 | static void _bind_methods(); |
| 296 | static String _get_name_num_separator(); |
| 297 | |
| 298 | friend class SceneState; |
| 299 | |
| 300 | void _add_child_nocheck(Node *p_child, const StringName &p_name, InternalMode p_internal_mode = INTERNAL_MODE_DISABLED); |
| 301 | void _set_owner_nocheck(Node *p_owner); |
| 302 | void _set_name_nocheck(const StringName &p_name); |
| 303 | |
| 304 | //call from SceneTree |
| 305 | void _call_input(const Ref<InputEvent> &p_event); |
| 306 | void _call_shortcut_input(const Ref<InputEvent> &p_event); |
| 307 | void _call_unhandled_input(const Ref<InputEvent> &p_event); |
| 308 | void _call_unhandled_key_input(const Ref<InputEvent> &p_event); |
| 309 | |
| 310 | void _validate_property(PropertyInfo &p_property) const; |
| 311 | |
| 312 | protected: |
| 313 | virtual void input(const Ref<InputEvent> &p_event); |
| 314 | virtual void shortcut_input(const Ref<InputEvent> &p_key_event); |
| 315 | virtual void unhandled_input(const Ref<InputEvent> &p_event); |
| 316 | virtual void unhandled_key_input(const Ref<InputEvent> &p_key_event); |
| 317 | |
| 318 | GDVIRTUAL1(_process, double) |
| 319 | GDVIRTUAL1(_physics_process, double) |
| 320 | GDVIRTUAL0(_enter_tree) |
| 321 | GDVIRTUAL0(_exit_tree) |
| 322 | GDVIRTUAL0(_ready) |
| 323 | GDVIRTUAL0RC(Vector<String>, _get_configuration_warnings) |
| 324 | |
| 325 | GDVIRTUAL1(_input, Ref<InputEvent>) |
| 326 | GDVIRTUAL1(_shortcut_input, Ref<InputEvent>) |
| 327 | GDVIRTUAL1(_unhandled_input, Ref<InputEvent>) |
| 328 | GDVIRTUAL1(_unhandled_key_input, Ref<InputEvent>) |
| 329 | |
| 330 | public: |
| 331 | enum { |
| 332 | // you can make your own, but don't use the same numbers as other notifications in other nodes |
| 333 | NOTIFICATION_ENTER_TREE = 10, |
| 334 | NOTIFICATION_EXIT_TREE = 11, |
| 335 | NOTIFICATION_MOVED_IN_PARENT = 12, |
| 336 | NOTIFICATION_READY = 13, |
| 337 | NOTIFICATION_PAUSED = 14, |
| 338 | NOTIFICATION_UNPAUSED = 15, |
| 339 | NOTIFICATION_PHYSICS_PROCESS = 16, |
| 340 | NOTIFICATION_PROCESS = 17, |
| 341 | NOTIFICATION_PARENTED = 18, |
| 342 | NOTIFICATION_UNPARENTED = 19, |
| 343 | NOTIFICATION_SCENE_INSTANTIATED = 20, |
| 344 | NOTIFICATION_DRAG_BEGIN = 21, |
| 345 | NOTIFICATION_DRAG_END = 22, |
| 346 | NOTIFICATION_PATH_RENAMED = 23, |
| 347 | NOTIFICATION_CHILD_ORDER_CHANGED = 24, |
| 348 | NOTIFICATION_INTERNAL_PROCESS = 25, |
| 349 | NOTIFICATION_INTERNAL_PHYSICS_PROCESS = 26, |
| 350 | NOTIFICATION_POST_ENTER_TREE = 27, |
| 351 | NOTIFICATION_DISABLED = 28, |
| 352 | NOTIFICATION_ENABLED = 29, |
| 353 | NOTIFICATION_NODE_RECACHE_REQUESTED = 30, |
| 354 | //keep these linked to node |
| 355 | |
| 356 | NOTIFICATION_WM_MOUSE_ENTER = 1002, |
| 357 | NOTIFICATION_WM_MOUSE_EXIT = 1003, |
| 358 | NOTIFICATION_WM_WINDOW_FOCUS_IN = 1004, |
| 359 | NOTIFICATION_WM_WINDOW_FOCUS_OUT = 1005, |
| 360 | NOTIFICATION_WM_CLOSE_REQUEST = 1006, |
| 361 | NOTIFICATION_WM_GO_BACK_REQUEST = 1007, |
| 362 | NOTIFICATION_WM_SIZE_CHANGED = 1008, |
| 363 | NOTIFICATION_WM_DPI_CHANGE = 1009, |
| 364 | NOTIFICATION_VP_MOUSE_ENTER = 1010, |
| 365 | NOTIFICATION_VP_MOUSE_EXIT = 1011, |
| 366 | |
| 367 | NOTIFICATION_OS_MEMORY_WARNING = MainLoop::NOTIFICATION_OS_MEMORY_WARNING, |
| 368 | NOTIFICATION_TRANSLATION_CHANGED = MainLoop::NOTIFICATION_TRANSLATION_CHANGED, |
| 369 | NOTIFICATION_WM_ABOUT = MainLoop::NOTIFICATION_WM_ABOUT, |
| 370 | NOTIFICATION_CRASH = MainLoop::NOTIFICATION_CRASH, |
| 371 | NOTIFICATION_OS_IME_UPDATE = MainLoop::NOTIFICATION_OS_IME_UPDATE, |
| 372 | NOTIFICATION_APPLICATION_RESUMED = MainLoop::NOTIFICATION_APPLICATION_RESUMED, |
| 373 | NOTIFICATION_APPLICATION_PAUSED = MainLoop::NOTIFICATION_APPLICATION_PAUSED, |
| 374 | NOTIFICATION_APPLICATION_FOCUS_IN = MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN, |
| 375 | NOTIFICATION_APPLICATION_FOCUS_OUT = MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT, |
| 376 | NOTIFICATION_TEXT_SERVER_CHANGED = MainLoop::NOTIFICATION_TEXT_SERVER_CHANGED, |
| 377 | |
| 378 | // Editor specific node notifications |
| 379 | NOTIFICATION_EDITOR_PRE_SAVE = 9001, |
| 380 | NOTIFICATION_EDITOR_POST_SAVE = 9002, |
| 381 | }; |
| 382 | |
| 383 | /* NODE/TREE */ |
| 384 | |
| 385 | StringName get_name() const; |
| 386 | String get_description() const; |
| 387 | void set_name(const String &p_name); |
| 388 | |
| 389 | InternalMode get_internal_mode() const; |
| 390 | |
| 391 | void add_child(Node *p_child, bool p_force_readable_name = false, InternalMode p_internal = INTERNAL_MODE_DISABLED); |
| 392 | void add_sibling(Node *p_sibling, bool p_force_readable_name = false); |
| 393 | void remove_child(Node *p_child); |
| 394 | |
| 395 | int get_child_count(bool p_include_internal = true) const; |
| 396 | Node *get_child(int p_index, bool p_include_internal = true) const; |
| 397 | TypedArray<Node> get_children(bool p_include_internal = true) const; |
| 398 | bool has_node(const NodePath &p_path) const; |
| 399 | Node *get_node(const NodePath &p_path) const; |
| 400 | Node *get_node_or_null(const NodePath &p_path) const; |
| 401 | Node *find_child(const String &p_pattern, bool p_recursive = true, bool p_owned = true) const; |
| 402 | TypedArray<Node> find_children(const String &p_pattern, const String &p_type = "" , bool p_recursive = true, bool p_owned = true) const; |
| 403 | bool has_node_and_resource(const NodePath &p_path) const; |
| 404 | Node *get_node_and_resource(const NodePath &p_path, Ref<Resource> &r_res, Vector<StringName> &r_leftover_subpath, bool p_last_is_property = true) const; |
| 405 | |
| 406 | virtual void reparent(Node *p_parent, bool p_keep_global_transform = true); |
| 407 | Node *get_parent() const; |
| 408 | Node *find_parent(const String &p_pattern) const; |
| 409 | |
| 410 | Window *get_window() const; |
| 411 | Window *get_last_exclusive_window() const; |
| 412 | |
| 413 | _FORCE_INLINE_ SceneTree *get_tree() const { |
| 414 | ERR_FAIL_COND_V(!data.tree, nullptr); |
| 415 | return data.tree; |
| 416 | } |
| 417 | |
| 418 | _FORCE_INLINE_ bool is_inside_tree() const { return data.inside_tree; } |
| 419 | |
| 420 | bool is_ancestor_of(const Node *p_node) const; |
| 421 | bool is_greater_than(const Node *p_node) const; |
| 422 | |
| 423 | NodePath get_path() const; |
| 424 | NodePath get_path_to(const Node *p_node, bool p_use_unique_path = false) const; |
| 425 | Node *find_common_parent_with(const Node *p_node) const; |
| 426 | |
| 427 | void add_to_group(const StringName &p_identifier, bool p_persistent = false); |
| 428 | void remove_from_group(const StringName &p_identifier); |
| 429 | bool is_in_group(const StringName &p_identifier) const; |
| 430 | |
| 431 | struct GroupInfo { |
| 432 | StringName name; |
| 433 | bool persistent = false; |
| 434 | }; |
| 435 | |
| 436 | void get_groups(List<GroupInfo> *p_groups) const; |
| 437 | int get_persistent_group_count() const; |
| 438 | |
| 439 | void move_child(Node *p_child, int p_index); |
| 440 | void _move_child(Node *p_child, int p_index, bool p_ignore_end = false); |
| 441 | |
| 442 | void set_owner(Node *p_owner); |
| 443 | Node *get_owner() const; |
| 444 | void get_owned_by(Node *p_by, List<Node *> *p_owned); |
| 445 | |
| 446 | void set_unique_name_in_owner(bool p_enabled); |
| 447 | bool is_unique_name_in_owner() const; |
| 448 | |
| 449 | _FORCE_INLINE_ int get_index(bool p_include_internal = true) const { |
| 450 | // p_include_internal = false doesn't make sense if the node is internal. |
| 451 | ERR_FAIL_COND_V_MSG(!p_include_internal && data.internal_mode != INTERNAL_MODE_DISABLED, -1, "Node is internal. Can't get index with 'include_internal' being false." ); |
| 452 | if (!data.parent) { |
| 453 | return data.index; |
| 454 | } |
| 455 | data.parent->_update_children_cache(); |
| 456 | |
| 457 | if (!p_include_internal) { |
| 458 | return data.index; |
| 459 | } else { |
| 460 | switch (data.internal_mode) { |
| 461 | case INTERNAL_MODE_DISABLED: { |
| 462 | return data.parent->data.internal_children_front_count_cache + data.index; |
| 463 | } break; |
| 464 | case INTERNAL_MODE_FRONT: { |
| 465 | return data.index; |
| 466 | } break; |
| 467 | case INTERNAL_MODE_BACK: { |
| 468 | return data.parent->data.internal_children_front_count_cache + data.parent->data.external_children_count_cache + data.index; |
| 469 | } break; |
| 470 | } |
| 471 | return -1; |
| 472 | } |
| 473 | } |
| 474 | |
| 475 | Ref<Tween> create_tween(); |
| 476 | |
| 477 | void print_tree(); |
| 478 | void print_tree_pretty(); |
| 479 | |
| 480 | void set_scene_file_path(const String &p_scene_file_path); |
| 481 | String get_scene_file_path() const; |
| 482 | |
| 483 | void set_editor_description(const String &p_editor_description); |
| 484 | String get_editor_description() const; |
| 485 | |
| 486 | void set_editable_instance(Node *p_node, bool p_editable); |
| 487 | bool is_editable_instance(const Node *p_node) const; |
| 488 | Node *get_deepest_editable_node(Node *p_start_node) const; |
| 489 | |
| 490 | #ifdef TOOLS_ENABLED |
| 491 | void set_property_pinned(const String &p_property, bool p_pinned); |
| 492 | bool is_property_pinned(const StringName &p_property) const; |
| 493 | virtual StringName get_property_store_alias(const StringName &p_property) const; |
| 494 | bool is_part_of_edited_scene() const; |
| 495 | #endif |
| 496 | void get_storable_properties(HashSet<StringName> &r_storable_properties) const; |
| 497 | |
| 498 | virtual String to_string() override; |
| 499 | |
| 500 | /* NOTIFICATIONS */ |
| 501 | |
| 502 | void propagate_notification(int p_notification); |
| 503 | |
| 504 | void propagate_call(const StringName &p_method, const Array &p_args = Array(), const bool p_parent_first = false); |
| 505 | |
| 506 | /* PROCESSING */ |
| 507 | void set_physics_process(bool p_process); |
| 508 | double get_physics_process_delta_time() const; |
| 509 | bool is_physics_processing() const; |
| 510 | |
| 511 | void set_process(bool p_process); |
| 512 | double get_process_delta_time() const; |
| 513 | bool is_processing() const; |
| 514 | |
| 515 | void set_physics_process_internal(bool p_process_internal); |
| 516 | bool is_physics_processing_internal() const; |
| 517 | |
| 518 | void set_process_internal(bool p_process_internal); |
| 519 | bool is_processing_internal() const; |
| 520 | |
| 521 | void set_process_priority(int p_priority); |
| 522 | int get_process_priority() const; |
| 523 | |
| 524 | void set_process_thread_group_order(int p_order); |
| 525 | int get_process_thread_group_order() const; |
| 526 | |
| 527 | void set_physics_process_priority(int p_priority); |
| 528 | int get_physics_process_priority() const; |
| 529 | |
| 530 | void set_process_input(bool p_enable); |
| 531 | bool is_processing_input() const; |
| 532 | |
| 533 | void set_process_shortcut_input(bool p_enable); |
| 534 | bool is_processing_shortcut_input() const; |
| 535 | |
| 536 | void set_process_unhandled_input(bool p_enable); |
| 537 | bool is_processing_unhandled_input() const; |
| 538 | |
| 539 | void set_process_unhandled_key_input(bool p_enable); |
| 540 | bool is_processing_unhandled_key_input() const; |
| 541 | |
| 542 | _FORCE_INLINE_ bool _is_any_processing() const { |
| 543 | return data.process || data.process_internal || data.physics_process || data.physics_process_internal; |
| 544 | } |
| 545 | _FORCE_INLINE_ bool is_accessible_from_caller_thread() const { |
| 546 | if (current_process_thread_group == nullptr) { |
| 547 | // No thread processing. |
| 548 | // Only accessible if node is outside the scene tree |
| 549 | // or access will happen from a node-safe thread. |
| 550 | return !data.inside_tree || is_current_thread_safe_for_nodes(); |
| 551 | } else { |
| 552 | // Thread processing. |
| 553 | return current_process_thread_group == data.process_thread_group_owner; |
| 554 | } |
| 555 | } |
| 556 | |
| 557 | _FORCE_INLINE_ bool is_readable_from_caller_thread() const { |
| 558 | if (current_process_thread_group == nullptr) { |
| 559 | // No thread processing. |
| 560 | return is_current_thread_safe_for_nodes(); |
| 561 | } else { |
| 562 | // Thread processing. |
| 563 | return true; |
| 564 | } |
| 565 | } |
| 566 | |
| 567 | _FORCE_INLINE_ static bool is_group_processing() { return current_process_thread_group; } |
| 568 | |
| 569 | void set_process_thread_messages(BitField<ProcessThreadMessages> p_flags); |
| 570 | BitField<ProcessThreadMessages> get_process_thread_messages() const; |
| 571 | |
| 572 | Node *duplicate(int p_flags = DUPLICATE_GROUPS | DUPLICATE_SIGNALS | DUPLICATE_SCRIPTS) const; |
| 573 | #ifdef TOOLS_ENABLED |
| 574 | Node *duplicate_from_editor(HashMap<const Node *, Node *> &r_duplimap) const; |
| 575 | Node *duplicate_from_editor(HashMap<const Node *, Node *> &r_duplimap, const HashMap<Ref<Resource>, Ref<Resource>> &p_resource_remap) const; |
| 576 | void remap_node_resources(Node *p_node, const HashMap<Ref<Resource>, Ref<Resource>> &p_resource_remap) const; |
| 577 | void remap_nested_resources(Ref<Resource> p_resource, const HashMap<Ref<Resource>, Ref<Resource>> &p_resource_remap) const; |
| 578 | #endif |
| 579 | |
| 580 | // used by editors, to save what has changed only |
| 581 | void set_scene_instance_state(const Ref<SceneState> &p_state); |
| 582 | Ref<SceneState> get_scene_instance_state() const; |
| 583 | |
| 584 | void set_scene_inherited_state(const Ref<SceneState> &p_state); |
| 585 | Ref<SceneState> get_scene_inherited_state() const; |
| 586 | |
| 587 | void set_scene_instance_load_placeholder(bool p_enable); |
| 588 | bool get_scene_instance_load_placeholder() const; |
| 589 | |
| 590 | template <typename... VarArgs> |
| 591 | Vector<Variant> make_binds(VarArgs... p_args) { |
| 592 | Vector<Variant> binds = { p_args... }; |
| 593 | return binds; |
| 594 | } |
| 595 | |
| 596 | void replace_by(Node *p_node, bool p_keep_data = false); |
| 597 | |
| 598 | void set_process_mode(ProcessMode p_mode); |
| 599 | ProcessMode get_process_mode() const; |
| 600 | bool can_process() const; |
| 601 | bool can_process_notification(int p_what) const; |
| 602 | bool is_enabled() const; |
| 603 | bool is_ready() const; |
| 604 | |
| 605 | void request_ready(); |
| 606 | |
| 607 | void set_process_thread_group(ProcessThreadGroup p_mode); |
| 608 | ProcessThreadGroup get_process_thread_group() const; |
| 609 | |
| 610 | static void print_orphan_nodes(); |
| 611 | |
| 612 | #ifdef TOOLS_ENABLED |
| 613 | String validate_child_name(Node *p_child); |
| 614 | #endif |
| 615 | static String adjust_name_casing(const String &p_name); |
| 616 | |
| 617 | void queue_free(); |
| 618 | |
| 619 | //hacks for speed |
| 620 | static void init_node_hrcr(); |
| 621 | |
| 622 | void force_parent_owned() { data.parent_owned = true; } //hack to avoid duplicate nodes |
| 623 | |
| 624 | void set_import_path(const NodePath &p_import_path); //path used when imported, used by scene editors to keep tracking |
| 625 | NodePath get_import_path() const; |
| 626 | |
| 627 | bool is_owned_by_parent() const; |
| 628 | |
| 629 | void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; |
| 630 | |
| 631 | void clear_internal_tree_resource_paths(); |
| 632 | |
| 633 | _FORCE_INLINE_ Viewport *get_viewport() const { return data.viewport; } |
| 634 | |
| 635 | virtual PackedStringArray get_configuration_warnings() const; |
| 636 | String get_configuration_warnings_as_string() const; |
| 637 | |
| 638 | void update_configuration_warnings(); |
| 639 | |
| 640 | void set_display_folded(bool p_folded); |
| 641 | bool is_displayed_folded() const; |
| 642 | /* NETWORK */ |
| 643 | |
| 644 | virtual void set_multiplayer_authority(int p_peer_id, bool p_recursive = true); |
| 645 | int get_multiplayer_authority() const; |
| 646 | bool is_multiplayer_authority() const; |
| 647 | |
| 648 | void rpc_config(const StringName &p_method, const Variant &p_config); // config a local method for RPC |
| 649 | const Variant get_node_rpc_config() const; |
| 650 | |
| 651 | template <typename... VarArgs> |
| 652 | Error rpc(const StringName &p_method, VarArgs... p_args); |
| 653 | |
| 654 | template <typename... VarArgs> |
| 655 | Error rpc_id(int p_peer_id, const StringName &p_method, VarArgs... p_args); |
| 656 | |
| 657 | Error rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount); |
| 658 | |
| 659 | Ref<MultiplayerAPI> get_multiplayer() const; |
| 660 | |
| 661 | void call_deferred_thread_groupp(const StringName &p_method, const Variant **p_args, int p_argcount, bool p_show_error = false); |
| 662 | template <typename... VarArgs> |
| 663 | void call_deferred_thread_group(const StringName &p_method, VarArgs... p_args) { |
| 664 | Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported. |
| 665 | const Variant *argptrs[sizeof...(p_args) + 1]; |
| 666 | for (uint32_t i = 0; i < sizeof...(p_args); i++) { |
| 667 | argptrs[i] = &args[i]; |
| 668 | } |
| 669 | call_deferred_thread_groupp(p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args)); |
| 670 | } |
| 671 | void set_deferred_thread_group(const StringName &p_property, const Variant &p_value); |
| 672 | void notify_deferred_thread_group(int p_notification); |
| 673 | |
| 674 | void call_thread_safep(const StringName &p_method, const Variant **p_args, int p_argcount, bool p_show_error = false); |
| 675 | template <typename... VarArgs> |
| 676 | void call_thread_safe(const StringName &p_method, VarArgs... p_args) { |
| 677 | Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported. |
| 678 | const Variant *argptrs[sizeof...(p_args) + 1]; |
| 679 | for (uint32_t i = 0; i < sizeof...(p_args); i++) { |
| 680 | argptrs[i] = &args[i]; |
| 681 | } |
| 682 | call_deferred_thread_groupp(p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args)); |
| 683 | } |
| 684 | void set_thread_safe(const StringName &p_property, const Variant &p_value); |
| 685 | void notify_thread_safe(int p_notification); |
| 686 | |
| 687 | // These inherited functions need proper multithread locking when overridden in Node. |
| 688 | #ifdef DEBUG_ENABLED |
| 689 | |
| 690 | virtual void set_script(const Variant &p_script) override; |
| 691 | virtual Variant get_script() const override; |
| 692 | |
| 693 | virtual bool has_meta(const StringName &p_name) const override; |
| 694 | virtual void set_meta(const StringName &p_name, const Variant &p_value) override; |
| 695 | virtual void remove_meta(const StringName &p_name) override; |
| 696 | virtual Variant get_meta(const StringName &p_name, const Variant &p_default = Variant()) const override; |
| 697 | virtual void get_meta_list(List<StringName> *p_list) const override; |
| 698 | |
| 699 | virtual Error emit_signalp(const StringName &p_name, const Variant **p_args, int p_argcount) override; |
| 700 | virtual bool has_signal(const StringName &p_name) const override; |
| 701 | virtual void get_signal_list(List<MethodInfo> *p_signals) const override; |
| 702 | virtual void get_signal_connection_list(const StringName &p_signal, List<Connection> *p_connections) const override; |
| 703 | virtual void get_all_signal_connections(List<Connection> *p_connections) const override; |
| 704 | virtual int get_persistent_signal_connection_count() const override; |
| 705 | virtual void get_signals_connected_to_this(List<Connection> *p_connections) const override; |
| 706 | |
| 707 | virtual Error connect(const StringName &p_signal, const Callable &p_callable, uint32_t p_flags = 0) override; |
| 708 | virtual void disconnect(const StringName &p_signal, const Callable &p_callable) override; |
| 709 | virtual bool is_connected(const StringName &p_signal, const Callable &p_callable) const override; |
| 710 | #endif |
| 711 | Node(); |
| 712 | ~Node(); |
| 713 | }; |
| 714 | |
| 715 | VARIANT_ENUM_CAST(Node::DuplicateFlags); |
| 716 | VARIANT_ENUM_CAST(Node::ProcessMode); |
| 717 | VARIANT_ENUM_CAST(Node::ProcessThreadGroup); |
| 718 | VARIANT_BITFIELD_CAST(Node::ProcessThreadMessages); |
| 719 | VARIANT_ENUM_CAST(Node::InternalMode); |
| 720 | |
| 721 | typedef HashSet<Node *, Node::Comparator> NodeSet; |
| 722 | |
| 723 | // Template definitions must be in the header so they are always fully initialized before their usage. |
| 724 | // See this StackOverflow question for more information: https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file |
| 725 | |
| 726 | template <typename... VarArgs> |
| 727 | Error Node::rpc(const StringName &p_method, VarArgs... p_args) { |
| 728 | return rpc_id(0, p_method, p_args...); |
| 729 | } |
| 730 | |
| 731 | template <typename... VarArgs> |
| 732 | Error Node::rpc_id(int p_peer_id, const StringName &p_method, VarArgs... p_args) { |
| 733 | Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported. |
| 734 | const Variant *argptrs[sizeof...(p_args) + 1]; |
| 735 | for (uint32_t i = 0; i < sizeof...(p_args); i++) { |
| 736 | argptrs[i] = &args[i]; |
| 737 | } |
| 738 | return rpcp(p_peer_id, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args)); |
| 739 | } |
| 740 | |
| 741 | #ifdef DEBUG_ENABLED |
| 742 | #define ERR_THREAD_GUARD ERR_FAIL_COND_MSG(!is_accessible_from_caller_thread(), vformat("Caller thread can't call this function in this node (%s). Use call_deferred() or call_thread_group() instead.", get_description())); |
| 743 | #define ERR_THREAD_GUARD_V(m_ret) ERR_FAIL_COND_V_MSG(!is_accessible_from_caller_thread(), (m_ret), vformat("Caller thread can't call this function in this node (%s). Use call_deferred() or call_thread_group() instead.", get_description())); |
| 744 | #define ERR_MAIN_THREAD_GUARD ERR_FAIL_COND_MSG(is_inside_tree() && !is_current_thread_safe_for_nodes(), vformat("This function in this node (%s) can only be accessed from the main thread. Use call_deferred() instead.", get_description())); |
| 745 | #define ERR_MAIN_THREAD_GUARD_V(m_ret) ERR_FAIL_COND_V_MSG(is_inside_tree() && !is_current_thread_safe_for_nodes(), (m_ret), vformat("This function in this node (%s) can only be accessed from the main thread. Use call_deferred() instead.", get_description())); |
| 746 | #define ERR_READ_THREAD_GUARD ERR_FAIL_COND_MSG(!is_readable_from_caller_thread(), vformat("This function in this node (%s) can only be accessed from either the main thread or a thread group. Use call_deferred() instead.", get_description())); |
| 747 | #define ERR_READ_THREAD_GUARD_V(m_ret) ERR_FAIL_COND_V_MSG(!is_readable_from_caller_thread(), (m_ret), vformat("This function in this node (%s) can only be accessed from either the main thread or a thread group. Use call_deferred() instead.", get_description())); |
| 748 | #else |
| 749 | #define ERR_THREAD_GUARD |
| 750 | #define ERR_THREAD_GUARD_V(m_ret) |
| 751 | #define ERR_MAIN_THREAD_GUARD |
| 752 | #define ERR_MAIN_THREAD_GUARD_V(m_ret) |
| 753 | #define ERR_READ_THREAD_GUARD |
| 754 | #define ERR_READ_THREAD_GUARD_V(m_ret) |
| 755 | #endif |
| 756 | |
| 757 | // Add these macro to your class's 'get_configuration_warnings' function to have warnings show up in the scene tree inspector. |
| 758 | #define DEPRECATED_NODE_WARNING warnings.push_back(RTR("This node is marked as deprecated and will be removed in future versions.\nPlease check the Godot documentation for information about migration.")); |
| 759 | #define EXPERIMENTAL_NODE_WARNING warnings.push_back(RTR("This node is marked as experimental and may be subject to removal or major changes in future versions.")); |
| 760 | |
| 761 | #endif // NODE_H |
| 762 | |