1/**************************************************************************/
2/* scene_tree.cpp */
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#include "scene_tree.h"
32
33#include "core/config/project_settings.h"
34#include "core/debugger/engine_debugger.h"
35#include "core/input/input.h"
36#include "core/io/dir_access.h"
37#include "core/io/image_loader.h"
38#include "core/io/marshalls.h"
39#include "core/io/resource_loader.h"
40#include "core/object/message_queue.h"
41#include "core/object/worker_thread_pool.h"
42#include "core/os/keyboard.h"
43#include "core/os/os.h"
44#include "core/string/print_string.h"
45#include "node.h"
46#include "scene/animation/tween.h"
47#include "scene/debugger/scene_debugger.h"
48#include "scene/gui/control.h"
49#include "scene/main/multiplayer_api.h"
50#include "scene/main/viewport.h"
51#include "scene/resources/environment.h"
52#include "scene/resources/font.h"
53#include "scene/resources/image_texture.h"
54#include "scene/resources/material.h"
55#include "scene/resources/mesh.h"
56#include "scene/resources/packed_scene.h"
57#include "scene/resources/world_2d.h"
58#include "scene/resources/world_3d.h"
59#include "scene/scene_string_names.h"
60#include "servers/display_server.h"
61#include "servers/navigation_server_3d.h"
62#include "servers/physics_server_2d.h"
63#include "servers/physics_server_3d.h"
64#include "window.h"
65#include <stdio.h>
66#include <stdlib.h>
67
68void SceneTreeTimer::_bind_methods() {
69 ClassDB::bind_method(D_METHOD("set_time_left", "time"), &SceneTreeTimer::set_time_left);
70 ClassDB::bind_method(D_METHOD("get_time_left"), &SceneTreeTimer::get_time_left);
71
72 ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_left", PROPERTY_HINT_NONE, "suffix:s"), "set_time_left", "get_time_left");
73
74 ADD_SIGNAL(MethodInfo("timeout"));
75}
76
77void SceneTreeTimer::set_time_left(double p_time) {
78 time_left = p_time;
79}
80
81double SceneTreeTimer::get_time_left() const {
82 return MAX(time_left, 0.0);
83}
84
85void SceneTreeTimer::set_process_always(bool p_process_always) {
86 process_always = p_process_always;
87}
88
89bool SceneTreeTimer::is_process_always() {
90 return process_always;
91}
92
93void SceneTreeTimer::set_process_in_physics(bool p_process_in_physics) {
94 process_in_physics = p_process_in_physics;
95}
96
97bool SceneTreeTimer::is_process_in_physics() {
98 return process_in_physics;
99}
100
101void SceneTreeTimer::set_ignore_time_scale(bool p_ignore) {
102 ignore_time_scale = p_ignore;
103}
104
105bool SceneTreeTimer::is_ignore_time_scale() {
106 return ignore_time_scale;
107}
108
109void SceneTreeTimer::release_connections() {
110 List<Connection> signal_connections;
111 get_all_signal_connections(&signal_connections);
112
113 for (const Connection &connection : signal_connections) {
114 disconnect(connection.signal.get_name(), connection.callable);
115 }
116}
117
118SceneTreeTimer::SceneTreeTimer() {}
119
120void SceneTree::tree_changed() {
121 tree_version++;
122 emit_signal(tree_changed_name);
123}
124
125void SceneTree::node_added(Node *p_node) {
126 emit_signal(node_added_name, p_node);
127}
128
129void SceneTree::node_removed(Node *p_node) {
130 // Nodes can only be removed from the main thread.
131 if (current_scene == p_node) {
132 current_scene = nullptr;
133 }
134 emit_signal(node_removed_name, p_node);
135 if (nodes_removed_on_group_call_lock) {
136 nodes_removed_on_group_call.insert(p_node);
137 }
138}
139
140void SceneTree::node_renamed(Node *p_node) {
141 emit_signal(node_renamed_name, p_node);
142}
143
144SceneTree::Group *SceneTree::add_to_group(const StringName &p_group, Node *p_node) {
145 _THREAD_SAFE_METHOD_
146
147 HashMap<StringName, Group>::Iterator E = group_map.find(p_group);
148 if (!E) {
149 E = group_map.insert(p_group, Group());
150 }
151
152 ERR_FAIL_COND_V_MSG(E->value.nodes.has(p_node), &E->value, "Already in group: " + p_group + ".");
153 E->value.nodes.push_back(p_node);
154 //E->value.last_tree_version=0;
155 E->value.changed = true;
156 return &E->value;
157}
158
159void SceneTree::remove_from_group(const StringName &p_group, Node *p_node) {
160 _THREAD_SAFE_METHOD_
161
162 HashMap<StringName, Group>::Iterator E = group_map.find(p_group);
163 ERR_FAIL_COND(!E);
164
165 E->value.nodes.erase(p_node);
166 if (E->value.nodes.is_empty()) {
167 group_map.remove(E);
168 }
169}
170
171void SceneTree::make_group_changed(const StringName &p_group) {
172 _THREAD_SAFE_METHOD_
173 HashMap<StringName, Group>::Iterator E = group_map.find(p_group);
174 if (E) {
175 E->value.changed = true;
176 }
177}
178
179void SceneTree::flush_transform_notifications() {
180 _THREAD_SAFE_METHOD_
181
182 SelfList<Node> *n = xform_change_list.first();
183 while (n) {
184 Node *node = n->self();
185 SelfList<Node> *nx = n->next();
186 xform_change_list.remove(n);
187 n = nx;
188 node->notification(NOTIFICATION_TRANSFORM_CHANGED);
189 }
190}
191
192void SceneTree::_flush_ugc() {
193 ugc_locked = true;
194
195 while (unique_group_calls.size()) {
196 HashMap<UGCall, Vector<Variant>, UGCall>::Iterator E = unique_group_calls.begin();
197
198 const Variant **argptrs = (const Variant **)alloca(E->value.size() * sizeof(Variant *));
199
200 for (int i = 0; i < E->value.size(); i++) {
201 argptrs[i] = &E->value[i];
202 }
203
204 call_group_flagsp(GROUP_CALL_DEFAULT, E->key.group, E->key.call, argptrs, E->value.size());
205
206 unique_group_calls.remove(E);
207 }
208
209 ugc_locked = false;
210}
211
212void SceneTree::_update_group_order(Group &g) {
213 if (!g.changed) {
214 return;
215 }
216 if (g.nodes.is_empty()) {
217 return;
218 }
219
220 Node **gr_nodes = g.nodes.ptrw();
221 int gr_node_count = g.nodes.size();
222
223 SortArray<Node *, Node::Comparator> node_sort;
224 node_sort.sort(gr_nodes, gr_node_count);
225
226 g.changed = false;
227}
228
229void SceneTree::call_group_flagsp(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, const Variant **p_args, int p_argcount) {
230 Vector<Node *> nodes_copy;
231
232 {
233 _THREAD_SAFE_METHOD_
234
235 HashMap<StringName, Group>::Iterator E = group_map.find(p_group);
236 if (!E) {
237 return;
238 }
239 Group &g = E->value;
240 if (g.nodes.is_empty()) {
241 return;
242 }
243
244 if (p_call_flags & GROUP_CALL_UNIQUE && p_call_flags & GROUP_CALL_DEFERRED) {
245 ERR_FAIL_COND(ugc_locked);
246
247 UGCall ug;
248 ug.call = p_function;
249 ug.group = p_group;
250
251 if (unique_group_calls.has(ug)) {
252 return;
253 }
254
255 Vector<Variant> args;
256 for (int i = 0; i < p_argcount; i++) {
257 args.push_back(*p_args[i]);
258 }
259
260 unique_group_calls[ug] = args;
261 return;
262 }
263
264 _update_group_order(g);
265 nodes_copy = g.nodes;
266 }
267
268 Node **gr_nodes = nodes_copy.ptrw();
269 int gr_node_count = nodes_copy.size();
270
271 {
272 _THREAD_SAFE_METHOD_
273 nodes_removed_on_group_call_lock++;
274 }
275
276 if (p_call_flags & GROUP_CALL_REVERSE) {
277 for (int i = gr_node_count - 1; i >= 0; i--) {
278 if (nodes_removed_on_group_call_lock && nodes_removed_on_group_call.has(gr_nodes[i])) {
279 continue;
280 }
281
282 if (!(p_call_flags & GROUP_CALL_DEFERRED)) {
283 Callable::CallError ce;
284 gr_nodes[i]->callp(p_function, p_args, p_argcount, ce);
285 } else {
286 MessageQueue::get_singleton()->push_callp(gr_nodes[i], p_function, p_args, p_argcount);
287 }
288 }
289
290 } else {
291 for (int i = 0; i < gr_node_count; i++) {
292 if (nodes_removed_on_group_call_lock && nodes_removed_on_group_call.has(gr_nodes[i])) {
293 continue;
294 }
295
296 if (!(p_call_flags & GROUP_CALL_DEFERRED)) {
297 Callable::CallError ce;
298 gr_nodes[i]->callp(p_function, p_args, p_argcount, ce);
299 } else {
300 MessageQueue::get_singleton()->push_callp(gr_nodes[i], p_function, p_args, p_argcount);
301 }
302 }
303 }
304
305 {
306 _THREAD_SAFE_METHOD_
307 nodes_removed_on_group_call_lock--;
308 if (nodes_removed_on_group_call_lock == 0) {
309 nodes_removed_on_group_call.clear();
310 }
311 }
312}
313
314void SceneTree::notify_group_flags(uint32_t p_call_flags, const StringName &p_group, int p_notification) {
315 Vector<Node *> nodes_copy;
316 {
317 _THREAD_SAFE_METHOD_
318 HashMap<StringName, Group>::Iterator E = group_map.find(p_group);
319 if (!E) {
320 return;
321 }
322 Group &g = E->value;
323 if (g.nodes.is_empty()) {
324 return;
325 }
326
327 _update_group_order(g);
328
329 nodes_copy = g.nodes;
330 }
331
332 Node **gr_nodes = nodes_copy.ptrw();
333 int gr_node_count = nodes_copy.size();
334
335 {
336 _THREAD_SAFE_METHOD_
337 nodes_removed_on_group_call_lock++;
338 }
339
340 if (p_call_flags & GROUP_CALL_REVERSE) {
341 for (int i = gr_node_count - 1; i >= 0; i--) {
342 if (nodes_removed_on_group_call.has(gr_nodes[i])) {
343 continue;
344 }
345
346 if (!(p_call_flags & GROUP_CALL_DEFERRED)) {
347 gr_nodes[i]->notification(p_notification, true);
348 } else {
349 MessageQueue::get_singleton()->push_notification(gr_nodes[i], p_notification);
350 }
351 }
352
353 } else {
354 for (int i = 0; i < gr_node_count; i++) {
355 if (nodes_removed_on_group_call.has(gr_nodes[i])) {
356 continue;
357 }
358
359 if (!(p_call_flags & GROUP_CALL_DEFERRED)) {
360 gr_nodes[i]->notification(p_notification);
361 } else {
362 MessageQueue::get_singleton()->push_notification(gr_nodes[i], p_notification);
363 }
364 }
365 }
366
367 {
368 _THREAD_SAFE_METHOD_
369 nodes_removed_on_group_call_lock--;
370 if (nodes_removed_on_group_call_lock == 0) {
371 nodes_removed_on_group_call.clear();
372 }
373 }
374}
375
376void SceneTree::set_group_flags(uint32_t p_call_flags, const StringName &p_group, const String &p_name, const Variant &p_value) {
377 Vector<Node *> nodes_copy;
378 {
379 _THREAD_SAFE_METHOD_
380
381 HashMap<StringName, Group>::Iterator E = group_map.find(p_group);
382 if (!E) {
383 return;
384 }
385 Group &g = E->value;
386 if (g.nodes.is_empty()) {
387 return;
388 }
389
390 _update_group_order(g);
391
392 nodes_copy = g.nodes;
393 }
394 Node **gr_nodes = nodes_copy.ptrw();
395 int gr_node_count = nodes_copy.size();
396
397 {
398 _THREAD_SAFE_METHOD_
399 nodes_removed_on_group_call_lock++;
400 }
401
402 if (p_call_flags & GROUP_CALL_REVERSE) {
403 for (int i = gr_node_count - 1; i >= 0; i--) {
404 if (nodes_removed_on_group_call.has(gr_nodes[i])) {
405 continue;
406 }
407
408 if (!(p_call_flags & GROUP_CALL_DEFERRED)) {
409 gr_nodes[i]->set(p_name, p_value);
410 } else {
411 MessageQueue::get_singleton()->push_set(gr_nodes[i], p_name, p_value);
412 }
413 }
414
415 } else {
416 for (int i = 0; i < gr_node_count; i++) {
417 if (nodes_removed_on_group_call.has(gr_nodes[i])) {
418 continue;
419 }
420
421 if (!(p_call_flags & GROUP_CALL_DEFERRED)) {
422 gr_nodes[i]->set(p_name, p_value);
423 } else {
424 MessageQueue::get_singleton()->push_set(gr_nodes[i], p_name, p_value);
425 }
426 }
427 }
428
429 {
430 _THREAD_SAFE_METHOD_
431 nodes_removed_on_group_call_lock--;
432 if (nodes_removed_on_group_call_lock == 0) {
433 nodes_removed_on_group_call.clear();
434 }
435 }
436}
437
438void SceneTree::notify_group(const StringName &p_group, int p_notification) {
439 notify_group_flags(GROUP_CALL_DEFAULT, p_group, p_notification);
440}
441
442void SceneTree::set_group(const StringName &p_group, const String &p_name, const Variant &p_value) {
443 set_group_flags(GROUP_CALL_DEFAULT, p_group, p_name, p_value);
444}
445
446void SceneTree::initialize() {
447 ERR_FAIL_NULL(root);
448 MainLoop::initialize();
449 root->_set_tree(this);
450}
451
452bool SceneTree::physics_process(double p_time) {
453 root_lock++;
454
455 current_frame++;
456
457 flush_transform_notifications();
458
459 if (MainLoop::physics_process(p_time)) {
460 _quit = true;
461 }
462 physics_process_time = p_time;
463
464 emit_signal(SNAME("physics_frame"));
465
466 call_group(SNAME("_picking_viewports"), SNAME("_process_picking"));
467
468 _process(true);
469
470 _flush_ugc();
471 MessageQueue::get_singleton()->flush(); //small little hack
472
473 process_timers(p_time, true); //go through timers
474
475 process_tweens(p_time, true);
476
477 flush_transform_notifications();
478 root_lock--;
479
480 _flush_delete_queue();
481 _call_idle_callbacks();
482
483 return _quit;
484}
485
486bool SceneTree::process(double p_time) {
487 root_lock++;
488
489 if (MainLoop::process(p_time)) {
490 _quit = true;
491 }
492
493 process_time = p_time;
494
495 if (multiplayer_poll) {
496 multiplayer->poll();
497 for (KeyValue<NodePath, Ref<MultiplayerAPI>> &E : custom_multiplayers) {
498 E.value->poll();
499 }
500 }
501
502 emit_signal(SNAME("process_frame"));
503
504 MessageQueue::get_singleton()->flush(); //small little hack
505
506 flush_transform_notifications();
507
508 _process(false);
509
510 _flush_ugc();
511 MessageQueue::get_singleton()->flush(); //small little hack
512 flush_transform_notifications(); //transforms after world update, to avoid unnecessary enter/exit notifications
513
514 root_lock--;
515
516 _flush_delete_queue();
517
518 process_timers(p_time, false); //go through timers
519
520 process_tweens(p_time, false);
521
522 flush_transform_notifications(); //additional transforms after timers update
523
524 _call_idle_callbacks();
525
526#ifdef TOOLS_ENABLED
527#ifndef _3D_DISABLED
528 if (Engine::get_singleton()->is_editor_hint()) {
529 //simple hack to reload fallback environment if it changed from editor
530 String env_path = GLOBAL_GET(SNAME("rendering/environment/defaults/default_environment"));
531 env_path = env_path.strip_edges(); //user may have added a space or two
532 String cpath;
533 Ref<Environment> fallback = get_root()->get_world_3d()->get_fallback_environment();
534 if (fallback.is_valid()) {
535 cpath = fallback->get_path();
536 }
537 if (cpath != env_path) {
538 if (!env_path.is_empty()) {
539 fallback = ResourceLoader::load(env_path);
540 if (fallback.is_null()) {
541 //could not load fallback, set as empty
542 ProjectSettings::get_singleton()->set("rendering/environment/defaults/default_environment", "");
543 }
544 } else {
545 fallback.unref();
546 }
547 get_root()->get_world_3d()->set_fallback_environment(fallback);
548 }
549 }
550#endif // _3D_DISABLED
551#endif // TOOLS_ENABLED
552
553 if (unlikely(pending_new_scene)) {
554 _flush_scene_change();
555 }
556
557 return _quit;
558}
559
560void SceneTree::process_timers(double p_delta, bool p_physics_frame) {
561 _THREAD_SAFE_METHOD_
562 List<Ref<SceneTreeTimer>>::Element *L = timers.back(); //last element
563
564 for (List<Ref<SceneTreeTimer>>::Element *E = timers.front(); E;) {
565 List<Ref<SceneTreeTimer>>::Element *N = E->next();
566 if ((paused && !E->get()->is_process_always()) || (E->get()->is_process_in_physics() != p_physics_frame)) {
567 if (E == L) {
568 break; //break on last, so if new timers were added during list traversal, ignore them.
569 }
570 E = N;
571 continue;
572 }
573
574 double time_left = E->get()->get_time_left();
575 if (E->get()->is_ignore_time_scale()) {
576 time_left -= Engine::get_singleton()->get_process_step();
577 } else {
578 time_left -= p_delta;
579 }
580 E->get()->set_time_left(time_left);
581
582 if (time_left <= 0) {
583 E->get()->emit_signal(SNAME("timeout"));
584 timers.erase(E);
585 }
586 if (E == L) {
587 break; //break on last, so if new timers were added during list traversal, ignore them.
588 }
589 E = N;
590 }
591}
592
593void SceneTree::process_tweens(double p_delta, bool p_physics) {
594 _THREAD_SAFE_METHOD_
595 // This methods works similarly to how SceneTreeTimers are handled.
596 List<Ref<Tween>>::Element *L = tweens.back();
597
598 for (List<Ref<Tween>>::Element *E = tweens.front(); E;) {
599 List<Ref<Tween>>::Element *N = E->next();
600 // Don't process if paused or process mode doesn't match.
601 if (!E->get()->can_process(paused) || (p_physics == (E->get()->get_process_mode() == Tween::TWEEN_PROCESS_IDLE))) {
602 if (E == L) {
603 break;
604 }
605 E = N;
606 continue;
607 }
608
609 if (!E->get()->step(p_delta)) {
610 E->get()->clear();
611 tweens.erase(E);
612 }
613 if (E == L) {
614 break;
615 }
616 E = N;
617 }
618}
619
620void SceneTree::finalize() {
621 _flush_delete_queue();
622
623 _flush_ugc();
624
625 if (root) {
626 root->_set_tree(nullptr);
627 root->_propagate_after_exit_tree();
628 memdelete(root); //delete root
629 root = nullptr;
630
631 // In case deletion of some objects was queued when destructing the `root`.
632 // E.g. if `queue_free()` was called for some node outside the tree when handling NOTIFICATION_PREDELETE for some node in the tree.
633 _flush_delete_queue();
634 }
635
636 MainLoop::finalize();
637
638 // Cleanup timers.
639 for (Ref<SceneTreeTimer> &timer : timers) {
640 timer->release_connections();
641 }
642 timers.clear();
643
644 // Cleanup tweens.
645 for (Ref<Tween> &tween : tweens) {
646 tween->clear();
647 }
648 tweens.clear();
649}
650
651void SceneTree::quit(int p_exit_code) {
652 _THREAD_SAFE_METHOD_
653
654 OS::get_singleton()->set_exit_code(p_exit_code);
655 _quit = true;
656}
657
658void SceneTree::_main_window_close() {
659 if (accept_quit) {
660 _quit = true;
661 }
662}
663
664void SceneTree::_main_window_go_back() {
665 if (quit_on_go_back) {
666 _quit = true;
667 }
668}
669
670void SceneTree::_main_window_focus_in() {
671 Input *id = Input::get_singleton();
672 if (id) {
673 id->ensure_touch_mouse_raised();
674 }
675}
676
677void SceneTree::_notification(int p_notification) {
678 switch (p_notification) {
679 case NOTIFICATION_TRANSLATION_CHANGED: {
680 if (!Engine::get_singleton()->is_editor_hint()) {
681 get_root()->propagate_notification(p_notification);
682 }
683 } break;
684
685 case NOTIFICATION_OS_MEMORY_WARNING:
686 case NOTIFICATION_OS_IME_UPDATE:
687 case NOTIFICATION_WM_ABOUT:
688 case NOTIFICATION_CRASH:
689 case NOTIFICATION_APPLICATION_RESUMED:
690 case NOTIFICATION_APPLICATION_PAUSED:
691 case NOTIFICATION_APPLICATION_FOCUS_IN:
692 case NOTIFICATION_APPLICATION_FOCUS_OUT: {
693 // Pass these to nodes, since they are mirrored.
694 get_root()->propagate_notification(p_notification);
695 } break;
696 }
697}
698
699bool SceneTree::is_auto_accept_quit() const {
700 return accept_quit;
701}
702
703void SceneTree::set_auto_accept_quit(bool p_enable) {
704 accept_quit = p_enable;
705}
706
707bool SceneTree::is_quit_on_go_back() const {
708 return quit_on_go_back;
709}
710
711void SceneTree::set_quit_on_go_back(bool p_enable) {
712 quit_on_go_back = p_enable;
713}
714
715#ifdef TOOLS_ENABLED
716
717bool SceneTree::is_node_being_edited(const Node *p_node) const {
718 return Engine::get_singleton()->is_editor_hint() && edited_scene_root && (edited_scene_root->is_ancestor_of(p_node) || edited_scene_root == p_node);
719}
720#endif
721
722#ifdef DEBUG_ENABLED
723void SceneTree::set_debug_collisions_hint(bool p_enabled) {
724 debug_collisions_hint = p_enabled;
725}
726
727bool SceneTree::is_debugging_collisions_hint() const {
728 return debug_collisions_hint;
729}
730
731void SceneTree::set_debug_paths_hint(bool p_enabled) {
732 debug_paths_hint = p_enabled;
733}
734
735bool SceneTree::is_debugging_paths_hint() const {
736 return debug_paths_hint;
737}
738
739void SceneTree::set_debug_navigation_hint(bool p_enabled) {
740 debug_navigation_hint = p_enabled;
741}
742
743bool SceneTree::is_debugging_navigation_hint() const {
744 return debug_navigation_hint;
745}
746#endif
747
748void SceneTree::set_debug_collisions_color(const Color &p_color) {
749 debug_collisions_color = p_color;
750}
751
752Color SceneTree::get_debug_collisions_color() const {
753 return debug_collisions_color;
754}
755
756void SceneTree::set_debug_collision_contact_color(const Color &p_color) {
757 debug_collision_contact_color = p_color;
758}
759
760Color SceneTree::get_debug_collision_contact_color() const {
761 return debug_collision_contact_color;
762}
763
764void SceneTree::set_debug_paths_color(const Color &p_color) {
765 debug_paths_color = p_color;
766}
767
768Color SceneTree::get_debug_paths_color() const {
769 return debug_paths_color;
770}
771
772void SceneTree::set_debug_paths_width(float p_width) {
773 debug_paths_width = p_width;
774}
775
776float SceneTree::get_debug_paths_width() const {
777 return debug_paths_width;
778}
779
780Ref<Material> SceneTree::get_debug_paths_material() {
781 _THREAD_SAFE_METHOD_
782
783 if (debug_paths_material.is_valid()) {
784 return debug_paths_material;
785 }
786
787 Ref<StandardMaterial3D> _debug_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
788 _debug_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
789 _debug_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
790 _debug_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
791 _debug_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
792 _debug_material->set_albedo(get_debug_paths_color());
793
794 debug_paths_material = _debug_material;
795
796 return debug_paths_material;
797}
798
799Ref<Material> SceneTree::get_debug_collision_material() {
800 _THREAD_SAFE_METHOD_
801
802 if (collision_material.is_valid()) {
803 return collision_material;
804 }
805
806 Ref<StandardMaterial3D> line_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
807 line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
808 line_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
809 line_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
810 line_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
811 line_material->set_albedo(get_debug_collisions_color());
812
813 collision_material = line_material;
814
815 return collision_material;
816}
817
818Ref<ArrayMesh> SceneTree::get_debug_contact_mesh() {
819 _THREAD_SAFE_METHOD_
820
821 if (debug_contact_mesh.is_valid()) {
822 return debug_contact_mesh;
823 }
824
825 debug_contact_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
826
827 Ref<StandardMaterial3D> mat = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
828 mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
829 mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
830 mat->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
831 mat->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
832 mat->set_albedo(get_debug_collision_contact_color());
833
834 Vector3 diamond[6] = {
835 Vector3(-1, 0, 0),
836 Vector3(1, 0, 0),
837 Vector3(0, -1, 0),
838 Vector3(0, 1, 0),
839 Vector3(0, 0, -1),
840 Vector3(0, 0, 1)
841 };
842
843 /* clang-format off */
844 int diamond_faces[8 * 3] = {
845 0, 2, 4,
846 0, 3, 4,
847 1, 2, 4,
848 1, 3, 4,
849 0, 2, 5,
850 0, 3, 5,
851 1, 2, 5,
852 1, 3, 5,
853 };
854 /* clang-format on */
855
856 Vector<int> indices;
857 for (int i = 0; i < 8 * 3; i++) {
858 indices.push_back(diamond_faces[i]);
859 }
860
861 Vector<Vector3> vertices;
862 for (int i = 0; i < 6; i++) {
863 vertices.push_back(diamond[i] * 0.1);
864 }
865
866 Array arr;
867 arr.resize(Mesh::ARRAY_MAX);
868 arr[Mesh::ARRAY_VERTEX] = vertices;
869 arr[Mesh::ARRAY_INDEX] = indices;
870
871 debug_contact_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arr);
872 debug_contact_mesh->surface_set_material(0, mat);
873
874 return debug_contact_mesh;
875}
876
877void SceneTree::set_pause(bool p_enabled) {
878 ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Pause can only be set from the main thread.");
879
880 if (p_enabled == paused) {
881 return;
882 }
883 paused = p_enabled;
884 PhysicsServer3D::get_singleton()->set_active(!p_enabled);
885 PhysicsServer2D::get_singleton()->set_active(!p_enabled);
886 if (get_root()) {
887 get_root()->_propagate_pause_notification(p_enabled);
888 }
889}
890
891bool SceneTree::is_paused() const {
892 return paused;
893}
894
895void SceneTree::_process_group(ProcessGroup *p_group, bool p_physics) {
896 // When reading this function, keep in mind that this code must work in a way where
897 // if any node is removed, this needs to continue working.
898
899 p_group->call_queue.flush(); // Flush messages before processing.
900
901 Vector<Node *> &nodes = p_physics ? p_group->physics_nodes : p_group->nodes;
902 if (nodes.is_empty()) {
903 return;
904 }
905
906 if (p_physics) {
907 if (p_group->physics_node_order_dirty) {
908 nodes.sort_custom<Node::ComparatorWithPhysicsPriority>();
909 p_group->physics_node_order_dirty = false;
910 }
911 } else {
912 if (p_group->node_order_dirty) {
913 nodes.sort_custom<Node::ComparatorWithPriority>();
914 p_group->node_order_dirty = false;
915 }
916 }
917
918 // Make a copy, so if nodes are added/removed from process, this does not break
919 Vector<Node *> nodes_copy = nodes;
920
921 uint32_t node_count = nodes_copy.size();
922 Node **nodes_ptr = (Node **)nodes_copy.ptr(); // Force cast, pointer will not change.
923
924 for (uint32_t i = 0; i < node_count; i++) {
925 Node *n = nodes_ptr[i];
926 if (nodes_removed_on_group_call.has(n)) {
927 // Node may have been removed during process, skip it.
928 // Keep in mind removals can only happen on the main thread.
929 continue;
930 }
931
932 if (!n->can_process() || !n->is_inside_tree()) {
933 continue;
934 }
935
936 if (p_physics) {
937 if (n->is_physics_processing_internal()) {
938 n->notification(Node::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
939 }
940 if (n->is_physics_processing()) {
941 n->notification(Node::NOTIFICATION_PHYSICS_PROCESS);
942 }
943 } else {
944 if (n->is_processing_internal()) {
945 n->notification(Node::NOTIFICATION_INTERNAL_PROCESS);
946 }
947 if (n->is_processing()) {
948 n->notification(Node::NOTIFICATION_PROCESS);
949 }
950 }
951 }
952
953 p_group->call_queue.flush(); // Flush messages also after processing (for potential deferred calls).
954}
955
956void SceneTree::_process_groups_thread(uint32_t p_index, bool p_physics) {
957 Node::current_process_thread_group = local_process_group_cache[p_index]->owner;
958 _process_group(local_process_group_cache[p_index], p_physics);
959 Node::current_process_thread_group = nullptr;
960}
961
962void SceneTree::_process(bool p_physics) {
963 if (process_groups_dirty) {
964 {
965 // First, remove dirty groups.
966 // This needs to be done when not processing to avoid problems.
967 ProcessGroup **pg_ptr = (ProcessGroup **)process_groups.ptr(); // discard constness.
968 uint32_t pg_count = process_groups.size();
969
970 for (uint32_t i = 0; i < pg_count; i++) {
971 if (pg_ptr[i]->removed) {
972 // Replace removed with last.
973 pg_ptr[i] = pg_ptr[pg_count - 1];
974 // Retry
975 i--;
976 pg_count--;
977 }
978 }
979 if (pg_count != process_groups.size()) {
980 process_groups.resize(pg_count);
981 }
982 }
983 {
984 // Then, re-sort groups.
985 process_groups.sort_custom<ProcessGroupSort>();
986 }
987
988 process_groups_dirty = false;
989 }
990
991 // Cache the group count, because during processing new groups may be added.
992 // They will be added at the end, hence for consistency they will be ignored by this process loop.
993 // No group will be removed from the array during processing (this is done earlier in this function by marking the groups dirty).
994 uint32_t group_count = process_groups.size();
995
996 if (group_count == 0) {
997 return;
998 }
999
1000 process_last_pass++; // Increment pass
1001 uint32_t from = 0;
1002 uint32_t process_count = 0;
1003 nodes_removed_on_group_call_lock++;
1004
1005 int current_order = process_groups[0]->owner ? process_groups[0]->owner->data.process_thread_group_order : 0;
1006 bool current_threaded = process_groups[0]->owner ? process_groups[0]->owner->data.process_thread_group == Node::PROCESS_THREAD_GROUP_SUB_THREAD : false;
1007
1008 for (uint32_t i = 0; i <= group_count; i++) {
1009 int order = i < group_count && process_groups[i]->owner ? process_groups[i]->owner->data.process_thread_group_order : 0;
1010 bool threaded = i < group_count && process_groups[i]->owner ? process_groups[i]->owner->data.process_thread_group == Node::PROCESS_THREAD_GROUP_SUB_THREAD : false;
1011
1012 if (i == group_count || current_order != order || current_threaded != threaded) {
1013 if (process_count > 0) {
1014 // Proceed to process the group.
1015 bool using_threads = process_groups[from]->owner && process_groups[from]->owner->data.process_thread_group == Node::PROCESS_THREAD_GROUP_SUB_THREAD && !node_threading_disabled;
1016
1017 if (using_threads) {
1018 local_process_group_cache.clear();
1019 }
1020 for (uint32_t j = from; j < i; j++) {
1021 if (process_groups[j]->last_pass == process_last_pass) {
1022 if (using_threads) {
1023 local_process_group_cache.push_back(process_groups[j]);
1024 } else {
1025 _process_group(process_groups[j], p_physics);
1026 }
1027 }
1028 }
1029
1030 if (using_threads) {
1031 WorkerThreadPool::GroupID id = WorkerThreadPool::get_singleton()->add_template_group_task(this, &SceneTree::_process_groups_thread, p_physics, local_process_group_cache.size(), -1, true);
1032 WorkerThreadPool::get_singleton()->wait_for_group_task_completion(id);
1033 }
1034 }
1035
1036 if (i == group_count) {
1037 // This one is invalid, no longer process
1038 break;
1039 }
1040
1041 from = i;
1042 current_threaded = threaded;
1043 current_order = order;
1044 }
1045
1046 if (process_groups[i]->removed) {
1047 continue;
1048 }
1049
1050 ProcessGroup *pg = process_groups[i];
1051
1052 // Validate group for processing
1053 bool process_valid = false;
1054 if (p_physics) {
1055 if (!pg->physics_nodes.is_empty()) {
1056 process_valid = true;
1057 } else if ((pg == &default_process_group || (pg->owner != nullptr && pg->owner->data.process_thread_messages.has_flag(Node::FLAG_PROCESS_THREAD_MESSAGES_PHYSICS))) && pg->call_queue.has_messages()) {
1058 process_valid = true;
1059 }
1060 } else {
1061 if (!pg->nodes.is_empty()) {
1062 process_valid = true;
1063 } else if ((pg == &default_process_group || (pg->owner != nullptr && pg->owner->data.process_thread_messages.has_flag(Node::FLAG_PROCESS_THREAD_MESSAGES))) && pg->call_queue.has_messages()) {
1064 process_valid = true;
1065 }
1066 }
1067
1068 if (process_valid) {
1069 pg->last_pass = process_last_pass; // Enable for processing
1070 process_count++;
1071 }
1072 }
1073
1074 nodes_removed_on_group_call_lock--;
1075 if (nodes_removed_on_group_call_lock == 0) {
1076 nodes_removed_on_group_call.clear();
1077 }
1078}
1079
1080bool SceneTree::ProcessGroupSort::operator()(const ProcessGroup *p_left, const ProcessGroup *p_right) const {
1081 int left_order = p_left->owner ? p_left->owner->data.process_thread_group_order : 0;
1082 int right_order = p_right->owner ? p_right->owner->data.process_thread_group_order : 0;
1083
1084 if (left_order == right_order) {
1085 int left_threaded = p_left->owner != nullptr && p_left->owner->data.process_thread_group == Node::PROCESS_THREAD_GROUP_SUB_THREAD ? 0 : 1;
1086 int right_threaded = p_right->owner != nullptr && p_right->owner->data.process_thread_group == Node::PROCESS_THREAD_GROUP_SUB_THREAD ? 0 : 1;
1087 return left_threaded < right_threaded;
1088 } else {
1089 return left_order < right_order;
1090 }
1091}
1092
1093void SceneTree::_remove_process_group(Node *p_node) {
1094 _THREAD_SAFE_METHOD_
1095 ProcessGroup *pg = (ProcessGroup *)p_node->data.process_group;
1096 ERR_FAIL_NULL(pg);
1097 ERR_FAIL_COND(pg->removed);
1098 pg->removed = true;
1099 pg->owner = nullptr;
1100 p_node->data.process_group = nullptr;
1101 process_groups_dirty = true;
1102}
1103
1104void SceneTree::_add_process_group(Node *p_node) {
1105 _THREAD_SAFE_METHOD_
1106 ERR_FAIL_NULL(p_node);
1107
1108 ProcessGroup *pg = memnew(ProcessGroup);
1109
1110 pg->owner = p_node;
1111 p_node->data.process_group = pg;
1112
1113 process_groups.push_back(pg);
1114
1115 process_groups_dirty = true;
1116}
1117
1118void SceneTree::_remove_node_from_process_group(Node *p_node, Node *p_owner) {
1119 _THREAD_SAFE_METHOD_
1120 ProcessGroup *pg = p_owner ? (ProcessGroup *)p_owner->data.process_group : &default_process_group;
1121
1122 if (p_node->is_processing() || p_node->is_processing_internal()) {
1123 bool found = pg->nodes.erase(p_node);
1124 ERR_FAIL_COND(!found);
1125 }
1126
1127 if (p_node->is_physics_processing() || p_node->is_physics_processing_internal()) {
1128 bool found = pg->physics_nodes.erase(p_node);
1129 ERR_FAIL_COND(!found);
1130 }
1131}
1132
1133void SceneTree::_add_node_to_process_group(Node *p_node, Node *p_owner) {
1134 _THREAD_SAFE_METHOD_
1135 ProcessGroup *pg = p_owner ? (ProcessGroup *)p_owner->data.process_group : &default_process_group;
1136
1137 if (p_node->is_processing() || p_node->is_processing_internal()) {
1138 pg->nodes.push_back(p_node);
1139 pg->node_order_dirty = true;
1140 }
1141
1142 if (p_node->is_physics_processing() || p_node->is_physics_processing_internal()) {
1143 pg->physics_nodes.push_back(p_node);
1144 pg->physics_node_order_dirty = true;
1145 }
1146}
1147
1148void SceneTree::_call_input_pause(const StringName &p_group, CallInputType p_call_type, const Ref<InputEvent> &p_input, Viewport *p_viewport) {
1149 Vector<Node *> nodes_copy;
1150 {
1151 _THREAD_SAFE_METHOD_
1152
1153 HashMap<StringName, Group>::Iterator E = group_map.find(p_group);
1154 if (!E) {
1155 return;
1156 }
1157 Group &g = E->value;
1158 if (g.nodes.is_empty()) {
1159 return;
1160 }
1161
1162 _update_group_order(g);
1163
1164 //copy, so copy on write happens in case something is removed from process while being called
1165 //performance is not lost because only if something is added/removed the vector is copied.
1166 nodes_copy = g.nodes;
1167 }
1168
1169 int gr_node_count = nodes_copy.size();
1170 Node **gr_nodes = nodes_copy.ptrw();
1171
1172 {
1173 _THREAD_SAFE_METHOD_
1174 nodes_removed_on_group_call_lock++;
1175 }
1176
1177 Vector<ObjectID> no_context_node_ids; // Nodes may be deleted due to this shortcut input.
1178
1179 for (int i = gr_node_count - 1; i >= 0; i--) {
1180 if (p_viewport->is_input_handled()) {
1181 break;
1182 }
1183
1184 Node *n = gr_nodes[i];
1185 if (nodes_removed_on_group_call.has(n)) {
1186 continue;
1187 }
1188
1189 if (!n->can_process()) {
1190 continue;
1191 }
1192
1193 switch (p_call_type) {
1194 case CALL_INPUT_TYPE_INPUT:
1195 n->_call_input(p_input);
1196 break;
1197 case CALL_INPUT_TYPE_SHORTCUT_INPUT: {
1198 const Control *c = Object::cast_to<Control>(n);
1199 if (c) {
1200 // If calling shortcut input on a control, ensure it respects the shortcut context.
1201 // Shortcut context (based on focus) only makes sense for controls (UI), so don't need to worry about it for nodes
1202 if (c->get_shortcut_context() == nullptr) {
1203 no_context_node_ids.append(n->get_instance_id());
1204 continue;
1205 }
1206 if (!c->is_focus_owner_in_shortcut_context()) {
1207 continue;
1208 }
1209 }
1210 n->_call_shortcut_input(p_input);
1211 break;
1212 }
1213 case CALL_INPUT_TYPE_UNHANDLED_INPUT:
1214 n->_call_unhandled_input(p_input);
1215 break;
1216 case CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT:
1217 n->_call_unhandled_key_input(p_input);
1218 break;
1219 }
1220 }
1221
1222 for (const ObjectID &id : no_context_node_ids) {
1223 if (p_viewport->is_input_handled()) {
1224 break;
1225 }
1226 Node *n = Object::cast_to<Node>(ObjectDB::get_instance(id));
1227 if (n) {
1228 n->_call_shortcut_input(p_input);
1229 }
1230 }
1231
1232 {
1233 _THREAD_SAFE_METHOD_
1234 nodes_removed_on_group_call_lock--;
1235 if (nodes_removed_on_group_call_lock == 0) {
1236 nodes_removed_on_group_call.clear();
1237 }
1238 }
1239}
1240
1241void SceneTree::_call_group_flags(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
1242 r_error.error = Callable::CallError::CALL_OK;
1243
1244 ERR_FAIL_COND(p_argcount < 3);
1245 ERR_FAIL_COND(!p_args[0]->is_num());
1246 ERR_FAIL_COND(p_args[1]->get_type() != Variant::STRING_NAME && p_args[1]->get_type() != Variant::STRING);
1247 ERR_FAIL_COND(p_args[2]->get_type() != Variant::STRING_NAME && p_args[2]->get_type() != Variant::STRING);
1248
1249 int flags = *p_args[0];
1250 StringName group = *p_args[1];
1251 StringName method = *p_args[2];
1252
1253 call_group_flagsp(flags, group, method, p_args + 3, p_argcount - 3);
1254}
1255
1256void SceneTree::_call_group(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
1257 r_error.error = Callable::CallError::CALL_OK;
1258
1259 ERR_FAIL_COND(p_argcount < 2);
1260 ERR_FAIL_COND(p_args[0]->get_type() != Variant::STRING_NAME && p_args[0]->get_type() != Variant::STRING);
1261 ERR_FAIL_COND(p_args[1]->get_type() != Variant::STRING_NAME && p_args[1]->get_type() != Variant::STRING);
1262
1263 StringName group = *p_args[0];
1264 StringName method = *p_args[1];
1265
1266 call_group_flagsp(GROUP_CALL_DEFAULT, group, method, p_args + 2, p_argcount - 2);
1267}
1268
1269int64_t SceneTree::get_frame() const {
1270 return current_frame;
1271}
1272
1273TypedArray<Node> SceneTree::_get_nodes_in_group(const StringName &p_group) {
1274 _THREAD_SAFE_METHOD_
1275 TypedArray<Node> ret;
1276 HashMap<StringName, Group>::Iterator E = group_map.find(p_group);
1277 if (!E) {
1278 return ret;
1279 }
1280
1281 _update_group_order(E->value); //update order just in case
1282 int nc = E->value.nodes.size();
1283 if (nc == 0) {
1284 return ret;
1285 }
1286
1287 ret.resize(nc);
1288
1289 Node **ptr = E->value.nodes.ptrw();
1290 for (int i = 0; i < nc; i++) {
1291 ret[i] = ptr[i];
1292 }
1293
1294 return ret;
1295}
1296
1297bool SceneTree::has_group(const StringName &p_identifier) const {
1298 _THREAD_SAFE_METHOD_
1299 return group_map.has(p_identifier);
1300}
1301
1302Node *SceneTree::get_first_node_in_group(const StringName &p_group) {
1303 _THREAD_SAFE_METHOD_
1304 HashMap<StringName, Group>::Iterator E = group_map.find(p_group);
1305 if (!E) {
1306 return nullptr; // No group.
1307 }
1308
1309 _update_group_order(E->value); // Update order just in case.
1310
1311 if (E->value.nodes.is_empty()) {
1312 return nullptr;
1313 }
1314
1315 return E->value.nodes[0];
1316}
1317
1318void SceneTree::get_nodes_in_group(const StringName &p_group, List<Node *> *p_list) {
1319 _THREAD_SAFE_METHOD_
1320 HashMap<StringName, Group>::Iterator E = group_map.find(p_group);
1321 if (!E) {
1322 return;
1323 }
1324
1325 _update_group_order(E->value); //update order just in case
1326 int nc = E->value.nodes.size();
1327 if (nc == 0) {
1328 return;
1329 }
1330 Node **ptr = E->value.nodes.ptrw();
1331 for (int i = 0; i < nc; i++) {
1332 p_list->push_back(ptr[i]);
1333 }
1334}
1335
1336void SceneTree::_flush_delete_queue() {
1337 _THREAD_SAFE_METHOD_
1338
1339 while (delete_queue.size()) {
1340 Object *obj = ObjectDB::get_instance(delete_queue.front()->get());
1341 if (obj) {
1342 memdelete(obj);
1343 }
1344 delete_queue.pop_front();
1345 }
1346}
1347
1348void SceneTree::queue_delete(Object *p_object) {
1349 _THREAD_SAFE_METHOD_
1350 ERR_FAIL_NULL(p_object);
1351 p_object->_is_queued_for_deletion = true;
1352 delete_queue.push_back(p_object->get_instance_id());
1353}
1354
1355int SceneTree::get_node_count() const {
1356 return nodes_in_tree_count;
1357}
1358
1359void SceneTree::set_edited_scene_root(Node *p_node) {
1360#ifdef TOOLS_ENABLED
1361 edited_scene_root = p_node;
1362#endif
1363}
1364
1365Node *SceneTree::get_edited_scene_root() const {
1366#ifdef TOOLS_ENABLED
1367 return edited_scene_root;
1368#else
1369 return nullptr;
1370#endif
1371}
1372
1373void SceneTree::set_current_scene(Node *p_scene) {
1374 ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Changing scene can only be done from the main thread.");
1375 ERR_FAIL_COND(p_scene && p_scene->get_parent() != root);
1376 current_scene = p_scene;
1377}
1378
1379Node *SceneTree::get_current_scene() const {
1380 return current_scene;
1381}
1382
1383void SceneTree::_flush_scene_change() {
1384 if (prev_scene) {
1385 memdelete(prev_scene);
1386 prev_scene = nullptr;
1387 }
1388 current_scene = pending_new_scene;
1389 root->add_child(pending_new_scene);
1390 pending_new_scene = nullptr;
1391 // Update display for cursor instantly.
1392 root->update_mouse_cursor_state();
1393}
1394
1395Error SceneTree::change_scene_to_file(const String &p_path) {
1396 ERR_FAIL_COND_V_MSG(!Thread::is_main_thread(), ERR_INVALID_PARAMETER, "Changing scene can only be done from the main thread.");
1397 Ref<PackedScene> new_scene = ResourceLoader::load(p_path);
1398 if (new_scene.is_null()) {
1399 return ERR_CANT_OPEN;
1400 }
1401
1402 return change_scene_to_packed(new_scene);
1403}
1404
1405Error SceneTree::change_scene_to_packed(const Ref<PackedScene> &p_scene) {
1406 ERR_FAIL_COND_V_MSG(p_scene.is_null(), ERR_INVALID_PARAMETER, "Can't change to a null scene. Use unload_current_scene() if you wish to unload it.");
1407
1408 Node *new_scene = p_scene->instantiate();
1409 ERR_FAIL_NULL_V(new_scene, ERR_CANT_CREATE);
1410
1411 // If called again while a change is pending.
1412 if (pending_new_scene) {
1413 queue_delete(pending_new_scene);
1414 pending_new_scene = nullptr;
1415 }
1416
1417 prev_scene = current_scene;
1418
1419 if (current_scene) {
1420 // Let as many side effects as possible happen or be queued now,
1421 // so they are run before the scene is actually deleted.
1422 root->remove_child(current_scene);
1423 }
1424 DEV_ASSERT(!current_scene);
1425
1426 pending_new_scene = new_scene;
1427 return OK;
1428}
1429
1430Error SceneTree::reload_current_scene() {
1431 ERR_FAIL_COND_V_MSG(!Thread::is_main_thread(), ERR_INVALID_PARAMETER, "Reloading scene can only be done from the main thread.");
1432 ERR_FAIL_NULL_V(current_scene, ERR_UNCONFIGURED);
1433 String fname = current_scene->get_scene_file_path();
1434 return change_scene_to_file(fname);
1435}
1436
1437void SceneTree::unload_current_scene() {
1438 ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Unloading the current scene can only be done from the main thread.");
1439 if (current_scene) {
1440 memdelete(current_scene);
1441 current_scene = nullptr;
1442 }
1443}
1444
1445void SceneTree::add_current_scene(Node *p_current) {
1446 ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Adding a current scene can only be done from the main thread.");
1447 current_scene = p_current;
1448 root->add_child(p_current);
1449}
1450
1451Ref<SceneTreeTimer> SceneTree::create_timer(double p_delay_sec, bool p_process_always, bool p_process_in_physics, bool p_ignore_time_scale) {
1452 _THREAD_SAFE_METHOD_
1453 Ref<SceneTreeTimer> stt;
1454 stt.instantiate();
1455 stt->set_process_always(p_process_always);
1456 stt->set_time_left(p_delay_sec);
1457 stt->set_process_in_physics(p_process_in_physics);
1458 stt->set_ignore_time_scale(p_ignore_time_scale);
1459 timers.push_back(stt);
1460 return stt;
1461}
1462
1463Ref<Tween> SceneTree::create_tween() {
1464 _THREAD_SAFE_METHOD_
1465 Ref<Tween> tween = memnew(Tween(true));
1466 tweens.push_back(tween);
1467 return tween;
1468}
1469
1470TypedArray<Tween> SceneTree::get_processed_tweens() {
1471 _THREAD_SAFE_METHOD_
1472 TypedArray<Tween> ret;
1473 ret.resize(tweens.size());
1474
1475 int i = 0;
1476 for (const Ref<Tween> &tween : tweens) {
1477 ret[i] = tween;
1478 i++;
1479 }
1480
1481 return ret;
1482}
1483
1484Ref<MultiplayerAPI> SceneTree::get_multiplayer(const NodePath &p_for_path) const {
1485 ERR_FAIL_COND_V_MSG(!Thread::is_main_thread(), Ref<MultiplayerAPI>(), "Multiplayer can only be manipulated from the main thread.");
1486 Ref<MultiplayerAPI> out = multiplayer;
1487 for (const KeyValue<NodePath, Ref<MultiplayerAPI>> &E : custom_multiplayers) {
1488 const Vector<StringName> snames = E.key.get_names();
1489 const Vector<StringName> tnames = p_for_path.get_names();
1490 if (tnames.size() < snames.size()) {
1491 continue;
1492 }
1493 const StringName *sptr = snames.ptr();
1494 const StringName *nptr = tnames.ptr();
1495 bool valid = true;
1496 for (int i = 0; i < snames.size(); i++) {
1497 if (sptr[i] != nptr[i]) {
1498 valid = false;
1499 break;
1500 }
1501 }
1502 if (valid) {
1503 out = E.value;
1504 break;
1505 }
1506 }
1507 return out;
1508}
1509
1510void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer, const NodePath &p_root_path) {
1511 ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Multiplayer can only be manipulated from the main thread.");
1512 if (p_root_path.is_empty()) {
1513 ERR_FAIL_COND(!p_multiplayer.is_valid());
1514 if (multiplayer.is_valid()) {
1515 multiplayer->object_configuration_remove(nullptr, NodePath("/" + root->get_name()));
1516 }
1517 multiplayer = p_multiplayer;
1518 multiplayer->object_configuration_add(nullptr, NodePath("/" + root->get_name()));
1519 } else {
1520 if (custom_multiplayers.has(p_root_path)) {
1521 custom_multiplayers[p_root_path]->object_configuration_remove(nullptr, p_root_path);
1522 }
1523 if (p_multiplayer.is_valid()) {
1524 custom_multiplayers[p_root_path] = p_multiplayer;
1525 p_multiplayer->object_configuration_add(nullptr, p_root_path);
1526 }
1527 }
1528}
1529
1530void SceneTree::set_multiplayer_poll_enabled(bool p_enabled) {
1531 ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Multiplayer can only be manipulated from the main thread.");
1532 multiplayer_poll = p_enabled;
1533}
1534
1535bool SceneTree::is_multiplayer_poll_enabled() const {
1536 return multiplayer_poll;
1537}
1538
1539void SceneTree::_bind_methods() {
1540 ClassDB::bind_method(D_METHOD("get_root"), &SceneTree::get_root);
1541 ClassDB::bind_method(D_METHOD("has_group", "name"), &SceneTree::has_group);
1542
1543 ClassDB::bind_method(D_METHOD("is_auto_accept_quit"), &SceneTree::is_auto_accept_quit);
1544 ClassDB::bind_method(D_METHOD("set_auto_accept_quit", "enabled"), &SceneTree::set_auto_accept_quit);
1545 ClassDB::bind_method(D_METHOD("is_quit_on_go_back"), &SceneTree::is_quit_on_go_back);
1546 ClassDB::bind_method(D_METHOD("set_quit_on_go_back", "enabled"), &SceneTree::set_quit_on_go_back);
1547
1548 ClassDB::bind_method(D_METHOD("set_debug_collisions_hint", "enable"), &SceneTree::set_debug_collisions_hint);
1549 ClassDB::bind_method(D_METHOD("is_debugging_collisions_hint"), &SceneTree::is_debugging_collisions_hint);
1550 ClassDB::bind_method(D_METHOD("set_debug_paths_hint", "enable"), &SceneTree::set_debug_paths_hint);
1551 ClassDB::bind_method(D_METHOD("is_debugging_paths_hint"), &SceneTree::is_debugging_paths_hint);
1552 ClassDB::bind_method(D_METHOD("set_debug_navigation_hint", "enable"), &SceneTree::set_debug_navigation_hint);
1553 ClassDB::bind_method(D_METHOD("is_debugging_navigation_hint"), &SceneTree::is_debugging_navigation_hint);
1554
1555 ClassDB::bind_method(D_METHOD("set_edited_scene_root", "scene"), &SceneTree::set_edited_scene_root);
1556 ClassDB::bind_method(D_METHOD("get_edited_scene_root"), &SceneTree::get_edited_scene_root);
1557
1558 ClassDB::bind_method(D_METHOD("set_pause", "enable"), &SceneTree::set_pause);
1559 ClassDB::bind_method(D_METHOD("is_paused"), &SceneTree::is_paused);
1560
1561 ClassDB::bind_method(D_METHOD("create_timer", "time_sec", "process_always", "process_in_physics", "ignore_time_scale"), &SceneTree::create_timer, DEFVAL(true), DEFVAL(false), DEFVAL(false));
1562 ClassDB::bind_method(D_METHOD("create_tween"), &SceneTree::create_tween);
1563 ClassDB::bind_method(D_METHOD("get_processed_tweens"), &SceneTree::get_processed_tweens);
1564
1565 ClassDB::bind_method(D_METHOD("get_node_count"), &SceneTree::get_node_count);
1566 ClassDB::bind_method(D_METHOD("get_frame"), &SceneTree::get_frame);
1567 ClassDB::bind_method(D_METHOD("quit", "exit_code"), &SceneTree::quit, DEFVAL(EXIT_SUCCESS));
1568
1569 ClassDB::bind_method(D_METHOD("queue_delete", "obj"), &SceneTree::queue_delete);
1570
1571 MethodInfo mi;
1572 mi.name = "call_group_flags";
1573 mi.arguments.push_back(PropertyInfo(Variant::INT, "flags"));
1574 mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "group"));
1575 mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "method"));
1576
1577 ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_group_flags", &SceneTree::_call_group_flags, mi);
1578
1579 ClassDB::bind_method(D_METHOD("notify_group_flags", "call_flags", "group", "notification"), &SceneTree::notify_group_flags);
1580 ClassDB::bind_method(D_METHOD("set_group_flags", "call_flags", "group", "property", "value"), &SceneTree::set_group_flags);
1581
1582 MethodInfo mi2;
1583 mi2.name = "call_group";
1584 mi2.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "group"));
1585 mi2.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "method"));
1586
1587 ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_group", &SceneTree::_call_group, mi2);
1588
1589 ClassDB::bind_method(D_METHOD("notify_group", "group", "notification"), &SceneTree::notify_group);
1590 ClassDB::bind_method(D_METHOD("set_group", "group", "property", "value"), &SceneTree::set_group);
1591
1592 ClassDB::bind_method(D_METHOD("get_nodes_in_group", "group"), &SceneTree::_get_nodes_in_group);
1593 ClassDB::bind_method(D_METHOD("get_first_node_in_group", "group"), &SceneTree::get_first_node_in_group);
1594
1595 ClassDB::bind_method(D_METHOD("set_current_scene", "child_node"), &SceneTree::set_current_scene);
1596 ClassDB::bind_method(D_METHOD("get_current_scene"), &SceneTree::get_current_scene);
1597
1598 ClassDB::bind_method(D_METHOD("change_scene_to_file", "path"), &SceneTree::change_scene_to_file);
1599 ClassDB::bind_method(D_METHOD("change_scene_to_packed", "packed_scene"), &SceneTree::change_scene_to_packed);
1600
1601 ClassDB::bind_method(D_METHOD("reload_current_scene"), &SceneTree::reload_current_scene);
1602 ClassDB::bind_method(D_METHOD("unload_current_scene"), &SceneTree::unload_current_scene);
1603
1604 ClassDB::bind_method(D_METHOD("set_multiplayer", "multiplayer", "root_path"), &SceneTree::set_multiplayer, DEFVAL(NodePath()));
1605 ClassDB::bind_method(D_METHOD("get_multiplayer", "for_path"), &SceneTree::get_multiplayer, DEFVAL(NodePath()));
1606 ClassDB::bind_method(D_METHOD("set_multiplayer_poll_enabled", "enabled"), &SceneTree::set_multiplayer_poll_enabled);
1607 ClassDB::bind_method(D_METHOD("is_multiplayer_poll_enabled"), &SceneTree::is_multiplayer_poll_enabled);
1608
1609 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_accept_quit"), "set_auto_accept_quit", "is_auto_accept_quit");
1610 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "quit_on_go_back"), "set_quit_on_go_back", "is_quit_on_go_back");
1611 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_collisions_hint"), "set_debug_collisions_hint", "is_debugging_collisions_hint");
1612 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_paths_hint"), "set_debug_paths_hint", "is_debugging_paths_hint");
1613 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_navigation_hint"), "set_debug_navigation_hint", "is_debugging_navigation_hint");
1614 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused"), "set_pause", "is_paused");
1615 ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "edited_scene_root", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_edited_scene_root", "get_edited_scene_root");
1616 ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "current_scene", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_current_scene", "get_current_scene");
1617 ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "", "get_root");
1618 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multiplayer_poll"), "set_multiplayer_poll_enabled", "is_multiplayer_poll_enabled");
1619
1620 ADD_SIGNAL(MethodInfo("tree_changed"));
1621 ADD_SIGNAL(MethodInfo("tree_process_mode_changed")); //editor only signal, but due to API hash it can't be removed in run-time
1622 ADD_SIGNAL(MethodInfo("node_added", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
1623 ADD_SIGNAL(MethodInfo("node_removed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
1624 ADD_SIGNAL(MethodInfo("node_renamed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
1625 ADD_SIGNAL(MethodInfo("node_configuration_warning_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
1626
1627 ADD_SIGNAL(MethodInfo("process_frame"));
1628 ADD_SIGNAL(MethodInfo("physics_frame"));
1629
1630 BIND_ENUM_CONSTANT(GROUP_CALL_DEFAULT);
1631 BIND_ENUM_CONSTANT(GROUP_CALL_REVERSE);
1632 BIND_ENUM_CONSTANT(GROUP_CALL_DEFERRED);
1633 BIND_ENUM_CONSTANT(GROUP_CALL_UNIQUE);
1634}
1635
1636SceneTree *SceneTree::singleton = nullptr;
1637
1638SceneTree::IdleCallback SceneTree::idle_callbacks[SceneTree::MAX_IDLE_CALLBACKS];
1639int SceneTree::idle_callback_count = 0;
1640
1641void SceneTree::_call_idle_callbacks() {
1642 for (int i = 0; i < idle_callback_count; i++) {
1643 idle_callbacks[i]();
1644 }
1645}
1646
1647void SceneTree::add_idle_callback(IdleCallback p_callback) {
1648 ERR_FAIL_COND(idle_callback_count >= MAX_IDLE_CALLBACKS);
1649 idle_callbacks[idle_callback_count++] = p_callback;
1650}
1651
1652void SceneTree::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
1653 if (p_function == "change_scene_to_file") {
1654 Ref<DirAccess> dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES);
1655 List<String> directories;
1656 directories.push_back(dir_access->get_current_dir());
1657
1658 while (!directories.is_empty()) {
1659 dir_access->change_dir(directories.back()->get());
1660 directories.pop_back();
1661
1662 dir_access->list_dir_begin();
1663 String filename = dir_access->get_next();
1664
1665 while (!filename.is_empty()) {
1666 if (filename == "." || filename == "..") {
1667 filename = dir_access->get_next();
1668 continue;
1669 }
1670
1671 if (dir_access->dir_exists(filename)) {
1672 directories.push_back(dir_access->get_current_dir().path_join(filename));
1673 } else if (filename.ends_with(".tscn") || filename.ends_with(".scn")) {
1674 r_options->push_back("\"" + dir_access->get_current_dir().path_join(filename) + "\"");
1675 }
1676
1677 filename = dir_access->get_next();
1678 }
1679 }
1680 }
1681}
1682
1683void SceneTree::set_disable_node_threading(bool p_disable) {
1684 node_threading_disabled = p_disable;
1685}
1686
1687SceneTree::SceneTree() {
1688 if (singleton == nullptr) {
1689 singleton = this;
1690 }
1691 debug_collisions_color = GLOBAL_DEF("debug/shapes/collision/shape_color", Color(0.0, 0.6, 0.7, 0.42));
1692 debug_collision_contact_color = GLOBAL_DEF("debug/shapes/collision/contact_color", Color(1.0, 0.2, 0.1, 0.8));
1693 debug_paths_color = GLOBAL_DEF("debug/shapes/paths/geometry_color", Color(0.1, 1.0, 0.7, 0.4));
1694 debug_paths_width = GLOBAL_DEF("debug/shapes/paths/geometry_width", 2.0);
1695 collision_debug_contacts = GLOBAL_DEF(PropertyInfo(Variant::INT, "debug/shapes/collision/max_contacts_displayed", PROPERTY_HINT_RANGE, "0,20000,1"), 10000);
1696
1697 GLOBAL_DEF("debug/shapes/collision/draw_2d_outlines", true);
1698
1699 process_group_call_queue_allocator = memnew(CallQueue::Allocator(64));
1700 Math::randomize();
1701
1702 // Create with mainloop.
1703
1704 root = memnew(Window);
1705 root->set_min_size(Size2i(64, 64)); // Define a very small minimum window size to prevent bugs such as GH-37242.
1706 root->set_process_mode(Node::PROCESS_MODE_PAUSABLE);
1707 root->set_name("root");
1708 root->set_title(GLOBAL_GET("application/config/name"));
1709
1710 if (Engine::get_singleton()->is_editor_hint()) {
1711 root->set_wrap_controls(true);
1712 }
1713
1714#ifndef _3D_DISABLED
1715 if (!root->get_world_3d().is_valid()) {
1716 root->set_world_3d(Ref<World3D>(memnew(World3D)));
1717 }
1718 root->set_as_audio_listener_3d(true);
1719#endif // _3D_DISABLED
1720
1721 // Initialize network state.
1722 set_multiplayer(MultiplayerAPI::create_default_interface());
1723
1724 root->set_as_audio_listener_2d(true);
1725 current_scene = nullptr;
1726
1727 const int msaa_mode_2d = GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/msaa_2d", PROPERTY_HINT_ENUM, String::utf8("Disabled (Fastest),2× (Average),4× (Slow),8× (Slowest)")), 0);
1728 root->set_msaa_2d(Viewport::MSAA(msaa_mode_2d));
1729
1730 const int msaa_mode_3d = GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/msaa_3d", PROPERTY_HINT_ENUM, String::utf8("Disabled (Fastest),2× (Average),4× (Slow),8× (Slowest)")), 0);
1731 root->set_msaa_3d(Viewport::MSAA(msaa_mode_3d));
1732
1733 const bool transparent_background = GLOBAL_DEF("rendering/viewport/transparent_background", false);
1734 root->set_transparent_background(transparent_background);
1735
1736 const bool use_hdr_2d = GLOBAL_DEF_RST_BASIC("rendering/viewport/hdr_2d", false);
1737 root->set_use_hdr_2d(use_hdr_2d);
1738
1739 const int ssaa_mode = GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/screen_space_aa", PROPERTY_HINT_ENUM, "Disabled (Fastest),FXAA (Fast)"), 0);
1740 root->set_screen_space_aa(Viewport::ScreenSpaceAA(ssaa_mode));
1741
1742 const bool use_taa = GLOBAL_DEF_BASIC("rendering/anti_aliasing/quality/use_taa", false);
1743 root->set_use_taa(use_taa);
1744
1745 const bool use_debanding = GLOBAL_DEF("rendering/anti_aliasing/quality/use_debanding", false);
1746 root->set_use_debanding(use_debanding);
1747
1748 const bool use_occlusion_culling = GLOBAL_DEF("rendering/occlusion_culling/use_occlusion_culling", false);
1749 root->set_use_occlusion_culling(use_occlusion_culling);
1750
1751 float mesh_lod_threshold = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/mesh_lod/lod_change/threshold_pixels", PROPERTY_HINT_RANGE, "0,1024,0.1"), 1.0);
1752 root->set_mesh_lod_threshold(mesh_lod_threshold);
1753
1754 bool snap_2d_transforms = GLOBAL_DEF("rendering/2d/snap/snap_2d_transforms_to_pixel", false);
1755 root->set_snap_2d_transforms_to_pixel(snap_2d_transforms);
1756
1757 bool snap_2d_vertices = GLOBAL_DEF("rendering/2d/snap/snap_2d_vertices_to_pixel", false);
1758 root->set_snap_2d_vertices_to_pixel(snap_2d_vertices);
1759
1760 // We setup VRS for the main viewport here, in the editor this will have little effect.
1761 const int vrs_mode = GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/vrs/mode", PROPERTY_HINT_ENUM, String::utf8("Disabled,Texture,XR")), 0);
1762 root->set_vrs_mode(Viewport::VRSMode(vrs_mode));
1763 const String vrs_texture_path = String(GLOBAL_DEF(PropertyInfo(Variant::STRING, "rendering/vrs/texture", PROPERTY_HINT_FILE, "*.bmp,*.png,*.tga,*.webp"), String())).strip_edges();
1764 if (vrs_mode == 1 && !vrs_texture_path.is_empty()) {
1765 Ref<Image> vrs_image;
1766 vrs_image.instantiate();
1767 Error load_err = ImageLoader::load_image(vrs_texture_path, vrs_image);
1768 if (load_err) {
1769 ERR_PRINT("Non-existing or invalid VRS texture at '" + vrs_texture_path + "'.");
1770 } else {
1771 Ref<ImageTexture> vrs_texture;
1772 vrs_texture.instantiate();
1773 vrs_texture->create_from_image(vrs_image);
1774 root->set_vrs_texture(vrs_texture);
1775 }
1776 }
1777
1778 int shadowmap_size = GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_size", PROPERTY_HINT_RANGE, "256,16384"), 4096);
1779 GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_size.mobile", 2048);
1780 bool shadowmap_16_bits = GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_16_bits", true);
1781 int atlas_q0 = GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_quadrant_0_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), 2);
1782 int atlas_q1 = GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_quadrant_1_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), 2);
1783 int atlas_q2 = GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_quadrant_2_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), 3);
1784 int atlas_q3 = GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_quadrant_3_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), 4);
1785
1786 root->set_positional_shadow_atlas_size(shadowmap_size);
1787 root->set_positional_shadow_atlas_16_bits(shadowmap_16_bits);
1788 root->set_positional_shadow_atlas_quadrant_subdiv(0, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q0));
1789 root->set_positional_shadow_atlas_quadrant_subdiv(1, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q1));
1790 root->set_positional_shadow_atlas_quadrant_subdiv(2, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q2));
1791 root->set_positional_shadow_atlas_quadrant_subdiv(3, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q3));
1792
1793 Viewport::SDFOversize sdf_oversize = Viewport::SDFOversize(int(GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/2d/sdf/oversize", PROPERTY_HINT_ENUM, "100%,120%,150%,200%"), 1)));
1794 root->set_sdf_oversize(sdf_oversize);
1795 Viewport::SDFScale sdf_scale = Viewport::SDFScale(int(GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/2d/sdf/scale", PROPERTY_HINT_ENUM, "100%,50%,25%"), 1)));
1796 root->set_sdf_scale(sdf_scale);
1797
1798#ifndef _3D_DISABLED
1799 { // Load default fallback environment.
1800 // Get possible extensions.
1801 List<String> exts;
1802 ResourceLoader::get_recognized_extensions_for_type("Environment", &exts);
1803 String ext_hint;
1804 for (const String &E : exts) {
1805 if (!ext_hint.is_empty()) {
1806 ext_hint += ",";
1807 }
1808 ext_hint += "*." + E;
1809 }
1810 // Get path.
1811 String env_path = GLOBAL_DEF(PropertyInfo(Variant::STRING, "rendering/environment/defaults/default_environment", PROPERTY_HINT_FILE, ext_hint), "");
1812 // Setup property.
1813 env_path = env_path.strip_edges();
1814 if (!env_path.is_empty()) {
1815 Ref<Environment> env = ResourceLoader::load(env_path);
1816 if (env.is_valid()) {
1817 root->get_world_3d()->set_fallback_environment(env);
1818 } else {
1819 if (Engine::get_singleton()->is_editor_hint()) {
1820 // File was erased, clear the field.
1821 ProjectSettings::get_singleton()->set("rendering/environment/defaults/default_environment", "");
1822 } else {
1823 // File was erased, notify user.
1824 ERR_PRINT(RTR("Default Environment as specified in the project setting \"rendering/environment/defaults/default_environment\" could not be loaded."));
1825 }
1826 }
1827 }
1828 }
1829#endif // _3D_DISABLED
1830
1831 root->set_physics_object_picking(GLOBAL_DEF("physics/common/enable_object_picking", true));
1832
1833 root->connect("close_requested", callable_mp(this, &SceneTree::_main_window_close));
1834 root->connect("go_back_requested", callable_mp(this, &SceneTree::_main_window_go_back));
1835 root->connect("focus_entered", callable_mp(this, &SceneTree::_main_window_focus_in));
1836
1837#ifdef TOOLS_ENABLED
1838 edited_scene_root = nullptr;
1839#endif
1840
1841 process_groups.push_back(&default_process_group);
1842}
1843
1844SceneTree::~SceneTree() {
1845 if (prev_scene) {
1846 memdelete(prev_scene);
1847 prev_scene = nullptr;
1848 }
1849 if (pending_new_scene) {
1850 memdelete(pending_new_scene);
1851 pending_new_scene = nullptr;
1852 }
1853 if (root) {
1854 root->_set_tree(nullptr);
1855 root->_propagate_after_exit_tree();
1856 memdelete(root);
1857 }
1858
1859 // Process groups are not deleted immediately, they may remain around. Delete them now.
1860 for (uint32_t i = 0; i < process_groups.size(); i++) {
1861 if (process_groups[i] != &default_process_group) {
1862 memdelete(process_groups[i]);
1863 }
1864 }
1865
1866 memdelete(process_group_call_queue_allocator);
1867
1868 if (singleton == this) {
1869 singleton = nullptr;
1870 }
1871}
1872