diff options
Diffstat (limited to 'scene/main/scene_tree.cpp')
-rw-r--r-- | scene/main/scene_tree.cpp | 1259 |
1 files changed, 274 insertions, 985 deletions
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 238d6c20cc..adefb53862 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -30,6 +30,8 @@ #include "scene_tree.h" +#include "core/debugger/engine_debugger.h" +#include "core/input/input.h" #include "core/io/marshalls.h" #include "core/io/resource_loader.h" #include "core/message_queue.h" @@ -38,26 +40,26 @@ #include "core/os/os.h" #include "core/print_string.h" #include "core/project_settings.h" -#include "main/input_default.h" #include "node.h" -#include "scene/debugger/script_debugger_remote.h" +#include "scene/debugger/scene_debugger.h" #include "scene/resources/dynamic_font.h" #include "scene/resources/material.h" #include "scene/resources/mesh.h" #include "scene/resources/packed_scene.h" #include "scene/scene_string_names.h" -#include "servers/physics_2d_server.h" -#include "servers/physics_server.h" -#include "viewport.h" +#include "servers/display_server.h" +#include "servers/navigation_server_3d.h" +#include "servers/physics_server_2d.h" +#include "servers/physics_server_3d.h" +#include "window.h" #include <stdio.h> void SceneTreeTimer::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_time_left", "time"), &SceneTreeTimer::set_time_left); ClassDB::bind_method(D_METHOD("get_time_left"), &SceneTreeTimer::get_time_left); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "time_left"), "set_time_left", "get_time_left"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_left"), "set_time_left", "get_time_left"); ADD_SIGNAL(MethodInfo("timeout")); } @@ -71,7 +73,6 @@ float SceneTreeTimer::get_time_left() const { } void SceneTreeTimer::set_pause_mode_process(bool p_pause_mode_process) { - process_pause = p_pause_mode_process; } @@ -80,13 +81,12 @@ bool SceneTreeTimer::is_pause_mode_process() { } void SceneTreeTimer::release_connections() { - List<Connection> connections; get_all_signal_connections(&connections); for (List<Connection>::Element *E = connections.front(); E; E = E->next()) { Connection const &connection = E->get(); - disconnect(connection.signal, connection.target, connection.method); + disconnect(connection.signal.get_name(), connection.callable); } } @@ -96,33 +96,29 @@ SceneTreeTimer::SceneTreeTimer() { } void SceneTree::tree_changed() { - tree_version++; emit_signal(tree_changed_name); } void SceneTree::node_added(Node *p_node) { - emit_signal(node_added_name, p_node); } void SceneTree::node_removed(Node *p_node) { - if (current_scene == p_node) { - current_scene = NULL; + current_scene = nullptr; } emit_signal(node_removed_name, p_node); - if (call_lock > 0) + if (call_lock > 0) { call_skip.insert(p_node); + } } void SceneTree::node_renamed(Node *p_node) { - emit_signal(node_renamed_name, p_node); } SceneTree::Group *SceneTree::add_to_group(const StringName &p_group, Node *p_node) { - Map<StringName, Group>::Element *E = group_map.find(p_group); if (!E) { E = group_map.insert(p_group, Group()); @@ -136,26 +132,25 @@ SceneTree::Group *SceneTree::add_to_group(const StringName &p_group, Node *p_nod } void SceneTree::remove_from_group(const StringName &p_group, Node *p_node) { - Map<StringName, Group>::Element *E = group_map.find(p_group); ERR_FAIL_COND(!E); E->get().nodes.erase(p_node); - if (E->get().nodes.empty()) + if (E->get().nodes.empty()) { group_map.erase(E); + } } void SceneTree::make_group_changed(const StringName &p_group) { Map<StringName, Group>::Element *E = group_map.find(p_group); - if (E) + if (E) { E->get().changed = true; + } } void SceneTree::flush_transform_notifications() { - SelfList<Node> *n = xform_change_list.first(); while (n) { - Node *node = n->self(); SelfList<Node> *nx = n->next(); xform_change_list.remove(n); @@ -165,17 +160,17 @@ void SceneTree::flush_transform_notifications() { } void SceneTree::_flush_ugc() { - ugc_locked = true; while (unique_group_calls.size()) { - - Map<UGCall, Vector<Variant> >::Element *E = unique_group_calls.front(); + Map<UGCall, Vector<Variant>>::Element *E = unique_group_calls.front(); Variant v[VARIANT_ARG_MAX]; - for (int i = 0; i < E->get().size(); i++) + for (int i = 0; i < E->get().size(); i++) { v[i] = E->get()[i]; + } + static_assert(VARIANT_ARG_MAX == 5, "This code needs to be updated if VARIANT_ARG_MAX != 5"); call_group_flags(GROUP_CALL_REALTIME, E->key().group, E->key().call, v[0], v[1], v[2], v[3], v[4]); unique_group_calls.erase(E); @@ -185,11 +180,12 @@ void SceneTree::_flush_ugc() { } void SceneTree::_update_group_order(Group &g, bool p_use_priority) { - - if (!g.changed) + if (!g.changed) { return; - if (g.nodes.empty()) + } + if (g.nodes.empty()) { return; + } Node **nodes = g.nodes.ptrw(); int node_count = g.nodes.size(); @@ -205,31 +201,33 @@ void SceneTree::_update_group_order(Group &g, bool p_use_priority) { } void SceneTree::call_group_flags(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, VARIANT_ARG_DECLARE) { - Map<StringName, Group>::Element *E = group_map.find(p_group); - if (!E) + if (!E) { return; + } Group &g = E->get(); - if (g.nodes.empty()) + if (g.nodes.empty()) { return; + } if (p_call_flags & GROUP_CALL_UNIQUE && !(p_call_flags & GROUP_CALL_REALTIME)) { - ERR_FAIL_COND(ugc_locked); UGCall ug; ug.call = p_function; ug.group = p_group; - if (unique_group_calls.has(ug)) + if (unique_group_calls.has(ug)) { return; + } VARIANT_ARGPTRS; Vector<Variant> args; for (int i = 0; i < VARIANT_ARG_MAX; i++) { - if (argptr[i]->get_type() == Variant::NIL) + if (argptr[i]->get_type() == Variant::NIL) { break; + } args.push_back(*argptr[i]); } @@ -246,51 +244,47 @@ void SceneTree::call_group_flags(uint32_t p_call_flags, const StringName &p_grou call_lock++; if (p_call_flags & GROUP_CALL_REVERSE) { - for (int i = node_count - 1; i >= 0; i--) { - - if (call_lock && call_skip.has(nodes[i])) + if (call_lock && call_skip.has(nodes[i])) { continue; + } if (p_call_flags & GROUP_CALL_REALTIME) { - if (p_call_flags & GROUP_CALL_MULTILEVEL) - nodes[i]->call_multilevel(p_function, VARIANT_ARG_PASS); - else - nodes[i]->call(p_function, VARIANT_ARG_PASS); - } else + nodes[i]->call(p_function, VARIANT_ARG_PASS); + } else { MessageQueue::get_singleton()->push_call(nodes[i], p_function, VARIANT_ARG_PASS); + } } } else { - for (int i = 0; i < node_count; i++) { - - if (call_lock && call_skip.has(nodes[i])) + if (call_lock && call_skip.has(nodes[i])) { continue; + } if (p_call_flags & GROUP_CALL_REALTIME) { - if (p_call_flags & GROUP_CALL_MULTILEVEL) - nodes[i]->call_multilevel(p_function, VARIANT_ARG_PASS); - else - nodes[i]->call(p_function, VARIANT_ARG_PASS); - } else + nodes[i]->call(p_function, VARIANT_ARG_PASS); + } else { MessageQueue::get_singleton()->push_call(nodes[i], p_function, VARIANT_ARG_PASS); + } } } call_lock--; - if (call_lock == 0) + if (call_lock == 0) { call_skip.clear(); + } } void SceneTree::notify_group_flags(uint32_t p_call_flags, const StringName &p_group, int p_notification) { - Map<StringName, Group>::Element *E = group_map.find(p_group); - if (!E) + if (!E) { return; + } Group &g = E->get(); - if (g.nodes.empty()) + if (g.nodes.empty()) { return; + } _update_group_order(g); @@ -301,45 +295,47 @@ void SceneTree::notify_group_flags(uint32_t p_call_flags, const StringName &p_gr call_lock++; if (p_call_flags & GROUP_CALL_REVERSE) { - for (int i = node_count - 1; i >= 0; i--) { - - if (call_lock && call_skip.has(nodes[i])) + if (call_lock && call_skip.has(nodes[i])) { continue; + } - if (p_call_flags & GROUP_CALL_REALTIME) + if (p_call_flags & GROUP_CALL_REALTIME) { nodes[i]->notification(p_notification); - else + } else { MessageQueue::get_singleton()->push_notification(nodes[i], p_notification); + } } } else { - for (int i = 0; i < node_count; i++) { - - if (call_lock && call_skip.has(nodes[i])) + if (call_lock && call_skip.has(nodes[i])) { continue; + } - if (p_call_flags & GROUP_CALL_REALTIME) + if (p_call_flags & GROUP_CALL_REALTIME) { nodes[i]->notification(p_notification); - else + } else { MessageQueue::get_singleton()->push_notification(nodes[i], p_notification); + } } } call_lock--; - if (call_lock == 0) + if (call_lock == 0) { call_skip.clear(); + } } void SceneTree::set_group_flags(uint32_t p_call_flags, const StringName &p_group, const String &p_name, const Variant &p_value) { - Map<StringName, Group>::Element *E = group_map.find(p_group); - if (!E) + if (!E) { return; + } Group &g = E->get(); - if (g.nodes.empty()) + if (g.nodes.empty()) { return; + } _update_group_order(g); @@ -350,35 +346,36 @@ void SceneTree::set_group_flags(uint32_t p_call_flags, const StringName &p_group call_lock++; if (p_call_flags & GROUP_CALL_REVERSE) { - for (int i = node_count - 1; i >= 0; i--) { - - if (call_lock && call_skip.has(nodes[i])) + if (call_lock && call_skip.has(nodes[i])) { continue; + } - if (p_call_flags & GROUP_CALL_REALTIME) + if (p_call_flags & GROUP_CALL_REALTIME) { nodes[i]->set(p_name, p_value); - else + } else { MessageQueue::get_singleton()->push_set(nodes[i], p_name, p_value); + } } } else { - for (int i = 0; i < node_count; i++) { - - if (call_lock && call_skip.has(nodes[i])) + if (call_lock && call_skip.has(nodes[i])) { continue; + } - if (p_call_flags & GROUP_CALL_REALTIME) + if (p_call_flags & GROUP_CALL_REALTIME) { nodes[i]->set(p_name, p_value); - else + } else { MessageQueue::get_singleton()->push_set(nodes[i], p_name, p_value); + } } } call_lock--; - if (call_lock == 0) + if (call_lock == 0) { call_skip.clear(); + } } void SceneTree::call_group(const StringName &p_group, const StringName &p_function, VARIANT_ARG_DECLARE) { @@ -386,78 +383,13 @@ void SceneTree::call_group(const StringName &p_group, const StringName &p_functi } void SceneTree::notify_group(const StringName &p_group, int p_notification) { - notify_group_flags(0, p_group, p_notification); } void SceneTree::set_group(const StringName &p_group, const String &p_name, const Variant &p_value) { - set_group_flags(0, p_group, p_name, p_value); } -void SceneTree::set_input_as_handled() { - - input_handled = true; -} - -void SceneTree::input_text(const String &p_text) { - - root_lock++; - - call_group_flags(GROUP_CALL_REALTIME, "_viewports", "_vp_input_text", p_text); //special one for GUI, as controls use their own process check - - root_lock--; -} - -bool SceneTree::is_input_handled() { - return input_handled; -} - -void SceneTree::input_event(const Ref<InputEvent> &p_event) { - - if (Engine::get_singleton()->is_editor_hint() && (Object::cast_to<InputEventJoypadButton>(p_event.ptr()) || Object::cast_to<InputEventJoypadMotion>(*p_event))) - return; //avoid joy input on editor - - current_event++; - root_lock++; - - input_handled = false; - - // Don't make const ref unless you can find and fix what caused GH-34691. - Ref<InputEvent> ev = p_event; - - MainLoop::input_event(ev); - - call_group_flags(GROUP_CALL_REALTIME, "_viewports", "_vp_input", ev); //special one for GUI, as controls use their own process check - - if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_remote()) { - //quit from game window using F8 - Ref<InputEventKey> k = ev; - if (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_scancode() == KEY_F8) { - ScriptDebugger::get_singleton()->request_quit(); - } - } - - _flush_ugc(); - root_lock--; - //MessageQueue::get_singleton()->flush(); //flushing here causes UI and other places slowness - - root_lock++; - - if (!input_handled) { - call_group_flags(GROUP_CALL_REALTIME, "_viewports", "_vp_unhandled_input", ev); //special one for GUI, as controls use their own process check - _flush_ugc(); - // input_handled = true; - no reason to set this as handled - root_lock--; - //MessageQueue::get_singleton()->flush(); //flushing here causes UI and other places slowness - } else { - // input_handled = true; - no reason to set this as handled - root_lock--; - } - - _call_idle_callbacks(); -} - void SceneTree::init() { initialized = true; root->_set_tree(this); @@ -465,7 +397,6 @@ void SceneTree::init() { } bool SceneTree::iteration(float p_time) { - root_lock++; current_frame++; @@ -491,19 +422,10 @@ bool SceneTree::iteration(float p_time) { return _quit; } -void SceneTree::_update_font_oversampling(float p_ratio) { - - if (use_font_oversampling) { - DynamicFontAtSize::font_oversampling = p_ratio; - DynamicFont::update_oversampling(); - } -} - bool SceneTree::idle(float p_time) { - //print_line("ram: "+itos(OS::get_singleton()->get_static_memory_usage())+" sram: "+itos(OS::get_singleton()->get_dynamic_memory_usage())); //print_line("node count: "+itos(get_node_count())); - //print_line("TEXTURE RAM: "+itos(VS::get_singleton()->get_render_info(VS::INFO_TEXTURE_MEM_USED))); + //print_line("TEXTURE RAM: "+itos(RS::get_singleton()->get_render_info(RS::INFO_TEXTURE_MEM_USED))); root_lock++; @@ -524,15 +446,6 @@ bool SceneTree::idle(float p_time) { _notify_group_pause("idle_process_internal", Node::NOTIFICATION_INTERNAL_PROCESS); _notify_group_pause("idle_process", Node::NOTIFICATION_PROCESS); - Size2 win_size = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height); - - if (win_size != last_screen_size) { - - last_screen_size = win_size; - _update_root_rect(); - emit_signal("screen_resized"); - } - _flush_ugc(); MessageQueue::get_singleton()->flush(); //small little hack flush_transform_notifications(); //transforms after world update, to avoid unnecessary enter/exit notifications @@ -544,11 +457,10 @@ bool SceneTree::idle(float p_time) { //go through timers - List<Ref<SceneTreeTimer> >::Element *L = timers.back(); //last element + List<Ref<SceneTreeTimer>>::Element *L = timers.back(); //last element - for (List<Ref<SceneTreeTimer> >::Element *E = timers.front(); E;) { - - List<Ref<SceneTreeTimer> >::Element *N = E->next(); + for (List<Ref<SceneTreeTimer>>::Element *E = timers.front(); E;) { + List<Ref<SceneTreeTimer>>::Element *N = E->next(); if (pause && !E->get()->is_pause_mode_process()) { if (E == L) { break; //break on last, so if new timers were added during list traversal, ignore them. @@ -581,12 +493,11 @@ bool SceneTree::idle(float p_time) { String env_path = ProjectSettings::get_singleton()->get("rendering/environment/default_environment"); env_path = env_path.strip_edges(); //user may have added a space or two String cpath; - Ref<Environment> fallback = get_root()->get_world()->get_fallback_environment(); + Ref<Environment> fallback = get_root()->get_world_3d()->get_fallback_environment(); if (fallback.is_valid()) { cpath = fallback->get_path(); } if (cpath != env_path) { - if (env_path != String()) { fallback = ResourceLoader::load(env_path); if (fallback.is_null()) { @@ -596,7 +507,7 @@ bool SceneTree::idle(float p_time) { } else { fallback.unref(); } - get_root()->get_world()->set_fallback_environment(fallback); + get_root()->get_world_3d()->set_fallback_environment(fallback); } } @@ -606,7 +517,6 @@ bool SceneTree::idle(float p_time) { } void SceneTree::finish() { - _flush_delete_queue(); _flush_ugc(); @@ -616,21 +526,20 @@ void SceneTree::finish() { MainLoop::finish(); if (root) { - root->_set_tree(NULL); + root->_set_tree(nullptr); root->_propagate_after_exit_tree(); memdelete(root); //delete root - root = NULL; + root = nullptr; } // cleanup timers - for (List<Ref<SceneTreeTimer> >::Element *E = timers.front(); E; E = E->next()) { + for (List<Ref<SceneTreeTimer>>::Element *E = timers.front(); E; E = E->next()) { E->get()->release_connections(); } timers.clear(); } void SceneTree::quit(int p_exit_code) { - if (p_exit_code >= 0) { // Override the exit code if a positive argument is given (the default is `-1`). // This is a shorthand for calling `set_exit_code()` on the OS singleton then quitting. @@ -640,65 +549,41 @@ void SceneTree::quit(int p_exit_code) { _quit = true; } -void SceneTree::_notification(int p_notification) { - - switch (p_notification) { - - case NOTIFICATION_WM_QUIT_REQUEST: { - - get_root()->propagate_notification(p_notification); - - if (accept_quit) { - _quit = true; - break; - } - } break; - - case NOTIFICATION_WM_GO_BACK_REQUEST: { - - get_root()->propagate_notification(p_notification); - - if (quit_on_go_back) { - _quit = true; - break; - } - } break; - - case NOTIFICATION_WM_FOCUS_IN: { +void SceneTree::_main_window_close() { + if (accept_quit) { + _quit = true; + } +} - InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton()); - if (id) { - id->ensure_touch_mouse_raised(); - } +void SceneTree::_main_window_go_back() { + if (quit_on_go_back) { + _quit = true; + } +} - get_root()->propagate_notification(p_notification); - } break; +void SceneTree::_main_window_focus_in() { + Input *id = Input::get_singleton(); + if (id) { + id->ensure_touch_mouse_raised(); + } +} +void SceneTree::_notification(int p_notification) { + switch (p_notification) { case NOTIFICATION_TRANSLATION_CHANGED: { if (!Engine::get_singleton()->is_editor_hint()) { get_root()->propagate_notification(p_notification); } } break; - - case NOTIFICATION_WM_UNFOCUS_REQUEST: { - - notify_group_flags(GROUP_CALL_REALTIME | GROUP_CALL_MULTILEVEL, "input", NOTIFICATION_WM_UNFOCUS_REQUEST); - - get_root()->propagate_notification(p_notification); - - } break; - case NOTIFICATION_OS_MEMORY_WARNING: case NOTIFICATION_OS_IME_UPDATE: - case NOTIFICATION_WM_MOUSE_ENTER: - case NOTIFICATION_WM_MOUSE_EXIT: - case NOTIFICATION_WM_FOCUS_OUT: case NOTIFICATION_WM_ABOUT: case NOTIFICATION_CRASH: - case NOTIFICATION_APP_RESUMED: - case NOTIFICATION_APP_PAUSED: { - - get_root()->propagate_notification(p_notification); + case NOTIFICATION_APPLICATION_RESUMED: + case NOTIFICATION_APPLICATION_PAUSED: + case NOTIFICATION_APPLICATION_FOCUS_IN: + case NOTIFICATION_APPLICATION_FOCUS_OUT: { + get_root()->propagate_notification(p_notification); //pass these to nodes, since they are mirrored } break; default: @@ -707,95 +592,80 @@ void SceneTree::_notification(int p_notification) { }; void SceneTree::set_auto_accept_quit(bool p_enable) { - accept_quit = p_enable; } void SceneTree::set_quit_on_go_back(bool p_enable) { - quit_on_go_back = p_enable; } #ifdef TOOLS_ENABLED bool SceneTree::is_node_being_edited(const Node *p_node) const { - return Engine::get_singleton()->is_editor_hint() && edited_scene_root && (edited_scene_root->is_a_parent_of(p_node) || edited_scene_root == p_node); } #endif #ifdef DEBUG_ENABLED void SceneTree::set_debug_collisions_hint(bool p_enabled) { - debug_collisions_hint = p_enabled; } bool SceneTree::is_debugging_collisions_hint() const { - return debug_collisions_hint; } void SceneTree::set_debug_navigation_hint(bool p_enabled) { - debug_navigation_hint = p_enabled; } bool SceneTree::is_debugging_navigation_hint() const { - return debug_navigation_hint; } #endif void SceneTree::set_debug_collisions_color(const Color &p_color) { - debug_collisions_color = p_color; } Color SceneTree::get_debug_collisions_color() const { - return debug_collisions_color; } void SceneTree::set_debug_collision_contact_color(const Color &p_color) { - debug_collision_contact_color = p_color; } Color SceneTree::get_debug_collision_contact_color() const { - return debug_collision_contact_color; } void SceneTree::set_debug_navigation_color(const Color &p_color) { - debug_navigation_color = p_color; } Color SceneTree::get_debug_navigation_color() const { - return debug_navigation_color; } void SceneTree::set_debug_navigation_disabled_color(const Color &p_color) { - debug_navigation_disabled_color = p_color; } Color SceneTree::get_debug_navigation_disabled_color() const { - return debug_navigation_disabled_color; } Ref<Material> SceneTree::get_debug_navigation_material() { - - if (navigation_material.is_valid()) + if (navigation_material.is_valid()) { return navigation_material; + } - Ref<SpatialMaterial> line_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); - line_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - line_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - line_material->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - line_material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + Ref<StandardMaterial3D> line_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); + line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + line_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); + line_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true); + line_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); line_material->set_albedo(get_debug_navigation_color()); navigation_material = line_material; @@ -804,31 +674,32 @@ Ref<Material> SceneTree::get_debug_navigation_material() { } Ref<Material> SceneTree::get_debug_navigation_disabled_material() { - - if (navigation_disabled_material.is_valid()) + if (navigation_disabled_material.is_valid()) { return navigation_disabled_material; + } - Ref<SpatialMaterial> line_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); - line_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - line_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - line_material->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - line_material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + Ref<StandardMaterial3D> line_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); + line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + line_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); + line_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true); + line_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); line_material->set_albedo(get_debug_navigation_disabled_color()); navigation_disabled_material = line_material; return navigation_disabled_material; } -Ref<Material> SceneTree::get_debug_collision_material() { - if (collision_material.is_valid()) +Ref<Material> SceneTree::get_debug_collision_material() { + if (collision_material.is_valid()) { return collision_material; + } - Ref<SpatialMaterial> line_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); - line_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - line_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - line_material->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - line_material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + Ref<StandardMaterial3D> line_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); + line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + line_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); + line_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true); + line_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); line_material->set_albedo(get_debug_collisions_color()); collision_material = line_material; @@ -837,17 +708,17 @@ Ref<Material> SceneTree::get_debug_collision_material() { } Ref<ArrayMesh> SceneTree::get_debug_contact_mesh() { - - if (debug_contact_mesh.is_valid()) + if (debug_contact_mesh.is_valid()) { return debug_contact_mesh; + } debug_contact_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); - Ref<SpatialMaterial> mat = Ref<SpatialMaterial>(memnew(SpatialMaterial)); - mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + Ref<StandardMaterial3D> mat = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); + mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); + mat->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true); + mat->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); mat->set_albedo(get_debug_collision_contact_color()); Vector3 diamond[6] = { @@ -872,13 +743,15 @@ Ref<ArrayMesh> SceneTree::get_debug_contact_mesh() { }; /* clang-format on */ - PoolVector<int> indices; - for (int i = 0; i < 8 * 3; i++) + Vector<int> indices; + for (int i = 0; i < 8 * 3; i++) { indices.push_back(diamond_faces[i]); + } - PoolVector<Vector3> vertices; - for (int i = 0; i < 6; i++) + Vector<Vector3> vertices; + for (int i = 0; i < 6; i++) { vertices.push_back(diamond[i] * 0.1); + } Array arr; arr.resize(Mesh::ARRAY_MAX); @@ -892,31 +765,33 @@ Ref<ArrayMesh> SceneTree::get_debug_contact_mesh() { } void SceneTree::set_pause(bool p_enabled) { - - if (p_enabled == pause) + if (p_enabled == pause) { return; + } pause = p_enabled; - PhysicsServer::get_singleton()->set_active(!p_enabled); - Physics2DServer::get_singleton()->set_active(!p_enabled); - if (get_root()) + NavigationServer3D::get_singleton()->set_active(!p_enabled); + PhysicsServer3D::get_singleton()->set_active(!p_enabled); + PhysicsServer2D::get_singleton()->set_active(!p_enabled); + if (get_root()) { get_root()->propagate_notification(p_enabled ? Node::NOTIFICATION_PAUSED : Node::NOTIFICATION_UNPAUSED); + } } bool SceneTree::is_paused() const { - return pause; } -void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p_method, const Ref<InputEvent> &p_input) { - +void SceneTree::_notify_group_pause(const StringName &p_group, int p_notification) { Map<StringName, Group>::Element *E = group_map.find(p_group); - if (!E) + if (!E) { return; + } Group &g = E->get(); - if (g.nodes.empty()) + if (g.nodes.empty()) { return; + } - _update_group_order(g); + _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); //copy, so copy on write happens in case something is removed from process while being called //performance is not lost because only if something is added/removed the vector is copied. @@ -925,42 +800,54 @@ void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p int node_count = nodes_copy.size(); Node **nodes = nodes_copy.ptrw(); - Variant arg = p_input; - const Variant *v[1] = { &arg }; - call_lock++; - for (int i = node_count - 1; i >= 0; i--) { - - if (input_handled) - break; - + for (int i = 0; i < node_count; i++) { Node *n = nodes[i]; - if (call_lock && call_skip.has(n)) + if (call_lock && call_skip.has(n)) { continue; + } - if (!n->can_process()) + if (!n->can_process()) { continue; + } + if (!n->can_process_notification(p_notification)) { + continue; + } - n->call_multilevel(p_method, (const Variant **)v, 1); + n->notification(p_notification); //ERR_FAIL_COND(node_count != g.nodes.size()); } call_lock--; - if (call_lock == 0) + if (call_lock == 0) { call_skip.clear(); + } } -void SceneTree::_notify_group_pause(const StringName &p_group, int p_notification) { +/* +void SceneMainLoop::_update_listener_2d() { + + if (listener_2d.is_valid()) { + + SpatialSound2DServer::get_singleton()->listener_set_space( listener_2d, world_2d->get_sound_space() ); + } +} + +*/ + +void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p_method, const Ref<InputEvent> &p_input, Viewport *p_viewport) { Map<StringName, Group>::Element *E = group_map.find(p_group); - if (!E) + if (!E) { return; + } Group &g = E->get(); - if (g.nodes.empty()) + if (g.nodes.empty()) { return; + } - _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); + _update_group_order(g); //copy, so copy on write happens in case something is removed from process while being called //performance is not lost because only if something is added/removed the vector is copied. @@ -969,47 +856,49 @@ void SceneTree::_notify_group_pause(const StringName &p_group, int p_notificatio int node_count = nodes_copy.size(); Node **nodes = nodes_copy.ptrw(); + Variant arg = p_input; + const Variant *v[1] = { &arg }; + call_lock++; - for (int i = 0; i < node_count; i++) { + for (int i = node_count - 1; i >= 0; i--) { + if (p_viewport->is_input_handled()) { + break; + } Node *n = nodes[i]; - if (call_lock && call_skip.has(n)) + if (call_lock && call_skip.has(n)) { continue; + } - if (!n->can_process()) - continue; - if (!n->can_process_notification(p_notification)) + if (!n->can_process()) { continue; + } - n->notification(p_notification); - //ERR_FAIL_COND(node_count != g.nodes.size()); + Callable::CallError err; + // Call both script and native method. + if (n->get_script_instance()) { + n->get_script_instance()->call(p_method, (const Variant **)v, 1, err); + } + MethodBind *method = ClassDB::get_method(n->get_class_name(), p_method); + if (method) { + method->call(n, (const Variant **)v, 1, err); + } } call_lock--; - if (call_lock == 0) + if (call_lock == 0) { call_skip.clear(); -} - -/* -void SceneMainLoop::_update_listener_2d() { - - if (listener_2d.is_valid()) { - - SpatialSound2DServer::get_singleton()->listener_set_space( listener_2d, world_2d->get_sound_space() ); } - } -*/ - -Variant SceneTree::_call_group_flags(const Variant **p_args, int p_argcount, Variant::CallError &r_error) { - r_error.error = Variant::CallError::CALL_OK; +Variant SceneTree::_call_group_flags(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { + r_error.error = Callable::CallError::CALL_OK; ERR_FAIL_COND_V(p_argcount < 3, Variant()); ERR_FAIL_COND_V(!p_args[0]->is_num(), Variant()); - ERR_FAIL_COND_V(p_args[1]->get_type() != Variant::STRING, Variant()); - ERR_FAIL_COND_V(p_args[2]->get_type() != Variant::STRING, Variant()); + ERR_FAIL_COND_V(p_args[1]->get_type() != Variant::STRING_NAME && p_args[1]->get_type() != Variant::STRING, Variant()); + ERR_FAIL_COND_V(p_args[2]->get_type() != Variant::STRING_NAME && p_args[2]->get_type() != Variant::STRING, Variant()); int flags = *p_args[0]; StringName group = *p_args[1]; @@ -1017,61 +906,55 @@ Variant SceneTree::_call_group_flags(const Variant **p_args, int p_argcount, Var Variant v[VARIANT_ARG_MAX]; for (int i = 0; i < MIN(p_argcount - 3, 5); i++) { - v[i] = *p_args[i + 3]; } + static_assert(VARIANT_ARG_MAX == 5, "This code needs to be updated if VARIANT_ARG_MAX != 5"); call_group_flags(flags, group, method, v[0], v[1], v[2], v[3], v[4]); return Variant(); } -Variant SceneTree::_call_group(const Variant **p_args, int p_argcount, Variant::CallError &r_error) { - - r_error.error = Variant::CallError::CALL_OK; +Variant SceneTree::_call_group(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { + r_error.error = Callable::CallError::CALL_OK; ERR_FAIL_COND_V(p_argcount < 2, Variant()); - ERR_FAIL_COND_V(p_args[0]->get_type() != Variant::STRING, Variant()); - ERR_FAIL_COND_V(p_args[1]->get_type() != Variant::STRING, Variant()); + ERR_FAIL_COND_V(p_args[0]->get_type() != Variant::STRING_NAME && p_args[0]->get_type() != Variant::STRING, Variant()); + ERR_FAIL_COND_V(p_args[1]->get_type() != Variant::STRING_NAME && p_args[1]->get_type() != Variant::STRING, Variant()); StringName group = *p_args[0]; StringName method = *p_args[1]; Variant v[VARIANT_ARG_MAX]; for (int i = 0; i < MIN(p_argcount - 2, 5); i++) { - v[i] = *p_args[i + 2]; } + static_assert(VARIANT_ARG_MAX == 5, "This code needs to be updated if VARIANT_ARG_MAX != 5"); call_group_flags(0, group, method, v[0], v[1], v[2], v[3], v[4]); return Variant(); } int64_t SceneTree::get_frame() const { - return current_frame; } -int64_t SceneTree::get_event_count() const { - - return current_event; -} Array SceneTree::_get_nodes_in_group(const StringName &p_group) { - Array ret; Map<StringName, Group>::Element *E = group_map.find(p_group); - if (!E) + if (!E) { return ret; + } _update_group_order(E->get()); //update order just in case int nc = E->get().nodes.size(); - if (nc == 0) + if (nc == 0) { return ret; + } ret.resize(nc); Node **ptr = E->get().nodes.ptrw(); for (int i = 0; i < nc; i++) { - ret[i] = ptr[i]; } @@ -1079,32 +962,30 @@ Array SceneTree::_get_nodes_in_group(const StringName &p_group) { } bool SceneTree::has_group(const StringName &p_identifier) const { - return group_map.has(p_identifier); } -void SceneTree::get_nodes_in_group(const StringName &p_group, List<Node *> *p_list) { +void SceneTree::get_nodes_in_group(const StringName &p_group, List<Node *> *p_list) { Map<StringName, Group>::Element *E = group_map.find(p_group); - if (!E) + if (!E) { return; + } _update_group_order(E->get()); //update order just in case int nc = E->get().nodes.size(); - if (nc == 0) + if (nc == 0) { return; + } Node **ptr = E->get().nodes.ptrw(); for (int i = 0; i < nc; i++) { - p_list->push_back(ptr[i]); } } void SceneTree::_flush_delete_queue() { - _THREAD_SAFE_METHOD_ while (delete_queue.size()) { - Object *obj = ObjectDB::get_instance(delete_queue.front()->get()); if (obj) { memdelete(obj); @@ -1114,7 +995,6 @@ void SceneTree::_flush_delete_queue() { } void SceneTree::queue_delete(Object *p_object) { - _THREAD_SAFE_METHOD_ ERR_FAIL_NULL(p_object); p_object->_is_queued_for_deletion = true; @@ -1122,133 +1002,9 @@ void SceneTree::queue_delete(Object *p_object) { } int SceneTree::get_node_count() const { - return node_count; } -void SceneTree::_update_root_rect() { - - if (stretch_mode == STRETCH_MODE_DISABLED) { - - _update_font_oversampling(1.0); - root->set_size((last_screen_size / stretch_shrink).floor()); - root->set_attach_to_screen_rect(Rect2(Point2(), last_screen_size)); - root->set_size_override_stretch(false); - root->set_size_override(false, Size2()); - root->update_canvas_items(); - return; //user will take care - } - - //actual screen video mode - Size2 video_mode = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height); - Size2 desired_res = stretch_min; - - Size2 viewport_size; - Size2 screen_size; - - float viewport_aspect = desired_res.aspect(); - float video_mode_aspect = video_mode.aspect(); - - if (use_font_oversampling && stretch_aspect == STRETCH_ASPECT_IGNORE) { - WARN_PRINT("Font oversampling only works with the resize modes 'Keep Width', 'Keep Height', and 'Expand'."); - } - - if (stretch_aspect == STRETCH_ASPECT_IGNORE || Math::is_equal_approx(viewport_aspect, video_mode_aspect)) { - //same aspect or ignore aspect - viewport_size = desired_res; - screen_size = video_mode; - } else if (viewport_aspect < video_mode_aspect) { - // screen ratio is smaller vertically - - if (stretch_aspect == STRETCH_ASPECT_KEEP_HEIGHT || stretch_aspect == STRETCH_ASPECT_EXPAND) { - - //will stretch horizontally - viewport_size.x = desired_res.y * video_mode_aspect; - viewport_size.y = desired_res.y; - screen_size = video_mode; - - } else { - //will need black bars - viewport_size = desired_res; - screen_size.x = video_mode.y * viewport_aspect; - screen_size.y = video_mode.y; - } - } else { - //screen ratio is smaller horizontally - if (stretch_aspect == STRETCH_ASPECT_KEEP_WIDTH || stretch_aspect == STRETCH_ASPECT_EXPAND) { - - //will stretch horizontally - viewport_size.x = desired_res.x; - viewport_size.y = desired_res.x / video_mode_aspect; - screen_size = video_mode; - - } else { - //will need black bars - viewport_size = desired_res; - screen_size.x = video_mode.x; - screen_size.y = video_mode.x / viewport_aspect; - } - } - - screen_size = screen_size.floor(); - viewport_size = viewport_size.floor(); - - Size2 margin; - Size2 offset; - //black bars and margin - if (stretch_aspect != STRETCH_ASPECT_EXPAND && screen_size.x < video_mode.x) { - margin.x = Math::round((video_mode.x - screen_size.x) / 2.0); - VisualServer::get_singleton()->black_bars_set_margins(margin.x, 0, margin.x, 0); - offset.x = Math::round(margin.x * viewport_size.y / screen_size.y); - } else if (stretch_aspect != STRETCH_ASPECT_EXPAND && screen_size.y < video_mode.y) { - margin.y = Math::round((video_mode.y - screen_size.y) / 2.0); - VisualServer::get_singleton()->black_bars_set_margins(0, margin.y, 0, margin.y); - offset.y = Math::round(margin.y * viewport_size.x / screen_size.x); - } else { - VisualServer::get_singleton()->black_bars_set_margins(0, 0, 0, 0); - } - - switch (stretch_mode) { - case STRETCH_MODE_DISABLED: { - // Already handled above - _update_font_oversampling(1.0); - } break; - case STRETCH_MODE_2D: { - - _update_font_oversampling(screen_size.x / viewport_size.x); //screen / viewport radio drives oversampling - root->set_size((screen_size / stretch_shrink).floor()); - root->set_attach_to_screen_rect(Rect2(margin, screen_size)); - root->set_size_override_stretch(true); - root->set_size_override(true, (viewport_size / stretch_shrink).floor()); - root->update_canvas_items(); //force them to update just in case - - } break; - case STRETCH_MODE_VIEWPORT: { - - _update_font_oversampling(1.0); - root->set_size((viewport_size / stretch_shrink).floor()); - root->set_attach_to_screen_rect(Rect2(margin, screen_size)); - root->set_size_override_stretch(false); - root->set_size_override(false, Size2()); - root->update_canvas_items(); //force them to update just in case - - if (use_font_oversampling) { - WARN_PRINT("Font oversampling does not work in 'Viewport' stretch mode, only '2D'."); - } - - } break; - } -} - -void SceneTree::set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 &p_minsize, real_t p_shrink) { - - stretch_mode = p_mode; - stretch_aspect = p_aspect; - stretch_min = p_minsize; - stretch_shrink = p_shrink; - _update_root_rect(); -} - void SceneTree::set_edited_scene_root(Node *p_node) { #ifdef TOOLS_ENABLED edited_scene_root = p_node; @@ -1256,30 +1012,26 @@ void SceneTree::set_edited_scene_root(Node *p_node) { } Node *SceneTree::get_edited_scene_root() const { - #ifdef TOOLS_ENABLED return edited_scene_root; #else - return NULL; + return nullptr; #endif } void SceneTree::set_current_scene(Node *p_scene) { - ERR_FAIL_COND(p_scene && p_scene->get_parent() != root); current_scene = p_scene; } Node *SceneTree::get_current_scene() const { - return current_scene; } void SceneTree::_change_scene(Node *p_to) { - if (current_scene) { memdelete(current_scene); - current_scene = NULL; + current_scene = nullptr; } // If we're quitting, abort. @@ -1298,14 +1050,15 @@ void SceneTree::_change_scene(Node *p_to) { Error SceneTree::change_scene(const String &p_path) { Ref<PackedScene> new_scene = ResourceLoader::load(p_path); - if (new_scene.is_null()) + if (new_scene.is_null()) { return ERR_CANT_OPEN; + } return change_scene_to(new_scene); } Error SceneTree::change_scene_to(const Ref<PackedScene> &p_scene) { - Node *new_scene = NULL; + Node *new_scene = nullptr; if (p_scene.is_valid()) { new_scene = p_scene->instance(); ERR_FAIL_COND_V(!new_scene, ERR_CANT_CREATE); @@ -1322,399 +1075,11 @@ Error SceneTree::reload_current_scene() { } void SceneTree::add_current_scene(Node *p_current) { - current_scene = p_current; root->add_child(p_current); } -#ifdef DEBUG_ENABLED - -static void _fill_array(Node *p_node, Array &array, int p_level) { - - array.push_back(p_node->get_child_count()); - array.push_back(p_node->get_name()); - array.push_back(p_node->get_class()); - array.push_back(p_node->get_instance_id()); - for (int i = 0; i < p_node->get_child_count(); i++) { - - _fill_array(p_node->get_child(i), array, p_level + 1); - } -} - -void SceneTree::_debugger_request_tree() { - - Array arr; - _fill_array(root, arr, 0); - ScriptDebugger::get_singleton()->send_message("scene_tree", arr); -} - -void SceneTree::_live_edit_node_path_func(const NodePath &p_path, int p_id) { - - live_edit_node_path_cache[p_id] = p_path; -} - -void SceneTree::_live_edit_res_path_func(const String &p_path, int p_id) { - - live_edit_resource_cache[p_id] = p_path; -} - -void SceneTree::_live_edit_node_set_func(int p_id, const StringName &p_prop, const Variant &p_value) { - - if (!live_edit_node_path_cache.has(p_id)) - return; - - NodePath np = live_edit_node_path_cache[p_id]; - Node *base = NULL; - if (root->has_node(live_edit_root)) - base = root->get_node(live_edit_root); - - Map<String, Set<Node *> >::Element *E = live_scene_edit_cache.find(live_edit_scene); - if (!E) - return; //scene not editable - - for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) { - - Node *n = F->get(); - - if (base && !base->is_a_parent_of(n)) - continue; - - if (!n->has_node(np)) - continue; - Node *n2 = n->get_node(np); - - n2->set(p_prop, p_value); - } -} - -void SceneTree::_live_edit_node_set_res_func(int p_id, const StringName &p_prop, const String &p_value) { - - RES r = ResourceLoader::load(p_value); - if (!r.is_valid()) - return; - _live_edit_node_set_func(p_id, p_prop, r); -} -void SceneTree::_live_edit_node_call_func(int p_id, const StringName &p_method, VARIANT_ARG_DECLARE) { - - if (!live_edit_node_path_cache.has(p_id)) - return; - - NodePath np = live_edit_node_path_cache[p_id]; - Node *base = NULL; - if (root->has_node(live_edit_root)) - base = root->get_node(live_edit_root); - - Map<String, Set<Node *> >::Element *E = live_scene_edit_cache.find(live_edit_scene); - if (!E) - return; //scene not editable - - for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) { - - Node *n = F->get(); - - if (base && !base->is_a_parent_of(n)) - continue; - - if (!n->has_node(np)) - continue; - Node *n2 = n->get_node(np); - - n2->call(p_method, VARIANT_ARG_PASS); - } -} -void SceneTree::_live_edit_res_set_func(int p_id, const StringName &p_prop, const Variant &p_value) { - - if (!live_edit_resource_cache.has(p_id)) - return; - - String resp = live_edit_resource_cache[p_id]; - - if (!ResourceCache::has(resp)) - return; - - RES r = ResourceCache::get(resp); - if (!r.is_valid()) - return; - - r->set(p_prop, p_value); -} -void SceneTree::_live_edit_res_set_res_func(int p_id, const StringName &p_prop, const String &p_value) { - - RES r = ResourceLoader::load(p_value); - if (!r.is_valid()) - return; - _live_edit_res_set_func(p_id, p_prop, r); -} -void SceneTree::_live_edit_res_call_func(int p_id, const StringName &p_method, VARIANT_ARG_DECLARE) { - - if (!live_edit_resource_cache.has(p_id)) - return; - - String resp = live_edit_resource_cache[p_id]; - - if (!ResourceCache::has(resp)) - return; - - RES r = ResourceCache::get(resp); - if (!r.is_valid()) - return; - - r->call(p_method, VARIANT_ARG_PASS); -} - -void SceneTree::_live_edit_root_func(const NodePath &p_scene_path, const String &p_scene_from) { - - live_edit_root = p_scene_path; - live_edit_scene = p_scene_from; -} - -void SceneTree::_live_edit_create_node_func(const NodePath &p_parent, const String &p_type, const String &p_name) { - - Node *base = NULL; - if (root->has_node(live_edit_root)) - base = root->get_node(live_edit_root); - - Map<String, Set<Node *> >::Element *E = live_scene_edit_cache.find(live_edit_scene); - if (!E) - return; //scene not editable - - for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) { - - Node *n = F->get(); - - if (base && !base->is_a_parent_of(n)) - continue; - - if (!n->has_node(p_parent)) - continue; - Node *n2 = n->get_node(p_parent); - - Node *no = Object::cast_to<Node>(ClassDB::instance(p_type)); - if (!no) { - continue; - } - - no->set_name(p_name); - n2->add_child(no); - } -} -void SceneTree::_live_edit_instance_node_func(const NodePath &p_parent, const String &p_path, const String &p_name) { - - Ref<PackedScene> ps = ResourceLoader::load(p_path); - - if (!ps.is_valid()) - return; - - Node *base = NULL; - if (root->has_node(live_edit_root)) - base = root->get_node(live_edit_root); - - Map<String, Set<Node *> >::Element *E = live_scene_edit_cache.find(live_edit_scene); - if (!E) - return; //scene not editable - - for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) { - - Node *n = F->get(); - - if (base && !base->is_a_parent_of(n)) - continue; - - if (!n->has_node(p_parent)) - continue; - Node *n2 = n->get_node(p_parent); - - Node *no = ps->instance(); - if (!no) { - continue; - } - - no->set_name(p_name); - n2->add_child(no); - } -} -void SceneTree::_live_edit_remove_node_func(const NodePath &p_at) { - - Node *base = NULL; - if (root->has_node(live_edit_root)) - base = root->get_node(live_edit_root); - - Map<String, Set<Node *> >::Element *E = live_scene_edit_cache.find(live_edit_scene); - if (!E) - return; //scene not editable - - for (Set<Node *>::Element *F = E->get().front(); F;) { - - Set<Node *>::Element *N = F->next(); - - Node *n = F->get(); - - if (base && !base->is_a_parent_of(n)) - continue; - - if (!n->has_node(p_at)) - continue; - Node *n2 = n->get_node(p_at); - - memdelete(n2); - - F = N; - } -} -void SceneTree::_live_edit_remove_and_keep_node_func(const NodePath &p_at, ObjectID p_keep_id) { - - Node *base = NULL; - if (root->has_node(live_edit_root)) - base = root->get_node(live_edit_root); - - Map<String, Set<Node *> >::Element *E = live_scene_edit_cache.find(live_edit_scene); - if (!E) - return; //scene not editable - - for (Set<Node *>::Element *F = E->get().front(); F;) { - - Set<Node *>::Element *N = F->next(); - - Node *n = F->get(); - - if (base && !base->is_a_parent_of(n)) - continue; - - if (!n->has_node(p_at)) - continue; - - Node *n2 = n->get_node(p_at); - - n2->get_parent()->remove_child(n2); - - live_edit_remove_list[n][p_keep_id] = n2; - - F = N; - } -} -void SceneTree::_live_edit_restore_node_func(ObjectID p_id, const NodePath &p_at, int p_at_pos) { - - Node *base = NULL; - if (root->has_node(live_edit_root)) - base = root->get_node(live_edit_root); - - Map<String, Set<Node *> >::Element *E = live_scene_edit_cache.find(live_edit_scene); - if (!E) - return; //scene not editable - - for (Set<Node *>::Element *F = E->get().front(); F;) { - - Set<Node *>::Element *N = F->next(); - - Node *n = F->get(); - - if (base && !base->is_a_parent_of(n)) - continue; - - if (!n->has_node(p_at)) - continue; - Node *n2 = n->get_node(p_at); - - Map<Node *, Map<ObjectID, Node *> >::Element *EN = live_edit_remove_list.find(n); - - if (!EN) - continue; - - Map<ObjectID, Node *>::Element *FN = EN->get().find(p_id); - - if (!FN) - continue; - n2->add_child(FN->get()); - - EN->get().erase(FN); - - if (EN->get().size() == 0) { - live_edit_remove_list.erase(EN); - } - - F = N; - } -} -void SceneTree::_live_edit_duplicate_node_func(const NodePath &p_at, const String &p_new_name) { - - Node *base = NULL; - if (root->has_node(live_edit_root)) - base = root->get_node(live_edit_root); - - Map<String, Set<Node *> >::Element *E = live_scene_edit_cache.find(live_edit_scene); - if (!E) - return; //scene not editable - - for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) { - - Node *n = F->get(); - - if (base && !base->is_a_parent_of(n)) - continue; - - if (!n->has_node(p_at)) - continue; - Node *n2 = n->get_node(p_at); - - Node *dup = n2->duplicate(Node::DUPLICATE_SIGNALS | Node::DUPLICATE_GROUPS | Node::DUPLICATE_SCRIPTS); - - if (!dup) - continue; - - dup->set_name(p_new_name); - n2->get_parent()->add_child(dup); - } -} -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) { - - Node *base = NULL; - if (root->has_node(live_edit_root)) - base = root->get_node(live_edit_root); - - Map<String, Set<Node *> >::Element *E = live_scene_edit_cache.find(live_edit_scene); - if (!E) - return; //scene not editable - - for (Set<Node *>::Element *F = E->get().front(); F; F = F->next()) { - - Node *n = F->get(); - - if (base && !base->is_a_parent_of(n)) - continue; - - if (!n->has_node(p_at)) - continue; - Node *nfrom = n->get_node(p_at); - - if (!n->has_node(p_new_place)) - continue; - Node *nto = n->get_node(p_new_place); - - nfrom->get_parent()->remove_child(nfrom); - nfrom->set_name(p_new_name); - - nto->add_child(nfrom); - if (p_at_pos >= 0) - nto->move_child(nfrom, p_at_pos); - } -} - -#endif - -void SceneTree::drop_files(const Vector<String> &p_files, int p_from_screen) { - - emit_signal("files_dropped", p_files, p_from_screen); - MainLoop::drop_files(p_files, p_from_screen); -} - -void SceneTree::global_menu_action(const Variant &p_id, const Variant &p_meta) { - - emit_signal("global_menu_action", p_id, p_meta); - MainLoop::global_menu_action(p_id, p_meta); -} - Ref<SceneTreeTimer> SceneTree::create_timer(float p_delay_sec, bool p_process_pause) { - Ref<SceneTreeTimer> stt; stt.instance(); stt->set_pause_mode_process(p_process_pause); @@ -1724,27 +1089,22 @@ Ref<SceneTreeTimer> SceneTree::create_timer(float p_delay_sec, bool p_process_pa } void SceneTree::_network_peer_connected(int p_id) { - emit_signal("network_peer_connected", p_id); } void SceneTree::_network_peer_disconnected(int p_id) { - emit_signal("network_peer_disconnected", p_id); } void SceneTree::_connected_to_server() { - emit_signal("connected_to_server"); } void SceneTree::_connection_failed() { - emit_signal("connection_failed"); } void SceneTree::_server_disconnected() { - emit_signal("server_disconnected"); } @@ -1764,35 +1124,32 @@ void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer) { ERR_FAIL_COND(!p_multiplayer.is_valid()); if (multiplayer.is_valid()) { - multiplayer->disconnect("network_peer_connected", this, "_network_peer_connected"); - multiplayer->disconnect("network_peer_disconnected", this, "_network_peer_disconnected"); - multiplayer->disconnect("connected_to_server", this, "_connected_to_server"); - multiplayer->disconnect("connection_failed", this, "_connection_failed"); - multiplayer->disconnect("server_disconnected", this, "_server_disconnected"); + multiplayer->disconnect("network_peer_connected", callable_mp(this, &SceneTree::_network_peer_connected)); + multiplayer->disconnect("network_peer_disconnected", callable_mp(this, &SceneTree::_network_peer_disconnected)); + multiplayer->disconnect("connected_to_server", callable_mp(this, &SceneTree::_connected_to_server)); + multiplayer->disconnect("connection_failed", callable_mp(this, &SceneTree::_connection_failed)); + multiplayer->disconnect("server_disconnected", callable_mp(this, &SceneTree::_server_disconnected)); } multiplayer = p_multiplayer; multiplayer->set_root_node(root); - multiplayer->connect("network_peer_connected", this, "_network_peer_connected"); - multiplayer->connect("network_peer_disconnected", this, "_network_peer_disconnected"); - multiplayer->connect("connected_to_server", this, "_connected_to_server"); - multiplayer->connect("connection_failed", this, "_connection_failed"); - multiplayer->connect("server_disconnected", this, "_server_disconnected"); + multiplayer->connect("network_peer_connected", callable_mp(this, &SceneTree::_network_peer_connected)); + multiplayer->connect("network_peer_disconnected", callable_mp(this, &SceneTree::_network_peer_disconnected)); + multiplayer->connect("connected_to_server", callable_mp(this, &SceneTree::_connected_to_server)); + multiplayer->connect("connection_failed", callable_mp(this, &SceneTree::_connection_failed)); + multiplayer->connect("server_disconnected", callable_mp(this, &SceneTree::_server_disconnected)); } void SceneTree::set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_network_peer) { - multiplayer->set_network_peer(p_network_peer); } Ref<NetworkedMultiplayerPeer> SceneTree::get_network_peer() const { - return multiplayer->get_network_peer(); } bool SceneTree::is_network_server() const { - return multiplayer->is_network_server(); } @@ -1801,12 +1158,10 @@ bool SceneTree::has_network_peer() const { } int SceneTree::get_network_unique_id() const { - return multiplayer->get_network_unique_id(); } Vector<int> SceneTree::get_network_connected_peers() const { - return multiplayer->get_network_connected_peers(); } @@ -1823,7 +1178,6 @@ bool SceneTree::is_refusing_new_network_connections() const { } void SceneTree::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_root"), &SceneTree::get_root); ClassDB::bind_method(D_METHOD("has_group", "name"), &SceneTree::has_group); @@ -1840,8 +1194,6 @@ void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pause", "enable"), &SceneTree::set_pause); ClassDB::bind_method(D_METHOD("is_paused"), &SceneTree::is_paused); - ClassDB::bind_method(D_METHOD("set_input_as_handled"), &SceneTree::set_input_as_handled); - ClassDB::bind_method(D_METHOD("is_input_handled"), &SceneTree::is_input_handled); ClassDB::bind_method(D_METHOD("create_timer", "time_sec", "pause_mode_process"), &SceneTree::create_timer, DEFVAL(true)); @@ -1849,15 +1201,13 @@ void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("get_frame"), &SceneTree::get_frame); ClassDB::bind_method(D_METHOD("quit", "exit_code"), &SceneTree::quit, DEFVAL(-1)); - ClassDB::bind_method(D_METHOD("set_screen_stretch", "mode", "aspect", "minsize", "shrink"), &SceneTree::set_screen_stretch, DEFVAL(1)); - ClassDB::bind_method(D_METHOD("queue_delete", "obj"), &SceneTree::queue_delete); MethodInfo mi; mi.name = "call_group_flags"; mi.arguments.push_back(PropertyInfo(Variant::INT, "flags")); - mi.arguments.push_back(PropertyInfo(Variant::STRING, "group")); - mi.arguments.push_back(PropertyInfo(Variant::STRING, "method")); + mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "group")); + mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "method")); ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_group_flags", &SceneTree::_call_group_flags, mi); @@ -1866,8 +1216,8 @@ void SceneTree::_bind_methods() { MethodInfo mi2; mi2.name = "call_group"; - mi2.arguments.push_back(PropertyInfo(Variant::STRING, "group")); - mi2.arguments.push_back(PropertyInfo(Variant::STRING, "method")); + mi2.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "group")); + mi2.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "method")); ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_group", &SceneTree::_call_group, mi2); @@ -1899,21 +1249,12 @@ void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("get_rpc_sender_id"), &SceneTree::get_rpc_sender_id); ClassDB::bind_method(D_METHOD("set_refuse_new_network_connections", "refuse"), &SceneTree::set_refuse_new_network_connections); ClassDB::bind_method(D_METHOD("is_refusing_new_network_connections"), &SceneTree::is_refusing_new_network_connections); - ClassDB::bind_method(D_METHOD("_network_peer_connected"), &SceneTree::_network_peer_connected); - ClassDB::bind_method(D_METHOD("_network_peer_disconnected"), &SceneTree::_network_peer_disconnected); - ClassDB::bind_method(D_METHOD("_connected_to_server"), &SceneTree::_connected_to_server); - ClassDB::bind_method(D_METHOD("_connection_failed"), &SceneTree::_connection_failed); - ClassDB::bind_method(D_METHOD("_server_disconnected"), &SceneTree::_server_disconnected); - - ClassDB::bind_method(D_METHOD("set_use_font_oversampling", "enable"), &SceneTree::set_use_font_oversampling); - ClassDB::bind_method(D_METHOD("is_using_font_oversampling"), &SceneTree::is_using_font_oversampling); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_collisions_hint"), "set_debug_collisions_hint", "is_debugging_collisions_hint"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_navigation_hint"), "set_debug_navigation_hint", "is_debugging_navigation_hint"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused"), "set_pause", "is_paused"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_network_connections"), "set_refuse_new_network_connections", "is_refusing_new_network_connections"); ADD_PROPERTY_DEFAULT("refuse_new_network_connections", false); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_font_oversampling"), "set_use_font_oversampling", "is_using_font_oversampling"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "edited_scene_root", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_edited_scene_root", "get_edited_scene_root"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "current_scene", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_current_scene", "get_current_scene"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "NetworkedMultiplayerPeer", 0), "set_network_peer", "get_network_peer"); @@ -1925,14 +1266,12 @@ void SceneTree::_bind_methods() { ADD_SIGNAL(MethodInfo("node_added", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("node_removed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("node_renamed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); - ADD_SIGNAL(MethodInfo("screen_resized")); ADD_SIGNAL(MethodInfo("node_configuration_warning_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("idle_frame")); ADD_SIGNAL(MethodInfo("physics_frame")); - ADD_SIGNAL(MethodInfo("files_dropped", PropertyInfo(Variant::POOL_STRING_ARRAY, "files"), PropertyInfo(Variant::INT, "screen"))); - ADD_SIGNAL(MethodInfo("global_menu_action", PropertyInfo(Variant::NIL, "id"), PropertyInfo(Variant::NIL, "meta"))); + ADD_SIGNAL(MethodInfo("files_dropped", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files"), PropertyInfo(Variant::INT, "screen"))); ADD_SIGNAL(MethodInfo("network_peer_connected", PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("network_peer_disconnected", PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("connected_to_server")); @@ -1943,25 +1282,14 @@ void SceneTree::_bind_methods() { BIND_ENUM_CONSTANT(GROUP_CALL_REVERSE); BIND_ENUM_CONSTANT(GROUP_CALL_REALTIME); BIND_ENUM_CONSTANT(GROUP_CALL_UNIQUE); - - BIND_ENUM_CONSTANT(STRETCH_MODE_DISABLED); - BIND_ENUM_CONSTANT(STRETCH_MODE_2D); - BIND_ENUM_CONSTANT(STRETCH_MODE_VIEWPORT); - - BIND_ENUM_CONSTANT(STRETCH_ASPECT_IGNORE); - BIND_ENUM_CONSTANT(STRETCH_ASPECT_KEEP); - BIND_ENUM_CONSTANT(STRETCH_ASPECT_KEEP_WIDTH); - BIND_ENUM_CONSTANT(STRETCH_ASPECT_KEEP_HEIGHT); - BIND_ENUM_CONSTANT(STRETCH_ASPECT_EXPAND); } -SceneTree *SceneTree::singleton = NULL; +SceneTree *SceneTree::singleton = nullptr; SceneTree::IdleCallback SceneTree::idle_callbacks[SceneTree::MAX_IDLE_CALLBACKS]; int SceneTree::idle_callback_count = 0; void SceneTree::_call_idle_callbacks() { - for (int i = 0; i < idle_callback_count; i++) { idle_callbacks[i](); } @@ -1972,21 +1300,7 @@ void SceneTree::add_idle_callback(IdleCallback p_callback) { idle_callbacks[idle_callback_count++] = p_callback; } -void SceneTree::set_use_font_oversampling(bool p_oversampling) { - - if (use_font_oversampling == p_oversampling) - return; - - use_font_oversampling = p_oversampling; - _update_root_rect(); -} - -bool SceneTree::is_using_font_oversampling() const { - return use_font_oversampling; -} - void SceneTree::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { - if (p_function == "change_scene") { DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES); List<String> directories; @@ -2018,13 +1332,13 @@ void SceneTree::get_argument_options(const StringName &p_function, int p_idx, Li } SceneTree::SceneTree() { - - if (singleton == NULL) singleton = this; + if (singleton == nullptr) { + singleton = this; + } _quit = false; accept_quit = true; quit_on_go_back = true; initialized = false; - use_font_oversampling = false; #ifdef DEBUG_ENABLED debug_collisions_hint = false; debug_navigation_hint = false; @@ -2040,11 +1354,9 @@ SceneTree::SceneTree() { physics_process_time = 1; idle_process_time = 1; - root = NULL; - input_handled = false; + root = nullptr; pause = false; current_frame = 0; - current_event = 0; tree_changed_name = "tree_changed"; node_added_name = "node_added"; node_removed_name = "node_removed"; @@ -2056,11 +1368,11 @@ SceneTree::SceneTree() { //create with mainloop - root = memnew(Viewport); + root = memnew(Window); root->set_name("root"); - root->set_handle_input_locally(false); - if (!root->get_world().is_valid()) - root->set_world(Ref<World>(memnew(World))); + if (!root->get_world_3d().is_valid()) { + root->set_world_3d(Ref<World3D>(memnew(World3D))); + } // Initialize network state multiplayer_poll = true; @@ -2069,23 +1381,15 @@ SceneTree::SceneTree() { //root->set_world_2d( Ref<World2D>( memnew( World2D ))); root->set_as_audio_listener(true); root->set_as_audio_listener_2d(true); - current_scene = NULL; - - int ref_atlas_size = GLOBAL_DEF("rendering/quality/reflections/atlas_size", 2048); - 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 - int ref_atlas_subdiv = GLOBAL_DEF("rendering/quality/reflections/atlas_subdiv", 8); - 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 - int msaa_mode = GLOBAL_DEF("rendering/quality/filters/msaa", 0); - 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")); - root->set_msaa(Viewport::MSAA(msaa_mode)); - - GLOBAL_DEF("rendering/quality/depth/hdr", true); - GLOBAL_DEF("rendering/quality/depth/hdr.mobile", false); + current_scene = nullptr; - bool hdr = GLOBAL_GET("rendering/quality/depth/hdr"); - root->set_hdr(hdr); + int msaa_mode = GLOBAL_DEF("rendering/quality/screen_filters/msaa", 0); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/screen_filters/msaa", PropertyInfo(Variant::INT, "rendering/quality/screen_filters/msaa", PROPERTY_HINT_ENUM, "Disabled (Fastest),2x (Fast),4x (Average),8x (Slow),16x (Slower)")); + root->set_msaa(Viewport::MSAA(msaa_mode)); - VS::get_singleton()->scenario_set_reflection_atlas_size(root->get_world()->get_scenario(), ref_atlas_size, ref_atlas_subdiv); + int ssaa_mode = GLOBAL_DEF("rendering/quality/screen_filters/screen_space_aa", 0); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/screen_filters/screen_space_aa", PropertyInfo(Variant::INT, "rendering/quality/screen_filters/screen_space_aa", PROPERTY_HINT_ENUM, "Disabled (Fastest),FXAA (Fast)")); + root->set_screen_space_aa(Viewport::ScreenSpaceAA(ssaa_mode)); { //load default fallback environment //get possible extensions @@ -2093,8 +1397,9 @@ SceneTree::SceneTree() { ResourceLoader::get_recognized_extensions_for_type("Environment", &exts); String ext_hint; for (List<String>::Element *E = exts.front(); E; E = E->next()) { - if (ext_hint != String()) + if (ext_hint != String()) { ext_hint += ","; + } ext_hint += "*." + E->get(); } //get path @@ -2105,54 +1410,38 @@ SceneTree::SceneTree() { if (env_path != String()) { Ref<Environment> env = ResourceLoader::load(env_path); if (env.is_valid()) { - root->get_world()->set_fallback_environment(env); + root->get_world_3d()->set_fallback_environment(env); } else { if (Engine::get_singleton()->is_editor_hint()) { //file was erased, clear the field. ProjectSettings::get_singleton()->set("rendering/environment/default_environment", ""); } else { //file was erased, notify user. - ERR_PRINTS(RTR("Default Environment as specified in Project Settings (Rendering -> Environment -> Default Environment) could not be loaded.")); + ERR_PRINT(RTR("Default Environment as specified in Project Settings (Rendering -> Environment -> Default Environment) could not be loaded.")); } } } } - stretch_mode = STRETCH_MODE_DISABLED; - stretch_aspect = STRETCH_ASPECT_IGNORE; - stretch_shrink = 1; - - last_screen_size = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height); - _update_root_rect(); - - if (ScriptDebugger::get_singleton()) { - if (ScriptDebugger::get_singleton()->is_remote()) { - ScriptDebuggerRemote *remote_debugger = static_cast<ScriptDebuggerRemote *>(ScriptDebugger::get_singleton()); - - remote_debugger->set_scene_tree(this); - } - ScriptDebugger::get_singleton()->set_multiplayer(multiplayer); - } - root->set_physics_object_picking(GLOBAL_DEF("physics/common/enable_object_picking", true)); -#ifdef TOOLS_ENABLED - edited_scene_root = NULL; -#endif - -#ifdef DEBUG_ENABLED - - live_edit_root = NodePath("/root"); + root->connect("close_requested", callable_mp(this, &SceneTree::_main_window_close)); + root->connect("go_back_requested", callable_mp(this, &SceneTree::_main_window_go_back)); + root->connect("focus_entered", callable_mp(this, &SceneTree::_main_window_focus_in)); +#ifdef TOOLS_ENABLED + edited_scene_root = nullptr; #endif } SceneTree::~SceneTree() { if (root) { - root->_set_tree(NULL); + root->_set_tree(nullptr); root->_propagate_after_exit_tree(); memdelete(root); } - if (singleton == this) singleton = NULL; + if (singleton == this) { + singleton = nullptr; + } } |