diff options
Diffstat (limited to 'scene/main/scene_tree.cpp')
-rw-r--r-- | scene/main/scene_tree.cpp | 513 |
1 files changed, 243 insertions, 270 deletions
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 22cd1c98ab..9f32c65f7b 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,19 +30,19 @@ #include "scene_tree.h" +#include "core/config/project_settings.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" +#include "core/object/message_queue.h" #include "core/os/dir_access.h" #include "core/os/keyboard.h" #include "core/os/os.h" -#include "core/print_string.h" -#include "core/project_settings.h" +#include "core/string/print_string.h" #include "node.h" #include "scene/debugger/scene_debugger.h" -#include "scene/resources/dynamic_font.h" +#include "scene/resources/font.h" #include "scene/resources/material.h" #include "scene/resources/mesh.h" #include "scene/resources/packed_scene.h" @@ -56,7 +56,6 @@ #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); @@ -73,17 +72,15 @@ float SceneTreeTimer::get_time_left() const { return time_left; } -void SceneTreeTimer::set_pause_mode_process(bool p_pause_mode_process) { - - process_pause = p_pause_mode_process; +void SceneTreeTimer::set_process_always(bool p_process_always) { + process_always = p_process_always; } -bool SceneTreeTimer::is_pause_mode_process() { - return process_pause; +bool SceneTreeTimer::is_process_always() { + return process_always; } void SceneTreeTimer::release_connections() { - List<Connection> connections; get_all_signal_connections(&connections); @@ -93,39 +90,32 @@ void SceneTreeTimer::release_connections() { } } -SceneTreeTimer::SceneTreeTimer() { - time_left = 0; - process_pause = true; -} +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 = 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()); @@ -139,26 +129,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.is_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); @@ -168,17 +157,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(); 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); @@ -188,11 +177,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.is_empty()) { return; + } Node **nodes = g.nodes.ptrw(); int node_count = g.nodes.size(); @@ -208,31 +198,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.is_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]); } @@ -249,51 +241,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.is_empty()) { return; + } _update_group_order(g); @@ -304,45 +292,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.is_empty()) { return; + } _update_group_order(g); @@ -353,35 +343,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) { @@ -389,35 +380,33 @@ 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::init() { +void SceneTree::initialize() { initialized = true; root->_set_tree(this); - MainLoop::init(); + MainLoop::initialize(); } -bool SceneTree::iteration(float p_time) { - +bool SceneTree::physics_process(float p_time) { root_lock++; current_frame++; flush_transform_notifications(); - MainLoop::iteration(p_time); + MainLoop::physics_process(p_time); physics_process_time = p_time; emit_signal("physics_frame"); _notify_group_pause("physics_process_internal", Node::NOTIFICATION_INTERNAL_PHYSICS_PROCESS); + call_group_flags(GROUP_CALL_REALTIME, "_viewports", "_process_picking"); _notify_group_pause("physics_process", Node::NOTIFICATION_PHYSICS_PROCESS); _flush_ugc(); MessageQueue::get_singleton()->flush(); //small little hack @@ -431,30 +420,25 @@ bool SceneTree::iteration(float p_time) { return _quit; } -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(RS::get_singleton()->get_render_info(RS::INFO_TEXTURE_MEM_USED))); - +bool SceneTree::process(float p_time) { root_lock++; - MainLoop::idle(p_time); + MainLoop::process(p_time); - idle_process_time = p_time; + process_time = p_time; if (multiplayer_poll) { multiplayer->poll(); } - emit_signal("idle_frame"); + emit_signal("process_frame"); MessageQueue::get_singleton()->flush(); //small little hack flush_transform_notifications(); - _notify_group_pause("idle_process_internal", Node::NOTIFICATION_INTERNAL_PROCESS); - _notify_group_pause("idle_process", Node::NOTIFICATION_PROCESS); + _notify_group_pause("process_internal", Node::NOTIFICATION_INTERNAL_PROCESS); + _notify_group_pause("process", Node::NOTIFICATION_PROCESS); _flush_ugc(); MessageQueue::get_singleton()->flush(); //small little hack @@ -470,9 +454,8 @@ bool SceneTree::idle(float p_time) { 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(); - if (pause && !E->get()->is_pause_mode_process()) { + if (paused && !E->get()->is_process_always()) { if (E == L) { break; //break on last, so if new timers were added during list traversal, ignore them. } @@ -501,25 +484,24 @@ bool SceneTree::idle(float p_time) { if (Engine::get_singleton()->is_editor_hint()) { //simple hack to reload fallback environment if it changed from editor - String env_path = ProjectSettings::get_singleton()->get("rendering/environment/default_environment"); + String env_path = ProjectSettings::get_singleton()->get("rendering/environment/defaults/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()) { //could not load fallback, set as empty - ProjectSettings::get_singleton()->set("rendering/environment/default_environment", ""); + ProjectSettings::get_singleton()->set("rendering/environment/defaults/default_environment", ""); } } else { fallback.unref(); } - get_root()->get_world()->set_fallback_environment(fallback); + get_root()->get_world_3d()->set_fallback_environment(fallback); } } @@ -528,15 +510,14 @@ bool SceneTree::idle(float p_time) { return _quit; } -void SceneTree::finish() { - +void SceneTree::finalize() { _flush_delete_queue(); _flush_ugc(); initialized = false; - MainLoop::finish(); + MainLoop::finalize(); if (root) { root->_set_tree(nullptr); @@ -553,7 +534,6 @@ void SceneTree::finish() { } 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. @@ -564,11 +544,11 @@ void SceneTree::quit(int p_exit_code) { } void SceneTree::_main_window_close() { - if (accept_quit) { _quit = true; } } + void SceneTree::_main_window_go_back() { if (quit_on_go_back) { _quit = true; @@ -583,9 +563,7 @@ void SceneTree::_main_window_focus_in() { } 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); @@ -595,10 +573,11 @@ void SceneTree::_notification(int p_notification) { case NOTIFICATION_OS_IME_UPDATE: 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: @@ -607,89 +586,74 @@ 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<StandardMaterial3D> line_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); @@ -704,9 +668,9 @@ 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<StandardMaterial3D> line_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); @@ -719,10 +683,11 @@ Ref<Material> SceneTree::get_debug_navigation_disabled_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<StandardMaterial3D> line_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); @@ -737,9 +702,9 @@ 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)); @@ -773,12 +738,14 @@ Ref<ArrayMesh> SceneTree::get_debug_contact_mesh() { /* clang-format on */ Vector<int> indices; - for (int i = 0; i < 8 * 3; i++) + for (int i = 0; i < 8 * 3; i++) { indices.push_back(diamond_faces[i]); + } Vector<Vector3> vertices; - for (int i = 0; i < 6; i++) + for (int i = 0; i < 6; i++) { vertices.push_back(diamond[i] * 0.1); + } Array arr; arr.resize(Mesh::ARRAY_MAX); @@ -792,30 +759,31 @@ Ref<ArrayMesh> SceneTree::get_debug_contact_mesh() { } void SceneTree::set_pause(bool p_enabled) { - - if (p_enabled == pause) + if (p_enabled == paused) { return; - pause = p_enabled; + } + paused = p_enabled; 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); + if (get_root()) { + get_root()->_propagate_pause_notification(p_enabled); + } } bool SceneTree::is_paused() const { - - return pause; + return paused; } 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.is_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); @@ -829,44 +797,46 @@ void SceneTree::_notify_group_pause(const StringName &p_group, int p_notificatio call_lock++; 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)) + } + if (!n->can_process_notification(p_notification)) { continue; + } 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 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.is_empty()) { return; + } _update_group_order(g); @@ -883,27 +853,37 @@ void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p call_lock++; for (int i = node_count - 1; i >= 0; i--) { - - if (p_viewport->is_input_handled()) + 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()) + if (!n->can_process()) { continue; + } - n->call_multilevel(p_method, (const Variant **)v, 1); - //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(); + } } -Variant SceneTree::_call_group_flags(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { +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()); @@ -917,16 +897,15 @@ Variant SceneTree::_call_group_flags(const Variant **p_args, int p_argcount, Cal 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, Callable::CallError &r_error) { - r_error.error = Callable::CallError::CALL_OK; ERR_FAIL_COND_V(p_argcount < 2, Variant()); @@ -938,40 +917,35 @@ Variant SceneTree::_call_group(const Variant **p_args, int p_argcount, Callable: 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]; } @@ -979,32 +953,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); @@ -1014,7 +986,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; @@ -1022,7 +993,6 @@ void SceneTree::queue_delete(Object *p_object) { } int SceneTree::get_node_count() const { - return node_count; } @@ -1033,7 +1003,6 @@ void SceneTree::set_edited_scene_root(Node *p_node) { } Node *SceneTree::get_edited_scene_root() const { - #ifdef TOOLS_ENABLED return edited_scene_root; #else @@ -1042,18 +1011,15 @@ Node *SceneTree::get_edited_scene_root() const { } 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 = nullptr; @@ -1075,8 +1041,9 @@ 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); } @@ -1099,43 +1066,36 @@ Error SceneTree::reload_current_scene() { } void SceneTree::add_current_scene(Node *p_current) { - current_scene = p_current; root->add_child(p_current); } -Ref<SceneTreeTimer> SceneTree::create_timer(float p_delay_sec, bool p_process_pause) { - +Ref<SceneTreeTimer> SceneTree::create_timer(float p_delay_sec, bool p_process_always) { Ref<SceneTreeTimer> stt; stt.instance(); - stt->set_pause_mode_process(p_process_pause); + stt->set_process_always(p_process_always); stt->set_time_left(p_delay_sec); timers.push_back(stt); return stt; } 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"); } @@ -1173,17 +1133,14 @@ void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer) { } 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(); } @@ -1192,12 +1149,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(); } @@ -1214,7 +1169,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); @@ -1232,7 +1186,7 @@ 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("create_timer", "time_sec", "pause_mode_process"), &SceneTree::create_timer, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("create_timer", "time_sec", "process_always"), &SceneTree::create_timer, DEFVAL(true)); ClassDB::bind_method(D_METHOD("get_node_count"), &SceneTree::get_node_count); ClassDB::bind_method(D_METHOD("get_frame"), &SceneTree::get_frame); @@ -1300,12 +1254,13 @@ void SceneTree::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multiplayer_poll"), "set_multiplayer_poll_enabled", "is_multiplayer_poll_enabled"); ADD_SIGNAL(MethodInfo("tree_changed")); + ADD_SIGNAL(MethodInfo("tree_process_mode_changed")); //editor only signal, but due to API hash it cant be removed in run-time 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("node_configuration_warning_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); - ADD_SIGNAL(MethodInfo("idle_frame")); + ADD_SIGNAL(MethodInfo("process_frame")); ADD_SIGNAL(MethodInfo("physics_frame")); ADD_SIGNAL(MethodInfo("files_dropped", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files"), PropertyInfo(Variant::INT, "screen"))); @@ -1327,7 +1282,6 @@ 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](); } @@ -1339,13 +1293,12 @@ void SceneTree::add_idle_callback(IdleCallback p_callback) { } 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; directories.push_back(dir_access->get_current_dir()); - while (!directories.empty()) { + while (!directories.is_empty()) { dir_access->change_dir(directories.back()->get()); directories.pop_back(); @@ -1371,49 +1324,25 @@ void SceneTree::get_argument_options(const StringName &p_function, int p_idx, Li } SceneTree::SceneTree() { - - if (singleton == nullptr) singleton = this; - _quit = false; - accept_quit = true; - quit_on_go_back = true; - initialized = false; -#ifdef DEBUG_ENABLED - debug_collisions_hint = false; - debug_navigation_hint = false; -#endif - debug_collisions_color = GLOBAL_DEF("debug/shapes/collision/shape_color", Color(0.0, 0.6, 0.7, 0.5)); + if (singleton == nullptr) { + singleton = this; + } + debug_collisions_color = GLOBAL_DEF("debug/shapes/collision/shape_color", Color(0.0, 0.6, 0.7, 0.42)); debug_collision_contact_color = GLOBAL_DEF("debug/shapes/collision/contact_color", Color(1.0, 0.2, 0.1, 0.8)); debug_navigation_color = GLOBAL_DEF("debug/shapes/navigation/geometry_color", Color(0.1, 1.0, 0.7, 0.4)); debug_navigation_disabled_color = GLOBAL_DEF("debug/shapes/navigation/disabled_geometry_color", Color(1.0, 0.7, 0.1, 0.4)); collision_debug_contacts = GLOBAL_DEF("debug/shapes/collision/max_contacts_displayed", 10000); 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 - tree_version = 1; - physics_process_time = 1; - idle_process_time = 1; - - 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"; - node_renamed_name = "node_renamed"; - ugc_locked = false; - call_lock = 0; - root_lock = 0; - node_count = 0; - - //create with mainloop + // Create with mainloop. root = memnew(Window); root->set_name("root"); - if (!root->get_world().is_valid()) - root->set_world(Ref<World3D>(memnew(World3D))); + if (!root->get_world_3d().is_valid()) { + root->set_world_3d(Ref<World3D>(memnew(World3D))); + } - // Initialize network state - multiplayer_poll = true; + // Initialize network state. set_multiplayer(Ref<MultiplayerAPI>(memnew(MultiplayerAPI))); //root->set_world_2d( Ref<World2D>( memnew( World2D ))); @@ -1421,39 +1350,81 @@ SceneTree::SceneTree() { root->set_as_audio_listener_2d(true); current_scene = nullptr; - 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,2x,4x,8x,16x")); + const int msaa_mode = GLOBAL_DEF("rendering/anti_aliasing/quality/msaa", 0); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/quality/msaa", PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/msaa", PROPERTY_HINT_ENUM, "Disabled (Fastest),2x (Fast),4x (Average),8x (Slow),16x (Slower)")); root->set_msaa(Viewport::MSAA(msaa_mode)); - 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,FXAA")); + const int ssaa_mode = GLOBAL_DEF("rendering/anti_aliasing/quality/screen_space_aa", 0); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/quality/screen_space_aa", PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/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 + const bool use_debanding = GLOBAL_DEF("rendering/anti_aliasing/quality/use_debanding", false); + root->set_use_debanding(use_debanding); + + float lod_threshold = GLOBAL_DEF("rendering/mesh_lod/lod_change/threshold_pixels", 1.0); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/mesh_lod/lod_change/threshold_pixels", PropertyInfo(Variant::FLOAT, "rendering/mesh_lod/lod_change/threshold_pixels", PROPERTY_HINT_RANGE, "0,1024,0.1")); + root->set_lod_threshold(lod_threshold); + + bool snap_2d_transforms = GLOBAL_DEF("rendering/2d/snap/snap_2d_transforms_to_pixel", false); + root->set_snap_2d_transforms_to_pixel(snap_2d_transforms); + + bool snap_2d_vertices = GLOBAL_DEF("rendering/2d/snap/snap_2d_vertices_to_pixel", false); + root->set_snap_2d_vertices_to_pixel(snap_2d_vertices); + + int shadowmap_size = GLOBAL_DEF("rendering/shadows/shadow_atlas/size", 4096); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadow_atlas/size", PropertyInfo(Variant::INT, "rendering/shadows/shadow_atlas/size", PROPERTY_HINT_RANGE, "256,16384")); + GLOBAL_DEF("rendering/shadows/shadow_atlas/size.mobile", 2048); + bool shadowmap_16_bits = GLOBAL_DEF("rendering/shadows/shadow_atlas/16_bits", true); + int atlas_q0 = GLOBAL_DEF("rendering/shadows/shadow_atlas/quadrant_0_subdiv", 2); + int atlas_q1 = GLOBAL_DEF("rendering/shadows/shadow_atlas/quadrant_1_subdiv", 2); + int atlas_q2 = GLOBAL_DEF("rendering/shadows/shadow_atlas/quadrant_2_subdiv", 3); + int atlas_q3 = GLOBAL_DEF("rendering/shadows/shadow_atlas/quadrant_3_subdiv", 4); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadow_atlas/quadrant_0_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/shadow_atlas/quadrant_0_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadow_atlas/quadrant_1_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/shadow_atlas/quadrant_1_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadow_atlas/quadrant_2_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/shadow_atlas/quadrant_2_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadow_atlas/quadrant_3_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/shadow_atlas/quadrant_3_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); + + root->set_shadow_atlas_size(shadowmap_size); + root->set_shadow_atlas_16_bits(shadowmap_16_bits); + root->set_shadow_atlas_quadrant_subdiv(0, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q0)); + root->set_shadow_atlas_quadrant_subdiv(1, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q1)); + root->set_shadow_atlas_quadrant_subdiv(2, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q2)); + root->set_shadow_atlas_quadrant_subdiv(3, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q3)); + + Viewport::SDFOversize sdf_oversize = Viewport::SDFOversize(int(GLOBAL_DEF("rendering/2d/sdf/oversize", 1))); + root->set_sdf_oversize(sdf_oversize); + Viewport::SDFScale sdf_scale = Viewport::SDFScale(int(GLOBAL_DEF("rendering/2d/sdf/scale", 1))); + root->set_sdf_scale(sdf_scale); + + ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/sdf/oversize", PropertyInfo(Variant::INT, "rendering/2d/sdf/oversize", PROPERTY_HINT_ENUM, "100%,120%,150%,200%")); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/sdf/scale", PropertyInfo(Variant::INT, "rendering/2d/sdf/scale", PROPERTY_HINT_ENUM, "100%,50%,25%")); + + { // Load default fallback environment. + // Get possible extensions. List<String> exts; 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 - String env_path = GLOBAL_DEF("rendering/environment/default_environment", ""); - //setup property - ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/default_environment", PropertyInfo(Variant::STRING, "rendering/viewport/default_environment", PROPERTY_HINT_FILE, ext_hint)); + // Get path. + String env_path = GLOBAL_DEF("rendering/environment/defaults/default_environment", ""); + // Setup property. + ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/defaults/default_environment", PropertyInfo(Variant::STRING, "rendering/viewport/default_environment", PROPERTY_HINT_FILE, ext_hint)); env_path = env_path.strip_edges(); 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", ""); + // File was erased, clear the field. + ProjectSettings::get_singleton()->set("rendering/environment/defaults/default_environment", ""); } else { - //file was erased, notify user. + // File was erased, notify user. ERR_PRINT(RTR("Default Environment as specified in Project Settings (Rendering -> Environment -> Default Environment) could not be loaded.")); } } @@ -1478,5 +1449,7 @@ SceneTree::~SceneTree() { memdelete(root); } - if (singleton == this) singleton = nullptr; + if (singleton == this) { + singleton = nullptr; + } } |