1 /*************************************************************************/
2 /* scene_tree.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
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/io/marshalls.h"
34 #include "core/io/resource_loader.h"
35 #include "core/message_queue.h"
36 #include "core/os/dir_access.h"
37 #include "core/os/keyboard.h"
38 #include "core/os/os.h"
39 #include "core/print_string.h"
40 #include "core/project_settings.h"
41 #include "main/input_default.h"
42 #include "node.h"
43 #include "scene/debugger/script_debugger_remote.h"
44 #include "scene/resources/dynamic_font.h"
45 #include "scene/resources/material.h"
46 #include "scene/resources/mesh.h"
47 #include "scene/resources/packed_scene.h"
48 #include "scene/scene_string_names.h"
49 #include "servers/physics_2d_server.h"
50 #include "servers/physics_server.h"
51 #include "viewport.h"
52
53 #include <stdio.h>
54
_bind_methods()55 void SceneTreeTimer::_bind_methods() {
56
57 ClassDB::bind_method(D_METHOD("set_time_left", "time"), &SceneTreeTimer::set_time_left);
58 ClassDB::bind_method(D_METHOD("get_time_left"), &SceneTreeTimer::get_time_left);
59
60 ADD_PROPERTY(PropertyInfo(Variant::REAL, "time_left"), "set_time_left", "get_time_left");
61
62 ADD_SIGNAL(MethodInfo("timeout"));
63 }
64
set_time_left(float p_time)65 void SceneTreeTimer::set_time_left(float p_time) {
66 time_left = p_time;
67 }
68
get_time_left() const69 float SceneTreeTimer::get_time_left() const {
70 return time_left;
71 }
72
set_pause_mode_process(bool p_pause_mode_process)73 void SceneTreeTimer::set_pause_mode_process(bool p_pause_mode_process) {
74
75 process_pause = p_pause_mode_process;
76 }
77
is_pause_mode_process()78 bool SceneTreeTimer::is_pause_mode_process() {
79 return process_pause;
80 }
81
release_connections()82 void SceneTreeTimer::release_connections() {
83
84 List<Connection> connections;
85 get_all_signal_connections(&connections);
86
87 for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {
88 Connection const &connection = E->get();
89 disconnect(connection.signal, connection.target, connection.method);
90 }
91 }
92
SceneTreeTimer()93 SceneTreeTimer::SceneTreeTimer() {
94 time_left = 0;
95 process_pause = true;
96 }
97
tree_changed()98 void SceneTree::tree_changed() {
99
100 tree_version++;
101 emit_signal(tree_changed_name);
102 }
103
node_added(Node * p_node)104 void SceneTree::node_added(Node *p_node) {
105
106 emit_signal(node_added_name, p_node);
107 }
108
node_removed(Node * p_node)109 void SceneTree::node_removed(Node *p_node) {
110
111 if (current_scene == p_node) {
112 current_scene = NULL;
113 }
114 emit_signal(node_removed_name, p_node);
115 if (call_lock > 0)
116 call_skip.insert(p_node);
117 }
118
node_renamed(Node * p_node)119 void SceneTree::node_renamed(Node *p_node) {
120
121 emit_signal(node_renamed_name, p_node);
122 }
123
add_to_group(const StringName & p_group,Node * p_node)124 SceneTree::Group *SceneTree::add_to_group(const StringName &p_group, Node *p_node) {
125
126 Map<StringName, Group>::Element *E = group_map.find(p_group);
127 if (!E) {
128 E = group_map.insert(p_group, Group());
129 }
130
131 ERR_FAIL_COND_V_MSG(E->get().nodes.find(p_node) != -1, &E->get(), "Already in group: " + p_group + ".");
132 E->get().nodes.push_back(p_node);
133 //E->get().last_tree_version=0;
134 E->get().changed = true;
135 return &E->get();
136 }
137
remove_from_group(const StringName & p_group,Node * p_node)138 void SceneTree::remove_from_group(const StringName &p_group, Node *p_node) {
139
140 Map<StringName, Group>::Element *E = group_map.find(p_group);
141 ERR_FAIL_COND(!E);
142
143 E->get().nodes.erase(p_node);
144 if (E->get().nodes.empty())
145 group_map.erase(E);
146 }
147
make_group_changed(const StringName & p_group)148 void SceneTree::make_group_changed(const StringName &p_group) {
149 Map<StringName, Group>::Element *E = group_map.find(p_group);
150 if (E)
151 E->get().changed = true;
152 }
153
flush_transform_notifications()154 void SceneTree::flush_transform_notifications() {
155
156 SelfList<Node> *n = xform_change_list.first();
157 while (n) {
158
159 Node *node = n->self();
160 SelfList<Node> *nx = n->next();
161 xform_change_list.remove(n);
162 n = nx;
163 node->notification(NOTIFICATION_TRANSFORM_CHANGED);
164 }
165 }
166
_flush_ugc()167 void SceneTree::_flush_ugc() {
168
169 ugc_locked = true;
170
171 while (unique_group_calls.size()) {
172
173 Map<UGCall, Vector<Variant> >::Element *E = unique_group_calls.front();
174
175 Variant v[VARIANT_ARG_MAX];
176 for (int i = 0; i < E->get().size(); i++)
177 v[i] = E->get()[i];
178
179 call_group_flags(GROUP_CALL_REALTIME, E->key().group, E->key().call, v[0], v[1], v[2], v[3], v[4]);
180
181 unique_group_calls.erase(E);
182 }
183
184 ugc_locked = false;
185 }
186
_update_group_order(Group & g,bool p_use_priority)187 void SceneTree::_update_group_order(Group &g, bool p_use_priority) {
188
189 if (!g.changed)
190 return;
191 if (g.nodes.empty())
192 return;
193
194 Node **nodes = g.nodes.ptrw();
195 int node_count = g.nodes.size();
196
197 if (p_use_priority) {
198 SortArray<Node *, Node::ComparatorWithPriority> node_sort;
199 node_sort.sort(nodes, node_count);
200 } else {
201 SortArray<Node *, Node::Comparator> node_sort;
202 node_sort.sort(nodes, node_count);
203 }
204 g.changed = false;
205 }
206
call_group_flags(uint32_t p_call_flags,const StringName & p_group,const StringName & p_function,VARIANT_ARG_DECLARE)207 void SceneTree::call_group_flags(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, VARIANT_ARG_DECLARE) {
208
209 Map<StringName, Group>::Element *E = group_map.find(p_group);
210 if (!E)
211 return;
212 Group &g = E->get();
213 if (g.nodes.empty())
214 return;
215
216 if (p_call_flags & GROUP_CALL_UNIQUE && !(p_call_flags & GROUP_CALL_REALTIME)) {
217
218 ERR_FAIL_COND(ugc_locked);
219
220 UGCall ug;
221 ug.call = p_function;
222 ug.group = p_group;
223
224 if (unique_group_calls.has(ug))
225 return;
226
227 VARIANT_ARGPTRS;
228
229 Vector<Variant> args;
230 for (int i = 0; i < VARIANT_ARG_MAX; i++) {
231 if (argptr[i]->get_type() == Variant::NIL)
232 break;
233 args.push_back(*argptr[i]);
234 }
235
236 unique_group_calls[ug] = args;
237 return;
238 }
239
240 _update_group_order(g);
241
242 Vector<Node *> nodes_copy = g.nodes;
243 Node **nodes = nodes_copy.ptrw();
244 int node_count = nodes_copy.size();
245
246 call_lock++;
247
248 if (p_call_flags & GROUP_CALL_REVERSE) {
249
250 for (int i = node_count - 1; i >= 0; i--) {
251
252 if (call_lock && call_skip.has(nodes[i]))
253 continue;
254
255 if (p_call_flags & GROUP_CALL_REALTIME) {
256 if (p_call_flags & GROUP_CALL_MULTILEVEL)
257 nodes[i]->call_multilevel(p_function, VARIANT_ARG_PASS);
258 else
259 nodes[i]->call(p_function, VARIANT_ARG_PASS);
260 } else
261 MessageQueue::get_singleton()->push_call(nodes[i], p_function, VARIANT_ARG_PASS);
262 }
263
264 } else {
265
266 for (int i = 0; i < node_count; i++) {
267
268 if (call_lock && call_skip.has(nodes[i]))
269 continue;
270
271 if (p_call_flags & GROUP_CALL_REALTIME) {
272 if (p_call_flags & GROUP_CALL_MULTILEVEL)
273 nodes[i]->call_multilevel(p_function, VARIANT_ARG_PASS);
274 else
275 nodes[i]->call(p_function, VARIANT_ARG_PASS);
276 } else
277 MessageQueue::get_singleton()->push_call(nodes[i], p_function, VARIANT_ARG_PASS);
278 }
279 }
280
281 call_lock--;
282 if (call_lock == 0)
283 call_skip.clear();
284 }
285
notify_group_flags(uint32_t p_call_flags,const StringName & p_group,int p_notification)286 void SceneTree::notify_group_flags(uint32_t p_call_flags, const StringName &p_group, int p_notification) {
287
288 Map<StringName, Group>::Element *E = group_map.find(p_group);
289 if (!E)
290 return;
291 Group &g = E->get();
292 if (g.nodes.empty())
293 return;
294
295 _update_group_order(g);
296
297 Vector<Node *> nodes_copy = g.nodes;
298 Node **nodes = nodes_copy.ptrw();
299 int node_count = nodes_copy.size();
300
301 call_lock++;
302
303 if (p_call_flags & GROUP_CALL_REVERSE) {
304
305 for (int i = node_count - 1; i >= 0; i--) {
306
307 if (call_lock && call_skip.has(nodes[i]))
308 continue;
309
310 if (p_call_flags & GROUP_CALL_REALTIME)
311 nodes[i]->notification(p_notification);
312 else
313 MessageQueue::get_singleton()->push_notification(nodes[i], p_notification);
314 }
315
316 } else {
317
318 for (int i = 0; i < node_count; i++) {
319
320 if (call_lock && call_skip.has(nodes[i]))
321 continue;
322
323 if (p_call_flags & GROUP_CALL_REALTIME)
324 nodes[i]->notification(p_notification);
325 else
326 MessageQueue::get_singleton()->push_notification(nodes[i], p_notification);
327 }
328 }
329
330 call_lock--;
331 if (call_lock == 0)
332 call_skip.clear();
333 }
334
set_group_flags(uint32_t p_call_flags,const StringName & p_group,const String & p_name,const Variant & p_value)335 void SceneTree::set_group_flags(uint32_t p_call_flags, const StringName &p_group, const String &p_name, const Variant &p_value) {
336
337 Map<StringName, Group>::Element *E = group_map.find(p_group);
338 if (!E)
339 return;
340 Group &g = E->get();
341 if (g.nodes.empty())
342 return;
343
344 _update_group_order(g);
345
346 Vector<Node *> nodes_copy = g.nodes;
347 Node **nodes = nodes_copy.ptrw();
348 int node_count = nodes_copy.size();
349
350 call_lock++;
351
352 if (p_call_flags & GROUP_CALL_REVERSE) {
353
354 for (int i = node_count - 1; i >= 0; i--) {
355
356 if (call_lock && call_skip.has(nodes[i]))
357 continue;
358
359 if (p_call_flags & GROUP_CALL_REALTIME)
360 nodes[i]->set(p_name, p_value);
361 else
362 MessageQueue::get_singleton()->push_set(nodes[i], p_name, p_value);
363 }
364
365 } else {
366
367 for (int i = 0; i < node_count; i++) {
368
369 if (call_lock && call_skip.has(nodes[i]))
370 continue;
371
372 if (p_call_flags & GROUP_CALL_REALTIME)
373 nodes[i]->set(p_name, p_value);
374 else
375 MessageQueue::get_singleton()->push_set(nodes[i], p_name, p_value);
376 }
377 }
378
379 call_lock--;
380 if (call_lock == 0)
381 call_skip.clear();
382 }
383
call_group(const StringName & p_group,const StringName & p_function,VARIANT_ARG_DECLARE)384 void SceneTree::call_group(const StringName &p_group, const StringName &p_function, VARIANT_ARG_DECLARE) {
385 call_group_flags(0, p_group, p_function, VARIANT_ARG_PASS);
386 }
387
notify_group(const StringName & p_group,int p_notification)388 void SceneTree::notify_group(const StringName &p_group, int p_notification) {
389
390 notify_group_flags(0, p_group, p_notification);
391 }
392
set_group(const StringName & p_group,const String & p_name,const Variant & p_value)393 void SceneTree::set_group(const StringName &p_group, const String &p_name, const Variant &p_value) {
394
395 set_group_flags(0, p_group, p_name, p_value);
396 }
397
set_input_as_handled()398 void SceneTree::set_input_as_handled() {
399
400 input_handled = true;
401 }
402
input_text(const String & p_text)403 void SceneTree::input_text(const String &p_text) {
404
405 root_lock++;
406
407 call_group_flags(GROUP_CALL_REALTIME, "_viewports", "_vp_input_text", p_text); //special one for GUI, as controls use their own process check
408
409 root_lock--;
410 }
411
is_input_handled()412 bool SceneTree::is_input_handled() {
413 return input_handled;
414 }
415
input_event(const Ref<InputEvent> & p_event)416 void SceneTree::input_event(const Ref<InputEvent> &p_event) {
417
418 if (Engine::get_singleton()->is_editor_hint() && (Object::cast_to<InputEventJoypadButton>(p_event.ptr()) || Object::cast_to<InputEventJoypadMotion>(*p_event)))
419 return; //avoid joy input on editor
420
421 current_event++;
422 root_lock++;
423
424 input_handled = false;
425
426 // Don't make const ref unless you can find and fix what caused GH-34691.
427 Ref<InputEvent> ev = p_event;
428
429 MainLoop::input_event(ev);
430
431 call_group_flags(GROUP_CALL_REALTIME, "_viewports", "_vp_input", ev); //special one for GUI, as controls use their own process check
432
433 if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_remote()) {
434 //quit from game window using F8
435 Ref<InputEventKey> k = ev;
436 if (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_scancode() == KEY_F8) {
437 ScriptDebugger::get_singleton()->request_quit();
438 }
439 }
440
441 _flush_ugc();
442 root_lock--;
443 //MessageQueue::get_singleton()->flush(); //flushing here causes UI and other places slowness
444
445 root_lock++;
446
447 if (!input_handled) {
448 call_group_flags(GROUP_CALL_REALTIME, "_viewports", "_vp_unhandled_input", ev); //special one for GUI, as controls use their own process check
449 _flush_ugc();
450 // input_handled = true; - no reason to set this as handled
451 root_lock--;
452 //MessageQueue::get_singleton()->flush(); //flushing here causes UI and other places slowness
453 } else {
454 // input_handled = true; - no reason to set this as handled
455 root_lock--;
456 }
457
458 _call_idle_callbacks();
459 }
460
init()461 void SceneTree::init() {
462 initialized = true;
463 root->_set_tree(this);
464 MainLoop::init();
465 }
466
iteration(float p_time)467 bool SceneTree::iteration(float p_time) {
468
469 root_lock++;
470
471 current_frame++;
472
473 flush_transform_notifications();
474
475 MainLoop::iteration(p_time);
476 physics_process_time = p_time;
477
478 emit_signal("physics_frame");
479
480 _notify_group_pause("physics_process_internal", Node::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
481 _notify_group_pause("physics_process", Node::NOTIFICATION_PHYSICS_PROCESS);
482 _flush_ugc();
483 MessageQueue::get_singleton()->flush(); //small little hack
484 flush_transform_notifications();
485 call_group_flags(GROUP_CALL_REALTIME, "_viewports", "update_worlds");
486 root_lock--;
487
488 _flush_delete_queue();
489 _call_idle_callbacks();
490
491 return _quit;
492 }
493
_update_font_oversampling(float p_ratio)494 void SceneTree::_update_font_oversampling(float p_ratio) {
495
496 if (use_font_oversampling) {
497 DynamicFontAtSize::font_oversampling = p_ratio;
498 DynamicFont::update_oversampling();
499 }
500 }
501
idle(float p_time)502 bool SceneTree::idle(float p_time) {
503
504 //print_line("ram: "+itos(OS::get_singleton()->get_static_memory_usage())+" sram: "+itos(OS::get_singleton()->get_dynamic_memory_usage()));
505 //print_line("node count: "+itos(get_node_count()));
506 //print_line("TEXTURE RAM: "+itos(VS::get_singleton()->get_render_info(VS::INFO_TEXTURE_MEM_USED)));
507
508 root_lock++;
509
510 MainLoop::idle(p_time);
511
512 idle_process_time = p_time;
513
514 if (multiplayer_poll) {
515 multiplayer->poll();
516 }
517
518 emit_signal("idle_frame");
519
520 MessageQueue::get_singleton()->flush(); //small little hack
521
522 flush_transform_notifications();
523
524 _notify_group_pause("idle_process_internal", Node::NOTIFICATION_INTERNAL_PROCESS);
525 _notify_group_pause("idle_process", Node::NOTIFICATION_PROCESS);
526
527 Size2 win_size = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height);
528
529 if (win_size != last_screen_size) {
530
531 last_screen_size = win_size;
532 _update_root_rect();
533 emit_signal("screen_resized");
534 }
535
536 _flush_ugc();
537 MessageQueue::get_singleton()->flush(); //small little hack
538 flush_transform_notifications(); //transforms after world update, to avoid unnecessary enter/exit notifications
539 call_group_flags(GROUP_CALL_REALTIME, "_viewports", "update_worlds");
540
541 root_lock--;
542
543 _flush_delete_queue();
544
545 //go through timers
546
547 List<Ref<SceneTreeTimer> >::Element *L = timers.back(); //last element
548
549 for (List<Ref<SceneTreeTimer> >::Element *E = timers.front(); E;) {
550
551 List<Ref<SceneTreeTimer> >::Element *N = E->next();
552 if (pause && !E->get()->is_pause_mode_process()) {
553 if (E == L) {
554 break; //break on last, so if new timers were added during list traversal, ignore them.
555 }
556 E = N;
557 continue;
558 }
559 float time_left = E->get()->get_time_left();
560 time_left -= p_time;
561 E->get()->set_time_left(time_left);
562
563 if (time_left < 0) {
564 E->get()->emit_signal("timeout");
565 timers.erase(E);
566 }
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 }
572
573 flush_transform_notifications(); //additional transforms after timers update
574
575 _call_idle_callbacks();
576
577 #ifdef TOOLS_ENABLED
578
579 if (Engine::get_singleton()->is_editor_hint()) {
580 //simple hack to reload fallback environment if it changed from editor
581 String env_path = ProjectSettings::get_singleton()->get("rendering/environment/default_environment");
582 env_path = env_path.strip_edges(); //user may have added a space or two
583 String cpath;
584 Ref<Environment> fallback = get_root()->get_world()->get_fallback_environment();
585 if (fallback.is_valid()) {
586 cpath = fallback->get_path();
587 }
588 if (cpath != env_path) {
589
590 if (env_path != String()) {
591 fallback = ResourceLoader::load(env_path);
592 if (fallback.is_null()) {
593 //could not load fallback, set as empty
594 ProjectSettings::get_singleton()->set("rendering/environment/default_environment", "");
595 }
596 } else {
597 fallback.unref();
598 }
599 get_root()->get_world()->set_fallback_environment(fallback);
600 }
601 }
602
603 #endif
604
605 return _quit;
606 }
607
finish()608 void SceneTree::finish() {
609
610 _flush_delete_queue();
611
612 _flush_ugc();
613
614 initialized = false;
615
616 MainLoop::finish();
617
618 if (root) {
619 root->_set_tree(NULL);
620 root->_propagate_after_exit_tree();
621 memdelete(root); //delete root
622 root = NULL;
623 }
624
625 // cleanup timers
626 for (List<Ref<SceneTreeTimer> >::Element *E = timers.front(); E; E = E->next()) {
627 E->get()->release_connections();
628 }
629 timers.clear();
630 }
631
quit(int p_exit_code)632 void SceneTree::quit(int p_exit_code) {
633
634 if (p_exit_code >= 0) {
635 // Override the exit code if a positive argument is given (the default is `-1`).
636 // This is a shorthand for calling `set_exit_code()` on the OS singleton then quitting.
637 OS::get_singleton()->set_exit_code(p_exit_code);
638 }
639
640 _quit = true;
641 }
642
_notification(int p_notification)643 void SceneTree::_notification(int p_notification) {
644
645 switch (p_notification) {
646
647 case NOTIFICATION_WM_QUIT_REQUEST: {
648
649 get_root()->propagate_notification(p_notification);
650
651 if (accept_quit) {
652 _quit = true;
653 break;
654 }
655 } break;
656
657 case NOTIFICATION_WM_GO_BACK_REQUEST: {
658
659 get_root()->propagate_notification(p_notification);
660
661 if (quit_on_go_back) {
662 _quit = true;
663 break;
664 }
665 } break;
666
667 case NOTIFICATION_WM_FOCUS_IN: {
668
669 InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton());
670 if (id) {
671 id->ensure_touch_mouse_raised();
672 }
673
674 get_root()->propagate_notification(p_notification);
675 } break;
676
677 case NOTIFICATION_TRANSLATION_CHANGED: {
678 if (!Engine::get_singleton()->is_editor_hint()) {
679 get_root()->propagate_notification(p_notification);
680 }
681 } break;
682
683 case NOTIFICATION_WM_UNFOCUS_REQUEST: {
684
685 notify_group_flags(GROUP_CALL_REALTIME | GROUP_CALL_MULTILEVEL, "input", NOTIFICATION_WM_UNFOCUS_REQUEST);
686
687 get_root()->propagate_notification(p_notification);
688
689 } break;
690
691 case NOTIFICATION_OS_MEMORY_WARNING:
692 case NOTIFICATION_OS_IME_UPDATE:
693 case NOTIFICATION_WM_MOUSE_ENTER:
694 case NOTIFICATION_WM_MOUSE_EXIT:
695 case NOTIFICATION_WM_FOCUS_OUT:
696 case NOTIFICATION_WM_ABOUT:
697 case NOTIFICATION_CRASH:
698 case NOTIFICATION_APP_RESUMED:
699 case NOTIFICATION_APP_PAUSED: {
700
701 get_root()->propagate_notification(p_notification);
702 } break;
703
704 default:
705 break;
706 };
707 };
708
set_auto_accept_quit(bool p_enable)709 void SceneTree::set_auto_accept_quit(bool p_enable) {
710
711 accept_quit = p_enable;
712 }
713
set_quit_on_go_back(bool p_enable)714 void SceneTree::set_quit_on_go_back(bool p_enable) {
715
716 quit_on_go_back = p_enable;
717 }
718
719 #ifdef TOOLS_ENABLED
720
is_node_being_edited(const Node * p_node) const721 bool SceneTree::is_node_being_edited(const Node *p_node) const {
722
723 return Engine::get_singleton()->is_editor_hint() && edited_scene_root && (edited_scene_root->is_a_parent_of(p_node) || edited_scene_root == p_node);
724 }
725 #endif
726
727 #ifdef DEBUG_ENABLED
set_debug_collisions_hint(bool p_enabled)728 void SceneTree::set_debug_collisions_hint(bool p_enabled) {
729
730 debug_collisions_hint = p_enabled;
731 }
732
is_debugging_collisions_hint() const733 bool SceneTree::is_debugging_collisions_hint() const {
734
735 return debug_collisions_hint;
736 }
737
set_debug_navigation_hint(bool p_enabled)738 void SceneTree::set_debug_navigation_hint(bool p_enabled) {
739
740 debug_navigation_hint = p_enabled;
741 }
742
is_debugging_navigation_hint() const743 bool SceneTree::is_debugging_navigation_hint() const {
744
745 return debug_navigation_hint;
746 }
747 #endif
748
set_debug_collisions_color(const Color & p_color)749 void SceneTree::set_debug_collisions_color(const Color &p_color) {
750
751 debug_collisions_color = p_color;
752 }
753
get_debug_collisions_color() const754 Color SceneTree::get_debug_collisions_color() const {
755
756 return debug_collisions_color;
757 }
758
set_debug_collision_contact_color(const Color & p_color)759 void SceneTree::set_debug_collision_contact_color(const Color &p_color) {
760
761 debug_collision_contact_color = p_color;
762 }
763
get_debug_collision_contact_color() const764 Color SceneTree::get_debug_collision_contact_color() const {
765
766 return debug_collision_contact_color;
767 }
768
set_debug_navigation_color(const Color & p_color)769 void SceneTree::set_debug_navigation_color(const Color &p_color) {
770
771 debug_navigation_color = p_color;
772 }
773
get_debug_navigation_color() const774 Color SceneTree::get_debug_navigation_color() const {
775
776 return debug_navigation_color;
777 }
778
set_debug_navigation_disabled_color(const Color & p_color)779 void SceneTree::set_debug_navigation_disabled_color(const Color &p_color) {
780
781 debug_navigation_disabled_color = p_color;
782 }
783
get_debug_navigation_disabled_color() const784 Color SceneTree::get_debug_navigation_disabled_color() const {
785
786 return debug_navigation_disabled_color;
787 }
788
get_debug_navigation_material()789 Ref<Material> SceneTree::get_debug_navigation_material() {
790
791 if (navigation_material.is_valid())
792 return navigation_material;
793
794 Ref<SpatialMaterial> line_material = Ref<SpatialMaterial>(memnew(SpatialMaterial));
795 line_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
796 line_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
797 line_material->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true);
798 line_material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
799 line_material->set_albedo(get_debug_navigation_color());
800
801 navigation_material = line_material;
802
803 return navigation_material;
804 }
805
get_debug_navigation_disabled_material()806 Ref<Material> SceneTree::get_debug_navigation_disabled_material() {
807
808 if (navigation_disabled_material.is_valid())
809 return navigation_disabled_material;
810
811 Ref<SpatialMaterial> line_material = Ref<SpatialMaterial>(memnew(SpatialMaterial));
812 line_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
813 line_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
814 line_material->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true);
815 line_material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
816 line_material->set_albedo(get_debug_navigation_disabled_color());
817
818 navigation_disabled_material = line_material;
819
820 return navigation_disabled_material;
821 }
get_debug_collision_material()822 Ref<Material> SceneTree::get_debug_collision_material() {
823
824 if (collision_material.is_valid())
825 return collision_material;
826
827 Ref<SpatialMaterial> line_material = Ref<SpatialMaterial>(memnew(SpatialMaterial));
828 line_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
829 line_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
830 line_material->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true);
831 line_material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
832 line_material->set_albedo(get_debug_collisions_color());
833
834 collision_material = line_material;
835
836 return collision_material;
837 }
838
get_debug_contact_mesh()839 Ref<ArrayMesh> SceneTree::get_debug_contact_mesh() {
840
841 if (debug_contact_mesh.is_valid())
842 return debug_contact_mesh;
843
844 debug_contact_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
845
846 Ref<SpatialMaterial> mat = Ref<SpatialMaterial>(memnew(SpatialMaterial));
847 mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
848 mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
849 mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true);
850 mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
851 mat->set_albedo(get_debug_collision_contact_color());
852
853 Vector3 diamond[6] = {
854 Vector3(-1, 0, 0),
855 Vector3(1, 0, 0),
856 Vector3(0, -1, 0),
857 Vector3(0, 1, 0),
858 Vector3(0, 0, -1),
859 Vector3(0, 0, 1)
860 };
861
862 /* clang-format off */
863 int diamond_faces[8 * 3] = {
864 0, 2, 4,
865 0, 3, 4,
866 1, 2, 4,
867 1, 3, 4,
868 0, 2, 5,
869 0, 3, 5,
870 1, 2, 5,
871 1, 3, 5,
872 };
873 /* clang-format on */
874
875 PoolVector<int> indices;
876 for (int i = 0; i < 8 * 3; i++)
877 indices.push_back(diamond_faces[i]);
878
879 PoolVector<Vector3> vertices;
880 for (int i = 0; i < 6; i++)
881 vertices.push_back(diamond[i] * 0.1);
882
883 Array arr;
884 arr.resize(Mesh::ARRAY_MAX);
885 arr[Mesh::ARRAY_VERTEX] = vertices;
886 arr[Mesh::ARRAY_INDEX] = indices;
887
888 debug_contact_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arr);
889 debug_contact_mesh->surface_set_material(0, mat);
890
891 return debug_contact_mesh;
892 }
893
set_pause(bool p_enabled)894 void SceneTree::set_pause(bool p_enabled) {
895
896 if (p_enabled == pause)
897 return;
898 pause = p_enabled;
899 PhysicsServer::get_singleton()->set_active(!p_enabled);
900 Physics2DServer::get_singleton()->set_active(!p_enabled);
901 if (get_root())
902 get_root()->propagate_notification(p_enabled ? Node::NOTIFICATION_PAUSED : Node::NOTIFICATION_UNPAUSED);
903 }
904
is_paused() const905 bool SceneTree::is_paused() const {
906
907 return pause;
908 }
909
_call_input_pause(const StringName & p_group,const StringName & p_method,const Ref<InputEvent> & p_input)910 void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p_method, const Ref<InputEvent> &p_input) {
911
912 Map<StringName, Group>::Element *E = group_map.find(p_group);
913 if (!E)
914 return;
915 Group &g = E->get();
916 if (g.nodes.empty())
917 return;
918
919 _update_group_order(g);
920
921 //copy, so copy on write happens in case something is removed from process while being called
922 //performance is not lost because only if something is added/removed the vector is copied.
923 Vector<Node *> nodes_copy = g.nodes;
924
925 int node_count = nodes_copy.size();
926 Node **nodes = nodes_copy.ptrw();
927
928 Variant arg = p_input;
929 const Variant *v[1] = { &arg };
930
931 call_lock++;
932
933 for (int i = node_count - 1; i >= 0; i--) {
934
935 if (input_handled)
936 break;
937
938 Node *n = nodes[i];
939 if (call_lock && call_skip.has(n))
940 continue;
941
942 if (!n->can_process())
943 continue;
944
945 n->call_multilevel(p_method, (const Variant **)v, 1);
946 //ERR_FAIL_COND(node_count != g.nodes.size());
947 }
948
949 call_lock--;
950 if (call_lock == 0)
951 call_skip.clear();
952 }
953
_notify_group_pause(const StringName & p_group,int p_notification)954 void SceneTree::_notify_group_pause(const StringName &p_group, int p_notification) {
955
956 Map<StringName, Group>::Element *E = group_map.find(p_group);
957 if (!E)
958 return;
959 Group &g = E->get();
960 if (g.nodes.empty())
961 return;
962
963 _update_group_order(g, p_notification == Node::NOTIFICATION_PROCESS || p_notification == Node::NOTIFICATION_INTERNAL_PROCESS || p_notification == Node::NOTIFICATION_PHYSICS_PROCESS || p_notification == Node::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
964
965 //copy, so copy on write happens in case something is removed from process while being called
966 //performance is not lost because only if something is added/removed the vector is copied.
967 Vector<Node *> nodes_copy = g.nodes;
968
969 int node_count = nodes_copy.size();
970 Node **nodes = nodes_copy.ptrw();
971
972 call_lock++;
973
974 for (int i = 0; i < node_count; i++) {
975
976 Node *n = nodes[i];
977 if (call_lock && call_skip.has(n))
978 continue;
979
980 if (!n->can_process())
981 continue;
982 if (!n->can_process_notification(p_notification))
983 continue;
984
985 n->notification(p_notification);
986 //ERR_FAIL_COND(node_count != g.nodes.size());
987 }
988
989 call_lock--;
990 if (call_lock == 0)
991 call_skip.clear();
992 }
993
994 /*
995 void SceneMainLoop::_update_listener_2d() {
996
997 if (listener_2d.is_valid()) {
998
999 SpatialSound2DServer::get_singleton()->listener_set_space( listener_2d, world_2d->get_sound_space() );
1000 }
1001
1002 }
1003 */
1004
_call_group_flags(const Variant ** p_args,int p_argcount,Variant::CallError & r_error)1005 Variant SceneTree::_call_group_flags(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
1006
1007 r_error.error = Variant::CallError::CALL_OK;
1008
1009 ERR_FAIL_COND_V(p_argcount < 3, Variant());
1010 ERR_FAIL_COND_V(!p_args[0]->is_num(), Variant());
1011 ERR_FAIL_COND_V(p_args[1]->get_type() != Variant::STRING, Variant());
1012 ERR_FAIL_COND_V(p_args[2]->get_type() != Variant::STRING, Variant());
1013
1014 int flags = *p_args[0];
1015 StringName group = *p_args[1];
1016 StringName method = *p_args[2];
1017 Variant v[VARIANT_ARG_MAX];
1018
1019 for (int i = 0; i < MIN(p_argcount - 3, 5); i++) {
1020
1021 v[i] = *p_args[i + 3];
1022 }
1023
1024 call_group_flags(flags, group, method, v[0], v[1], v[2], v[3], v[4]);
1025 return Variant();
1026 }
1027
_call_group(const Variant ** p_args,int p_argcount,Variant::CallError & r_error)1028 Variant SceneTree::_call_group(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
1029
1030 r_error.error = Variant::CallError::CALL_OK;
1031
1032 ERR_FAIL_COND_V(p_argcount < 2, Variant());
1033 ERR_FAIL_COND_V(p_args[0]->get_type() != Variant::STRING, Variant());
1034 ERR_FAIL_COND_V(p_args[1]->get_type() != Variant::STRING, Variant());
1035
1036 StringName group = *p_args[0];
1037 StringName method = *p_args[1];
1038 Variant v[VARIANT_ARG_MAX];
1039
1040 for (int i = 0; i < MIN(p_argcount - 2, 5); i++) {
1041
1042 v[i] = *p_args[i + 2];
1043 }
1044
1045 call_group_flags(0, group, method, v[0], v[1], v[2], v[3], v[4]);
1046 return Variant();
1047 }
1048
get_frame() const1049 int64_t SceneTree::get_frame() const {
1050
1051 return current_frame;
1052 }
get_event_count() const1053 int64_t SceneTree::get_event_count() const {
1054
1055 return current_event;
1056 }
1057
_get_nodes_in_group(const StringName & p_group)1058 Array SceneTree::_get_nodes_in_group(const StringName &p_group) {
1059
1060 Array ret;
1061 Map<StringName, Group>::Element *E = group_map.find(p_group);
1062 if (!E)
1063 return ret;
1064
1065 _update_group_order(E->get()); //update order just in case
1066 int nc = E->get().nodes.size();
1067 if (nc == 0)
1068 return ret;
1069
1070 ret.resize(nc);
1071
1072 Node **ptr = E->get().nodes.ptrw();
1073 for (int i = 0; i < nc; i++) {
1074
1075 ret[i] = ptr[i];
1076 }
1077
1078 return ret;
1079 }
1080
has_group(const StringName & p_identifier) const1081 bool SceneTree::has_group(const StringName &p_identifier) const {
1082
1083 return group_map.has(p_identifier);
1084 }
get_nodes_in_group(const StringName & p_group,List<Node * > * p_list)1085 void SceneTree::get_nodes_in_group(const StringName &p_group, List<Node *> *p_list) {
1086
1087 Map<StringName, Group>::Element *E = group_map.find(p_group);
1088 if (!E)
1089 return;
1090
1091 _update_group_order(E->get()); //update order just in case
1092 int nc = E->get().nodes.size();
1093 if (nc == 0)
1094 return;
1095 Node **ptr = E->get().nodes.ptrw();
1096 for (int i = 0; i < nc; i++) {
1097
1098 p_list->push_back(ptr[i]);
1099 }
1100 }
1101
_flush_delete_queue()1102 void SceneTree::_flush_delete_queue() {
1103
1104 _THREAD_SAFE_METHOD_
1105
1106 while (delete_queue.size()) {
1107
1108 Object *obj = ObjectDB::get_instance(delete_queue.front()->get());
1109 if (obj) {
1110 memdelete(obj);
1111 }
1112 delete_queue.pop_front();
1113 }
1114 }
1115
queue_delete(Object * p_object)1116 void SceneTree::queue_delete(Object *p_object) {
1117
1118 _THREAD_SAFE_METHOD_
1119 ERR_FAIL_NULL(p_object);
1120 p_object->_is_queued_for_deletion = true;
1121 delete_queue.push_back(p_object->get_instance_id());
1122 }
1123
get_node_count() const1124 int SceneTree::get_node_count() const {
1125
1126 return node_count;
1127 }
1128
_update_root_rect()1129 void SceneTree::_update_root_rect() {
1130
1131 if (stretch_mode == STRETCH_MODE_DISABLED) {
1132
1133 _update_font_oversampling(1.0);
1134 root->set_size((last_screen_size / stretch_shrink).floor());
1135 root->set_attach_to_screen_rect(Rect2(Point2(), last_screen_size));
1136 root->set_size_override_stretch(false);
1137 root->set_size_override(false, Size2());
1138 root->update_canvas_items();
1139 return; //user will take care
1140 }
1141
1142 //actual screen video mode
1143 Size2 video_mode = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height);
1144 Size2 desired_res = stretch_min;
1145
1146 Size2 viewport_size;
1147 Size2 screen_size;
1148
1149 float viewport_aspect = desired_res.aspect();
1150 float video_mode_aspect = video_mode.aspect();
1151
1152 if (use_font_oversampling && stretch_aspect == STRETCH_ASPECT_IGNORE) {
1153 WARN_PRINT("Font oversampling only works with the resize modes 'Keep Width', 'Keep Height', and 'Expand'.");
1154 }
1155
1156 if (stretch_aspect == STRETCH_ASPECT_IGNORE || Math::is_equal_approx(viewport_aspect, video_mode_aspect)) {
1157 //same aspect or ignore aspect
1158 viewport_size = desired_res;
1159 screen_size = video_mode;
1160 } else if (viewport_aspect < video_mode_aspect) {
1161 // screen ratio is smaller vertically
1162
1163 if (stretch_aspect == STRETCH_ASPECT_KEEP_HEIGHT || stretch_aspect == STRETCH_ASPECT_EXPAND) {
1164
1165 //will stretch horizontally
1166 viewport_size.x = desired_res.y * video_mode_aspect;
1167 viewport_size.y = desired_res.y;
1168 screen_size = video_mode;
1169
1170 } else {
1171 //will need black bars
1172 viewport_size = desired_res;
1173 screen_size.x = video_mode.y * viewport_aspect;
1174 screen_size.y = video_mode.y;
1175 }
1176 } else {
1177 //screen ratio is smaller horizontally
1178 if (stretch_aspect == STRETCH_ASPECT_KEEP_WIDTH || stretch_aspect == STRETCH_ASPECT_EXPAND) {
1179
1180 //will stretch horizontally
1181 viewport_size.x = desired_res.x;
1182 viewport_size.y = desired_res.x / video_mode_aspect;
1183 screen_size = video_mode;
1184
1185 } else {
1186 //will need black bars
1187 viewport_size = desired_res;
1188 screen_size.x = video_mode.x;
1189 screen_size.y = video_mode.x / viewport_aspect;
1190 }
1191 }
1192
1193 screen_size = screen_size.floor();
1194 viewport_size = viewport_size.floor();
1195
1196 Size2 margin;
1197 Size2 offset;
1198 //black bars and margin
1199 if (stretch_aspect != STRETCH_ASPECT_EXPAND && screen_size.x < video_mode.x) {
1200 margin.x = Math::round((video_mode.x - screen_size.x) / 2.0);
1201 VisualServer::get_singleton()->black_bars_set_margins(margin.x, 0, margin.x, 0);
1202 offset.x = Math::round(margin.x * viewport_size.y / screen_size.y);
1203 } else if (stretch_aspect != STRETCH_ASPECT_EXPAND && screen_size.y < video_mode.y) {
1204 margin.y = Math::round((video_mode.y - screen_size.y) / 2.0);
1205 VisualServer::get_singleton()->black_bars_set_margins(0, margin.y, 0, margin.y);
1206 offset.y = Math::round(margin.y * viewport_size.x / screen_size.x);
1207 } else {
1208 VisualServer::get_singleton()->black_bars_set_margins(0, 0, 0, 0);
1209 }
1210
1211 switch (stretch_mode) {
1212 case STRETCH_MODE_DISABLED: {
1213 // Already handled above
1214 _update_font_oversampling(1.0);
1215 } break;
1216 case STRETCH_MODE_2D: {
1217
1218 _update_font_oversampling(screen_size.x / viewport_size.x); //screen / viewport radio drives oversampling
1219 root->set_size((screen_size / stretch_shrink).floor());
1220 root->set_attach_to_screen_rect(Rect2(margin, screen_size));
1221 root->set_size_override_stretch(true);
1222 root->set_size_override(true, (viewport_size / stretch_shrink).floor());
1223 root->update_canvas_items(); //force them to update just in case
1224
1225 } break;
1226 case STRETCH_MODE_VIEWPORT: {
1227
1228 _update_font_oversampling(1.0);
1229 root->set_size((viewport_size / stretch_shrink).floor());
1230 root->set_attach_to_screen_rect(Rect2(margin, screen_size));
1231 root->set_size_override_stretch(false);
1232 root->set_size_override(false, Size2());
1233 root->update_canvas_items(); //force them to update just in case
1234
1235 if (use_font_oversampling) {
1236 WARN_PRINT("Font oversampling does not work in 'Viewport' stretch mode, only '2D'.");
1237 }
1238
1239 } break;
1240 }
1241 }
1242
set_screen_stretch(StretchMode p_mode,StretchAspect p_aspect,const Size2 & p_minsize,real_t p_shrink)1243 void SceneTree::set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 &p_minsize, real_t p_shrink) {
1244
1245 stretch_mode = p_mode;
1246 stretch_aspect = p_aspect;
1247 stretch_min = p_minsize;
1248 stretch_shrink = p_shrink;
1249 _update_root_rect();
1250 }
1251
set_edited_scene_root(Node * p_node)1252 void SceneTree::set_edited_scene_root(Node *p_node) {
1253 #ifdef TOOLS_ENABLED
1254 edited_scene_root = p_node;
1255 #endif
1256 }
1257
get_edited_scene_root() const1258 Node *SceneTree::get_edited_scene_root() const {
1259
1260 #ifdef TOOLS_ENABLED
1261 return edited_scene_root;
1262 #else
1263 return NULL;
1264 #endif
1265 }
1266
set_current_scene(Node * p_scene)1267 void SceneTree::set_current_scene(Node *p_scene) {
1268
1269 ERR_FAIL_COND(p_scene && p_scene->get_parent() != root);
1270 current_scene = p_scene;
1271 }
1272
get_current_scene() const1273 Node *SceneTree::get_current_scene() const {
1274
1275 return current_scene;
1276 }
1277
_change_scene(Node * p_to)1278 void SceneTree::_change_scene(Node *p_to) {
1279
1280 if (current_scene) {
1281 memdelete(current_scene);
1282 current_scene = NULL;
1283 }
1284
1285 // If we're quitting, abort.
1286 if (unlikely(_quit)) {
1287 if (p_to) { // Prevent memory leak.
1288 memdelete(p_to);
1289 }
1290 return;
1291 }
1292
1293 if (p_to) {
1294 current_scene = p_to;
1295 root->add_child(p_to);
1296 }
1297 }
1298
change_scene(const String & p_path)1299 Error SceneTree::change_scene(const String &p_path) {
1300 Ref<PackedScene> new_scene = ResourceLoader::load(p_path);
1301 if (new_scene.is_null())
1302 return ERR_CANT_OPEN;
1303
1304 return change_scene_to(new_scene);
1305 }
1306
change_scene_to(const Ref<PackedScene> & p_scene)1307 Error SceneTree::change_scene_to(const Ref<PackedScene> &p_scene) {
1308 Node *new_scene = NULL;
1309 if (p_scene.is_valid()) {
1310 new_scene = p_scene->instance();
1311 ERR_FAIL_COND_V(!new_scene, ERR_CANT_CREATE);
1312 }
1313
1314 call_deferred("_change_scene", new_scene);
1315 return OK;
1316 }
1317
reload_current_scene()1318 Error SceneTree::reload_current_scene() {
1319 ERR_FAIL_COND_V(!current_scene, ERR_UNCONFIGURED);
1320 String fname = current_scene->get_filename();
1321 return change_scene(fname);
1322 }
1323
add_current_scene(Node * p_current)1324 void SceneTree::add_current_scene(Node *p_current) {
1325
1326 current_scene = p_current;
1327 root->add_child(p_current);
1328 }
1329
1330 #ifdef DEBUG_ENABLED
1331
_fill_array(Node * p_node,Array & array,int p_level)1332 static void _fill_array(Node *p_node, Array &array, int p_level) {
1333
1334 array.push_back(p_node->get_child_count());
1335 array.push_back(p_node->get_name());
1336 array.push_back(p_node->get_class());
1337 array.push_back(p_node->get_instance_id());
1338 for (int i = 0; i < p_node->get_child_count(); i++) {
1339
1340 _fill_array(p_node->get_child(i), array, p_level + 1);
1341 }
1342 }
1343
_debugger_request_tree()1344 void SceneTree::_debugger_request_tree() {
1345
1346 Array arr;
1347 _fill_array(root, arr, 0);
1348 ScriptDebugger::get_singleton()->send_message("scene_tree", arr);
1349 }
1350
_live_edit_node_path_func(const NodePath & p_path,int p_id)1351 void SceneTree::_live_edit_node_path_func(const NodePath &p_path, int p_id) {
1352
1353 live_edit_node_path_cache[p_id] = p_path;
1354 }
1355
_live_edit_res_path_func(const String & p_path,int p_id)1356 void SceneTree::_live_edit_res_path_func(const String &p_path, int p_id) {
1357
1358 live_edit_resource_cache[p_id] = p_path;
1359 }
1360
_live_edit_node_set_func(int p_id,const StringName & p_prop,const Variant & p_value)1361 void SceneTree::_live_edit_node_set_func(int p_id, const StringName &p_prop, const Variant &p_value) {
1362
1363 if (!live_edit_node_path_cache.has(p_id))
1364 return;
1365
1366 NodePath np = live_edit_node_path_cache[p_id];
1367 Node *base = NULL;
1368 if (root->has_node(live_edit_root))
1369 base = root->get_node(live_edit_root);
1370
1371 Map<String, Set<Node *> >::Element *E = live_scene_edit_cache.find(live_edit_scene);
1372 if (!E)
1373 return; //scene not editable
1374
1375 for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) {
1376
1377 Node *n = F->get();
1378
1379 if (base && !base->is_a_parent_of(n))
1380 continue;
1381
1382 if (!n->has_node(np))
1383 continue;
1384 Node *n2 = n->get_node(np);
1385
1386 n2->set(p_prop, p_value);
1387 }
1388 }
1389
_live_edit_node_set_res_func(int p_id,const StringName & p_prop,const String & p_value)1390 void SceneTree::_live_edit_node_set_res_func(int p_id, const StringName &p_prop, const String &p_value) {
1391
1392 RES r = ResourceLoader::load(p_value);
1393 if (!r.is_valid())
1394 return;
1395 _live_edit_node_set_func(p_id, p_prop, r);
1396 }
_live_edit_node_call_func(int p_id,const StringName & p_method,VARIANT_ARG_DECLARE)1397 void SceneTree::_live_edit_node_call_func(int p_id, const StringName &p_method, VARIANT_ARG_DECLARE) {
1398
1399 if (!live_edit_node_path_cache.has(p_id))
1400 return;
1401
1402 NodePath np = live_edit_node_path_cache[p_id];
1403 Node *base = NULL;
1404 if (root->has_node(live_edit_root))
1405 base = root->get_node(live_edit_root);
1406
1407 Map<String, Set<Node *> >::Element *E = live_scene_edit_cache.find(live_edit_scene);
1408 if (!E)
1409 return; //scene not editable
1410
1411 for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) {
1412
1413 Node *n = F->get();
1414
1415 if (base && !base->is_a_parent_of(n))
1416 continue;
1417
1418 if (!n->has_node(np))
1419 continue;
1420 Node *n2 = n->get_node(np);
1421
1422 n2->call(p_method, VARIANT_ARG_PASS);
1423 }
1424 }
_live_edit_res_set_func(int p_id,const StringName & p_prop,const Variant & p_value)1425 void SceneTree::_live_edit_res_set_func(int p_id, const StringName &p_prop, const Variant &p_value) {
1426
1427 if (!live_edit_resource_cache.has(p_id))
1428 return;
1429
1430 String resp = live_edit_resource_cache[p_id];
1431
1432 if (!ResourceCache::has(resp))
1433 return;
1434
1435 RES r = ResourceCache::get(resp);
1436 if (!r.is_valid())
1437 return;
1438
1439 r->set(p_prop, p_value);
1440 }
_live_edit_res_set_res_func(int p_id,const StringName & p_prop,const String & p_value)1441 void SceneTree::_live_edit_res_set_res_func(int p_id, const StringName &p_prop, const String &p_value) {
1442
1443 RES r = ResourceLoader::load(p_value);
1444 if (!r.is_valid())
1445 return;
1446 _live_edit_res_set_func(p_id, p_prop, r);
1447 }
_live_edit_res_call_func(int p_id,const StringName & p_method,VARIANT_ARG_DECLARE)1448 void SceneTree::_live_edit_res_call_func(int p_id, const StringName &p_method, VARIANT_ARG_DECLARE) {
1449
1450 if (!live_edit_resource_cache.has(p_id))
1451 return;
1452
1453 String resp = live_edit_resource_cache[p_id];
1454
1455 if (!ResourceCache::has(resp))
1456 return;
1457
1458 RES r = ResourceCache::get(resp);
1459 if (!r.is_valid())
1460 return;
1461
1462 r->call(p_method, VARIANT_ARG_PASS);
1463 }
1464
_live_edit_root_func(const NodePath & p_scene_path,const String & p_scene_from)1465 void SceneTree::_live_edit_root_func(const NodePath &p_scene_path, const String &p_scene_from) {
1466
1467 live_edit_root = p_scene_path;
1468 live_edit_scene = p_scene_from;
1469 }
1470
_live_edit_create_node_func(const NodePath & p_parent,const String & p_type,const String & p_name)1471 void SceneTree::_live_edit_create_node_func(const NodePath &p_parent, const String &p_type, const String &p_name) {
1472
1473 Node *base = NULL;
1474 if (root->has_node(live_edit_root))
1475 base = root->get_node(live_edit_root);
1476
1477 Map<String, Set<Node *> >::Element *E = live_scene_edit_cache.find(live_edit_scene);
1478 if (!E)
1479 return; //scene not editable
1480
1481 for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) {
1482
1483 Node *n = F->get();
1484
1485 if (base && !base->is_a_parent_of(n))
1486 continue;
1487
1488 if (!n->has_node(p_parent))
1489 continue;
1490 Node *n2 = n->get_node(p_parent);
1491
1492 Node *no = Object::cast_to<Node>(ClassDB::instance(p_type));
1493 if (!no) {
1494 continue;
1495 }
1496
1497 no->set_name(p_name);
1498 n2->add_child(no);
1499 }
1500 }
_live_edit_instance_node_func(const NodePath & p_parent,const String & p_path,const String & p_name)1501 void SceneTree::_live_edit_instance_node_func(const NodePath &p_parent, const String &p_path, const String &p_name) {
1502
1503 Ref<PackedScene> ps = ResourceLoader::load(p_path);
1504
1505 if (!ps.is_valid())
1506 return;
1507
1508 Node *base = NULL;
1509 if (root->has_node(live_edit_root))
1510 base = root->get_node(live_edit_root);
1511
1512 Map<String, Set<Node *> >::Element *E = live_scene_edit_cache.find(live_edit_scene);
1513 if (!E)
1514 return; //scene not editable
1515
1516 for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) {
1517
1518 Node *n = F->get();
1519
1520 if (base && !base->is_a_parent_of(n))
1521 continue;
1522
1523 if (!n->has_node(p_parent))
1524 continue;
1525 Node *n2 = n->get_node(p_parent);
1526
1527 Node *no = ps->instance();
1528 if (!no) {
1529 continue;
1530 }
1531
1532 no->set_name(p_name);
1533 n2->add_child(no);
1534 }
1535 }
_live_edit_remove_node_func(const NodePath & p_at)1536 void SceneTree::_live_edit_remove_node_func(const NodePath &p_at) {
1537
1538 Node *base = NULL;
1539 if (root->has_node(live_edit_root))
1540 base = root->get_node(live_edit_root);
1541
1542 Map<String, Set<Node *> >::Element *E = live_scene_edit_cache.find(live_edit_scene);
1543 if (!E)
1544 return; //scene not editable
1545
1546 for (Set<Node *>::Element *F = E->get().front(); F;) {
1547
1548 Set<Node *>::Element *N = F->next();
1549
1550 Node *n = F->get();
1551
1552 if (base && !base->is_a_parent_of(n))
1553 continue;
1554
1555 if (!n->has_node(p_at))
1556 continue;
1557 Node *n2 = n->get_node(p_at);
1558
1559 memdelete(n2);
1560
1561 F = N;
1562 }
1563 }
_live_edit_remove_and_keep_node_func(const NodePath & p_at,ObjectID p_keep_id)1564 void SceneTree::_live_edit_remove_and_keep_node_func(const NodePath &p_at, ObjectID p_keep_id) {
1565
1566 Node *base = NULL;
1567 if (root->has_node(live_edit_root))
1568 base = root->get_node(live_edit_root);
1569
1570 Map<String, Set<Node *> >::Element *E = live_scene_edit_cache.find(live_edit_scene);
1571 if (!E)
1572 return; //scene not editable
1573
1574 for (Set<Node *>::Element *F = E->get().front(); F;) {
1575
1576 Set<Node *>::Element *N = F->next();
1577
1578 Node *n = F->get();
1579
1580 if (base && !base->is_a_parent_of(n))
1581 continue;
1582
1583 if (!n->has_node(p_at))
1584 continue;
1585
1586 Node *n2 = n->get_node(p_at);
1587
1588 n2->get_parent()->remove_child(n2);
1589
1590 live_edit_remove_list[n][p_keep_id] = n2;
1591
1592 F = N;
1593 }
1594 }
_live_edit_restore_node_func(ObjectID p_id,const NodePath & p_at,int p_at_pos)1595 void SceneTree::_live_edit_restore_node_func(ObjectID p_id, const NodePath &p_at, int p_at_pos) {
1596
1597 Node *base = NULL;
1598 if (root->has_node(live_edit_root))
1599 base = root->get_node(live_edit_root);
1600
1601 Map<String, Set<Node *> >::Element *E = live_scene_edit_cache.find(live_edit_scene);
1602 if (!E)
1603 return; //scene not editable
1604
1605 for (Set<Node *>::Element *F = E->get().front(); F;) {
1606
1607 Set<Node *>::Element *N = F->next();
1608
1609 Node *n = F->get();
1610
1611 if (base && !base->is_a_parent_of(n))
1612 continue;
1613
1614 if (!n->has_node(p_at))
1615 continue;
1616 Node *n2 = n->get_node(p_at);
1617
1618 Map<Node *, Map<ObjectID, Node *> >::Element *EN = live_edit_remove_list.find(n);
1619
1620 if (!EN)
1621 continue;
1622
1623 Map<ObjectID, Node *>::Element *FN = EN->get().find(p_id);
1624
1625 if (!FN)
1626 continue;
1627 n2->add_child(FN->get());
1628
1629 EN->get().erase(FN);
1630
1631 if (EN->get().size() == 0) {
1632 live_edit_remove_list.erase(EN);
1633 }
1634
1635 F = N;
1636 }
1637 }
_live_edit_duplicate_node_func(const NodePath & p_at,const String & p_new_name)1638 void SceneTree::_live_edit_duplicate_node_func(const NodePath &p_at, const String &p_new_name) {
1639
1640 Node *base = NULL;
1641 if (root->has_node(live_edit_root))
1642 base = root->get_node(live_edit_root);
1643
1644 Map<String, Set<Node *> >::Element *E = live_scene_edit_cache.find(live_edit_scene);
1645 if (!E)
1646 return; //scene not editable
1647
1648 for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) {
1649
1650 Node *n = F->get();
1651
1652 if (base && !base->is_a_parent_of(n))
1653 continue;
1654
1655 if (!n->has_node(p_at))
1656 continue;
1657 Node *n2 = n->get_node(p_at);
1658
1659 Node *dup = n2->duplicate(Node::DUPLICATE_SIGNALS | Node::DUPLICATE_GROUPS | Node::DUPLICATE_SCRIPTS);
1660
1661 if (!dup)
1662 continue;
1663
1664 dup->set_name(p_new_name);
1665 n2->get_parent()->add_child(dup);
1666 }
1667 }
_live_edit_reparent_node_func(const NodePath & p_at,const NodePath & p_new_place,const String & p_new_name,int p_at_pos)1668 void SceneTree::_live_edit_reparent_node_func(const NodePath &p_at, const NodePath &p_new_place, const String &p_new_name, int p_at_pos) {
1669
1670 Node *base = NULL;
1671 if (root->has_node(live_edit_root))
1672 base = root->get_node(live_edit_root);
1673
1674 Map<String, Set<Node *> >::Element *E = live_scene_edit_cache.find(live_edit_scene);
1675 if (!E)
1676 return; //scene not editable
1677
1678 for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) {
1679
1680 Node *n = F->get();
1681
1682 if (base && !base->is_a_parent_of(n))
1683 continue;
1684
1685 if (!n->has_node(p_at))
1686 continue;
1687 Node *nfrom = n->get_node(p_at);
1688
1689 if (!n->has_node(p_new_place))
1690 continue;
1691 Node *nto = n->get_node(p_new_place);
1692
1693 nfrom->get_parent()->remove_child(nfrom);
1694 nfrom->set_name(p_new_name);
1695
1696 nto->add_child(nfrom);
1697 if (p_at_pos >= 0)
1698 nto->move_child(nfrom, p_at_pos);
1699 }
1700 }
1701
1702 #endif
1703
drop_files(const Vector<String> & p_files,int p_from_screen)1704 void SceneTree::drop_files(const Vector<String> &p_files, int p_from_screen) {
1705
1706 emit_signal("files_dropped", p_files, p_from_screen);
1707 MainLoop::drop_files(p_files, p_from_screen);
1708 }
1709
global_menu_action(const Variant & p_id,const Variant & p_meta)1710 void SceneTree::global_menu_action(const Variant &p_id, const Variant &p_meta) {
1711
1712 emit_signal("global_menu_action", p_id, p_meta);
1713 MainLoop::global_menu_action(p_id, p_meta);
1714 }
1715
create_timer(float p_delay_sec,bool p_process_pause)1716 Ref<SceneTreeTimer> SceneTree::create_timer(float p_delay_sec, bool p_process_pause) {
1717
1718 Ref<SceneTreeTimer> stt;
1719 stt.instance();
1720 stt->set_pause_mode_process(p_process_pause);
1721 stt->set_time_left(p_delay_sec);
1722 timers.push_back(stt);
1723 return stt;
1724 }
1725
_network_peer_connected(int p_id)1726 void SceneTree::_network_peer_connected(int p_id) {
1727
1728 emit_signal("network_peer_connected", p_id);
1729 }
1730
_network_peer_disconnected(int p_id)1731 void SceneTree::_network_peer_disconnected(int p_id) {
1732
1733 emit_signal("network_peer_disconnected", p_id);
1734 }
1735
_connected_to_server()1736 void SceneTree::_connected_to_server() {
1737
1738 emit_signal("connected_to_server");
1739 }
1740
_connection_failed()1741 void SceneTree::_connection_failed() {
1742
1743 emit_signal("connection_failed");
1744 }
1745
_server_disconnected()1746 void SceneTree::_server_disconnected() {
1747
1748 emit_signal("server_disconnected");
1749 }
1750
get_multiplayer() const1751 Ref<MultiplayerAPI> SceneTree::get_multiplayer() const {
1752 return multiplayer;
1753 }
1754
set_multiplayer_poll_enabled(bool p_enabled)1755 void SceneTree::set_multiplayer_poll_enabled(bool p_enabled) {
1756 multiplayer_poll = p_enabled;
1757 }
1758
is_multiplayer_poll_enabled() const1759 bool SceneTree::is_multiplayer_poll_enabled() const {
1760 return multiplayer_poll;
1761 }
1762
set_multiplayer(Ref<MultiplayerAPI> p_multiplayer)1763 void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer) {
1764 ERR_FAIL_COND(!p_multiplayer.is_valid());
1765
1766 if (multiplayer.is_valid()) {
1767 multiplayer->disconnect("network_peer_connected", this, "_network_peer_connected");
1768 multiplayer->disconnect("network_peer_disconnected", this, "_network_peer_disconnected");
1769 multiplayer->disconnect("connected_to_server", this, "_connected_to_server");
1770 multiplayer->disconnect("connection_failed", this, "_connection_failed");
1771 multiplayer->disconnect("server_disconnected", this, "_server_disconnected");
1772 }
1773
1774 multiplayer = p_multiplayer;
1775 multiplayer->set_root_node(root);
1776
1777 multiplayer->connect("network_peer_connected", this, "_network_peer_connected");
1778 multiplayer->connect("network_peer_disconnected", this, "_network_peer_disconnected");
1779 multiplayer->connect("connected_to_server", this, "_connected_to_server");
1780 multiplayer->connect("connection_failed", this, "_connection_failed");
1781 multiplayer->connect("server_disconnected", this, "_server_disconnected");
1782 }
1783
set_network_peer(const Ref<NetworkedMultiplayerPeer> & p_network_peer)1784 void SceneTree::set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_network_peer) {
1785
1786 multiplayer->set_network_peer(p_network_peer);
1787 }
1788
get_network_peer() const1789 Ref<NetworkedMultiplayerPeer> SceneTree::get_network_peer() const {
1790
1791 return multiplayer->get_network_peer();
1792 }
1793
is_network_server() const1794 bool SceneTree::is_network_server() const {
1795
1796 return multiplayer->is_network_server();
1797 }
1798
has_network_peer() const1799 bool SceneTree::has_network_peer() const {
1800 return multiplayer->has_network_peer();
1801 }
1802
get_network_unique_id() const1803 int SceneTree::get_network_unique_id() const {
1804
1805 return multiplayer->get_network_unique_id();
1806 }
1807
get_network_connected_peers() const1808 Vector<int> SceneTree::get_network_connected_peers() const {
1809
1810 return multiplayer->get_network_connected_peers();
1811 }
1812
get_rpc_sender_id() const1813 int SceneTree::get_rpc_sender_id() const {
1814 return multiplayer->get_rpc_sender_id();
1815 }
1816
set_refuse_new_network_connections(bool p_refuse)1817 void SceneTree::set_refuse_new_network_connections(bool p_refuse) {
1818 multiplayer->set_refuse_new_network_connections(p_refuse);
1819 }
1820
is_refusing_new_network_connections() const1821 bool SceneTree::is_refusing_new_network_connections() const {
1822 return multiplayer->is_refusing_new_network_connections();
1823 }
1824
_bind_methods()1825 void SceneTree::_bind_methods() {
1826
1827 ClassDB::bind_method(D_METHOD("get_root"), &SceneTree::get_root);
1828 ClassDB::bind_method(D_METHOD("has_group", "name"), &SceneTree::has_group);
1829
1830 ClassDB::bind_method(D_METHOD("set_auto_accept_quit", "enabled"), &SceneTree::set_auto_accept_quit);
1831 ClassDB::bind_method(D_METHOD("set_quit_on_go_back", "enabled"), &SceneTree::set_quit_on_go_back);
1832
1833 ClassDB::bind_method(D_METHOD("set_debug_collisions_hint", "enable"), &SceneTree::set_debug_collisions_hint);
1834 ClassDB::bind_method(D_METHOD("is_debugging_collisions_hint"), &SceneTree::is_debugging_collisions_hint);
1835 ClassDB::bind_method(D_METHOD("set_debug_navigation_hint", "enable"), &SceneTree::set_debug_navigation_hint);
1836 ClassDB::bind_method(D_METHOD("is_debugging_navigation_hint"), &SceneTree::is_debugging_navigation_hint);
1837
1838 ClassDB::bind_method(D_METHOD("set_edited_scene_root", "scene"), &SceneTree::set_edited_scene_root);
1839 ClassDB::bind_method(D_METHOD("get_edited_scene_root"), &SceneTree::get_edited_scene_root);
1840
1841 ClassDB::bind_method(D_METHOD("set_pause", "enable"), &SceneTree::set_pause);
1842 ClassDB::bind_method(D_METHOD("is_paused"), &SceneTree::is_paused);
1843 ClassDB::bind_method(D_METHOD("set_input_as_handled"), &SceneTree::set_input_as_handled);
1844 ClassDB::bind_method(D_METHOD("is_input_handled"), &SceneTree::is_input_handled);
1845
1846 ClassDB::bind_method(D_METHOD("create_timer", "time_sec", "pause_mode_process"), &SceneTree::create_timer, DEFVAL(true));
1847
1848 ClassDB::bind_method(D_METHOD("get_node_count"), &SceneTree::get_node_count);
1849 ClassDB::bind_method(D_METHOD("get_frame"), &SceneTree::get_frame);
1850 ClassDB::bind_method(D_METHOD("quit", "exit_code"), &SceneTree::quit, DEFVAL(-1));
1851
1852 ClassDB::bind_method(D_METHOD("set_screen_stretch", "mode", "aspect", "minsize", "shrink"), &SceneTree::set_screen_stretch, DEFVAL(1));
1853
1854 ClassDB::bind_method(D_METHOD("queue_delete", "obj"), &SceneTree::queue_delete);
1855
1856 MethodInfo mi;
1857 mi.name = "call_group_flags";
1858 mi.arguments.push_back(PropertyInfo(Variant::INT, "flags"));
1859 mi.arguments.push_back(PropertyInfo(Variant::STRING, "group"));
1860 mi.arguments.push_back(PropertyInfo(Variant::STRING, "method"));
1861
1862 ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_group_flags", &SceneTree::_call_group_flags, mi);
1863
1864 ClassDB::bind_method(D_METHOD("notify_group_flags", "call_flags", "group", "notification"), &SceneTree::notify_group_flags);
1865 ClassDB::bind_method(D_METHOD("set_group_flags", "call_flags", "group", "property", "value"), &SceneTree::set_group_flags);
1866
1867 MethodInfo mi2;
1868 mi2.name = "call_group";
1869 mi2.arguments.push_back(PropertyInfo(Variant::STRING, "group"));
1870 mi2.arguments.push_back(PropertyInfo(Variant::STRING, "method"));
1871
1872 ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_group", &SceneTree::_call_group, mi2);
1873
1874 ClassDB::bind_method(D_METHOD("notify_group", "group", "notification"), &SceneTree::notify_group);
1875 ClassDB::bind_method(D_METHOD("set_group", "group", "property", "value"), &SceneTree::set_group);
1876
1877 ClassDB::bind_method(D_METHOD("get_nodes_in_group", "group"), &SceneTree::_get_nodes_in_group);
1878
1879 ClassDB::bind_method(D_METHOD("set_current_scene", "child_node"), &SceneTree::set_current_scene);
1880 ClassDB::bind_method(D_METHOD("get_current_scene"), &SceneTree::get_current_scene);
1881
1882 ClassDB::bind_method(D_METHOD("change_scene", "path"), &SceneTree::change_scene);
1883 ClassDB::bind_method(D_METHOD("change_scene_to", "packed_scene"), &SceneTree::change_scene_to);
1884
1885 ClassDB::bind_method(D_METHOD("reload_current_scene"), &SceneTree::reload_current_scene);
1886
1887 ClassDB::bind_method(D_METHOD("_change_scene"), &SceneTree::_change_scene);
1888
1889 ClassDB::bind_method(D_METHOD("set_multiplayer", "multiplayer"), &SceneTree::set_multiplayer);
1890 ClassDB::bind_method(D_METHOD("get_multiplayer"), &SceneTree::get_multiplayer);
1891 ClassDB::bind_method(D_METHOD("set_multiplayer_poll_enabled", "enabled"), &SceneTree::set_multiplayer_poll_enabled);
1892 ClassDB::bind_method(D_METHOD("is_multiplayer_poll_enabled"), &SceneTree::is_multiplayer_poll_enabled);
1893 ClassDB::bind_method(D_METHOD("set_network_peer", "peer"), &SceneTree::set_network_peer);
1894 ClassDB::bind_method(D_METHOD("get_network_peer"), &SceneTree::get_network_peer);
1895 ClassDB::bind_method(D_METHOD("is_network_server"), &SceneTree::is_network_server);
1896 ClassDB::bind_method(D_METHOD("has_network_peer"), &SceneTree::has_network_peer);
1897 ClassDB::bind_method(D_METHOD("get_network_connected_peers"), &SceneTree::get_network_connected_peers);
1898 ClassDB::bind_method(D_METHOD("get_network_unique_id"), &SceneTree::get_network_unique_id);
1899 ClassDB::bind_method(D_METHOD("get_rpc_sender_id"), &SceneTree::get_rpc_sender_id);
1900 ClassDB::bind_method(D_METHOD("set_refuse_new_network_connections", "refuse"), &SceneTree::set_refuse_new_network_connections);
1901 ClassDB::bind_method(D_METHOD("is_refusing_new_network_connections"), &SceneTree::is_refusing_new_network_connections);
1902 ClassDB::bind_method(D_METHOD("_network_peer_connected"), &SceneTree::_network_peer_connected);
1903 ClassDB::bind_method(D_METHOD("_network_peer_disconnected"), &SceneTree::_network_peer_disconnected);
1904 ClassDB::bind_method(D_METHOD("_connected_to_server"), &SceneTree::_connected_to_server);
1905 ClassDB::bind_method(D_METHOD("_connection_failed"), &SceneTree::_connection_failed);
1906 ClassDB::bind_method(D_METHOD("_server_disconnected"), &SceneTree::_server_disconnected);
1907
1908 ClassDB::bind_method(D_METHOD("set_use_font_oversampling", "enable"), &SceneTree::set_use_font_oversampling);
1909 ClassDB::bind_method(D_METHOD("is_using_font_oversampling"), &SceneTree::is_using_font_oversampling);
1910
1911 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_collisions_hint"), "set_debug_collisions_hint", "is_debugging_collisions_hint");
1912 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_navigation_hint"), "set_debug_navigation_hint", "is_debugging_navigation_hint");
1913 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused"), "set_pause", "is_paused");
1914 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_network_connections"), "set_refuse_new_network_connections", "is_refusing_new_network_connections");
1915 ADD_PROPERTY_DEFAULT("refuse_new_network_connections", false);
1916 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_font_oversampling"), "set_use_font_oversampling", "is_using_font_oversampling");
1917 ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "edited_scene_root", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_edited_scene_root", "get_edited_scene_root");
1918 ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "current_scene", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_current_scene", "get_current_scene");
1919 ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "NetworkedMultiplayerPeer", 0), "set_network_peer", "get_network_peer");
1920 ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "", "get_root");
1921 ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", 0), "set_multiplayer", "get_multiplayer");
1922 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multiplayer_poll"), "set_multiplayer_poll_enabled", "is_multiplayer_poll_enabled");
1923
1924 ADD_SIGNAL(MethodInfo("tree_changed"));
1925 ADD_SIGNAL(MethodInfo("node_added", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
1926 ADD_SIGNAL(MethodInfo("node_removed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
1927 ADD_SIGNAL(MethodInfo("node_renamed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
1928 ADD_SIGNAL(MethodInfo("screen_resized"));
1929 ADD_SIGNAL(MethodInfo("node_configuration_warning_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
1930
1931 ADD_SIGNAL(MethodInfo("idle_frame"));
1932 ADD_SIGNAL(MethodInfo("physics_frame"));
1933
1934 ADD_SIGNAL(MethodInfo("files_dropped", PropertyInfo(Variant::POOL_STRING_ARRAY, "files"), PropertyInfo(Variant::INT, "screen")));
1935 ADD_SIGNAL(MethodInfo("global_menu_action", PropertyInfo(Variant::NIL, "id"), PropertyInfo(Variant::NIL, "meta")));
1936 ADD_SIGNAL(MethodInfo("network_peer_connected", PropertyInfo(Variant::INT, "id")));
1937 ADD_SIGNAL(MethodInfo("network_peer_disconnected", PropertyInfo(Variant::INT, "id")));
1938 ADD_SIGNAL(MethodInfo("connected_to_server"));
1939 ADD_SIGNAL(MethodInfo("connection_failed"));
1940 ADD_SIGNAL(MethodInfo("server_disconnected"));
1941
1942 BIND_ENUM_CONSTANT(GROUP_CALL_DEFAULT);
1943 BIND_ENUM_CONSTANT(GROUP_CALL_REVERSE);
1944 BIND_ENUM_CONSTANT(GROUP_CALL_REALTIME);
1945 BIND_ENUM_CONSTANT(GROUP_CALL_UNIQUE);
1946
1947 BIND_ENUM_CONSTANT(STRETCH_MODE_DISABLED);
1948 BIND_ENUM_CONSTANT(STRETCH_MODE_2D);
1949 BIND_ENUM_CONSTANT(STRETCH_MODE_VIEWPORT);
1950
1951 BIND_ENUM_CONSTANT(STRETCH_ASPECT_IGNORE);
1952 BIND_ENUM_CONSTANT(STRETCH_ASPECT_KEEP);
1953 BIND_ENUM_CONSTANT(STRETCH_ASPECT_KEEP_WIDTH);
1954 BIND_ENUM_CONSTANT(STRETCH_ASPECT_KEEP_HEIGHT);
1955 BIND_ENUM_CONSTANT(STRETCH_ASPECT_EXPAND);
1956 }
1957
1958 SceneTree *SceneTree::singleton = NULL;
1959
1960 SceneTree::IdleCallback SceneTree::idle_callbacks[SceneTree::MAX_IDLE_CALLBACKS];
1961 int SceneTree::idle_callback_count = 0;
1962
_call_idle_callbacks()1963 void SceneTree::_call_idle_callbacks() {
1964
1965 for (int i = 0; i < idle_callback_count; i++) {
1966 idle_callbacks[i]();
1967 }
1968 }
1969
add_idle_callback(IdleCallback p_callback)1970 void SceneTree::add_idle_callback(IdleCallback p_callback) {
1971 ERR_FAIL_COND(idle_callback_count >= MAX_IDLE_CALLBACKS);
1972 idle_callbacks[idle_callback_count++] = p_callback;
1973 }
1974
set_use_font_oversampling(bool p_oversampling)1975 void SceneTree::set_use_font_oversampling(bool p_oversampling) {
1976
1977 if (use_font_oversampling == p_oversampling)
1978 return;
1979
1980 use_font_oversampling = p_oversampling;
1981 _update_root_rect();
1982 }
1983
is_using_font_oversampling() const1984 bool SceneTree::is_using_font_oversampling() const {
1985 return use_font_oversampling;
1986 }
1987
get_argument_options(const StringName & p_function,int p_idx,List<String> * r_options) const1988 void SceneTree::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
1989
1990 if (p_function == "change_scene") {
1991 DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES);
1992 List<String> directories;
1993 directories.push_back(dir_access->get_current_dir());
1994
1995 while (!directories.empty()) {
1996 dir_access->change_dir(directories.back()->get());
1997 directories.pop_back();
1998
1999 dir_access->list_dir_begin();
2000 String filename = dir_access->get_next();
2001
2002 while (filename != "") {
2003 if (filename == "." || filename == "..") {
2004 filename = dir_access->get_next();
2005 continue;
2006 }
2007
2008 if (dir_access->dir_exists(filename)) {
2009 directories.push_back(dir_access->get_current_dir().plus_file(filename));
2010 } else if (filename.ends_with(".tscn") || filename.ends_with(".scn")) {
2011 r_options->push_back("\"" + dir_access->get_current_dir().plus_file(filename) + "\"");
2012 }
2013
2014 filename = dir_access->get_next();
2015 }
2016 }
2017 }
2018 }
2019
SceneTree()2020 SceneTree::SceneTree() {
2021
2022 if (singleton == NULL) singleton = this;
2023 _quit = false;
2024 accept_quit = true;
2025 quit_on_go_back = true;
2026 initialized = false;
2027 use_font_oversampling = false;
2028 #ifdef DEBUG_ENABLED
2029 debug_collisions_hint = false;
2030 debug_navigation_hint = false;
2031 #endif
2032 debug_collisions_color = GLOBAL_DEF("debug/shapes/collision/shape_color", Color(0.0, 0.6, 0.7, 0.5));
2033 debug_collision_contact_color = GLOBAL_DEF("debug/shapes/collision/contact_color", Color(1.0, 0.2, 0.1, 0.8));
2034 debug_navigation_color = GLOBAL_DEF("debug/shapes/navigation/geometry_color", Color(0.1, 1.0, 0.7, 0.4));
2035 debug_navigation_disabled_color = GLOBAL_DEF("debug/shapes/navigation/disabled_geometry_color", Color(1.0, 0.7, 0.1, 0.4));
2036 collision_debug_contacts = GLOBAL_DEF("debug/shapes/collision/max_contacts_displayed", 10000);
2037 ProjectSettings::get_singleton()->set_custom_property_info("debug/shapes/collision/max_contacts_displayed", PropertyInfo(Variant::INT, "debug/shapes/collision/max_contacts_displayed", PROPERTY_HINT_RANGE, "0,20000,1")); // No negative
2038
2039 tree_version = 1;
2040 physics_process_time = 1;
2041 idle_process_time = 1;
2042
2043 root = NULL;
2044 input_handled = false;
2045 pause = false;
2046 current_frame = 0;
2047 current_event = 0;
2048 tree_changed_name = "tree_changed";
2049 node_added_name = "node_added";
2050 node_removed_name = "node_removed";
2051 node_renamed_name = "node_renamed";
2052 ugc_locked = false;
2053 call_lock = 0;
2054 root_lock = 0;
2055 node_count = 0;
2056
2057 //create with mainloop
2058
2059 root = memnew(Viewport);
2060 root->set_name("root");
2061 root->set_handle_input_locally(false);
2062 if (!root->get_world().is_valid())
2063 root->set_world(Ref<World>(memnew(World)));
2064
2065 // Initialize network state
2066 multiplayer_poll = true;
2067 set_multiplayer(Ref<MultiplayerAPI>(memnew(MultiplayerAPI)));
2068
2069 //root->set_world_2d( Ref<World2D>( memnew( World2D )));
2070 root->set_as_audio_listener(true);
2071 root->set_as_audio_listener_2d(true);
2072 current_scene = NULL;
2073
2074 int ref_atlas_size = GLOBAL_DEF("rendering/quality/reflections/atlas_size", 2048);
2075 ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/reflections/atlas_size", PropertyInfo(Variant::INT, "rendering/quality/reflections/atlas_size", PROPERTY_HINT_RANGE, "0,8192,or_greater")); //next_power_of_2 will return a 0 as min value
2076 int ref_atlas_subdiv = GLOBAL_DEF("rendering/quality/reflections/atlas_subdiv", 8);
2077 ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/reflections/atlas_subdiv", PropertyInfo(Variant::INT, "rendering/quality/reflections/atlas_subdiv", PROPERTY_HINT_RANGE, "0,32,or_greater")); //next_power_of_2 will return a 0 as min value
2078 int msaa_mode = GLOBAL_DEF("rendering/quality/filters/msaa", 0);
2079 ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/msaa", PropertyInfo(Variant::INT, "rendering/quality/filters/msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x,AndroidVR 2x,AndroidVR 4x"));
2080 root->set_msaa(Viewport::MSAA(msaa_mode));
2081
2082 GLOBAL_DEF("rendering/quality/depth/hdr", true);
2083 GLOBAL_DEF("rendering/quality/depth/hdr.mobile", false);
2084
2085 bool hdr = GLOBAL_GET("rendering/quality/depth/hdr");
2086 root->set_hdr(hdr);
2087
2088 VS::get_singleton()->scenario_set_reflection_atlas_size(root->get_world()->get_scenario(), ref_atlas_size, ref_atlas_subdiv);
2089
2090 { //load default fallback environment
2091 //get possible extensions
2092 List<String> exts;
2093 ResourceLoader::get_recognized_extensions_for_type("Environment", &exts);
2094 String ext_hint;
2095 for (List<String>::Element *E = exts.front(); E; E = E->next()) {
2096 if (ext_hint != String())
2097 ext_hint += ",";
2098 ext_hint += "*." + E->get();
2099 }
2100 //get path
2101 String env_path = GLOBAL_DEF("rendering/environment/default_environment", "");
2102 //setup property
2103 ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/default_environment", PropertyInfo(Variant::STRING, "rendering/viewport/default_environment", PROPERTY_HINT_FILE, ext_hint));
2104 env_path = env_path.strip_edges();
2105 if (env_path != String()) {
2106 Ref<Environment> env = ResourceLoader::load(env_path);
2107 if (env.is_valid()) {
2108 root->get_world()->set_fallback_environment(env);
2109 } else {
2110 if (Engine::get_singleton()->is_editor_hint()) {
2111 //file was erased, clear the field.
2112 ProjectSettings::get_singleton()->set("rendering/environment/default_environment", "");
2113 } else {
2114 //file was erased, notify user.
2115 ERR_PRINTS(RTR("Default Environment as specified in Project Settings (Rendering -> Environment -> Default Environment) could not be loaded."));
2116 }
2117 }
2118 }
2119 }
2120
2121 stretch_mode = STRETCH_MODE_DISABLED;
2122 stretch_aspect = STRETCH_ASPECT_IGNORE;
2123 stretch_shrink = 1;
2124
2125 last_screen_size = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height);
2126 _update_root_rect();
2127
2128 if (ScriptDebugger::get_singleton()) {
2129 if (ScriptDebugger::get_singleton()->is_remote()) {
2130 ScriptDebuggerRemote *remote_debugger = static_cast<ScriptDebuggerRemote *>(ScriptDebugger::get_singleton());
2131
2132 remote_debugger->set_scene_tree(this);
2133 }
2134 ScriptDebugger::get_singleton()->set_multiplayer(multiplayer);
2135 }
2136
2137 root->set_physics_object_picking(GLOBAL_DEF("physics/common/enable_object_picking", true));
2138
2139 #ifdef TOOLS_ENABLED
2140 edited_scene_root = NULL;
2141 #endif
2142
2143 #ifdef DEBUG_ENABLED
2144
2145 live_edit_root = NodePath("/root");
2146
2147 #endif
2148 }
2149
~SceneTree()2150 SceneTree::~SceneTree() {
2151 if (root) {
2152 root->_set_tree(NULL);
2153 root->_propagate_after_exit_tree();
2154 memdelete(root);
2155 }
2156
2157 if (singleton == this) singleton = NULL;
2158 }
2159