Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/scene/main/scene_tree.cpp
20897 views
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/input/input.h"
35
#include "core/io/image_loader.h"
36
#include "core/io/resource_loader.h"
37
#include "core/object/message_queue.h"
38
#include "core/object/worker_thread_pool.h"
39
#include "core/os/os.h"
40
#include "core/profiling/profiling.h"
41
#include "node.h"
42
#include "scene/animation/tween.h"
43
#include "scene/debugger/scene_debugger.h"
44
#include "scene/gui/control.h"
45
#include "scene/main/multiplayer_api.h"
46
#include "scene/main/viewport.h"
47
#include "scene/main/window.h"
48
#include "scene/resources/environment.h"
49
#include "scene/resources/image_texture.h"
50
#include "scene/resources/material.h"
51
#include "scene/resources/mesh.h"
52
#include "scene/resources/packed_scene.h"
53
#include "scene/resources/world_2d.h"
54
55
#ifndef _3D_DISABLED
56
#include "scene/3d/node_3d.h"
57
#include "scene/resources/3d/world_3d.h"
58
#endif // _3D_DISABLED
59
60
#ifndef PHYSICS_2D_DISABLED
61
#include "servers/physics_2d/physics_server_2d.h"
62
#endif // PHYSICS_2D_DISABLED
63
64
#ifndef PHYSICS_3D_DISABLED
65
#include "servers/physics_3d/physics_server_3d.h"
66
#endif // PHYSICS_3D_DISABLED
67
68
void 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
77
void SceneTreeTimer::set_time_left(double p_time) {
78
time_left = p_time;
79
}
80
81
double SceneTreeTimer::get_time_left() const {
82
return MAX(time_left, 0.0);
83
}
84
85
void SceneTreeTimer::set_process_always(bool p_process_always) {
86
process_always = p_process_always;
87
}
88
89
bool SceneTreeTimer::is_process_always() {
90
return process_always;
91
}
92
93
void SceneTreeTimer::set_process_in_physics(bool p_process_in_physics) {
94
process_in_physics = p_process_in_physics;
95
}
96
97
bool SceneTreeTimer::is_process_in_physics() {
98
return process_in_physics;
99
}
100
101
void SceneTreeTimer::set_ignore_time_scale(bool p_ignore) {
102
ignore_time_scale = p_ignore;
103
}
104
105
bool SceneTreeTimer::is_ignoring_time_scale() {
106
return ignore_time_scale;
107
}
108
109
void 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
118
#ifndef _3D_DISABLED
119
// This should be called once per physics tick, to make sure the transform previous and current
120
// is kept up to date on the few Node3Ds that are using client side physics interpolation.
121
void SceneTree::ClientPhysicsInterpolation::physics_process() {
122
for (SelfList<Node3D> *E = _node_3d_list.first(); E;) {
123
Node3D *node_3d = E->self();
124
125
SelfList<Node3D> *current = E;
126
127
// Get the next element here BEFORE we potentially delete one.
128
E = E->next();
129
130
// This will return false if the Node3D has timed out ..
131
// i.e. if get_global_transform_interpolated() has not been called
132
// for a few seconds, we can delete from the list to keep processing
133
// to a minimum.
134
if (!node_3d->update_client_physics_interpolation_data()) {
135
_node_3d_list.remove(current);
136
}
137
}
138
}
139
#endif // _3D_DISABLED
140
141
bool SceneTree::_physics_interpolation_enabled = false;
142
bool SceneTree::_physics_interpolation_enabled_in_project = false;
143
144
void SceneTree::tree_changed() {
145
emit_signal(tree_changed_name);
146
}
147
148
void SceneTree::node_added(Node *p_node) {
149
emit_signal(node_added_name, p_node);
150
}
151
152
void SceneTree::node_removed(Node *p_node) {
153
// Nodes can only be removed from the main thread.
154
if (current_scene == p_node) {
155
current_scene = nullptr;
156
}
157
emit_signal(node_removed_name, p_node);
158
if (nodes_removed_on_group_call_lock) {
159
nodes_removed_on_group_call.insert(p_node);
160
}
161
}
162
163
void SceneTree::node_renamed(Node *p_node) {
164
emit_signal(node_renamed_name, p_node);
165
}
166
167
SceneTree::Group *SceneTree::add_to_group(const StringName &p_group, Node *p_node) {
168
_THREAD_SAFE_METHOD_
169
170
HashMap<StringName, Group>::Iterator E = group_map.find(p_group);
171
if (!E) {
172
E = group_map.insert(p_group, Group());
173
}
174
175
ERR_FAIL_COND_V_MSG(E->value.nodes.has(p_node), &E->value, "Already in group: " + p_group + ".");
176
E->value.nodes.push_back(p_node);
177
E->value.changed = true;
178
return &E->value;
179
}
180
181
void SceneTree::remove_from_group(const StringName &p_group, Node *p_node) {
182
_THREAD_SAFE_METHOD_
183
184
HashMap<StringName, Group>::Iterator E = group_map.find(p_group);
185
ERR_FAIL_COND(!E);
186
187
E->value.nodes.erase(p_node);
188
if (E->value.nodes.is_empty()) {
189
group_map.remove(E);
190
}
191
}
192
193
void SceneTree::flush_transform_notifications() {
194
_THREAD_SAFE_METHOD_
195
196
SelfList<Node> *n = xform_change_list.first();
197
while (n) {
198
Node *node = n->self();
199
SelfList<Node> *nx = n->next();
200
xform_change_list.remove(n);
201
n = nx;
202
node->notification(NOTIFICATION_TRANSFORM_CHANGED);
203
}
204
}
205
206
bool SceneTree::is_accessibility_enabled() const {
207
if (!DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_ACCESSIBILITY_SCREEN_READER)) {
208
return false;
209
}
210
211
DisplayServer::AccessibilityMode accessibility_mode = DisplayServer::accessibility_get_mode();
212
int screen_reader_active = DisplayServer::get_singleton()->accessibility_screen_reader_active();
213
if ((accessibility_mode == DisplayServer::AccessibilityMode::ACCESSIBILITY_DISABLED) || ((accessibility_mode == DisplayServer::AccessibilityMode::ACCESSIBILITY_AUTO) && (screen_reader_active != 1))) {
214
return false;
215
}
216
return true;
217
}
218
219
bool SceneTree::is_accessibility_supported() const {
220
if (!DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_ACCESSIBILITY_SCREEN_READER)) {
221
return false;
222
}
223
224
DisplayServer::AccessibilityMode accessibility_mode = DisplayServer::accessibility_get_mode();
225
if (accessibility_mode == DisplayServer::AccessibilityMode::ACCESSIBILITY_DISABLED) {
226
return false;
227
}
228
return true;
229
}
230
231
void SceneTree::_accessibility_force_update() {
232
accessibility_force_update = true;
233
}
234
235
void SceneTree::_accessibility_notify_change(const Node *p_node, bool p_remove) {
236
if (p_node) {
237
if (p_remove) {
238
accessibility_change_queue.erase(p_node->get_instance_id());
239
} else {
240
accessibility_change_queue.insert(p_node->get_instance_id());
241
}
242
}
243
}
244
245
void SceneTree::_process_accessibility_changes(DisplayServer::WindowID p_window_id) {
246
// Process NOTIFICATION_ACCESSIBILITY_UPDATE.
247
Vector<ObjectID> processed;
248
for (const ObjectID &id : accessibility_change_queue) {
249
Node *node = Object::cast_to<Node>(ObjectDB::get_instance(id));
250
if (!node || !node->get_non_popup_window() || !node->get_window()->is_visible()) {
251
processed.push_back(id);
252
continue; // Invalid node, remove from list and skip.
253
} else if (node->get_non_popup_window()->get_window_id() != p_window_id) {
254
continue; // Another window, skip.
255
}
256
node->notification(Node::NOTIFICATION_ACCESSIBILITY_UPDATE);
257
processed.push_back(id);
258
}
259
260
// Track focus change.
261
// Note: Do not use `Window::get_focused_window()`, it returns both native and embedded windows, and we only care about focused element in the currently processed native window.
262
// Native window focus is handled in the DisplayServer, or AccessKit subclassing adapter.
263
ObjectID oid = DisplayServer::get_singleton()->window_get_attached_instance_id(p_window_id);
264
Window *w_this = (Window *)ObjectDB::get_instance(oid);
265
if (w_this) {
266
Window *w_focus = w_this->get_focused_subwindow();
267
if (w_focus && !w_focus->is_part_of_edited_scene()) {
268
w_this = w_focus;
269
}
270
271
// Popups have no native window focus, but have focused element.
272
DisplayServer::WindowID popup_id = DisplayServer::get_singleton()->window_get_active_popup();
273
if (popup_id != DisplayServer::INVALID_WINDOW_ID) {
274
Window *popup_w = Window::get_from_id(popup_id);
275
if (popup_w && w_this->is_ancestor_of(popup_w)) {
276
w_this = popup_w;
277
}
278
}
279
280
RID new_focus_element;
281
Control *n_focus = w_this->gui_get_focus_owner();
282
if (n_focus && !n_focus->is_part_of_edited_scene()) {
283
new_focus_element = n_focus->get_focused_accessibility_element();
284
} else {
285
new_focus_element = w_this->get_focused_accessibility_element();
286
}
287
288
DisplayServer::get_singleton()->accessibility_update_set_focus(new_focus_element);
289
}
290
291
// Cleanup.
292
for (const ObjectID &id : processed) {
293
accessibility_change_queue.erase(id);
294
}
295
}
296
297
void SceneTree::_flush_accessibility_changes() {
298
if (is_accessibility_enabled()) {
299
uint64_t time = OS::get_singleton()->get_ticks_msec();
300
if (!accessibility_force_update) {
301
if (time - accessibility_last_update < 1000 / accessibility_upd_per_sec) {
302
return;
303
}
304
}
305
accessibility_force_update = false;
306
accessibility_last_update = time;
307
308
// Push update to the accessibility driver.
309
DisplayServer::get_singleton()->accessibility_update_if_active(callable_mp(this, &SceneTree::_process_accessibility_changes));
310
}
311
}
312
313
void SceneTree::_flush_ugc() {
314
ugc_locked = true;
315
316
while (unique_group_calls.size()) {
317
HashMap<UGCall, Vector<Variant>, UGCall>::Iterator E = unique_group_calls.begin();
318
319
const Variant **argptrs = (const Variant **)alloca(E->value.size() * sizeof(Variant *));
320
321
for (int i = 0; i < E->value.size(); i++) {
322
argptrs[i] = &E->value[i];
323
}
324
325
call_group_flagsp(GROUP_CALL_DEFAULT, E->key.group, E->key.call, argptrs, E->value.size());
326
327
unique_group_calls.remove(E);
328
}
329
330
ugc_locked = false;
331
}
332
333
void SceneTree::_update_group_order(Group &g) {
334
if (!g.changed) {
335
return;
336
}
337
if (g.nodes.is_empty()) {
338
return;
339
}
340
341
Node **gr_nodes = g.nodes.ptrw();
342
int gr_node_count = g.nodes.size();
343
344
SortArray<Node *, Node::Comparator> node_sort;
345
node_sort.sort(gr_nodes, gr_node_count);
346
347
g.changed = false;
348
}
349
350
void SceneTree::call_group_flagsp(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, const Variant **p_args, int p_argcount) {
351
Vector<Node *> nodes_copy;
352
353
{
354
_THREAD_SAFE_METHOD_
355
356
HashMap<StringName, Group>::Iterator E = group_map.find(p_group);
357
if (!E) {
358
return;
359
}
360
Group &g = E->value;
361
if (g.nodes.is_empty()) {
362
return;
363
}
364
365
if (p_call_flags & GROUP_CALL_UNIQUE && p_call_flags & GROUP_CALL_DEFERRED) {
366
ERR_FAIL_COND(ugc_locked);
367
368
UGCall ug;
369
ug.call = p_function;
370
ug.group = p_group;
371
372
if (unique_group_calls.has(ug)) {
373
return;
374
}
375
376
Vector<Variant> args;
377
for (int i = 0; i < p_argcount; i++) {
378
args.push_back(*p_args[i]);
379
}
380
381
unique_group_calls[ug] = args;
382
return;
383
}
384
385
_update_group_order(g);
386
nodes_copy = g.nodes;
387
}
388
389
Node **gr_nodes = nodes_copy.ptrw();
390
int gr_node_count = nodes_copy.size();
391
392
{
393
_THREAD_SAFE_METHOD_
394
nodes_removed_on_group_call_lock++;
395
}
396
397
if (p_call_flags & GROUP_CALL_REVERSE) {
398
for (int i = gr_node_count - 1; i >= 0; i--) {
399
if (nodes_removed_on_group_call_lock && nodes_removed_on_group_call.has(gr_nodes[i])) {
400
continue;
401
}
402
403
Node *node = gr_nodes[i];
404
if (!(p_call_flags & GROUP_CALL_DEFERRED)) {
405
Callable::CallError ce;
406
node->callp(p_function, p_args, p_argcount, ce);
407
if (unlikely(ce.error != Callable::CallError::CALL_OK && ce.error != Callable::CallError::CALL_ERROR_INVALID_METHOD)) {
408
ERR_PRINT(vformat("Error calling group method on node \"%s\": %s.", node->get_name(), Variant::get_callable_error_text(Callable(node, p_function), p_args, p_argcount, ce)));
409
}
410
} else {
411
MessageQueue::get_singleton()->push_callp(node, p_function, p_args, p_argcount);
412
}
413
}
414
415
} else {
416
for (int i = 0; i < gr_node_count; i++) {
417
if (nodes_removed_on_group_call_lock && nodes_removed_on_group_call.has(gr_nodes[i])) {
418
continue;
419
}
420
421
Node *node = gr_nodes[i];
422
if (!(p_call_flags & GROUP_CALL_DEFERRED)) {
423
Callable::CallError ce;
424
node->callp(p_function, p_args, p_argcount, ce);
425
if (unlikely(ce.error != Callable::CallError::CALL_OK && ce.error != Callable::CallError::CALL_ERROR_INVALID_METHOD)) {
426
ERR_PRINT(vformat("Error calling group method on node \"%s\": %s.", node->get_name(), Variant::get_callable_error_text(Callable(node, p_function), p_args, p_argcount, ce)));
427
}
428
} else {
429
MessageQueue::get_singleton()->push_callp(node, p_function, p_args, p_argcount);
430
}
431
}
432
}
433
434
{
435
_THREAD_SAFE_METHOD_
436
nodes_removed_on_group_call_lock--;
437
if (nodes_removed_on_group_call_lock == 0) {
438
nodes_removed_on_group_call.clear();
439
}
440
}
441
}
442
443
void SceneTree::notify_group_flags(uint32_t p_call_flags, const StringName &p_group, int p_notification) {
444
Vector<Node *> nodes_copy;
445
{
446
_THREAD_SAFE_METHOD_
447
HashMap<StringName, Group>::Iterator E = group_map.find(p_group);
448
if (!E) {
449
return;
450
}
451
Group &g = E->value;
452
if (g.nodes.is_empty()) {
453
return;
454
}
455
456
_update_group_order(g);
457
458
nodes_copy = g.nodes;
459
}
460
461
Node **gr_nodes = nodes_copy.ptrw();
462
int gr_node_count = nodes_copy.size();
463
464
{
465
_THREAD_SAFE_METHOD_
466
nodes_removed_on_group_call_lock++;
467
}
468
469
if (p_call_flags & GROUP_CALL_REVERSE) {
470
for (int i = gr_node_count - 1; i >= 0; i--) {
471
if (nodes_removed_on_group_call.has(gr_nodes[i])) {
472
continue;
473
}
474
475
if (!(p_call_flags & GROUP_CALL_DEFERRED)) {
476
gr_nodes[i]->notification(p_notification, true);
477
} else {
478
MessageQueue::get_singleton()->push_notification(gr_nodes[i], p_notification);
479
}
480
}
481
482
} else {
483
for (int i = 0; i < gr_node_count; i++) {
484
if (nodes_removed_on_group_call.has(gr_nodes[i])) {
485
continue;
486
}
487
488
if (!(p_call_flags & GROUP_CALL_DEFERRED)) {
489
gr_nodes[i]->notification(p_notification);
490
} else {
491
MessageQueue::get_singleton()->push_notification(gr_nodes[i], p_notification);
492
}
493
}
494
}
495
496
{
497
_THREAD_SAFE_METHOD_
498
nodes_removed_on_group_call_lock--;
499
if (nodes_removed_on_group_call_lock == 0) {
500
nodes_removed_on_group_call.clear();
501
}
502
}
503
}
504
505
void SceneTree::set_group_flags(uint32_t p_call_flags, const StringName &p_group, const String &p_name, const Variant &p_value) {
506
Vector<Node *> nodes_copy;
507
{
508
_THREAD_SAFE_METHOD_
509
510
HashMap<StringName, Group>::Iterator E = group_map.find(p_group);
511
if (!E) {
512
return;
513
}
514
Group &g = E->value;
515
if (g.nodes.is_empty()) {
516
return;
517
}
518
519
_update_group_order(g);
520
521
nodes_copy = g.nodes;
522
}
523
Node **gr_nodes = nodes_copy.ptrw();
524
int gr_node_count = nodes_copy.size();
525
526
{
527
_THREAD_SAFE_METHOD_
528
nodes_removed_on_group_call_lock++;
529
}
530
531
if (p_call_flags & GROUP_CALL_REVERSE) {
532
for (int i = gr_node_count - 1; i >= 0; i--) {
533
if (nodes_removed_on_group_call.has(gr_nodes[i])) {
534
continue;
535
}
536
537
if (!(p_call_flags & GROUP_CALL_DEFERRED)) {
538
gr_nodes[i]->set(p_name, p_value);
539
} else {
540
MessageQueue::get_singleton()->push_set(gr_nodes[i], p_name, p_value);
541
}
542
}
543
544
} else {
545
for (int i = 0; i < gr_node_count; i++) {
546
if (nodes_removed_on_group_call.has(gr_nodes[i])) {
547
continue;
548
}
549
550
if (!(p_call_flags & GROUP_CALL_DEFERRED)) {
551
gr_nodes[i]->set(p_name, p_value);
552
} else {
553
MessageQueue::get_singleton()->push_set(gr_nodes[i], p_name, p_value);
554
}
555
}
556
}
557
558
{
559
_THREAD_SAFE_METHOD_
560
nodes_removed_on_group_call_lock--;
561
if (nodes_removed_on_group_call_lock == 0) {
562
nodes_removed_on_group_call.clear();
563
}
564
}
565
}
566
567
void SceneTree::notify_group(const StringName &p_group, int p_notification) {
568
notify_group_flags(GROUP_CALL_DEFAULT, p_group, p_notification);
569
}
570
571
void SceneTree::set_group(const StringName &p_group, const String &p_name, const Variant &p_value) {
572
set_group_flags(GROUP_CALL_DEFAULT, p_group, p_name, p_value);
573
}
574
575
void SceneTree::initialize() {
576
GodotProfileZone("SceneTree::initialize");
577
ERR_FAIL_NULL(root);
578
MainLoop::initialize();
579
root->_set_tree(this);
580
}
581
582
void SceneTree::set_physics_interpolation_enabled(bool p_enabled) {
583
// This version is for use in editor.
584
_physics_interpolation_enabled_in_project = p_enabled;
585
586
// We never want interpolation in the editor.
587
if (Engine::get_singleton()->is_editor_hint()) {
588
p_enabled = false;
589
}
590
591
if (p_enabled == _physics_interpolation_enabled) {
592
return;
593
}
594
595
_physics_interpolation_enabled = p_enabled;
596
RenderingServer::get_singleton()->set_physics_interpolation_enabled(p_enabled);
597
598
get_scene_tree_fti().set_enabled(get_root(), p_enabled);
599
600
// Perform an auto reset on the root node for convenience for the user.
601
if (root) {
602
root->reset_physics_interpolation();
603
}
604
}
605
606
#ifndef _3D_DISABLED
607
void SceneTree::client_physics_interpolation_add_node_3d(SelfList<Node3D> *p_elem) {
608
// This ensures that _update_physics_interpolation_data() will be called at least once every
609
// physics tick, to ensure the previous and current transforms are kept up to date.
610
_client_physics_interpolation._node_3d_list.add(p_elem);
611
}
612
613
void SceneTree::client_physics_interpolation_remove_node_3d(SelfList<Node3D> *p_elem) {
614
_client_physics_interpolation._node_3d_list.remove(p_elem);
615
}
616
#endif
617
618
void SceneTree::iteration_prepare() {
619
if (_physics_interpolation_enabled) {
620
// Make sure any pending transforms from the last tick / frame
621
// are flushed before pumping the interpolation prev and currents.
622
flush_transform_notifications();
623
get_scene_tree_fti().tick_update();
624
RenderingServer::get_singleton()->tick();
625
}
626
}
627
628
bool SceneTree::physics_process(double p_time) {
629
current_frame++;
630
631
flush_transform_notifications();
632
633
if (MainLoop::physics_process(p_time)) {
634
_quit = true;
635
}
636
physics_process_time = p_time;
637
638
emit_signal(SNAME("physics_frame"));
639
640
#if !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
641
call_group(SNAME("_picking_viewports"), SNAME("_process_picking"));
642
#endif // !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
643
644
_process(true);
645
646
_flush_ugc();
647
MessageQueue::get_singleton()->flush(); //small little hack
648
649
process_timers(p_time, true); //go through timers
650
process_tweens(p_time, true);
651
652
flush_transform_notifications();
653
654
// This should happen last because any processing that deletes something beforehand might expect the object to be removed in the same frame.
655
_flush_delete_queue();
656
657
_call_idle_callbacks();
658
659
return _quit;
660
}
661
662
void SceneTree::iteration_end() {
663
// When physics interpolation is active, we want all pending transforms
664
// to be flushed to the RenderingServer before finishing a physics tick.
665
if (_physics_interpolation_enabled) {
666
flush_transform_notifications();
667
668
#ifndef _3D_DISABLED
669
// Any objects performing client physics interpolation
670
// should be given an opportunity to keep their previous transforms
671
// up to date.
672
_client_physics_interpolation.physics_process();
673
#endif
674
}
675
}
676
677
bool SceneTree::process(double p_time) {
678
// First pass of scene tree fixed timestep interpolation.
679
if (get_scene_tree_fti().is_enabled()) {
680
// Special, we need to ensure RenderingServer is up to date
681
// with *all* the pending xforms *before* updating it during
682
// the FTI update.
683
// If this is not done, we can end up with a deferred `set_transform()`
684
// overwriting the interpolated xform in the server.
685
flush_transform_notifications();
686
get_scene_tree_fti().frame_update(get_root(), true);
687
}
688
689
if (MainLoop::process(p_time)) {
690
_quit = true;
691
}
692
693
process_time = p_time;
694
695
if (multiplayer_poll) {
696
multiplayer->poll();
697
for (KeyValue<NodePath, Ref<MultiplayerAPI>> &E : custom_multiplayers) {
698
E.value->poll();
699
}
700
}
701
702
emit_signal(SNAME("process_frame"));
703
704
MessageQueue::get_singleton()->flush(); //small little hack
705
706
flush_transform_notifications();
707
708
_process(false);
709
710
_flush_ugc();
711
MessageQueue::get_singleton()->flush(); //small little hack
712
flush_transform_notifications(); //transforms after world update, to avoid unnecessary enter/exit notifications
713
714
if (unlikely(pending_new_scene_id.is_valid())) {
715
_flush_scene_change();
716
}
717
718
process_timers(p_time, false); //go through timers
719
process_tweens(p_time, false);
720
721
flush_transform_notifications(); // Additional transforms after timers update.
722
723
// This should happen last because any processing that deletes something beforehand might expect the object to be removed in the same frame.
724
_flush_delete_queue();
725
726
_flush_accessibility_changes();
727
728
_call_idle_callbacks();
729
730
#ifdef TOOLS_ENABLED
731
#ifndef _3D_DISABLED
732
if (Engine::get_singleton()->is_editor_hint()) {
733
String env_path = GLOBAL_GET("rendering/environment/defaults/default_environment");
734
env_path = env_path.strip_edges(); // User may have added a space or two.
735
736
bool can_load = true;
737
if (env_path.begins_with("uid://")) {
738
// If an uid path, ensure it is mapped to a resource which could not be
739
// the case if the editor is still scanning the filesystem.
740
ResourceUID::ID id = ResourceUID::get_singleton()->text_to_id(env_path);
741
can_load = ResourceUID::get_singleton()->has_id(id);
742
if (can_load) {
743
env_path = ResourceUID::get_singleton()->get_id_path(id);
744
}
745
}
746
747
if (can_load) {
748
String cpath;
749
Ref<Environment> fallback = get_root()->get_world_3d()->get_fallback_environment();
750
if (fallback.is_valid()) {
751
cpath = fallback->get_path();
752
}
753
if (cpath != env_path) {
754
if (!env_path.is_empty()) {
755
fallback = ResourceLoader::load(env_path);
756
if (fallback.is_null()) {
757
//could not load fallback, set as empty
758
ProjectSettings::get_singleton()->set("rendering/environment/defaults/default_environment", "");
759
}
760
} else {
761
fallback.unref();
762
}
763
get_root()->get_world_3d()->set_fallback_environment(fallback);
764
}
765
}
766
}
767
#endif // _3D_DISABLED
768
#endif // TOOLS_ENABLED
769
770
// Second pass of scene tree fixed timestep interpolation.
771
// ToDo: Possibly needs another flush_transform_notifications here
772
// depending on whether there are side effects to _call_idle_callbacks().
773
get_scene_tree_fti().frame_update(get_root(), false);
774
775
if (_physics_interpolation_enabled) {
776
RenderingServer::get_singleton()->pre_draw(true);
777
}
778
779
return _quit;
780
}
781
782
void SceneTree::process_timers(double p_delta, bool p_physics_frame) {
783
_THREAD_SAFE_METHOD_
784
const List<Ref<SceneTreeTimer>>::Element *L = timers.back(); // Last element.
785
const double unscaled_delta = Engine::get_singleton()->get_process_step();
786
787
for (List<Ref<SceneTreeTimer>>::Element *E = timers.front(); E;) {
788
List<Ref<SceneTreeTimer>>::Element *N = E->next();
789
Ref<SceneTreeTimer> timer = E->get();
790
791
if ((paused && !timer->is_process_always()) || (timer->is_process_in_physics() != p_physics_frame)) {
792
if (E == L) {
793
break; // Break on last, so if new timers were added during list traversal, ignore them.
794
}
795
E = N;
796
continue;
797
}
798
799
double time_left = timer->get_time_left();
800
time_left -= timer->is_ignoring_time_scale() ? unscaled_delta : p_delta;
801
timer->set_time_left(time_left);
802
803
if (time_left <= 0) {
804
E->get()->emit_signal(SNAME("timeout"));
805
timers.erase(E);
806
}
807
if (E == L) {
808
break; // Break on last, so if new timers were added during list traversal, ignore them.
809
}
810
E = N;
811
}
812
}
813
814
void SceneTree::process_tweens(double p_delta, bool p_physics) {
815
_THREAD_SAFE_METHOD_
816
// This methods works similarly to how SceneTreeTimers are handled.
817
const List<Ref<Tween>>::Element *L = tweens.back();
818
const double unscaled_delta = Engine::get_singleton()->get_process_step();
819
820
for (List<Ref<Tween>>::Element *E = tweens.front(); E;) {
821
List<Ref<Tween>>::Element *N = E->next();
822
Ref<Tween> &tween = E->get();
823
824
// Don't process if paused or process mode doesn't match.
825
if (!tween->can_process(paused) || (p_physics == (tween->get_process_mode() == Tween::TWEEN_PROCESS_IDLE))) {
826
if (E == L) {
827
break;
828
}
829
E = N;
830
continue;
831
}
832
833
if (!tween->step(tween->is_ignoring_time_scale() ? unscaled_delta : p_delta)) {
834
tween->clear();
835
tweens.erase(E);
836
}
837
if (E == L) {
838
break;
839
}
840
E = N;
841
}
842
}
843
844
void SceneTree::finalize() {
845
_flush_delete_queue();
846
847
_flush_ugc();
848
849
if (root) {
850
root->_set_tree(nullptr);
851
root->_propagate_after_exit_tree();
852
memdelete(root); //delete root
853
root = nullptr;
854
855
// In case deletion of some objects was queued when destructing the `root`.
856
// E.g. if `queue_free()` was called for some node outside the tree when handling NOTIFICATION_PREDELETE for some node in the tree.
857
_flush_delete_queue();
858
}
859
860
MainLoop::finalize();
861
862
// Cleanup timers.
863
for (Ref<SceneTreeTimer> &timer : timers) {
864
timer->release_connections();
865
}
866
timers.clear();
867
868
// Cleanup tweens.
869
for (Ref<Tween> &tween : tweens) {
870
tween->clear();
871
}
872
tweens.clear();
873
}
874
875
void SceneTree::quit(int p_exit_code) {
876
_THREAD_SAFE_METHOD_
877
878
OS::get_singleton()->set_exit_code(p_exit_code);
879
_quit = true;
880
}
881
882
void SceneTree::_main_window_close() {
883
if (accept_quit) {
884
_quit = true;
885
}
886
}
887
888
void SceneTree::_main_window_go_back() {
889
if (quit_on_go_back) {
890
_quit = true;
891
}
892
}
893
894
void SceneTree::_main_window_focus_in() {
895
Input *id = Input::get_singleton();
896
if (id) {
897
id->ensure_touch_mouse_raised();
898
}
899
}
900
901
void SceneTree::_notification(int p_notification) {
902
if (!get_root()) {
903
return;
904
}
905
906
switch (p_notification) {
907
case NOTIFICATION_TRANSLATION_CHANGED: {
908
get_root()->propagate_notification(p_notification);
909
} break;
910
911
case NOTIFICATION_OS_MEMORY_WARNING:
912
case NOTIFICATION_OS_IME_UPDATE:
913
case NOTIFICATION_WM_ABOUT:
914
case NOTIFICATION_CRASH:
915
case NOTIFICATION_APPLICATION_RESUMED:
916
case NOTIFICATION_APPLICATION_PAUSED:
917
case NOTIFICATION_APPLICATION_FOCUS_IN:
918
case NOTIFICATION_APPLICATION_FOCUS_OUT: {
919
// Pass these to nodes, since they are mirrored.
920
get_root()->propagate_notification(p_notification);
921
} break;
922
}
923
}
924
925
bool SceneTree::is_auto_accept_quit() const {
926
return accept_quit;
927
}
928
929
void SceneTree::set_auto_accept_quit(bool p_enable) {
930
accept_quit = p_enable;
931
}
932
933
bool SceneTree::is_quit_on_go_back() const {
934
return quit_on_go_back;
935
}
936
937
void SceneTree::set_quit_on_go_back(bool p_enable) {
938
quit_on_go_back = p_enable;
939
}
940
941
#ifdef DEBUG_ENABLED
942
void SceneTree::set_debug_collisions_hint(bool p_enabled) {
943
debug_collisions_hint = p_enabled;
944
}
945
946
bool SceneTree::is_debugging_collisions_hint() const {
947
return debug_collisions_hint;
948
}
949
950
void SceneTree::set_debug_paths_hint(bool p_enabled) {
951
debug_paths_hint = p_enabled;
952
}
953
954
bool SceneTree::is_debugging_paths_hint() const {
955
return debug_paths_hint;
956
}
957
958
void SceneTree::set_debug_navigation_hint(bool p_enabled) {
959
debug_navigation_hint = p_enabled;
960
}
961
962
bool SceneTree::is_debugging_navigation_hint() const {
963
return debug_navigation_hint;
964
}
965
#endif
966
967
void SceneTree::set_debug_collisions_color(const Color &p_color) {
968
debug_collisions_color = p_color;
969
}
970
971
Color SceneTree::get_debug_collisions_color() const {
972
return debug_collisions_color;
973
}
974
975
void SceneTree::set_debug_collision_contact_color(const Color &p_color) {
976
debug_collision_contact_color = p_color;
977
}
978
979
Color SceneTree::get_debug_collision_contact_color() const {
980
return debug_collision_contact_color;
981
}
982
983
void SceneTree::set_debug_paths_color(const Color &p_color) {
984
debug_paths_color = p_color;
985
}
986
987
Color SceneTree::get_debug_paths_color() const {
988
return debug_paths_color;
989
}
990
991
void SceneTree::set_debug_paths_width(float p_width) {
992
debug_paths_width = p_width;
993
}
994
995
float SceneTree::get_debug_paths_width() const {
996
return debug_paths_width;
997
}
998
999
Ref<Material> SceneTree::get_debug_paths_material() {
1000
_THREAD_SAFE_METHOD_
1001
1002
if (debug_paths_material.is_valid()) {
1003
return debug_paths_material;
1004
}
1005
1006
Ref<StandardMaterial3D> _debug_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
1007
_debug_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
1008
_debug_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
1009
_debug_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
1010
_debug_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
1011
_debug_material->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true);
1012
_debug_material->set_albedo(get_debug_paths_color());
1013
1014
debug_paths_material = _debug_material;
1015
1016
return debug_paths_material;
1017
}
1018
1019
Ref<Material> SceneTree::get_debug_collision_material() {
1020
_THREAD_SAFE_METHOD_
1021
1022
if (collision_material.is_valid()) {
1023
return collision_material;
1024
}
1025
1026
Ref<StandardMaterial3D> material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
1027
material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
1028
material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
1029
material->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MIN + 1);
1030
material->set_cull_mode(StandardMaterial3D::CULL_BACK);
1031
material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
1032
material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
1033
material->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true);
1034
1035
collision_material = material;
1036
1037
return collision_material;
1038
}
1039
1040
Ref<ArrayMesh> SceneTree::get_debug_contact_mesh() {
1041
_THREAD_SAFE_METHOD_
1042
1043
if (debug_contact_mesh.is_valid()) {
1044
return debug_contact_mesh;
1045
}
1046
1047
debug_contact_mesh.instantiate();
1048
1049
Ref<StandardMaterial3D> mat = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
1050
mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
1051
mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
1052
mat->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
1053
mat->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
1054
mat->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true);
1055
mat->set_albedo(get_debug_collision_contact_color());
1056
1057
Vector3 diamond[6] = {
1058
Vector3(-1, 0, 0),
1059
Vector3(1, 0, 0),
1060
Vector3(0, -1, 0),
1061
Vector3(0, 1, 0),
1062
Vector3(0, 0, -1),
1063
Vector3(0, 0, 1)
1064
};
1065
1066
/* clang-format off */
1067
int diamond_faces[8 * 3] = {
1068
0, 2, 4,
1069
0, 3, 4,
1070
1, 2, 4,
1071
1, 3, 4,
1072
0, 2, 5,
1073
0, 3, 5,
1074
1, 2, 5,
1075
1, 3, 5,
1076
};
1077
/* clang-format on */
1078
1079
Vector<int> indices;
1080
for (int i = 0; i < 8 * 3; i++) {
1081
indices.push_back(diamond_faces[i]);
1082
}
1083
1084
Vector<Vector3> vertices;
1085
for (int i = 0; i < 6; i++) {
1086
vertices.push_back(diamond[i] * 0.1);
1087
}
1088
1089
Array arr;
1090
arr.resize(Mesh::ARRAY_MAX);
1091
arr[Mesh::ARRAY_VERTEX] = vertices;
1092
arr[Mesh::ARRAY_INDEX] = indices;
1093
1094
debug_contact_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arr);
1095
debug_contact_mesh->surface_set_material(0, mat);
1096
1097
return debug_contact_mesh;
1098
}
1099
1100
void SceneTree::set_pause(bool p_enabled) {
1101
ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Pause can only be set from the main thread.");
1102
ERR_FAIL_COND_MSG(suspended, "Pause state cannot be modified while suspended.");
1103
1104
if (p_enabled == paused) {
1105
return;
1106
}
1107
1108
paused = p_enabled;
1109
1110
#ifndef PHYSICS_3D_DISABLED
1111
PhysicsServer3D::get_singleton()->set_active(!p_enabled);
1112
#endif // PHYSICS_3D_DISABLED
1113
#ifndef PHYSICS_2D_DISABLED
1114
PhysicsServer2D::get_singleton()->set_active(!p_enabled);
1115
#endif // PHYSICS_2D_DISABLED
1116
if (get_root()) {
1117
get_root()->_propagate_pause_notification(p_enabled);
1118
}
1119
}
1120
1121
bool SceneTree::is_paused() const {
1122
return paused;
1123
}
1124
1125
void SceneTree::set_suspend(bool p_enabled) {
1126
ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Suspend can only be set from the main thread.");
1127
1128
if (p_enabled == suspended) {
1129
return;
1130
}
1131
1132
suspended = p_enabled;
1133
1134
Engine::get_singleton()->set_freeze_time_scale(p_enabled);
1135
1136
#ifndef PHYSICS_3D_DISABLED
1137
PhysicsServer3D::get_singleton()->set_active(!p_enabled && !paused);
1138
#endif // PHYSICS_3D_DISABLED
1139
#ifndef PHYSICS_2D_DISABLED
1140
PhysicsServer2D::get_singleton()->set_active(!p_enabled && !paused);
1141
#endif // PHYSICS_2D_DISABLED
1142
if (get_root()) {
1143
get_root()->_propagate_suspend_notification(p_enabled);
1144
}
1145
}
1146
1147
bool SceneTree::is_suspended() const {
1148
return suspended;
1149
}
1150
1151
void SceneTree::_process_group(ProcessGroup *p_group, bool p_physics) {
1152
// When reading this function, keep in mind that this code must work in a way where
1153
// if any node is removed, this needs to continue working.
1154
1155
p_group->call_queue.flush(); // Flush messages before processing.
1156
1157
Vector<Node *> &nodes = p_physics ? p_group->physics_nodes : p_group->nodes;
1158
if (nodes.is_empty()) {
1159
return;
1160
}
1161
1162
if (p_physics) {
1163
if (p_group->physics_node_order_dirty) {
1164
nodes.sort_custom<Node::ComparatorWithPhysicsPriority>();
1165
p_group->physics_node_order_dirty = false;
1166
}
1167
} else {
1168
if (p_group->node_order_dirty) {
1169
nodes.sort_custom<Node::ComparatorWithPriority>();
1170
p_group->node_order_dirty = false;
1171
}
1172
}
1173
1174
// Make a copy, so if nodes are added/removed from process, this does not break
1175
Vector<Node *> nodes_copy = nodes;
1176
1177
uint32_t node_count = nodes_copy.size();
1178
Node **nodes_ptr = (Node **)nodes_copy.ptr(); // Force cast, pointer will not change.
1179
1180
for (uint32_t i = 0; i < node_count; i++) {
1181
Node *n = nodes_ptr[i];
1182
if (nodes_removed_on_group_call.has(n)) {
1183
// Node may have been removed during process, skip it.
1184
// Keep in mind removals can only happen on the main thread.
1185
continue;
1186
}
1187
1188
if (!n->can_process() || !n->is_inside_tree()) {
1189
continue;
1190
}
1191
1192
if (p_physics) {
1193
if (n->is_physics_processing_internal()) {
1194
n->notification(Node::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
1195
}
1196
if (n->is_physics_processing()) {
1197
n->notification(Node::NOTIFICATION_PHYSICS_PROCESS);
1198
}
1199
} else {
1200
if (n->is_processing_internal()) {
1201
n->notification(Node::NOTIFICATION_INTERNAL_PROCESS);
1202
}
1203
if (n->is_processing()) {
1204
n->notification(Node::NOTIFICATION_PROCESS);
1205
}
1206
}
1207
}
1208
1209
p_group->call_queue.flush(); // Flush messages also after processing (for potential deferred calls).
1210
}
1211
1212
void SceneTree::_process_groups_thread(uint32_t p_index, bool p_physics) {
1213
Node::current_process_thread_group = local_process_group_cache[p_index]->owner;
1214
_process_group(local_process_group_cache[p_index], p_physics);
1215
Node::current_process_thread_group = nullptr;
1216
}
1217
1218
void SceneTree::_process(bool p_physics) {
1219
if (process_groups_dirty) {
1220
{
1221
// First, remove dirty groups.
1222
// This needs to be done when not processing to avoid problems.
1223
ProcessGroup **pg_ptr = (ProcessGroup **)process_groups.ptr(); // discard constness.
1224
uint32_t pg_count = process_groups.size();
1225
1226
for (uint32_t i = 0; i < pg_count; i++) {
1227
if (pg_ptr[i]->removed) {
1228
// Replace removed with last.
1229
pg_ptr[i] = pg_ptr[pg_count - 1];
1230
// Retry
1231
i--;
1232
pg_count--;
1233
}
1234
}
1235
if (pg_count != process_groups.size()) {
1236
process_groups.resize(pg_count);
1237
}
1238
}
1239
{
1240
// Then, re-sort groups.
1241
process_groups.sort_custom<ProcessGroupSort>();
1242
}
1243
1244
process_groups_dirty = false;
1245
}
1246
1247
// Cache the group count, because during processing new groups may be added.
1248
// They will be added at the end, hence for consistency they will be ignored by this process loop.
1249
// No group will be removed from the array during processing (this is done earlier in this function by marking the groups dirty).
1250
uint32_t group_count = process_groups.size();
1251
1252
if (group_count == 0) {
1253
return;
1254
}
1255
1256
process_last_pass++; // Increment pass
1257
uint32_t from = 0;
1258
uint32_t process_count = 0;
1259
nodes_removed_on_group_call_lock++;
1260
1261
int current_order = process_groups[0]->owner ? process_groups[0]->owner->data.process_thread_group_order : 0;
1262
bool current_threaded = process_groups[0]->owner ? process_groups[0]->owner->data.process_thread_group == Node::PROCESS_THREAD_GROUP_SUB_THREAD : false;
1263
1264
for (uint32_t i = 0; i <= group_count; i++) {
1265
int order = i < group_count && process_groups[i]->owner ? process_groups[i]->owner->data.process_thread_group_order : 0;
1266
bool threaded = i < group_count && process_groups[i]->owner ? process_groups[i]->owner->data.process_thread_group == Node::PROCESS_THREAD_GROUP_SUB_THREAD : false;
1267
1268
if (i == group_count || current_order != order || current_threaded != threaded) {
1269
if (process_count > 0) {
1270
// Proceed to process the group.
1271
bool using_threads = process_groups[from]->owner && process_groups[from]->owner->data.process_thread_group == Node::PROCESS_THREAD_GROUP_SUB_THREAD && !node_threading_disabled;
1272
1273
if (using_threads) {
1274
local_process_group_cache.clear();
1275
}
1276
for (uint32_t j = from; j < i; j++) {
1277
if (process_groups[j]->last_pass == process_last_pass) {
1278
if (using_threads) {
1279
local_process_group_cache.push_back(process_groups[j]);
1280
} else {
1281
_process_group(process_groups[j], p_physics);
1282
}
1283
}
1284
}
1285
1286
if (using_threads) {
1287
WorkerThreadPool::GroupID id = WorkerThreadPool::get_singleton()->add_template_group_task(this, &SceneTree::_process_groups_thread, p_physics, local_process_group_cache.size(), -1, true);
1288
WorkerThreadPool::get_singleton()->wait_for_group_task_completion(id);
1289
}
1290
}
1291
1292
if (i == group_count) {
1293
// This one is invalid, no longer process
1294
break;
1295
}
1296
1297
from = i;
1298
current_threaded = threaded;
1299
current_order = order;
1300
}
1301
1302
if (process_groups[i]->removed) {
1303
continue;
1304
}
1305
1306
ProcessGroup *pg = process_groups[i];
1307
1308
// Validate group for processing
1309
bool process_valid = false;
1310
if (p_physics) {
1311
if (!pg->physics_nodes.is_empty()) {
1312
process_valid = true;
1313
} 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()) {
1314
process_valid = true;
1315
}
1316
} else {
1317
if (!pg->nodes.is_empty()) {
1318
process_valid = true;
1319
} 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()) {
1320
process_valid = true;
1321
}
1322
}
1323
1324
if (process_valid) {
1325
pg->last_pass = process_last_pass; // Enable for processing
1326
process_count++;
1327
}
1328
}
1329
1330
nodes_removed_on_group_call_lock--;
1331
if (nodes_removed_on_group_call_lock == 0) {
1332
nodes_removed_on_group_call.clear();
1333
}
1334
}
1335
1336
bool SceneTree::ProcessGroupSort::operator()(const ProcessGroup *p_left, const ProcessGroup *p_right) const {
1337
int left_order = p_left->owner ? p_left->owner->data.process_thread_group_order : 0;
1338
int right_order = p_right->owner ? p_right->owner->data.process_thread_group_order : 0;
1339
1340
if (left_order == right_order) {
1341
int left_threaded = p_left->owner != nullptr && p_left->owner->data.process_thread_group == Node::PROCESS_THREAD_GROUP_SUB_THREAD ? 0 : 1;
1342
int right_threaded = p_right->owner != nullptr && p_right->owner->data.process_thread_group == Node::PROCESS_THREAD_GROUP_SUB_THREAD ? 0 : 1;
1343
return left_threaded < right_threaded;
1344
} else {
1345
return left_order < right_order;
1346
}
1347
}
1348
1349
void SceneTree::_remove_process_group(Node *p_node) {
1350
_THREAD_SAFE_METHOD_
1351
ProcessGroup *pg = (ProcessGroup *)p_node->data.process_group;
1352
ERR_FAIL_NULL(pg);
1353
ERR_FAIL_COND(pg->removed);
1354
pg->removed = true;
1355
pg->owner = nullptr;
1356
p_node->data.process_group = nullptr;
1357
process_groups_dirty = true;
1358
}
1359
1360
void SceneTree::_add_process_group(Node *p_node) {
1361
_THREAD_SAFE_METHOD_
1362
ERR_FAIL_NULL(p_node);
1363
1364
ProcessGroup *pg = memnew(ProcessGroup);
1365
1366
pg->owner = p_node;
1367
p_node->data.process_group = pg;
1368
1369
process_groups.push_back(pg);
1370
1371
process_groups_dirty = true;
1372
}
1373
1374
void SceneTree::_remove_node_from_process_group(Node *p_node, Node *p_owner) {
1375
_THREAD_SAFE_METHOD_
1376
ProcessGroup *pg = p_owner ? (ProcessGroup *)p_owner->data.process_group : &default_process_group;
1377
1378
if (p_node->is_processing() || p_node->is_processing_internal()) {
1379
bool found = pg->nodes.erase(p_node);
1380
ERR_FAIL_COND(!found);
1381
}
1382
1383
if (p_node->is_physics_processing() || p_node->is_physics_processing_internal()) {
1384
bool found = pg->physics_nodes.erase(p_node);
1385
ERR_FAIL_COND(!found);
1386
}
1387
}
1388
1389
void SceneTree::_add_node_to_process_group(Node *p_node, Node *p_owner) {
1390
_THREAD_SAFE_METHOD_
1391
ProcessGroup *pg = p_owner ? (ProcessGroup *)p_owner->data.process_group : &default_process_group;
1392
1393
if (p_node->is_processing() || p_node->is_processing_internal()) {
1394
pg->nodes.push_back(p_node);
1395
pg->node_order_dirty = true;
1396
}
1397
1398
if (p_node->is_physics_processing() || p_node->is_physics_processing_internal()) {
1399
pg->physics_nodes.push_back(p_node);
1400
pg->physics_node_order_dirty = true;
1401
}
1402
}
1403
1404
void SceneTree::_call_input_pause(const StringName &p_group, CallInputType p_call_type, const Ref<InputEvent> &p_input, Viewport *p_viewport) {
1405
Vector<Node *> nodes_copy;
1406
{
1407
_THREAD_SAFE_METHOD_
1408
1409
HashMap<StringName, Group>::Iterator E = group_map.find(p_group);
1410
if (!E) {
1411
return;
1412
}
1413
Group &g = E->value;
1414
if (g.nodes.is_empty()) {
1415
return;
1416
}
1417
1418
_update_group_order(g);
1419
1420
//copy, so copy on write happens in case something is removed from process while being called
1421
//performance is not lost because only if something is added/removed the vector is copied.
1422
nodes_copy = g.nodes;
1423
}
1424
1425
int gr_node_count = nodes_copy.size();
1426
Node **gr_nodes = nodes_copy.ptrw();
1427
1428
{
1429
_THREAD_SAFE_METHOD_
1430
nodes_removed_on_group_call_lock++;
1431
}
1432
1433
Vector<ObjectID> no_context_node_ids; // Nodes may be deleted due to this shortcut input.
1434
1435
for (int i = gr_node_count - 1; i >= 0; i--) {
1436
if (p_viewport->is_input_handled()) {
1437
break;
1438
}
1439
1440
Node *n = gr_nodes[i];
1441
if (nodes_removed_on_group_call.has(n)) {
1442
continue;
1443
}
1444
1445
if (!n->can_process()) {
1446
continue;
1447
}
1448
1449
switch (p_call_type) {
1450
case CALL_INPUT_TYPE_INPUT:
1451
n->_call_input(p_input);
1452
break;
1453
case CALL_INPUT_TYPE_SHORTCUT_INPUT: {
1454
const Control *c = Object::cast_to<Control>(n);
1455
if (c) {
1456
// If calling shortcut input on a control, ensure it respects the shortcut context.
1457
// Shortcut context (based on focus) only makes sense for controls (UI), so don't need to worry about it for nodes
1458
if (c->get_shortcut_context() == nullptr) {
1459
no_context_node_ids.append(n->get_instance_id());
1460
continue;
1461
}
1462
if (!c->is_focus_owner_in_shortcut_context()) {
1463
continue;
1464
}
1465
}
1466
n->_call_shortcut_input(p_input);
1467
break;
1468
}
1469
case CALL_INPUT_TYPE_UNHANDLED_INPUT:
1470
n->_call_unhandled_input(p_input);
1471
break;
1472
case CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT:
1473
n->_call_unhandled_key_input(p_input);
1474
break;
1475
}
1476
}
1477
1478
for (const ObjectID &id : no_context_node_ids) {
1479
if (p_viewport->is_input_handled()) {
1480
break;
1481
}
1482
Node *n = ObjectDB::get_instance<Node>(id);
1483
if (n) {
1484
n->_call_shortcut_input(p_input);
1485
}
1486
}
1487
1488
{
1489
_THREAD_SAFE_METHOD_
1490
nodes_removed_on_group_call_lock--;
1491
if (nodes_removed_on_group_call_lock == 0) {
1492
nodes_removed_on_group_call.clear();
1493
}
1494
}
1495
}
1496
1497
void SceneTree::_call_group_flags(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
1498
r_error.error = Callable::CallError::CALL_OK;
1499
1500
ERR_FAIL_COND(p_argcount < 3);
1501
ERR_FAIL_COND(!p_args[0]->is_num());
1502
ERR_FAIL_COND(!p_args[1]->is_string());
1503
ERR_FAIL_COND(!p_args[2]->is_string());
1504
1505
int flags = *p_args[0];
1506
StringName group = *p_args[1];
1507
StringName method = *p_args[2];
1508
1509
call_group_flagsp(flags, group, method, p_args + 3, p_argcount - 3);
1510
}
1511
1512
void SceneTree::_call_group(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
1513
r_error.error = Callable::CallError::CALL_OK;
1514
1515
ERR_FAIL_COND(p_argcount < 2);
1516
ERR_FAIL_COND(!p_args[0]->is_string());
1517
ERR_FAIL_COND(!p_args[1]->is_string());
1518
1519
StringName group = *p_args[0];
1520
StringName method = *p_args[1];
1521
1522
call_group_flagsp(GROUP_CALL_DEFAULT, group, method, p_args + 2, p_argcount - 2);
1523
}
1524
1525
int64_t SceneTree::get_frame() const {
1526
return current_frame;
1527
}
1528
1529
TypedArray<Node> SceneTree::_get_nodes_in_group(const StringName &p_group) {
1530
_THREAD_SAFE_METHOD_
1531
TypedArray<Node> ret;
1532
HashMap<StringName, Group>::Iterator E = group_map.find(p_group);
1533
if (!E) {
1534
return ret;
1535
}
1536
1537
_update_group_order(E->value); //update order just in case
1538
int nc = E->value.nodes.size();
1539
if (nc == 0) {
1540
return ret;
1541
}
1542
1543
ret.resize(nc);
1544
1545
Node **ptr = E->value.nodes.ptrw();
1546
for (int i = 0; i < nc; i++) {
1547
ret[i] = ptr[i];
1548
}
1549
1550
return ret;
1551
}
1552
1553
bool SceneTree::has_group(const StringName &p_identifier) const {
1554
_THREAD_SAFE_METHOD_
1555
return group_map.has(p_identifier);
1556
}
1557
1558
int SceneTree::get_node_count_in_group(const StringName &p_group) const {
1559
_THREAD_SAFE_METHOD_
1560
HashMap<StringName, Group>::ConstIterator E = group_map.find(p_group);
1561
if (!E) {
1562
return 0;
1563
}
1564
1565
return E->value.nodes.size();
1566
}
1567
1568
Node *SceneTree::get_first_node_in_group(const StringName &p_group) {
1569
_THREAD_SAFE_METHOD_
1570
HashMap<StringName, Group>::Iterator E = group_map.find(p_group);
1571
if (!E) {
1572
return nullptr; // No group.
1573
}
1574
1575
_update_group_order(E->value); // Update order just in case.
1576
1577
if (E->value.nodes.is_empty()) {
1578
return nullptr;
1579
}
1580
1581
return E->value.nodes[0];
1582
}
1583
1584
Vector<Node *> SceneTree::get_nodes_in_group(const StringName &p_group) {
1585
_THREAD_SAFE_METHOD_
1586
HashMap<StringName, Group>::Iterator E = group_map.find(p_group);
1587
if (!E) {
1588
return {};
1589
}
1590
1591
_update_group_order(E->value); //update order just in case
1592
int nc = E->value.nodes.size();
1593
if (nc == 0) {
1594
return {};
1595
}
1596
1597
return E->value.nodes;
1598
}
1599
1600
void SceneTree::_flush_delete_queue() {
1601
_THREAD_SAFE_METHOD_
1602
1603
while (delete_queue.size()) {
1604
Object *obj = ObjectDB::get_instance(delete_queue.front()->get());
1605
if (obj) {
1606
memdelete(obj);
1607
}
1608
delete_queue.pop_front();
1609
}
1610
}
1611
1612
void SceneTree::queue_delete(RequiredParam<Object> rp_object) {
1613
_THREAD_SAFE_METHOD_
1614
EXTRACT_PARAM_OR_FAIL(p_object, rp_object);
1615
p_object->_is_queued_for_deletion = true;
1616
delete_queue.push_back(p_object->get_instance_id());
1617
}
1618
1619
int SceneTree::get_node_count() const {
1620
return nodes_in_tree_count;
1621
}
1622
1623
void SceneTree::set_edited_scene_root(Node *p_node) {
1624
#ifdef TOOLS_ENABLED
1625
edited_scene_root = p_node;
1626
#endif
1627
}
1628
1629
Node *SceneTree::get_edited_scene_root() const {
1630
#ifdef TOOLS_ENABLED
1631
return edited_scene_root;
1632
#else
1633
return nullptr;
1634
#endif
1635
}
1636
1637
void SceneTree::set_current_scene(Node *p_scene) {
1638
ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Changing scene can only be done from the main thread.");
1639
ERR_FAIL_COND(p_scene && p_scene->get_parent() != root);
1640
current_scene = p_scene;
1641
}
1642
1643
Node *SceneTree::get_current_scene() const {
1644
return current_scene;
1645
}
1646
1647
void SceneTree::_flush_scene_change() {
1648
if (prev_scene_id.is_valid()) {
1649
// Might have already been freed externally.
1650
Node *prev_scene = ObjectDB::get_instance<Node>(prev_scene_id);
1651
if (prev_scene) {
1652
memdelete(prev_scene);
1653
}
1654
prev_scene_id = ObjectID();
1655
}
1656
1657
DEV_ASSERT(pending_new_scene_id.is_valid());
1658
Node *pending_new_scene = ObjectDB::get_instance<Node>(pending_new_scene_id);
1659
if (pending_new_scene) {
1660
// Ensure correct state before `add_child` (might enqueue subsequent scene change).
1661
current_scene = pending_new_scene;
1662
pending_new_scene_id = ObjectID();
1663
1664
root->add_child(pending_new_scene);
1665
// Update display for cursor instantly.
1666
root->update_mouse_cursor_state();
1667
1668
// Only on successful scene change.
1669
emit_signal(SNAME("scene_changed"));
1670
} else {
1671
current_scene = nullptr;
1672
pending_new_scene_id = ObjectID();
1673
ERR_PRINT("Scene instance has been freed before becoming the current scene. No current scene is set.");
1674
}
1675
}
1676
1677
Error SceneTree::change_scene_to_file(const String &p_path) {
1678
ERR_FAIL_COND_V_MSG(!Thread::is_main_thread(), ERR_INVALID_PARAMETER, "Changing scene can only be done from the main thread.");
1679
Ref<PackedScene> new_scene = ResourceLoader::load(p_path);
1680
if (new_scene.is_null()) {
1681
return ERR_CANT_OPEN;
1682
}
1683
1684
return change_scene_to_packed(new_scene);
1685
}
1686
1687
Error SceneTree::change_scene_to_packed(RequiredParam<PackedScene> rp_scene) {
1688
EXTRACT_PARAM_OR_FAIL_V_MSG(p_scene, rp_scene, ERR_INVALID_PARAMETER, "Can't change to a null scene. Use unload_current_scene() if you wish to unload it.");
1689
1690
Node *new_scene = p_scene->instantiate();
1691
ERR_FAIL_NULL_V(new_scene, ERR_CANT_CREATE);
1692
1693
return change_scene_to_node(new_scene);
1694
}
1695
1696
Error SceneTree::change_scene_to_node(RequiredParam<Node> rp_node) {
1697
EXTRACT_PARAM_OR_FAIL_V_MSG(p_node, rp_node, ERR_INVALID_PARAMETER, "Can't change to a null node. Use unload_current_scene() if you wish to unload it.");
1698
ERR_FAIL_COND_V_MSG(p_node->is_inside_tree(), ERR_UNCONFIGURED, "The new scene node can't already be inside scene tree.");
1699
1700
// If called again while a change is pending.
1701
if (pending_new_scene_id.is_valid()) {
1702
Node *pending_new_scene = ObjectDB::get_instance<Node>(pending_new_scene_id);
1703
if (pending_new_scene) {
1704
queue_delete(pending_new_scene);
1705
}
1706
pending_new_scene_id = ObjectID();
1707
}
1708
1709
if (current_scene) {
1710
prev_scene_id = current_scene->get_instance_id();
1711
// Let as many side effects as possible happen or be queued now,
1712
// so they are run before the scene is actually deleted.
1713
root->remove_child(current_scene);
1714
}
1715
DEV_ASSERT(!current_scene);
1716
1717
pending_new_scene_id = p_node->get_instance_id();
1718
return OK;
1719
}
1720
1721
Error SceneTree::reload_current_scene() {
1722
ERR_FAIL_COND_V_MSG(!Thread::is_main_thread(), ERR_INVALID_PARAMETER, "Reloading scene can only be done from the main thread.");
1723
ERR_FAIL_NULL_V(current_scene, ERR_UNCONFIGURED);
1724
String fname = current_scene->get_scene_file_path();
1725
return change_scene_to_file(fname);
1726
}
1727
1728
void SceneTree::unload_current_scene() {
1729
ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Unloading the current scene can only be done from the main thread.");
1730
if (current_scene) {
1731
memdelete(current_scene);
1732
current_scene = nullptr;
1733
}
1734
}
1735
1736
void SceneTree::add_current_scene(Node *p_current) {
1737
ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Adding a current scene can only be done from the main thread.");
1738
current_scene = p_current;
1739
root->add_child(p_current);
1740
}
1741
1742
RequiredResult<SceneTreeTimer> SceneTree::create_timer(double p_delay_sec, bool p_process_always, bool p_process_in_physics, bool p_ignore_time_scale) {
1743
_THREAD_SAFE_METHOD_
1744
Ref<SceneTreeTimer> stt;
1745
stt.instantiate();
1746
stt->set_process_always(p_process_always);
1747
stt->set_time_left(p_delay_sec);
1748
stt->set_process_in_physics(p_process_in_physics);
1749
stt->set_ignore_time_scale(p_ignore_time_scale);
1750
timers.push_back(stt);
1751
return stt;
1752
}
1753
1754
RequiredResult<Tween> SceneTree::create_tween() {
1755
_THREAD_SAFE_METHOD_
1756
Ref<Tween> tween;
1757
tween.instantiate(this);
1758
tweens.push_back(tween);
1759
return tween;
1760
}
1761
1762
void SceneTree::remove_tween(const Ref<Tween> &p_tween) {
1763
_THREAD_SAFE_METHOD_
1764
for (List<Ref<Tween>>::Element *E = tweens.back(); E; E = E->prev()) {
1765
if (E->get() == p_tween) {
1766
E->erase();
1767
break;
1768
}
1769
}
1770
}
1771
1772
TypedArray<Tween> SceneTree::get_processed_tweens() {
1773
_THREAD_SAFE_METHOD_
1774
TypedArray<Tween> ret;
1775
ret.resize(tweens.size());
1776
1777
int i = 0;
1778
for (const Ref<Tween> &tween : tweens) {
1779
ret[i] = tween;
1780
i++;
1781
}
1782
1783
return ret;
1784
}
1785
1786
Ref<MultiplayerAPI> SceneTree::get_multiplayer(const NodePath &p_for_path) const {
1787
ERR_FAIL_COND_V_MSG(!Thread::is_main_thread(), Ref<MultiplayerAPI>(), "Multiplayer can only be manipulated from the main thread.");
1788
if (p_for_path.is_empty()) {
1789
return multiplayer;
1790
}
1791
1792
const Vector<StringName> tnames = p_for_path.get_names();
1793
const StringName *nptr = tnames.ptr();
1794
for (const KeyValue<NodePath, Ref<MultiplayerAPI>> &E : custom_multiplayers) {
1795
const Vector<StringName> snames = E.key.get_names();
1796
if (tnames.size() < snames.size()) {
1797
continue;
1798
}
1799
const StringName *sptr = snames.ptr();
1800
bool valid = true;
1801
for (int i = 0; i < snames.size(); i++) {
1802
if (sptr[i] != nptr[i]) {
1803
valid = false;
1804
break;
1805
}
1806
}
1807
if (valid) {
1808
return E.value;
1809
}
1810
}
1811
1812
return multiplayer;
1813
}
1814
1815
void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer, const NodePath &p_root_path) {
1816
ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Multiplayer can only be manipulated from the main thread.");
1817
if (p_root_path.is_empty()) {
1818
ERR_FAIL_COND(p_multiplayer.is_null());
1819
if (multiplayer.is_valid()) {
1820
multiplayer->object_configuration_remove(nullptr, NodePath("/" + root->get_name()));
1821
}
1822
multiplayer = p_multiplayer;
1823
multiplayer->object_configuration_add(nullptr, NodePath("/" + root->get_name()));
1824
} else {
1825
if (custom_multiplayers.has(p_root_path)) {
1826
custom_multiplayers[p_root_path]->object_configuration_remove(nullptr, p_root_path);
1827
} else if (p_multiplayer.is_valid()) {
1828
const Vector<StringName> tnames = p_root_path.get_names();
1829
const StringName *nptr = tnames.ptr();
1830
for (const KeyValue<NodePath, Ref<MultiplayerAPI>> &E : custom_multiplayers) {
1831
const Vector<StringName> snames = E.key.get_names();
1832
if (tnames.size() < snames.size()) {
1833
continue;
1834
}
1835
const StringName *sptr = snames.ptr();
1836
bool valid = true;
1837
for (int i = 0; i < snames.size(); i++) {
1838
if (sptr[i] != nptr[i]) {
1839
valid = false;
1840
break;
1841
}
1842
}
1843
ERR_FAIL_COND_MSG(valid, "Multiplayer is already configured for a parent of this path: '" + String(p_root_path) + "' in '" + String(E.key) + "'.");
1844
}
1845
}
1846
if (p_multiplayer.is_valid()) {
1847
custom_multiplayers[p_root_path] = p_multiplayer;
1848
p_multiplayer->object_configuration_add(nullptr, p_root_path);
1849
} else {
1850
custom_multiplayers.erase(p_root_path);
1851
}
1852
}
1853
}
1854
1855
void SceneTree::set_multiplayer_poll_enabled(bool p_enabled) {
1856
ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Multiplayer can only be manipulated from the main thread.");
1857
multiplayer_poll = p_enabled;
1858
}
1859
1860
bool SceneTree::is_multiplayer_poll_enabled() const {
1861
return multiplayer_poll;
1862
}
1863
1864
void SceneTree::_bind_methods() {
1865
ClassDB::bind_method(D_METHOD("get_root"), &SceneTree::get_root);
1866
ClassDB::bind_method(D_METHOD("has_group", "name"), &SceneTree::has_group);
1867
1868
ClassDB::bind_method(D_METHOD("is_accessibility_enabled"), &SceneTree::is_accessibility_enabled);
1869
ClassDB::bind_method(D_METHOD("is_accessibility_supported"), &SceneTree::is_accessibility_supported);
1870
1871
ClassDB::bind_method(D_METHOD("is_auto_accept_quit"), &SceneTree::is_auto_accept_quit);
1872
ClassDB::bind_method(D_METHOD("set_auto_accept_quit", "enabled"), &SceneTree::set_auto_accept_quit);
1873
ClassDB::bind_method(D_METHOD("is_quit_on_go_back"), &SceneTree::is_quit_on_go_back);
1874
ClassDB::bind_method(D_METHOD("set_quit_on_go_back", "enabled"), &SceneTree::set_quit_on_go_back);
1875
1876
ClassDB::bind_method(D_METHOD("set_debug_collisions_hint", "enable"), &SceneTree::set_debug_collisions_hint);
1877
ClassDB::bind_method(D_METHOD("is_debugging_collisions_hint"), &SceneTree::is_debugging_collisions_hint);
1878
ClassDB::bind_method(D_METHOD("set_debug_paths_hint", "enable"), &SceneTree::set_debug_paths_hint);
1879
ClassDB::bind_method(D_METHOD("is_debugging_paths_hint"), &SceneTree::is_debugging_paths_hint);
1880
ClassDB::bind_method(D_METHOD("set_debug_navigation_hint", "enable"), &SceneTree::set_debug_navigation_hint);
1881
ClassDB::bind_method(D_METHOD("is_debugging_navigation_hint"), &SceneTree::is_debugging_navigation_hint);
1882
1883
ClassDB::bind_method(D_METHOD("set_edited_scene_root", "scene"), &SceneTree::set_edited_scene_root);
1884
ClassDB::bind_method(D_METHOD("get_edited_scene_root"), &SceneTree::get_edited_scene_root);
1885
1886
ClassDB::bind_method(D_METHOD("set_pause", "enable"), &SceneTree::set_pause);
1887
ClassDB::bind_method(D_METHOD("is_paused"), &SceneTree::is_paused);
1888
1889
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));
1890
ClassDB::bind_method(D_METHOD("create_tween"), &SceneTree::create_tween);
1891
ClassDB::bind_method(D_METHOD("get_processed_tweens"), &SceneTree::get_processed_tweens);
1892
1893
ClassDB::bind_method(D_METHOD("get_node_count"), &SceneTree::get_node_count);
1894
ClassDB::bind_method(D_METHOD("get_frame"), &SceneTree::get_frame);
1895
ClassDB::bind_method(D_METHOD("quit", "exit_code"), &SceneTree::quit, DEFVAL(EXIT_SUCCESS));
1896
1897
ClassDB::bind_method(D_METHOD("set_physics_interpolation_enabled", "enabled"), &SceneTree::set_physics_interpolation_enabled);
1898
ClassDB::bind_method(D_METHOD("is_physics_interpolation_enabled"), &SceneTree::is_physics_interpolation_enabled);
1899
1900
ClassDB::bind_method(D_METHOD("queue_delete", "obj"), &SceneTree::queue_delete);
1901
1902
MethodInfo mi;
1903
mi.name = "call_group_flags";
1904
mi.arguments.push_back(PropertyInfo(Variant::INT, "flags"));
1905
mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "group"));
1906
mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "method"));
1907
1908
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_group_flags", &SceneTree::_call_group_flags, mi);
1909
1910
ClassDB::bind_method(D_METHOD("notify_group_flags", "call_flags", "group", "notification"), &SceneTree::notify_group_flags);
1911
ClassDB::bind_method(D_METHOD("set_group_flags", "call_flags", "group", "property", "value"), &SceneTree::set_group_flags);
1912
1913
MethodInfo mi2;
1914
mi2.name = "call_group";
1915
mi2.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "group"));
1916
mi2.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "method"));
1917
1918
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_group", &SceneTree::_call_group, mi2);
1919
1920
ClassDB::bind_method(D_METHOD("notify_group", "group", "notification"), &SceneTree::notify_group);
1921
ClassDB::bind_method(D_METHOD("set_group", "group", "property", "value"), &SceneTree::set_group);
1922
1923
ClassDB::bind_method(D_METHOD("get_nodes_in_group", "group"), &SceneTree::_get_nodes_in_group);
1924
ClassDB::bind_method(D_METHOD("get_first_node_in_group", "group"), &SceneTree::get_first_node_in_group);
1925
ClassDB::bind_method(D_METHOD("get_node_count_in_group", "group"), &SceneTree::get_node_count_in_group);
1926
1927
ClassDB::bind_method(D_METHOD("set_current_scene", "child_node"), &SceneTree::set_current_scene);
1928
ClassDB::bind_method(D_METHOD("get_current_scene"), &SceneTree::get_current_scene);
1929
1930
ClassDB::bind_method(D_METHOD("change_scene_to_file", "path"), &SceneTree::change_scene_to_file);
1931
ClassDB::bind_method(D_METHOD("change_scene_to_packed", "packed_scene"), &SceneTree::change_scene_to_packed);
1932
ClassDB::bind_method(D_METHOD("change_scene_to_node", "node"), &SceneTree::change_scene_to_node);
1933
1934
ClassDB::bind_method(D_METHOD("reload_current_scene"), &SceneTree::reload_current_scene);
1935
ClassDB::bind_method(D_METHOD("unload_current_scene"), &SceneTree::unload_current_scene);
1936
1937
ClassDB::bind_method(D_METHOD("set_multiplayer", "multiplayer", "root_path"), &SceneTree::set_multiplayer, DEFVAL(NodePath()));
1938
ClassDB::bind_method(D_METHOD("get_multiplayer", "for_path"), &SceneTree::get_multiplayer, DEFVAL(NodePath()));
1939
ClassDB::bind_method(D_METHOD("set_multiplayer_poll_enabled", "enabled"), &SceneTree::set_multiplayer_poll_enabled);
1940
ClassDB::bind_method(D_METHOD("is_multiplayer_poll_enabled"), &SceneTree::is_multiplayer_poll_enabled);
1941
1942
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_accept_quit"), "set_auto_accept_quit", "is_auto_accept_quit");
1943
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "quit_on_go_back"), "set_quit_on_go_back", "is_quit_on_go_back");
1944
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_collisions_hint"), "set_debug_collisions_hint", "is_debugging_collisions_hint");
1945
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_paths_hint"), "set_debug_paths_hint", "is_debugging_paths_hint");
1946
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_navigation_hint"), "set_debug_navigation_hint", "is_debugging_navigation_hint");
1947
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused"), "set_pause", "is_paused");
1948
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "edited_scene_root", PROPERTY_HINT_RESOURCE_TYPE, Node::get_class_static(), PROPERTY_USAGE_NONE), "set_edited_scene_root", "get_edited_scene_root");
1949
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "current_scene", PROPERTY_HINT_RESOURCE_TYPE, Node::get_class_static(), PROPERTY_USAGE_NONE), "set_current_scene", "get_current_scene");
1950
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root", PROPERTY_HINT_RESOURCE_TYPE, Node::get_class_static(), PROPERTY_USAGE_NONE), "", "get_root");
1951
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multiplayer_poll"), "set_multiplayer_poll_enabled", "is_multiplayer_poll_enabled");
1952
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "physics_interpolation"), "set_physics_interpolation_enabled", "is_physics_interpolation_enabled");
1953
1954
ADD_SIGNAL(MethodInfo("tree_changed"));
1955
ADD_SIGNAL(MethodInfo("scene_changed"));
1956
ADD_SIGNAL(MethodInfo("tree_process_mode_changed")); //editor only signal, but due to API hash it can't be removed in run-time
1957
ADD_SIGNAL(MethodInfo("node_added", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, Node::get_class_static())));
1958
ADD_SIGNAL(MethodInfo("node_removed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, Node::get_class_static())));
1959
ADD_SIGNAL(MethodInfo("node_renamed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, Node::get_class_static())));
1960
ADD_SIGNAL(MethodInfo("node_configuration_warning_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, Node::get_class_static())));
1961
1962
ADD_SIGNAL(MethodInfo("process_frame"));
1963
ADD_SIGNAL(MethodInfo("physics_frame"));
1964
1965
BIND_ENUM_CONSTANT(GROUP_CALL_DEFAULT);
1966
BIND_ENUM_CONSTANT(GROUP_CALL_REVERSE);
1967
BIND_ENUM_CONSTANT(GROUP_CALL_DEFERRED);
1968
BIND_ENUM_CONSTANT(GROUP_CALL_UNIQUE);
1969
}
1970
1971
SceneTree *SceneTree::singleton = nullptr;
1972
1973
SceneTree::IdleCallback SceneTree::idle_callbacks[SceneTree::MAX_IDLE_CALLBACKS];
1974
int SceneTree::idle_callback_count = 0;
1975
1976
void SceneTree::_call_idle_callbacks() {
1977
for (int i = 0; i < idle_callback_count; i++) {
1978
idle_callbacks[i]();
1979
}
1980
}
1981
1982
void SceneTree::add_idle_callback(IdleCallback p_callback) {
1983
ERR_FAIL_COND(idle_callback_count >= MAX_IDLE_CALLBACKS);
1984
idle_callbacks[idle_callback_count++] = p_callback;
1985
}
1986
1987
#ifdef TOOLS_ENABLED
1988
void SceneTree::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
1989
bool add_options = false;
1990
if (p_idx == 0) {
1991
static const Vector<StringName> names = {
1992
StringName("add_to_group", true),
1993
StringName("call_group", true),
1994
StringName("get_first_node_in_group", true),
1995
StringName("get_node_count_in_group", true),
1996
StringName("get_nodes_in_group", true),
1997
StringName("has_group", true),
1998
StringName("notify_group", true),
1999
StringName("set_group", true),
2000
};
2001
add_options = names.has(p_function);
2002
} else if (p_idx == 1) {
2003
static const Vector<StringName> names = {
2004
StringName("call_group_flags", true),
2005
StringName("notify_group_flags", true),
2006
StringName("set_group_flags", true),
2007
};
2008
add_options = names.has(p_function);
2009
}
2010
if (add_options) {
2011
HashMap<StringName, String> global_groups(ProjectSettings::get_singleton()->get_global_groups_list());
2012
for (const KeyValue<StringName, String> &E : global_groups) {
2013
r_options->push_back(E.key.operator String().quote());
2014
}
2015
}
2016
MainLoop::get_argument_options(p_function, p_idx, r_options);
2017
}
2018
#endif
2019
2020
void SceneTree::set_disable_node_threading(bool p_disable) {
2021
node_threading_disabled = p_disable;
2022
}
2023
2024
SceneTree::SceneTree() {
2025
if (singleton == nullptr) {
2026
singleton = this;
2027
}
2028
debug_collisions_color = GLOBAL_DEF("debug/shapes/collision/shape_color", Color(0.0, 0.6, 0.7, 0.42));
2029
debug_collision_contact_color = GLOBAL_DEF("debug/shapes/collision/contact_color", Color(1.0, 0.2, 0.1, 0.8));
2030
debug_paths_color = GLOBAL_DEF("debug/shapes/paths/geometry_color", Color(0.1, 1.0, 0.7, 0.4));
2031
debug_paths_width = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "debug/shapes/paths/geometry_width", PROPERTY_HINT_RANGE, "0.01,10,0.001,or_greater"), 2.0);
2032
collision_debug_contacts = GLOBAL_DEF(PropertyInfo(Variant::INT, "debug/shapes/collision/max_contacts_displayed", PROPERTY_HINT_RANGE, "0,20000,1"), 10000);
2033
accessibility_upd_per_sec = GLOBAL_GET(SNAME("accessibility/general/updates_per_second"));
2034
2035
GLOBAL_DEF("debug/shapes/collision/draw_2d_outlines", true);
2036
2037
process_group_call_queue_allocator = memnew(CallQueue::Allocator(64));
2038
Math::randomize();
2039
2040
// Create with mainloop.
2041
2042
root = memnew(Window);
2043
root->set_min_size(Size2i(64, 64)); // Define a very small minimum window size to prevent bugs such as GH-37242.
2044
root->set_process_mode(Node::PROCESS_MODE_PAUSABLE);
2045
root->set_name("root");
2046
2047
if (Engine::get_singleton()->is_editor_hint()) {
2048
root->set_wrap_controls(true);
2049
root->set_auto_translate_mode(Node::AUTO_TRANSLATE_MODE_ALWAYS);
2050
} else {
2051
root->set_auto_translate_mode(GLOBAL_GET("internationalization/rendering/root_node_auto_translate") ? Node::AUTO_TRANSLATE_MODE_ALWAYS : Node::AUTO_TRANSLATE_MODE_DISABLED);
2052
}
2053
2054
// Set after auto translate mode to avoid changing the displayed title back and forth.
2055
root->set_title(GLOBAL_GET("application/config/name"));
2056
2057
#ifndef _3D_DISABLED
2058
if (root->get_world_3d().is_null()) {
2059
root->set_world_3d(Ref<World3D>(memnew(World3D)));
2060
}
2061
root->set_as_audio_listener_3d(true);
2062
#endif // _3D_DISABLED
2063
2064
set_physics_interpolation_enabled(GLOBAL_DEF("physics/common/physics_interpolation", false));
2065
2066
// Always disable jitter fix if physics interpolation is enabled -
2067
// Jitter fix will interfere with interpolation, and is not necessary
2068
// when interpolation is active.
2069
if (is_physics_interpolation_enabled()) {
2070
Engine::get_singleton()->set_physics_jitter_fix(0);
2071
}
2072
2073
// Initialize network state.
2074
set_multiplayer(MultiplayerAPI::create_default_interface());
2075
2076
root->set_as_audio_listener_2d(true);
2077
current_scene = nullptr;
2078
2079
const int msaa_mode_2d = GLOBAL_GET("rendering/anti_aliasing/quality/msaa_2d");
2080
root->set_msaa_2d(Viewport::MSAA(msaa_mode_2d));
2081
2082
const int msaa_mode_3d = GLOBAL_GET("rendering/anti_aliasing/quality/msaa_3d");
2083
root->set_msaa_3d(Viewport::MSAA(msaa_mode_3d));
2084
2085
const bool transparent_background = GLOBAL_DEF("rendering/viewport/transparent_background", false);
2086
root->set_transparent_background(transparent_background);
2087
2088
const bool use_hdr_2d = GLOBAL_GET("rendering/viewport/hdr_2d");
2089
root->set_use_hdr_2d(use_hdr_2d);
2090
2091
const int ssaa_mode = GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/screen_space_aa", PROPERTY_HINT_ENUM, "Disabled (Fastest),FXAA (Fast),SMAA (Average)"), 0);
2092
root->set_screen_space_aa(Viewport::ScreenSpaceAA(ssaa_mode));
2093
2094
const bool use_taa = GLOBAL_DEF_BASIC("rendering/anti_aliasing/quality/use_taa", false);
2095
root->set_use_taa(use_taa);
2096
2097
const bool use_debanding = GLOBAL_GET("rendering/anti_aliasing/quality/use_debanding");
2098
root->set_use_debanding(use_debanding);
2099
2100
const bool use_occlusion_culling = GLOBAL_DEF("rendering/occlusion_culling/use_occlusion_culling", false);
2101
root->set_use_occlusion_culling(use_occlusion_culling);
2102
2103
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);
2104
root->set_mesh_lod_threshold(mesh_lod_threshold);
2105
2106
bool snap_2d_transforms = GLOBAL_DEF_BASIC("rendering/2d/snap/snap_2d_transforms_to_pixel", false);
2107
root->set_snap_2d_transforms_to_pixel(snap_2d_transforms);
2108
2109
bool snap_2d_vertices = GLOBAL_DEF("rendering/2d/snap/snap_2d_vertices_to_pixel", false);
2110
root->set_snap_2d_vertices_to_pixel(snap_2d_vertices);
2111
2112
// We setup VRS for the main viewport here, in the editor this will have little effect.
2113
const int vrs_mode = GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/vrs/mode", PROPERTY_HINT_ENUM, String::utf8("Disabled,Texture,XR")), 0);
2114
root->set_vrs_mode(Viewport::VRSMode(vrs_mode));
2115
const String vrs_texture_path = String(GLOBAL_DEF(PropertyInfo(Variant::STRING, "rendering/vrs/texture", PROPERTY_HINT_FILE, "*.bmp,*.png,*.tga,*.webp"), String())).strip_edges();
2116
if (vrs_mode == 1 && !vrs_texture_path.is_empty()) {
2117
Ref<Image> vrs_image;
2118
vrs_image.instantiate();
2119
Error load_err = ImageLoader::load_image(vrs_texture_path, vrs_image);
2120
if (load_err) {
2121
ERR_PRINT("Non-existing or invalid VRS texture at '" + vrs_texture_path + "'.");
2122
} else {
2123
Ref<ImageTexture> vrs_texture;
2124
vrs_texture.instantiate();
2125
vrs_texture->create_from_image(vrs_image);
2126
root->set_vrs_texture(vrs_texture);
2127
}
2128
}
2129
2130
int shadowmap_size = GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_size", PROPERTY_HINT_RANGE, "256,16384"), 4096);
2131
GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_size.mobile", 2048);
2132
bool shadowmap_16_bits = GLOBAL_GET("rendering/lights_and_shadows/positional_shadow/atlas_16_bits");
2133
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);
2134
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);
2135
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);
2136
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);
2137
2138
root->set_positional_shadow_atlas_size(shadowmap_size);
2139
root->set_positional_shadow_atlas_16_bits(shadowmap_16_bits);
2140
root->set_positional_shadow_atlas_quadrant_subdiv(0, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q0));
2141
root->set_positional_shadow_atlas_quadrant_subdiv(1, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q1));
2142
root->set_positional_shadow_atlas_quadrant_subdiv(2, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q2));
2143
root->set_positional_shadow_atlas_quadrant_subdiv(3, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q3));
2144
2145
Viewport::SDFOversize sdf_oversize = Viewport::SDFOversize(int(GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/2d/sdf/oversize", PROPERTY_HINT_ENUM, "100%,120%,150%,200%"), 1)));
2146
root->set_sdf_oversize(sdf_oversize);
2147
Viewport::SDFScale sdf_scale = Viewport::SDFScale(int(GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/2d/sdf/scale", PROPERTY_HINT_ENUM, "100%,50%,25%"), 1)));
2148
root->set_sdf_scale(sdf_scale);
2149
2150
#ifndef _3D_DISABLED
2151
{ // Load default fallback environment.
2152
// Get possible extensions.
2153
List<String> exts;
2154
ResourceLoader::get_recognized_extensions_for_type("Environment", &exts);
2155
String ext_hint;
2156
for (const String &E : exts) {
2157
if (!ext_hint.is_empty()) {
2158
ext_hint += ",";
2159
}
2160
ext_hint += "*." + E;
2161
}
2162
// Get path.
2163
String env_path = GLOBAL_DEF(PropertyInfo(Variant::STRING, "rendering/environment/defaults/default_environment", PROPERTY_HINT_FILE, ext_hint), "");
2164
// Setup property.
2165
env_path = env_path.strip_edges();
2166
if (!env_path.is_empty()) {
2167
Ref<Environment> env = ResourceLoader::load(env_path);
2168
if (env.is_valid()) {
2169
root->get_world_3d()->set_fallback_environment(env);
2170
} else {
2171
if (Engine::get_singleton()->is_editor_hint()) {
2172
// File was erased, clear the field.
2173
ProjectSettings::get_singleton()->set("rendering/environment/defaults/default_environment", "");
2174
} else {
2175
// File was erased, notify user.
2176
ERR_PRINT("Default Environment as specified in the project setting \"rendering/environment/defaults/default_environment\" could not be loaded.");
2177
}
2178
}
2179
}
2180
}
2181
#endif // _3D_DISABLED
2182
2183
#if !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
2184
root->set_physics_object_picking(GLOBAL_DEF("physics/common/enable_object_picking", true));
2185
#endif // !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
2186
2187
root->connect("close_requested", callable_mp(this, &SceneTree::_main_window_close));
2188
root->connect("go_back_requested", callable_mp(this, &SceneTree::_main_window_go_back));
2189
root->connect(SceneStringName(focus_entered), callable_mp(this, &SceneTree::_main_window_focus_in));
2190
2191
#ifdef TOOLS_ENABLED
2192
edited_scene_root = nullptr;
2193
#endif
2194
2195
process_groups.push_back(&default_process_group);
2196
}
2197
2198
SceneTree::~SceneTree() {
2199
if (prev_scene_id.is_valid()) {
2200
Node *prev_scene = ObjectDB::get_instance<Node>(prev_scene_id);
2201
if (prev_scene) {
2202
memdelete(prev_scene);
2203
}
2204
prev_scene_id = ObjectID();
2205
}
2206
if (pending_new_scene_id.is_valid()) {
2207
Node *pending_new_scene = ObjectDB::get_instance<Node>(pending_new_scene_id);
2208
if (pending_new_scene) {
2209
memdelete(pending_new_scene);
2210
}
2211
pending_new_scene_id = ObjectID();
2212
}
2213
if (root) {
2214
root->_set_tree(nullptr);
2215
root->_propagate_after_exit_tree();
2216
memdelete(root);
2217
}
2218
2219
// Process groups are not deleted immediately, they may remain around. Delete them now.
2220
for (uint32_t i = 0; i < process_groups.size(); i++) {
2221
if (process_groups[i] != &default_process_group) {
2222
memdelete(process_groups[i]);
2223
}
2224
}
2225
2226
memdelete(process_group_call_queue_allocator);
2227
2228
if (singleton == this) {
2229
singleton = nullptr;
2230
}
2231
}
2232
2233