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 | |