diff options
Diffstat (limited to 'scene/main')
-rw-r--r-- | scene/main/canvas_item.cpp | 2 | ||||
-rw-r--r-- | scene/main/node.cpp | 160 | ||||
-rw-r--r-- | scene/main/node.h | 16 | ||||
-rw-r--r-- | scene/main/scene_tree.cpp | 73 | ||||
-rw-r--r-- | scene/main/scene_tree.h | 5 | ||||
-rw-r--r-- | scene/main/viewport.cpp | 8 | ||||
-rw-r--r-- | scene/main/window.cpp | 15 |
7 files changed, 217 insertions, 62 deletions
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index 708359f106..20f3f82a4e 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -1293,7 +1293,7 @@ void CanvasTexture::_bind_methods() { ADD_GROUP("Diffuse", "diffuse_"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "diffuse_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_diffuse_texture", "get_diffuse_texture"); - ADD_GROUP("Normalmap", "normal_"); + ADD_GROUP("NormalMap", "normal_"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "normal_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_normal_texture", "get_normal_texture"); ADD_GROUP("Specular", "specular_"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "specular_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_specular_texture", "get_specular_texture"); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 34bb1cde05..f1c0260dd5 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -257,6 +257,9 @@ void Node::_propagate_after_exit_tree() { } if (!found) { + if (data.unique_name_in_owner) { + _release_unique_name_in_owner(); + } data.owner->data.owned.erase(data.OW); data.owner = nullptr; } @@ -650,21 +653,10 @@ void Node::rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg } Ref<MultiplayerAPI> Node::get_multiplayer() const { - if (multiplayer.is_valid()) { - return multiplayer; - } if (!is_inside_tree()) { return Ref<MultiplayerAPI>(); } - return get_tree()->get_multiplayer(); -} - -Ref<MultiplayerAPI> Node::get_custom_multiplayer() const { - return multiplayer; -} - -void Node::set_custom_multiplayer(Ref<MultiplayerAPI> p_multiplayer) { - multiplayer = p_multiplayer; + return get_tree()->get_multiplayer(get_path()); } Vector<Multiplayer::RPCConfig> Node::get_node_rpc_methods() const { @@ -917,12 +909,20 @@ void Node::set_name(const String &p_name) { String name = p_name.validate_node_name(); ERR_FAIL_COND(name.is_empty()); + + if (data.unique_name_in_owner && data.owner) { + _release_unique_name_in_owner(); + } data.name = name; if (data.parent) { data.parent->_validate_child_name(this, true); } + if (data.unique_name_in_owner && data.owner) { + _acquire_unique_name_in_owner(); + } + propagate_notification(NOTIFICATION_PATH_RENAMED); if (is_inside_tree()) { @@ -1303,6 +1303,24 @@ Node *Node::get_node_or_null(const NodePath &p_path) const { next = root; } + } else if (name.is_node_unique_name()) { + if (current->data.owned_unique_nodes.size()) { + // Has unique nodes in ownership + Node **unique = current->data.owned_unique_nodes.getptr(name); + if (!unique) { + return nullptr; + } + next = *unique; + } else if (current->data.owner) { + Node **unique = current->data.owner->data.owned_unique_nodes.getptr(name); + if (!unique) { + return nullptr; + } + next = *unique; + } else { + return nullptr; + } + } else { next = nullptr; @@ -1344,9 +1362,39 @@ bool Node::has_node(const NodePath &p_path) const { return get_node_or_null(p_path) != nullptr; } -TypedArray<Node> Node::find_nodes(const String &p_mask, const String &p_type, bool p_recursive, bool p_owned) const { +// Finds the first child node (in tree order) whose name matches the given pattern. +// Can be recursive or not, and limited to owned nodes. +Node *Node::find_child(const String &p_pattern, bool p_recursive, bool p_owned) const { + ERR_FAIL_COND_V(p_pattern.is_empty(), nullptr); + + Node *const *cptr = data.children.ptr(); + int ccount = data.children.size(); + for (int i = 0; i < ccount; i++) { + if (p_owned && !cptr[i]->data.owner) { + continue; + } + if (cptr[i]->data.name.operator String().match(p_pattern)) { + return cptr[i]; + } + + if (!p_recursive) { + continue; + } + + Node *ret = cptr[i]->find_child(p_pattern, true, p_owned); + if (ret) { + return ret; + } + } + return nullptr; +} + +// Finds child nodes based on their name using pattern matching, or class name, +// or both (either pattern or type can be left empty). +// Can be recursive or not, and limited to owned nodes. +TypedArray<Node> Node::find_children(const String &p_pattern, const String &p_type, bool p_recursive, bool p_owned) const { TypedArray<Node> ret; - ERR_FAIL_COND_V(p_mask.is_empty() && p_type.is_empty(), ret); + ERR_FAIL_COND_V(p_pattern.is_empty() && p_type.is_empty(), ret); Node *const *cptr = data.children.ptr(); int ccount = data.children.size(); @@ -1355,8 +1403,8 @@ TypedArray<Node> Node::find_nodes(const String &p_mask, const String &p_type, bo continue; } - if (!p_mask.is_empty()) { - if (!cptr[i]->data.name.operator String().match(p_mask)) { + if (!p_pattern.is_empty()) { + if (!cptr[i]->data.name.operator String().match(p_pattern)) { continue; } else if (p_type.is_empty()) { ret.append(cptr[i]); @@ -1378,7 +1426,7 @@ TypedArray<Node> Node::find_nodes(const String &p_mask, const String &p_type, bo } if (p_recursive) { - ret.append_array(cptr[i]->find_nodes(p_mask, p_type, true, p_owned)); + ret.append_array(cptr[i]->find_children(p_pattern, p_type, true, p_owned)); } } @@ -1389,10 +1437,10 @@ Node *Node::get_parent() const { return data.parent; } -Node *Node::find_parent(const String &p_mask) const { +Node *Node::find_parent(const String &p_pattern) const { Node *p = data.parent; while (p) { - if (p->data.name.operator String().match(p_mask)) { + if (p->data.name.operator String().match(p_pattern)) { return p; } p = p->data.parent; @@ -1498,8 +1546,56 @@ void Node::_set_owner_nocheck(Node *p_owner) { data.OW = data.owner->data.owned.back(); } +void Node::_release_unique_name_in_owner() { + ERR_FAIL_NULL(data.owner); // Sanity check. + StringName key = StringName(UNIQUE_NODE_PREFIX + data.name.operator String()); + Node **which = data.owner->data.owned_unique_nodes.getptr(key); + if (which == nullptr || *which != this) { + return; // Ignore. + } + data.owner->data.owned_unique_nodes.erase(key); +} + +void Node::_acquire_unique_name_in_owner() { + ERR_FAIL_NULL(data.owner); // Sanity check. + StringName key = StringName(UNIQUE_NODE_PREFIX + data.name.operator String()); + Node **which = data.owner->data.owned_unique_nodes.getptr(key); + if (which != nullptr && *which != this) { + String which_path = is_inside_tree() ? (*which)->get_path() : data.owner->get_path_to(*which); + WARN_PRINT(vformat(RTR("Setting node name '%s' to be unique within scene for '%s', but it's already claimed by '%s'.\n'%s' is no longer set as having a unique name."), + get_name(), is_inside_tree() ? get_path() : data.owner->get_path_to(this), which_path, which_path)); + data.unique_name_in_owner = false; + return; + } + data.owner->data.owned_unique_nodes[key] = this; +} + +void Node::set_unique_name_in_owner(bool p_enabled) { + if (data.unique_name_in_owner == p_enabled) { + return; + } + + if (data.unique_name_in_owner && data.owner != nullptr) { + _release_unique_name_in_owner(); + } + data.unique_name_in_owner = p_enabled; + + if (data.unique_name_in_owner && data.owner != nullptr) { + _acquire_unique_name_in_owner(); + } + + update_configuration_warnings(); +} + +bool Node::is_unique_name_in_owner() const { + return data.unique_name_in_owner; +} + void Node::set_owner(Node *p_owner) { if (data.owner) { + if (data.unique_name_in_owner) { + _release_unique_name_in_owner(); + } data.owner->data.owned.erase(data.OW); data.OW = nullptr; data.owner = nullptr; @@ -1526,6 +1622,10 @@ void Node::set_owner(Node *p_owner) { ERR_FAIL_COND(!owner_valid); _set_owner_nocheck(p_owner); + + if (data.unique_name_in_owner) { + _acquire_unique_name_in_owner(); + } } Node *Node::get_owner() const { @@ -2585,16 +2685,16 @@ void Node::clear_internal_tree_resource_paths() { } TypedArray<String> Node::get_configuration_warnings() const { + TypedArray<String> ret; + Vector<String> warnings; if (GDVIRTUAL_CALL(_get_configuration_warnings, warnings)) { - TypedArray<String> ret; - ret.resize(warnings.size()); for (int i = 0; i < warnings.size(); i++) { - ret[i] = warnings[i]; + ret.push_back(warnings[i]); } - return ret; } - return Array(); + + return ret; } String Node::get_configuration_warnings_as_string() const { @@ -2701,8 +2801,9 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("get_node", "path"), &Node::get_node); ClassDB::bind_method(D_METHOD("get_node_or_null", "path"), &Node::get_node_or_null); ClassDB::bind_method(D_METHOD("get_parent"), &Node::get_parent); - ClassDB::bind_method(D_METHOD("find_nodes", "mask", "type", "recursive", "owned"), &Node::find_nodes, DEFVAL(""), DEFVAL(true), DEFVAL(true)); - ClassDB::bind_method(D_METHOD("find_parent", "mask"), &Node::find_parent); + ClassDB::bind_method(D_METHOD("find_child", "pattern", "recursive", "owned"), &Node::find_child, DEFVAL(true), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("find_children", "pattern", "type", "recursive", "owned"), &Node::find_children, DEFVAL(""), DEFVAL(true), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("find_parent", "pattern"), &Node::find_parent); ClassDB::bind_method(D_METHOD("has_node_and_resource", "path"), &Node::has_node_and_resource); ClassDB::bind_method(D_METHOD("get_node_and_resource", "path"), &Node::_get_node_and_resource); @@ -2780,8 +2881,6 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("is_multiplayer_authority"), &Node::is_multiplayer_authority); ClassDB::bind_method(D_METHOD("get_multiplayer"), &Node::get_multiplayer); - ClassDB::bind_method(D_METHOD("get_custom_multiplayer"), &Node::get_custom_multiplayer); - ClassDB::bind_method(D_METHOD("set_custom_multiplayer", "api"), &Node::set_custom_multiplayer); ClassDB::bind_method(D_METHOD("rpc_config", "method", "rpc_mode", "call_local", "transfer_mode", "channel"), &Node::rpc_config, DEFVAL(false), DEFVAL(Multiplayer::TRANSFER_MODE_RELIABLE), DEFVAL(0)); ClassDB::bind_method(D_METHOD("set_editor_description", "editor_description"), &Node::set_editor_description); @@ -2790,6 +2889,9 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_import_path", "import_path"), &Node::set_import_path); ClassDB::bind_method(D_METHOD("_get_import_path"), &Node::get_import_path); + ClassDB::bind_method(D_METHOD("set_unique_name_in_owner", "enable"), &Node::set_unique_name_in_owner); + ClassDB::bind_method(D_METHOD("is_unique_name_in_owner"), &Node::is_unique_name_in_owner); + #ifdef TOOLS_ENABLED ClassDB::bind_method(D_METHOD("_set_property_pinned", "property", "pinned"), &Node::set_property_pinned); #endif @@ -2880,10 +2982,10 @@ void Node::_bind_methods() { ADD_SIGNAL(MethodInfo("child_exited_tree", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT, "Node"))); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_name", "get_name"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "unique_name_in_owner", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_unique_name_in_owner", "is_unique_name_in_owner"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "scene_file_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_scene_file_path", "get_scene_file_path"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "owner", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_owner", "get_owner"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", PROPERTY_USAGE_NONE), "", "get_multiplayer"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", PROPERTY_USAGE_NONE), "set_custom_multiplayer", "get_custom_multiplayer"); ADD_GROUP("Process", "process_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Inherit,Pausable,When Paused,Always,Disabled"), "set_process_mode", "get_process_mode"); diff --git a/scene/main/node.h b/scene/main/node.h index 57b150e29a..fb84aabb62 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -99,6 +99,9 @@ private: Node *parent = nullptr; Node *owner = nullptr; Vector<Node *> children; + HashMap<StringName, Node *> owned_unique_nodes; + bool unique_name_in_owner = false; + int internal_children_front = 0; int internal_children_back = 0; int pos = -1; @@ -193,6 +196,9 @@ private: _FORCE_INLINE_ bool _can_process(bool p_paused) const; _FORCE_INLINE_ bool _is_enabled() const; + void _release_unique_name_in_owner(); + void _acquire_unique_name_in_owner(); + protected: void _block() { data.blocked++; } void _unblock() { data.blocked--; } @@ -304,12 +310,13 @@ public: bool has_node(const NodePath &p_path) const; Node *get_node(const NodePath &p_path) const; Node *get_node_or_null(const NodePath &p_path) const; - TypedArray<Node> find_nodes(const String &p_mask, const String &p_type = "", bool p_recursive = true, bool p_owned = true) const; + Node *find_child(const String &p_pattern, bool p_recursive = true, bool p_owned = true) const; + TypedArray<Node> find_children(const String &p_pattern, const String &p_type = "", bool p_recursive = true, bool p_owned = true) const; bool has_node_and_resource(const NodePath &p_path) const; Node *get_node_and_resource(const NodePath &p_path, RES &r_res, Vector<StringName> &r_leftover_subpath, bool p_last_is_property = true) const; Node *get_parent() const; - Node *find_parent(const String &p_mask) const; + Node *find_parent(const String &p_pattern) const; _FORCE_INLINE_ SceneTree *get_tree() const { ERR_FAIL_COND_V(!data.tree, nullptr); @@ -345,6 +352,9 @@ public: Node *get_owner() const; void get_owned_by(Node *p_by, List<Node *> *p_owned); + void set_unique_name_in_owner(bool p_enabled); + bool is_unique_name_in_owner() const; + void remove_and_skip(); int get_index(bool p_include_internal = true) const; @@ -505,8 +515,6 @@ public: void rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount); Ref<MultiplayerAPI> get_multiplayer() const; - Ref<MultiplayerAPI> get_custom_multiplayer() const; - void set_custom_multiplayer(Ref<MultiplayerAPI> p_multiplayer); Node(); ~Node(); diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 151239c9e7..a151d3cb33 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -438,6 +438,10 @@ bool SceneTree::process(double p_time) { if (multiplayer_poll) { multiplayer->poll(); + const NodePath *rpath = nullptr; + while ((rpath = custom_multiplayers.next(rpath))) { + custom_multiplayers[*rpath]->poll(); + } } emit_signal(SNAME("process_frame")); @@ -977,12 +981,12 @@ bool SceneTree::has_group(const StringName &p_identifier) const { Node *SceneTree::get_first_node_in_group(const StringName &p_group) { Map<StringName, Group>::Element *E = group_map.find(p_group); if (!E) { - return nullptr; //no group + return nullptr; // No group. } - _update_group_order(E->get()); //update order just in case + _update_group_order(E->get()); // Update order just in case. - if (E->get().nodes.size() == 0) { + if (E->get().nodes.is_empty()) { return nullptr; } @@ -1113,9 +1117,7 @@ Ref<SceneTreeTimer> SceneTree::create_timer(double p_delay_sec, bool p_process_a } Ref<Tween> SceneTree::create_tween() { - Ref<Tween> tween; - tween.instantiate(); - tween->set_valid(true); + Ref<Tween> tween = memnew(Tween(true)); tweens.push_back(tween); return tween; } @@ -1133,8 +1135,51 @@ Array SceneTree::get_processed_tweens() { return ret; } -Ref<MultiplayerAPI> SceneTree::get_multiplayer() const { - return multiplayer; +Ref<MultiplayerAPI> SceneTree::get_multiplayer(const NodePath &p_for_path) const { + Ref<MultiplayerAPI> out = multiplayer; + const NodePath *spath = nullptr; + while ((spath = custom_multiplayers.next(spath))) { + const Vector<StringName> snames = (*spath).get_names(); + const Vector<StringName> tnames = p_for_path.get_names(); + if (tnames.size() < snames.size()) { + continue; + } + const StringName *sptr = snames.ptr(); + const StringName *nptr = tnames.ptr(); + bool valid = true; + for (int i = 0; i < snames.size(); i++) { + if (sptr[i] != nptr[i]) { + valid = false; + break; + } + } + if (valid) { + out = custom_multiplayers[*spath]; + break; + } + } + return out; +} + +void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer, const NodePath &p_root_path) { + if (p_root_path.is_empty()) { + ERR_FAIL_COND(!p_multiplayer.is_valid()); + if (multiplayer.is_valid()) { + multiplayer->set_root_path(NodePath()); + } + multiplayer = p_multiplayer; + multiplayer->set_root_path("/" + root->get_name()); + } else { + if (p_multiplayer.is_valid()) { + custom_multiplayers[p_root_path] = p_multiplayer; + p_multiplayer->set_root_path(p_root_path); + } else { + if (custom_multiplayers.has(p_root_path)) { + custom_multiplayers[p_root_path]->set_root_path(NodePath()); + custom_multiplayers.erase(p_root_path); + } + } + } } void SceneTree::set_multiplayer_poll_enabled(bool p_enabled) { @@ -1145,13 +1190,6 @@ bool SceneTree::is_multiplayer_poll_enabled() const { return multiplayer_poll; } -void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer) { - ERR_FAIL_COND(!p_multiplayer.is_valid()); - - multiplayer = p_multiplayer; - multiplayer->set_root_path("/" + root->get_name()); -} - 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); @@ -1214,8 +1252,8 @@ void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("_change_scene"), &SceneTree::_change_scene); - ClassDB::bind_method(D_METHOD("set_multiplayer", "multiplayer"), &SceneTree::set_multiplayer); - ClassDB::bind_method(D_METHOD("get_multiplayer"), &SceneTree::get_multiplayer); + ClassDB::bind_method(D_METHOD("set_multiplayer", "multiplayer", "root_path"), &SceneTree::set_multiplayer, DEFVAL(NodePath())); + ClassDB::bind_method(D_METHOD("get_multiplayer", "for_path"), &SceneTree::get_multiplayer, DEFVAL(NodePath())); ClassDB::bind_method(D_METHOD("set_multiplayer_poll_enabled", "enabled"), &SceneTree::set_multiplayer_poll_enabled); ClassDB::bind_method(D_METHOD("is_multiplayer_poll_enabled"), &SceneTree::is_multiplayer_poll_enabled); @@ -1225,7 +1263,6 @@ void SceneTree::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "edited_scene_root", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_edited_scene_root", "get_edited_scene_root"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "current_scene", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_current_scene", "get_current_scene"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "", "get_root"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", PROPERTY_USAGE_NONE), "set_multiplayer", "get_multiplayer"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multiplayer_poll"), "set_multiplayer_poll_enabled", "is_multiplayer_poll_enabled"); ADD_SIGNAL(MethodInfo("tree_changed")); diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index 705ca6ebd3..9d7757e0a3 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -159,6 +159,7 @@ private: ///network/// Ref<MultiplayerAPI> multiplayer; + HashMap<NodePath, Ref<MultiplayerAPI>> custom_multiplayers; bool multiplayer_poll = true; static SceneTree *singleton; @@ -351,10 +352,10 @@ public: //network API - Ref<MultiplayerAPI> get_multiplayer() const; + Ref<MultiplayerAPI> get_multiplayer(const NodePath &p_for_path = NodePath()) const; + void set_multiplayer(Ref<MultiplayerAPI> p_multiplayer, const NodePath &p_root_path = NodePath()); void set_multiplayer_poll_enabled(bool p_enabled); bool is_multiplayer_poll_enabled() const; - void set_multiplayer(Ref<MultiplayerAPI> p_multiplayer); static void add_idle_callback(IdleCallback p_callback); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index b78f07b6d0..5fef8d4b5f 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -239,8 +239,8 @@ void Viewport::_sub_window_update(Window *p_window) { int font_size = p_window->get_theme_font_size(SNAME("title_font_size")); Color title_color = p_window->get_theme_color(SNAME("title_color")); int title_height = p_window->get_theme_constant(SNAME("title_height")); - int close_h_ofs = p_window->get_theme_constant(SNAME("close_h_ofs")); - int close_v_ofs = p_window->get_theme_constant(SNAME("close_v_ofs")); + int close_h_ofs = p_window->get_theme_constant(SNAME("close_h_offset")); + int close_v_ofs = p_window->get_theme_constant(SNAME("close_v_offset")); TextLine title_text = TextLine(p_window->atr(p_window->get_title()), title_font, font_size, Dictionary(), TranslationServer::get_singleton()->get_tool_locale()); title_text.set_width(r.size.width - panel->get_minimum_size().x - close_h_ofs); @@ -2583,8 +2583,8 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) { if (title_bar.has_point(mb->get_position())) { click_on_window = true; - int close_h_ofs = sw.window->get_theme_constant(SNAME("close_h_ofs")); - int close_v_ofs = sw.window->get_theme_constant(SNAME("close_v_ofs")); + int close_h_ofs = sw.window->get_theme_constant(SNAME("close_h_offset")); + int close_v_ofs = sw.window->get_theme_constant(SNAME("close_v_offset")); Ref<Texture2D> close_icon = sw.window->get_theme_icon(SNAME("close")); Rect2 close_rect; diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 8b1a4680d2..6feccb7eec 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -1045,7 +1045,9 @@ void Window::popup_centered_clamped(const Size2i &p_size, float p_fallback_ratio Rect2i popup_rect; popup_rect.size = Vector2i(MIN(size_ratio.x, p_size.x), MIN(size_ratio.y, p_size.y)); - popup_rect.position = parent_rect.position + (parent_rect.size - popup_rect.size) / 2; + if (parent_rect != Rect2()) { + popup_rect.position = parent_rect.position + (parent_rect.size - popup_rect.size) / 2; + } popup(popup_rect); } @@ -1069,7 +1071,10 @@ void Window::popup_centered(const Size2i &p_minsize) { Size2 contents_minsize = _get_contents_minimum_size(); popup_rect.size.x = MAX(p_minsize.x, contents_minsize.x); popup_rect.size.y = MAX(p_minsize.y, contents_minsize.y); - popup_rect.position = parent_rect.position + (parent_rect.size - popup_rect.size) / 2; + + if (parent_rect != Rect2()) { + popup_rect.position = parent_rect.position + (parent_rect.size - popup_rect.size) / 2; + } popup(popup_rect); } @@ -1091,8 +1096,10 @@ void Window::popup_centered_ratio(float p_ratio) { } Rect2i popup_rect; - popup_rect.size = parent_rect.size * p_ratio; - popup_rect.position = parent_rect.position + (parent_rect.size - popup_rect.size) / 2; + if (parent_rect != Rect2()) { + popup_rect.size = parent_rect.size * p_ratio; + popup_rect.position = parent_rect.position + (parent_rect.size - popup_rect.size) / 2; + } popup(popup_rect); } |