summaryrefslogtreecommitdiff
path: root/scene/main
diff options
context:
space:
mode:
Diffstat (limited to 'scene/main')
-rw-r--r--scene/main/canvas_item.cpp20
-rw-r--r--scene/main/node.cpp29
-rw-r--r--scene/main/node.h4
-rw-r--r--scene/main/scene_tree.cpp68
-rw-r--r--scene/main/scene_tree.h1
-rw-r--r--scene/main/viewport.cpp41
-rw-r--r--scene/main/viewport.h4
-rw-r--r--scene/main/window.cpp40
-rw-r--r--scene/main/window.h12
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