diff options
Diffstat (limited to 'scene/main')
-rw-r--r-- | scene/main/canvas_item.cpp | 20 | ||||
-rw-r--r-- | scene/main/node.cpp | 29 | ||||
-rw-r--r-- | scene/main/node.h | 4 | ||||
-rw-r--r-- | scene/main/scene_tree.cpp | 68 | ||||
-rw-r--r-- | scene/main/scene_tree.h | 1 | ||||
-rw-r--r-- | scene/main/viewport.cpp | 41 | ||||
-rw-r--r-- | scene/main/viewport.h | 4 | ||||
-rw-r--r-- | scene/main/window.cpp | 40 | ||||
-rw-r--r-- | scene/main/window.h | 12 |
9 files changed, 140 insertions, 79 deletions
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index a04c299705..3f98b540fc 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -195,7 +195,15 @@ void CanvasItem::_top_level_raise_self() { } void CanvasItem::_enter_canvas() { - if ((!Object::cast_to<CanvasItem>(get_parent())) || top_level) { + // Resolves to nullptr if the node is toplevel. + CanvasItem *parent_item = get_parent_item(); + + if (parent_item) { + canvas_layer = parent_item->canvas_layer; + RenderingServer::get_singleton()->canvas_item_set_parent(canvas_item, parent_item->get_canvas_item()); + RenderingServer::get_singleton()->canvas_item_set_draw_index(canvas_item, get_index()); + RenderingServer::get_singleton()->canvas_item_set_visibility_layer(canvas_item, visibility_layer); + } else { Node *n = this; canvas_layer = nullptr; @@ -231,13 +239,6 @@ void CanvasItem::_enter_canvas() { } get_tree()->call_group_flags(SceneTree::GROUP_CALL_UNIQUE | SceneTree::GROUP_CALL_DEFERRED, canvas_group, SNAME("_top_level_raise_self")); - - } else { - CanvasItem *parent = get_parent_item(); - canvas_layer = parent->canvas_layer; - RenderingServer::get_singleton()->canvas_item_set_parent(canvas_item, parent->get_canvas_item()); - RenderingServer::get_singleton()->canvas_item_set_draw_index(canvas_item, get_index()); - RenderingServer::get_singleton()->canvas_item_set_visibility_layer(canvas_item, visibility_layer); } pending_update = false; @@ -320,8 +321,7 @@ void CanvasItem::_notification(int p_what) { if (canvas_group != StringName()) { get_tree()->call_group_flags(SceneTree::GROUP_CALL_UNIQUE | SceneTree::GROUP_CALL_DEFERRED, canvas_group, "_top_level_raise_self"); } else { - CanvasItem *p = get_parent_item(); - ERR_FAIL_COND(!p); + ERR_FAIL_COND_MSG(!get_parent_item(), "Moved child is in incorrect state (no canvas group, no canvas item parent)."); RenderingServer::get_singleton()->canvas_item_set_draw_index(canvas_item, get_index()); } } break; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 0670b97d55..eb57ccfef1 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -39,6 +39,7 @@ #include "scene/animation/tween.h" #include "scene/debugger/scene_debugger.h" #include "scene/main/multiplayer_api.h" +#include "scene/main/window.h" #include "scene/resources/packed_scene.h" #include "scene/scene_string_names.h" #include "viewport.h" @@ -1439,6 +1440,18 @@ TypedArray<Node> Node::find_children(const String &p_pattern, const String &p_ty return ret; } +void Node::reparent(Node *p_parent, bool p_keep_global_transform) { + ERR_FAIL_NULL(p_parent); + ERR_FAIL_NULL_MSG(data.parent, "Node needs a parent to be reparented."); + + if (p_parent == data.parent) { + return; + } + + data.parent->remove_child(this); + p_parent->add_child(this); +} + Node *Node::get_parent() const { return data.parent; } @@ -1455,6 +1468,14 @@ Node *Node::find_parent(const String &p_pattern) const { return nullptr; } +Window *Node::get_window() const { + Viewport *vp = get_viewport(); + if (vp) { + return vp->get_base_window(); + } + return nullptr; +} + bool Node::is_ancestor_of(const Node *p_node) const { ERR_FAIL_NULL_V(p_node, false); Node *p = p_node->data.parent; @@ -2774,10 +2795,8 @@ void Node::unhandled_key_input(const Ref<InputEvent> &p_key_event) { } void Node::_bind_methods() { - GLOBAL_DEF("editor/node_naming/name_num_separator", 0); - ProjectSettings::get_singleton()->set_custom_property_info("editor/node_naming/name_num_separator", PropertyInfo(Variant::INT, "editor/node_naming/name_num_separator", PROPERTY_HINT_ENUM, "None,Space,Underscore,Dash")); - GLOBAL_DEF("editor/node_naming/name_casing", NAME_CASING_PASCAL_CASE); - ProjectSettings::get_singleton()->set_custom_property_info("editor/node_naming/name_casing", PropertyInfo(Variant::INT, "editor/node_naming/name_casing", PROPERTY_HINT_ENUM, "PascalCase,camelCase,snake_case")); + GLOBAL_DEF(PropertyInfo(Variant::INT, "editor/node_naming/name_num_separator", PROPERTY_HINT_ENUM, "None,Space,Underscore,Dash"), 0); + GLOBAL_DEF(PropertyInfo(Variant::INT, "editor/node_naming/name_casing", PROPERTY_HINT_ENUM, "PascalCase,camelCase,snake_case"), NAME_CASING_PASCAL_CASE); ClassDB::bind_static_method("Node", D_METHOD("print_orphan_nodes"), &Node::print_orphan_nodes); ClassDB::bind_method(D_METHOD("add_sibling", "sibling", "force_readable_name"), &Node::add_sibling, DEFVAL(false)); @@ -2786,6 +2805,7 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("get_name"), &Node::get_name); ClassDB::bind_method(D_METHOD("add_child", "node", "force_readable_name", "internal"), &Node::add_child, DEFVAL(false), DEFVAL(0)); ClassDB::bind_method(D_METHOD("remove_child", "node"), &Node::remove_child); + ClassDB::bind_method(D_METHOD("reparent", "new_parent", "keep_global_transform"), &Node::reparent, DEFVAL(true)); ClassDB::bind_method(D_METHOD("get_child_count", "include_internal"), &Node::get_child_count, DEFVAL(false)); // Note that the default value bound for include_internal is false, while the method is declared with true. This is because internal nodes are irrelevant for GDSCript. ClassDB::bind_method(D_METHOD("get_children", "include_internal"), &Node::_get_children, DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_child", "idx", "include_internal"), &Node::get_child, DEFVAL(false)); @@ -2847,6 +2867,7 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("set_physics_process_internal", "enable"), &Node::set_physics_process_internal); ClassDB::bind_method(D_METHOD("is_physics_processing_internal"), &Node::is_physics_processing_internal); + ClassDB::bind_method(D_METHOD("get_window"), &Node::get_window); ClassDB::bind_method(D_METHOD("get_tree"), &Node::get_tree); ClassDB::bind_method(D_METHOD("create_tween"), &Node::create_tween); diff --git a/scene/main/node.h b/scene/main/node.h index 611f48c400..dbdcca6170 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -37,6 +37,7 @@ #include "scene/main/scene_tree.h" class Viewport; +class Window; class SceneState; class Tween; class PropertyTweener; @@ -317,9 +318,12 @@ public: bool has_node_and_resource(const NodePath &p_path) const; Node *get_node_and_resource(const NodePath &p_path, Ref<Resource> &r_res, Vector<StringName> &r_leftover_subpath, bool p_last_is_property = true) const; + virtual void reparent(Node *p_parent, bool p_keep_global_transform = true); Node *get_parent() const; Node *find_parent(const String &p_pattern) const; + Window *get_window() const; + _FORCE_INLINE_ SceneTree *get_tree() const { ERR_FAIL_COND_V(!data.tree, nullptr); return data.tree; diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 18253c6094..b5c587c0aa 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -1131,11 +1131,11 @@ Error SceneTree::change_scene_to_file(const String &p_path) { } Error SceneTree::change_scene_to_packed(const Ref<PackedScene> &p_scene) { - Node *new_scene = nullptr; - if (p_scene.is_valid()) { - new_scene = p_scene->instantiate(); - ERR_FAIL_COND_V(!new_scene, ERR_CANT_CREATE); - } + ERR_FAIL_COND_V_MSG(p_scene.is_null(), ERR_INVALID_PARAMETER, "Can't change to a null scene. Use unload_current_scene() if you wish to unload it."); + + Node *new_scene = p_scene->instantiate(); + new_scene = p_scene->instantiate(); + ERR_FAIL_COND_V(!new_scene, ERR_CANT_CREATE); call_deferred(SNAME("_change_scene"), new_scene); return OK; @@ -1147,6 +1147,13 @@ Error SceneTree::reload_current_scene() { return change_scene_to_file(fname); } +void SceneTree::unload_current_scene() { + if (current_scene) { + memdelete(current_scene); + current_scene = nullptr; + } +} + void SceneTree::add_current_scene(Node *p_current) { current_scene = p_current; root->add_child(p_current); @@ -1297,6 +1304,7 @@ void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("change_scene_to_packed", "packed_scene"), &SceneTree::change_scene_to_packed); ClassDB::bind_method(D_METHOD("reload_current_scene"), &SceneTree::reload_current_scene); + ClassDB::bind_method(D_METHOD("unload_current_scene"), &SceneTree::unload_current_scene); ClassDB::bind_method(D_METHOD("_change_scene"), &SceneTree::_change_scene); @@ -1387,8 +1395,7 @@ SceneTree::SceneTree() { debug_collision_contact_color = GLOBAL_DEF("debug/shapes/collision/contact_color", Color(1.0, 0.2, 0.1, 0.8)); debug_paths_color = GLOBAL_DEF("debug/shapes/paths/geometry_color", Color(0.1, 1.0, 0.7, 0.4)); debug_paths_width = GLOBAL_DEF("debug/shapes/paths/geometry_width", 2.0); - 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 + collision_debug_contacts = GLOBAL_DEF(PropertyInfo(Variant::INT, "debug/shapes/collision/max_contacts_displayed", PROPERTY_HINT_RANGE, "0,20000,1"), 10000); GLOBAL_DEF("debug/shapes/collision/draw_2d_outlines", true); @@ -1397,6 +1404,7 @@ SceneTree::SceneTree() { // Create with mainloop. root = memnew(Window); + root->set_min_size(Size2i(64, 64)); // Define a very small minimum window size to prevent bugs such as GH-37242. root->set_process_mode(Node::PROCESS_MODE_PAUSABLE); root->set_name("root"); root->set_title(GLOBAL_GET("application/config/name")); @@ -1414,19 +1422,16 @@ SceneTree::SceneTree() { root->set_as_audio_listener_2d(true); current_scene = nullptr; - const int msaa_mode_2d = GLOBAL_DEF_BASIC("rendering/anti_aliasing/quality/msaa_2d", 0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/quality/msaa_2d", PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/msaa_2d", PROPERTY_HINT_ENUM, String::utf8("Disabled (Fastest),2× (Average),4× (Slow),8× (Slowest)"))); + const int msaa_mode_2d = GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/msaa_2d", PROPERTY_HINT_ENUM, String::utf8("Disabled (Fastest),2× (Average),4× (Slow),8× (Slowest)")), 0); root->set_msaa_2d(Viewport::MSAA(msaa_mode_2d)); - const int msaa_mode_3d = GLOBAL_DEF_BASIC("rendering/anti_aliasing/quality/msaa_3d", 0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/quality/msaa_3d", PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/msaa_3d", PROPERTY_HINT_ENUM, String::utf8("Disabled (Fastest),2× (Average),4× (Slow),8× (Slowest)"))); + const int msaa_mode_3d = GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/msaa_3d", PROPERTY_HINT_ENUM, String::utf8("Disabled (Fastest),2× (Average),4× (Slow),8× (Slowest)")), 0); root->set_msaa_3d(Viewport::MSAA(msaa_mode_3d)); const bool transparent_background = GLOBAL_DEF("rendering/viewport/transparent_background", false); root->set_transparent_background(transparent_background); - const int ssaa_mode = GLOBAL_DEF_BASIC("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)")); + const int ssaa_mode = GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/screen_space_aa", PROPERTY_HINT_ENUM, "Disabled (Fastest),FXAA (Fast)"), 0); root->set_screen_space_aa(Viewport::ScreenSpaceAA(ssaa_mode)); const bool use_taa = GLOBAL_DEF_BASIC("rendering/anti_aliasing/quality/use_taa", false); @@ -1438,8 +1443,7 @@ SceneTree::SceneTree() { const bool use_occlusion_culling = GLOBAL_DEF("rendering/occlusion_culling/use_occlusion_culling", false); root->set_use_occlusion_culling(use_occlusion_culling); - float mesh_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")); + float mesh_lod_threshold = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/mesh_lod/lod_change/threshold_pixels", PROPERTY_HINT_RANGE, "0,1024,0.1"), 1.0); root->set_mesh_lod_threshold(mesh_lod_threshold); bool snap_2d_transforms = GLOBAL_DEF("rendering/2d/snap/snap_2d_transforms_to_pixel", false); @@ -1449,14 +1453,9 @@ SceneTree::SceneTree() { root->set_snap_2d_vertices_to_pixel(snap_2d_vertices); // We setup VRS for the main viewport here, in the editor this will have little effect. - const int vrs_mode = GLOBAL_DEF("rendering/vrs/mode", 0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/vrs/mode", PropertyInfo(Variant::INT, "rendering/vrs/mode", PROPERTY_HINT_ENUM, String::utf8("Disabled,Texture,XR"))); + const int vrs_mode = GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/vrs/mode", PROPERTY_HINT_ENUM, String::utf8("Disabled,Texture,XR")), 0); root->set_vrs_mode(Viewport::VRSMode(vrs_mode)); - const String vrs_texture_path = String(GLOBAL_DEF("rendering/vrs/texture", String())).strip_edges(); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/vrs/texture", - PropertyInfo(Variant::STRING, - "rendering/vrs/texture", - PROPERTY_HINT_FILE, "*.bmp,*.png,*.tga,*.webp")); + const String vrs_texture_path = String(GLOBAL_DEF(PropertyInfo(Variant::STRING, "rendering/vrs/texture", PROPERTY_HINT_FILE, "*.bmp,*.png,*.tga,*.webp"), String())).strip_edges(); if (vrs_mode == 1 && !vrs_texture_path.is_empty()) { Ref<Image> vrs_image; vrs_image.instantiate(); @@ -1471,18 +1470,13 @@ SceneTree::SceneTree() { } } - int shadowmap_size = GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_size", 4096); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/lights_and_shadows/positional_shadow/atlas_size", PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_size", PROPERTY_HINT_RANGE, "256,16384")); + int shadowmap_size = GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_size", PROPERTY_HINT_RANGE, "256,16384"), 4096); GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_size.mobile", 2048); bool shadowmap_16_bits = GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_16_bits", true); - int atlas_q0 = GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_0_subdiv", 2); - int atlas_q1 = GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_1_subdiv", 2); - int atlas_q2 = GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_2_subdiv", 3); - int atlas_q3 = GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_3_subdiv", 4); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_0_subdiv", PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_quadrant_0_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_1_subdiv", PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_quadrant_1_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_2_subdiv", PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_quadrant_2_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_3_subdiv", PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_quadrant_3_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); + int atlas_q0 = GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_quadrant_0_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), 2); + int atlas_q1 = GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_quadrant_1_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), 2); + int atlas_q2 = GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_quadrant_2_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), 3); + int atlas_q3 = GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_quadrant_3_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), 4); root->set_positional_shadow_atlas_size(shadowmap_size); root->set_positional_shadow_atlas_16_bits(shadowmap_16_bits); @@ -1491,14 +1485,11 @@ SceneTree::SceneTree() { root->set_positional_shadow_atlas_quadrant_subdiv(2, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q2)); root->set_positional_shadow_atlas_quadrant_subdiv(3, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q3)); - Viewport::SDFOversize sdf_oversize = Viewport::SDFOversize(int(GLOBAL_DEF("rendering/2d/sdf/oversize", 1))); + Viewport::SDFOversize sdf_oversize = Viewport::SDFOversize(int(GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/2d/sdf/oversize", PROPERTY_HINT_ENUM, "100%,120%,150%,200%"), 1))); root->set_sdf_oversize(sdf_oversize); - Viewport::SDFScale sdf_scale = Viewport::SDFScale(int(GLOBAL_DEF("rendering/2d/sdf/scale", 1))); + Viewport::SDFScale sdf_scale = Viewport::SDFScale(int(GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/2d/sdf/scale", PROPERTY_HINT_ENUM, "100%,50%,25%"), 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%")); - #ifndef _3D_DISABLED { // Load default fallback environment. // Get possible extensions. @@ -1512,9 +1503,8 @@ SceneTree::SceneTree() { ext_hint += "*." + E; } // Get path. - String env_path = GLOBAL_DEF("rendering/environment/defaults/default_environment", ""); + String env_path = GLOBAL_DEF(PropertyInfo(Variant::STRING, "rendering/environment/defaults/default_environment", PROPERTY_HINT_FILE, ext_hint), ""); // 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.is_empty()) { Ref<Environment> env = ResourceLoader::load(env_path); diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index 77cfe0a04a..fc185b4f37 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -361,6 +361,7 @@ public: Error change_scene_to_file(const String &p_path); Error change_scene_to_packed(const Ref<PackedScene> &p_scene); Error reload_current_scene(); + void unload_current_scene(); Ref<SceneTreeTimer> create_timer(double p_delay_sec, bool p_process_always = true, bool p_process_in_physics = false, bool p_ignore_time_scale = false); Ref<Tween> create_tween(); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 43f9863d14..7ca1f9d3ec 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -603,9 +603,9 @@ void Viewport::_process_picking() { physics_last_mouse_state.meta = mb->is_meta_pressed(); if (mb->is_pressed()) { - physics_last_mouse_state.mouse_mask |= mouse_button_to_mask(mb->get_button_index()); + physics_last_mouse_state.mouse_mask.set_flag(mouse_button_to_mask(mb->get_button_index())); } else { - physics_last_mouse_state.mouse_mask &= ~mouse_button_to_mask(mb->get_button_index()); + physics_last_mouse_state.mouse_mask.clear_flag(mouse_button_to_mask(mb->get_button_index())); // If touch mouse raised, assume we don't know last mouse pos until new events come if (mb->get_device() == InputEvent::DEVICE_ID_TOUCH_MOUSE) { @@ -1298,7 +1298,6 @@ void Viewport::_gui_show_tooltip() { r.position.y = vr.position.y; } - gui.tooltip_popup->set_current_screen(window->get_current_screen()); gui.tooltip_popup->set_position(r.position); gui.tooltip_popup->set_size(r.size); @@ -1497,19 +1496,20 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { Point2 mpos = mb->get_position(); if (mb->is_pressed()) { Size2 pos = mpos; - if (gui.mouse_focus_mask != MouseButton::NONE) { + if (!gui.mouse_focus_mask.is_empty()) { // Do not steal mouse focus and stuff while a focus mask exists. - gui.mouse_focus_mask |= mouse_button_to_mask(mb->get_button_index()); + gui.mouse_focus_mask.set_flag(mouse_button_to_mask(mb->get_button_index())); } else { gui.mouse_focus = gui_find_control(pos); gui.last_mouse_focus = gui.mouse_focus; if (!gui.mouse_focus) { - gui.mouse_focus_mask = MouseButton::NONE; + gui.mouse_focus_mask.clear(); return; } - gui.mouse_focus_mask = mouse_button_to_mask(mb->get_button_index()); + gui.mouse_focus_mask.clear(); + gui.mouse_focus_mask.set_flag(mouse_button_to_mask(mb->get_button_index())); if (mb->get_button_index() == MouseButton::LEFT) { gui.drag_accum = Vector2(); @@ -1579,7 +1579,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { _perform_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos); } - gui.mouse_focus_mask &= ~mouse_button_to_mask(mb->get_button_index()); // Remove from mask. + gui.mouse_focus_mask.clear_flag(mouse_button_to_mask(mb->get_button_index())); // Remove from mask. if (!gui.mouse_focus) { // Release event is only sent if a mouse focus (previously pressed button) exists. @@ -1598,7 +1598,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { // Disable mouse focus if needed before calling input, // this makes popups on mouse press event work better, // as the release will never be received otherwise. - if (gui.mouse_focus_mask == MouseButton::NONE) { + if (gui.mouse_focus_mask.is_empty()) { gui.mouse_focus = nullptr; gui.forced_mouse_focus = false; } @@ -1620,7 +1620,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { Point2 mpos = mm->get_position(); // Drag & drop. - if (!gui.drag_attempted && gui.mouse_focus && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { + if (!gui.drag_attempted && gui.mouse_focus && (mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) { gui.drag_accum += mm->get_relative(); float len = gui.drag_accum.length(); if (len > 10) { @@ -1634,7 +1634,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { if (gui.drag_data.get_type() != Variant::NIL) { gui.mouse_focus = nullptr; gui.forced_mouse_focus = false; - gui.mouse_focus_mask = MouseButton::NONE; + gui.mouse_focus_mask.clear(); break; } else { Control *drag_preview = _gui_get_drag_preview(); @@ -1702,7 +1702,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { mm->set_velocity(velocity); mm->set_relative(rel); - if (mm->get_button_mask() == MouseButton::NONE) { + if (mm->get_button_mask().is_empty()) { // Nothing pressed. bool is_tooltip_shown = false; @@ -1745,7 +1745,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { Control *c = over; Vector2 cpos = pos; while (c) { - if (gui.mouse_focus_mask != MouseButton::NONE || c->has_point(cpos)) { + if (!gui.mouse_focus_mask.is_empty() || c->has_point(cpos)) { cursor_shape = c->get_cursor_shape(cpos); } else { cursor_shape = Control::CURSOR_ARROW; @@ -2104,7 +2104,7 @@ void Viewport::_gui_cleanup_internal_state(Ref<InputEvent> p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { if (!mb->is_pressed()) { - gui.mouse_focus_mask &= ~mouse_button_to_mask(mb->get_button_index()); // Remove from mask. + gui.mouse_focus_mask.clear_flag(mouse_button_to_mask(mb->get_button_index())); // Remove from mask. } } } @@ -2195,7 +2195,7 @@ void Viewport::_gui_remove_control(Control *p_control) { if (gui.mouse_focus == p_control) { gui.mouse_focus = nullptr; gui.forced_mouse_focus = false; - gui.mouse_focus_mask = MouseButton::NONE; + gui.mouse_focus_mask.clear(); } if (gui.last_mouse_focus == p_control) { gui.last_mouse_focus = nullptr; @@ -2264,10 +2264,10 @@ void Viewport::_drop_mouse_over() { void Viewport::_drop_mouse_focus() { Control *c = gui.mouse_focus; - MouseButton mask = gui.mouse_focus_mask; + BitField<MouseButtonMask> mask = gui.mouse_focus_mask; gui.mouse_focus = nullptr; gui.forced_mouse_focus = false; - gui.mouse_focus_mask = MouseButton::NONE; + gui.mouse_focus_mask.clear(); for (int i = 0; i < 3; i++) { if ((int)mask & (1 << i)) { @@ -2375,7 +2375,7 @@ void Viewport::_post_gui_grab_click_focus() { return; } - MouseButton mask = gui.mouse_focus_mask; + BitField<MouseButtonMask> mask = gui.mouse_focus_mask; Point2 click = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse().xform(gui.last_mouse_pos); for (int i = 0; i < 3; i++) { @@ -3240,7 +3240,7 @@ void Viewport::pass_mouse_focus_to(Viewport *p_viewport, Control *p_control) { gui.mouse_focus = nullptr; gui.forced_mouse_focus = false; - gui.mouse_focus_mask = MouseButton::NONE; + gui.mouse_focus_mask.clear(); } } @@ -4104,8 +4104,7 @@ Viewport::Viewport() { unhandled_key_input_group = "_vp_unhandled_key_input" + id; // Window tooltip. - gui.tooltip_delay = GLOBAL_DEF("gui/timers/tooltip_delay_sec", 0.5); - ProjectSettings::get_singleton()->set_custom_property_info("gui/timers/tooltip_delay_sec", PropertyInfo(Variant::FLOAT, "gui/timers/tooltip_delay_sec", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater")); // No negative numbers + gui.tooltip_delay = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "gui/timers/tooltip_delay_sec", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"), 0.5); #ifndef _3D_DISABLED set_scaling_3d_mode((Viewport::Scaling3DMode)(int)GLOBAL_GET("rendering/scaling_3d/mode")); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index ca6f3163df..9f182682d7 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -259,7 +259,7 @@ private: bool control = false; bool shift = false; bool meta = false; - MouseButton mouse_mask = MouseButton::NONE; + BitField<MouseButtonMask> mouse_mask; } physics_last_mouse_state; @@ -358,7 +358,7 @@ private: Control *mouse_focus = nullptr; Control *last_mouse_focus = nullptr; Control *mouse_click_grabber = nullptr; - MouseButton mouse_focus_mask = MouseButton::NONE; + BitField<MouseButtonMask> mouse_focus_mask; Control *key_focus = nullptr; Control *mouse_over = nullptr; Control *drag_mouse_over = nullptr; diff --git a/scene/main/window.cpp b/scene/main/window.cpp index d3fcf29927..c5dbfffd7b 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -223,6 +223,14 @@ void Window::_get_property_list(List<PropertyInfo> *p_list) const { } void Window::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "position" && initial_position != WINDOW_INITIAL_POSITION_ABSOLUTE) { + p_property.usage = PROPERTY_USAGE_NONE; + } + + if (p_property.name == "current_screen" && initial_position != WINDOW_INITIAL_POSITION_CENTER_SCREEN) { + p_property.usage = PROPERTY_USAGE_NONE; + } + if (p_property.name == "theme_type_variation") { List<StringName> names; @@ -275,6 +283,15 @@ String Window::get_title() const { return title; } +void Window::set_initial_position(Window::WindowInitialPosition p_initial_position) { + initial_position = p_initial_position; + notify_property_list_changed(); +} + +Window::WindowInitialPosition Window::get_initial_position() const { + return initial_position; +} + void Window::set_current_screen(int p_screen) { current_screen = p_screen; if (window_id == DisplayServer::INVALID_WINDOW_ID) { @@ -462,7 +479,13 @@ void Window::_make_window() { } DisplayServer::VSyncMode vsync_mode = DisplayServer::get_singleton()->window_get_vsync_mode(DisplayServer::MAIN_WINDOW_ID); - window_id = DisplayServer::get_singleton()->create_sub_window(DisplayServer::WindowMode(mode), vsync_mode, f, Rect2i(position, size), current_screen); + Rect2i window_rect; + if (initial_position == WINDOW_INITIAL_POSITION_ABSOLUTE) { + window_rect = Rect2i(position, size); + } else if (initial_position == WINDOW_INITIAL_POSITION_CENTER_SCREEN) { + window_rect = Rect2i(DisplayServer::get_singleton()->screen_get_position(current_screen) + (DisplayServer::get_singleton()->screen_get_size(current_screen) - size) / 2, size); + } + window_id = DisplayServer::get_singleton()->create_sub_window(DisplayServer::WindowMode(mode), vsync_mode, f, window_rect); ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID); DisplayServer::get_singleton()->window_set_max_size(Size2i(), window_id); DisplayServer::get_singleton()->window_set_min_size(Size2i(), window_id); @@ -2068,6 +2091,9 @@ void Window::_bind_methods() { ClassDB::bind_method(D_METHOD("set_title", "title"), &Window::set_title); ClassDB::bind_method(D_METHOD("get_title"), &Window::get_title); + ClassDB::bind_method(D_METHOD("set_initial_position", "initial_position"), &Window::set_initial_position); + ClassDB::bind_method(D_METHOD("get_initial_position"), &Window::get_initial_position); + ClassDB::bind_method(D_METHOD("set_current_screen", "index"), &Window::set_current_screen); ClassDB::bind_method(D_METHOD("get_current_screen"), &Window::get_current_screen); @@ -2204,11 +2230,18 @@ void Window::_bind_methods() { ClassDB::bind_method(D_METHOD("popup_centered", "minsize"), &Window::popup_centered, DEFVAL(Size2i())); ClassDB::bind_method(D_METHOD("popup_centered_clamped", "minsize", "fallback_ratio"), &Window::popup_centered_clamped, DEFVAL(Size2i()), DEFVAL(0.75)); + ADD_PROPERTY(PropertyInfo(Variant::INT, "initial_position", PROPERTY_HINT_ENUM, "Absolute,Screen Center"), "set_initial_position", "get_initial_position"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "position", PROPERTY_HINT_NONE, "suffix:px"), "set_position", "get_position"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size", PROPERTY_HINT_NONE, "suffix:px"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Windowed,Minimized,Maximized,Fullscreen"), "set_mode", "get_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "current_screen"), "set_current_screen", "get_current_screen"); + + // Keep the enum values in sync with the `DisplayServer::SCREEN_` enum. + String screen_hints = "Primary Monitor:-2,Main Window Monitor:-1"; + for (int i = 0; i < 64; i++) { + screen_hints += ",Monitor " + itos(i + 1) + ":" + itos(i); + } + ADD_PROPERTY(PropertyInfo(Variant::INT, "current_screen", PROPERTY_HINT_ENUM, screen_hints), "set_current_screen", "get_current_screen"); ADD_GROUP("Flags", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible"); @@ -2285,6 +2318,9 @@ void Window::_bind_methods() { BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LOCALE); BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LTR); BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_RTL); + + BIND_ENUM_CONSTANT(WINDOW_INITIAL_POSITION_ABSOLUTE); + BIND_ENUM_CONSTANT(WINDOW_INITIAL_POSITION_CENTER_SCREEN); } Window::Window() { diff --git a/scene/main/window.h b/scene/main/window.h index 9a16a24e57..97f8450628 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -87,11 +87,16 @@ public: DEFAULT_WINDOW_SIZE = 100, }; + enum WindowInitialPosition { + WINDOW_INITIAL_POSITION_ABSOLUTE, + WINDOW_INITIAL_POSITION_CENTER_SCREEN, + }; + private: DisplayServer::WindowID window_id = DisplayServer::INVALID_WINDOW_ID; String title; - mutable int current_screen = 0; + mutable int current_screen = DisplayServer::SCREEN_PRIMARY; mutable Vector2i position; mutable Size2i size = Size2i(DEFAULT_WINDOW_SIZE, DEFAULT_WINDOW_SIZE); mutable Size2i min_size; @@ -100,6 +105,7 @@ private: mutable bool flags[FLAG_MAX] = {}; bool visible = true; bool focused = false; + WindowInitialPosition initial_position = WINDOW_INITIAL_POSITION_ABSOLUTE; bool use_font_oversampling = false; bool transient = false; @@ -201,6 +207,9 @@ public: void set_title(const String &p_title); String get_title() const; + void set_initial_position(WindowInitialPosition p_initial_position); + WindowInitialPosition get_initial_position() const; + void set_current_screen(int p_screen); int get_current_screen() const; @@ -369,5 +378,6 @@ VARIANT_ENUM_CAST(Window::Flags); VARIANT_ENUM_CAST(Window::ContentScaleMode); VARIANT_ENUM_CAST(Window::ContentScaleAspect); VARIANT_ENUM_CAST(Window::LayoutDirection); +VARIANT_ENUM_CAST(Window::WindowInitialPosition); #endif // WINDOW_H |