diff options
author | Rémi Verschelde <rverschelde@gmail.com> | 2023-05-16 10:49:09 +0200 |
---|---|---|
committer | Rémi Verschelde <rverschelde@gmail.com> | 2023-05-16 10:49:09 +0200 |
commit | 508a5bf16ea50552c56539da4c96ea13fdf8853e (patch) | |
tree | f42e03285cd781512b8aef168668c247a7358d26 | |
parent | 59c19a7172b8d4fd2000125b760533789b367c04 (diff) | |
parent | 17f492fb8223d80ed94a55d3df313579b841da97 (diff) | |
download | redot-engine-508a5bf16ea50552c56539da4c96ea13fdf8853e.tar.gz |
Merge pull request #76025 from YuriSizov/editor-reparentable-windows
Expose dialog parent-and-popup logic to the API
-rw-r--r-- | doc/classes/EditorInterface.xml | 37 | ||||
-rw-r--r-- | doc/classes/Node.xml | 6 | ||||
-rw-r--r-- | doc/classes/Window.xml | 54 | ||||
-rw-r--r-- | editor/editor_interface.cpp | 22 | ||||
-rw-r--r-- | editor/editor_interface.h | 6 | ||||
-rw-r--r-- | editor/editor_node.cpp | 71 | ||||
-rw-r--r-- | editor/editor_node.h | 11 | ||||
-rw-r--r-- | editor/progress_dialog.cpp | 13 | ||||
-rw-r--r-- | scene/main/node.cpp | 10 | ||||
-rw-r--r-- | scene/main/node.h | 1 | ||||
-rw-r--r-- | scene/main/window.cpp | 77 | ||||
-rw-r--r-- | scene/main/window.h | 16 |
12 files changed, 242 insertions, 82 deletions
diff --git a/doc/classes/EditorInterface.xml b/doc/classes/EditorInterface.xml index 74825493a1..3ad28f9062 100644 --- a/doc/classes/EditorInterface.xml +++ b/doc/classes/EditorInterface.xml @@ -205,6 +205,43 @@ Plays the main scene. </description> </method> + <method name="popup_dialog"> + <return type="void" /> + <param index="0" name="dialog" type="Window" /> + <param index="1" name="rect" type="Rect2i" default="Rect2i(0, 0, 0, 0)" /> + <description> + Pops up the [param dialog] in the editor UI with [method Window.popup_exclusive]. The dialog must have no current parent, otherwise the method fails. + See also [method Window.set_unparent_when_invisible]. + </description> + </method> + <method name="popup_dialog_centered"> + <return type="void" /> + <param index="0" name="dialog" type="Window" /> + <param index="1" name="minsize" type="Vector2i" default="Vector2i(0, 0)" /> + <description> + Pops up the [param dialog] in the editor UI with [method Window.popup_exclusive_centered]. The dialog must have no current parent, otherwise the method fails. + See also [method Window.set_unparent_when_invisible]. + </description> + </method> + <method name="popup_dialog_centered_clamped"> + <return type="void" /> + <param index="0" name="dialog" type="Window" /> + <param index="1" name="minsize" type="Vector2i" default="Vector2i(0, 0)" /> + <param index="2" name="fallback_ratio" type="float" default="0.75" /> + <description> + Pops up the [param dialog] in the editor UI with [method Window.popup_exclusive_centered_clamped]. The dialog must have no current parent, otherwise the method fails. + See also [method Window.set_unparent_when_invisible]. + </description> + </method> + <method name="popup_dialog_centered_ratio"> + <return type="void" /> + <param index="0" name="dialog" type="Window" /> + <param index="1" name="ratio" type="float" default="0.8" /> + <description> + Pops up the [param dialog] in the editor UI with [method Window.popup_exclusive_centered_ratio]. The dialog must have no current parent, otherwise the method fails. + See also [method Window.set_unparent_when_invisible]. + </description> + </method> <method name="reload_scene_from_path"> <return type="void" /> <param index="0" name="scene_filepath" type="String" /> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 3f79822ca9..328f0c3fa1 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -328,6 +328,12 @@ If [param include_internal] is [code]false[/code], the index won't take internal children into account, i.e. first non-internal child will have index of 0 (see [code]internal[/code] parameter in [method add_child]). </description> </method> + <method name="get_last_exclusive_window" qualifiers="const"> + <return type="Window" /> + <description> + Returns the [Window] that contains this node, or the last exclusive child in a chain of windows starting with the one that contains this node. + </description> + </method> <method name="get_multiplayer_authority" qualifiers="const"> <return type="int" /> <description> diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml index 336d73290f..bed4078796 100644 --- a/doc/classes/Window.xml +++ b/doc/classes/Window.xml @@ -375,6 +375,52 @@ Popups the [Window] centered inside its parent [Window] and sets its size as a [param ratio] of parent's size. </description> </method> + <method name="popup_exclusive"> + <return type="void" /> + <param index="0" name="from_node" type="Node" /> + <param index="1" name="rect" type="Rect2i" default="Rect2i(0, 0, 0, 0)" /> + <description> + Attempts to parent this dialog to the last exclusive window relative to [param from_node], and then calls [method Window.popup] on it. The dialog must have no current parent, otherwise the method fails. + See also [method set_unparent_when_invisible] and [method Node.get_last_exclusive_window]. + </description> + </method> + <method name="popup_exclusive_centered"> + <return type="void" /> + <param index="0" name="from_node" type="Node" /> + <param index="1" name="minsize" type="Vector2i" default="Vector2i(0, 0)" /> + <description> + Attempts to parent this dialog to the last exclusive window relative to [param from_node], and then calls [method Window.popup_centered] on it. The dialog must have no current parent, otherwise the method fails. + See also [method set_unparent_when_invisible] and [method Node.get_last_exclusive_window]. + </description> + </method> + <method name="popup_exclusive_centered_clamped"> + <return type="void" /> + <param index="0" name="from_node" type="Node" /> + <param index="1" name="minsize" type="Vector2i" default="Vector2i(0, 0)" /> + <param index="2" name="fallback_ratio" type="float" default="0.75" /> + <description> + Attempts to parent this dialog to the last exclusive window relative to [param from_node], and then calls [method Window.popup_centered_clamped] on it. The dialog must have no current parent, otherwise the method fails. + See also [method set_unparent_when_invisible] and [method Node.get_last_exclusive_window]. + </description> + </method> + <method name="popup_exclusive_centered_ratio"> + <return type="void" /> + <param index="0" name="from_node" type="Node" /> + <param index="1" name="ratio" type="float" default="0.8" /> + <description> + Attempts to parent this dialog to the last exclusive window relative to [param from_node], and then calls [method Window.popup_centered_ratio] on it. The dialog must have no current parent, otherwise the method fails. + See also [method set_unparent_when_invisible] and [method Node.get_last_exclusive_window]. + </description> + </method> + <method name="popup_exclusive_on_parent"> + <return type="void" /> + <param index="0" name="from_node" type="Node" /> + <param index="1" name="parent_rect" type="Rect2i" /> + <description> + Attempts to parent this dialog to the last exclusive window relative to [param from_node], and then calls [method Window.popup_on_parent] on it. The dialog must have no current parent, otherwise the method fails. + See also [method set_unparent_when_invisible] and [method Node.get_last_exclusive_window]. + </description> + </method> <method name="popup_on_parent"> <return type="void" /> <param index="0" name="parent_rect" type="Rect2i" /> @@ -465,6 +511,14 @@ Sets layout direction and text writing direction. Right-to-left layouts are necessary for certain languages (e.g. Arabic and Hebrew). </description> </method> + <method name="set_unparent_when_invisible"> + <return type="void" /> + <param index="0" name="unparent" type="bool" /> + <description> + If [param unparent] is [code]true[/code], the window is automatically unparented when going invisible. + [b]Note:[/b] Make sure to keep a reference to the node, otherwise it will be orphaned. You also need to manually call [method Node.queue_free] to free the window if it's not parented. + </description> + </method> <method name="set_use_font_oversampling"> <return type="void" /> <param index="0" name="enable" type="bool" /> diff --git a/editor/editor_interface.cpp b/editor/editor_interface.cpp index 167a5a3dba..50833c3a09 100644 --- a/editor/editor_interface.cpp +++ b/editor/editor_interface.cpp @@ -42,6 +42,7 @@ #include "main/main.h" #include "scene/gui/box_container.h" #include "scene/gui/control.h" +#include "scene/main/window.h" EditorInterface *EditorInterface::singleton = nullptr; @@ -221,6 +222,22 @@ float EditorInterface::get_editor_scale() const { return EDSCALE; } +void EditorInterface::popup_dialog(Window *p_dialog, const Rect2i &p_screen_rect) { + p_dialog->popup_exclusive(EditorNode::get_singleton(), p_screen_rect); +} + +void EditorInterface::popup_dialog_centered(Window *p_dialog, const Size2i &p_minsize) { + p_dialog->popup_exclusive_centered(EditorNode::get_singleton(), p_minsize); +} + +void EditorInterface::popup_dialog_centered_ratio(Window *p_dialog, float p_ratio) { + p_dialog->popup_exclusive_centered_ratio(EditorNode::get_singleton(), p_ratio); +} + +void EditorInterface::popup_dialog_centered_clamped(Window *p_dialog, const Size2i &p_size, float p_fallback_ratio) { + p_dialog->popup_exclusive_centered_clamped(EditorNode::get_singleton(), p_size, p_fallback_ratio); +} + // Editor docks. FileSystemDock *EditorInterface::get_file_system_dock() const { @@ -380,6 +397,11 @@ void EditorInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("get_editor_scale"), &EditorInterface::get_editor_scale); + ClassDB::bind_method(D_METHOD("popup_dialog", "dialog", "rect"), &EditorInterface::popup_dialog, DEFVAL(Rect2i())); + ClassDB::bind_method(D_METHOD("popup_dialog_centered", "dialog", "minsize"), &EditorInterface::popup_dialog_centered, DEFVAL(Size2i())); + ClassDB::bind_method(D_METHOD("popup_dialog_centered_ratio", "dialog", "ratio"), &EditorInterface::popup_dialog_centered_ratio, DEFVAL(0.8)); + ClassDB::bind_method(D_METHOD("popup_dialog_centered_clamped", "dialog", "minsize", "fallback_ratio"), &EditorInterface::popup_dialog_centered_clamped, DEFVAL(Size2i()), DEFVAL(0.75)); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "distraction_free_mode"), "set_distraction_free_mode", "is_distraction_free_mode_enabled"); // Editor docks. diff --git a/editor/editor_interface.h b/editor/editor_interface.h index 9a64969e88..1436bf83af 100644 --- a/editor/editor_interface.h +++ b/editor/editor_interface.h @@ -50,6 +50,7 @@ class Node; class ScriptEditor; class Texture2D; class VBoxContainer; +class Window; class EditorInterface : public Object { GDCLASS(EditorInterface, Object); @@ -94,6 +95,11 @@ public: float get_editor_scale() const; + void popup_dialog(Window *p_dialog, const Rect2i &p_screen_rect = Rect2i()); + void popup_dialog_centered(Window *p_dialog, const Size2i &p_minsize = Size2i()); + void popup_dialog_centered_ratio(Window *p_dialog, float p_ratio = 0.8); + void popup_dialog_centered_clamped(Window *p_dialog, const Size2i &p_size = Size2i(), float p_fallback_ratio = 0.75); + // Editor docks. FileSystemDock *get_file_system_dock() const; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 2d9f9645b8..564cdf1192 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -160,51 +160,6 @@ static const String META_TEXT_TO_COPY = "text_to_copy"; static const String EDITOR_NODE_CONFIG_SECTION = "EditorNode"; -class AcceptDialogAutoReparent : public AcceptDialog { - GDCLASS(AcceptDialogAutoReparent, AcceptDialog); - -protected: - void _notification(int p_what) { - if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { - if (!is_visible()) { - Node *p = get_parent(); - if (p) { - p->remove_child(this); - } - } - } - } - -public: - void attach_and_popup_centered() { - EditorNode *ed = EditorNode::get_singleton(); - if (ed && !is_inside_tree()) { - Window *w = ed->get_window(); - while (w && w->get_exclusive_child()) { - w = w->get_exclusive_child(); - } - if (w && w != this) { - w->add_child(this); - popup_centered(); - } - } - } - - void attach_and_popup_centered_ratio(float p_ratio = 0.8) { - EditorNode *ed = EditorNode::get_singleton(); - if (ed && !is_inside_tree()) { - Window *w = ed->get_window(); - while (w && w->get_exclusive_child()) { - w = w->get_exclusive_child(); - } - if (w && w != this) { - w->add_child(this); - popup_centered_ratio(p_ratio); - } - } - } -}; - void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vector<String> &r_filenames) { ERR_FAIL_COND_MSG(p_full_paths.size() != r_filenames.size(), vformat("disambiguate_filenames requires two string vectors of same length (%d != %d).", p_full_paths.size(), r_filenames.size())); @@ -4118,7 +4073,7 @@ void EditorNode::add_io_error(const String &p_error) { DEV_ASSERT(Thread::get_caller_id() == Thread::get_main_id()); singleton->load_errors->add_image(singleton->gui_base->get_theme_icon(SNAME("Error"), SNAME("EditorIcons"))); singleton->load_errors->add_text(p_error + "\n"); - singleton->load_error_dialog->attach_and_popup_centered_ratio(0.5); + EditorInterface::get_singleton()->popup_dialog_centered_ratio(singleton->load_error_dialog, 0.5); } bool EditorNode::_find_scene_in_use(Node *p_node, const String &p_path) const { @@ -4459,7 +4414,7 @@ void EditorNode::show_accept(const String &p_text, const String &p_title) { if (accept) { accept->set_ok_button_text(p_title); accept->set_text(p_text); - accept->attach_and_popup_centered(); + EditorInterface::get_singleton()->popup_dialog_centered(accept); } } @@ -4468,7 +4423,7 @@ void EditorNode::show_save_accept(const String &p_text, const String &p_title) { if (save_accept) { save_accept->set_ok_button_text(p_title); save_accept->set_text(p_text); - save_accept->attach_and_popup_centered(); + EditorInterface::get_singleton()->popup_dialog_centered(save_accept); } } @@ -4476,7 +4431,7 @@ void EditorNode::show_warning(const String &p_text, const String &p_title) { if (warning) { warning->set_text(p_text); warning->set_title(p_title); - warning->attach_and_popup_centered(); + EditorInterface::get_singleton()->popup_dialog_centered(warning); } else { WARN_PRINT(p_title + " " + p_text); } @@ -6574,7 +6529,7 @@ int EditorNode::execute_and_show_output(const String &p_title, const String &p_p execute_output_dialog->get_ok_button()->set_disabled(true); execute_outputs->clear(); execute_outputs->set_scroll_follow(true); - execute_output_dialog->attach_and_popup_centered_ratio(); + EditorInterface::get_singleton()->popup_dialog_centered_ratio(execute_output_dialog); } ExecuteThreadArgs eta; @@ -7188,10 +7143,11 @@ EditorNode::EditorNode() { prev_scene->set_position(Point2(3, 24)); prev_scene->hide(); - accept = memnew(AcceptDialogAutoReparent); - accept->connect("confirmed", callable_mp(this, &EditorNode::_menu_confirm_current)); + accept = memnew(AcceptDialog); + accept->set_unparent_when_invisible(true); - save_accept = memnew(AcceptDialogAutoReparent); + save_accept = memnew(AcceptDialog); + save_accept->set_unparent_when_invisible(true); save_accept->connect("confirmed", callable_mp(this, &EditorNode::_menu_option).bind((int)MenuOptions::FILE_SAVE_AS_SCENE)); project_export = memnew(ProjectExportDialog); @@ -7236,7 +7192,8 @@ EditorNode::EditorNode() { gui_base->add_child(fbx_importer_manager); #endif - warning = memnew(AcceptDialogAutoReparent); + warning = memnew(AcceptDialog); + warning->set_unparent_when_invisible(true); warning->add_button(TTR("Copy Text"), true, "copy"); warning->connect("custom_action", callable_mp(this, &EditorNode::_copy_warning)); @@ -7909,14 +7866,16 @@ EditorNode::EditorNode() { set_process_shortcut_input(true); load_errors = memnew(RichTextLabel); - load_error_dialog = memnew(AcceptDialogAutoReparent); + load_error_dialog = memnew(AcceptDialog); + load_error_dialog->set_unparent_when_invisible(true); load_error_dialog->add_child(load_errors); load_error_dialog->set_title(TTR("Load Errors")); execute_outputs = memnew(RichTextLabel); execute_outputs->set_selection_enabled(true); execute_outputs->set_context_menu_enabled(true); - execute_output_dialog = memnew(AcceptDialogAutoReparent); + execute_output_dialog = memnew(AcceptDialog); + execute_output_dialog->set_unparent_when_invisible(true); execute_output_dialog->add_child(execute_outputs); execute_output_dialog->set_title(""); diff --git a/editor/editor_node.h b/editor/editor_node.h index 221637be1c..b5f84a3204 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -41,7 +41,6 @@ typedef void (*EditorPluginInitializeCallback)(); typedef bool (*EditorBuildCallback)(); class AcceptDialog; -class AcceptDialogAutoReparent; class CenterContainer; class CheckBox; class ColorPicker; @@ -359,10 +358,10 @@ private: PluginConfigDialog *plugin_config_dialog = nullptr; RichTextLabel *load_errors = nullptr; - AcceptDialogAutoReparent *load_error_dialog = nullptr; + AcceptDialog *load_error_dialog = nullptr; RichTextLabel *execute_outputs = nullptr; - AcceptDialogAutoReparent *execute_output_dialog = nullptr; + AcceptDialog *execute_output_dialog = nullptr; Ref<Theme> theme; @@ -377,10 +376,10 @@ private: ConfirmationDialog *import_confirmation = nullptr; ConfirmationDialog *pick_main_scene = nullptr; Button *select_current_scene_button = nullptr; - AcceptDialogAutoReparent *accept = nullptr; - AcceptDialogAutoReparent *save_accept = nullptr; + AcceptDialog *accept = nullptr; + AcceptDialog *save_accept = nullptr; EditorAbout *about = nullptr; - AcceptDialogAutoReparent *warning = nullptr; + AcceptDialog *warning = nullptr; int overridden_default_layout = -1; Ref<ConfigFile> default_layout; diff --git a/editor/progress_dialog.cpp b/editor/progress_dialog.cpp index 4d76fdc997..6c63f0ba6a 100644 --- a/editor/progress_dialog.cpp +++ b/editor/progress_dialog.cpp @@ -32,6 +32,7 @@ #include "core/object/message_queue.h" #include "core/os/os.h" +#include "editor/editor_interface.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "main/main.h" @@ -155,17 +156,7 @@ void ProgressDialog::_popup() { main->set_offset(SIDE_TOP, style->get_margin(SIDE_TOP)); main->set_offset(SIDE_BOTTOM, -style->get_margin(SIDE_BOTTOM)); - EditorNode *ed = EditorNode::get_singleton(); - if (ed && !is_inside_tree()) { - Window *w = ed->get_window(); - while (w && w->get_exclusive_child()) { - w = w->get_exclusive_child(); - } - if (w && w != this) { - w->add_child(this); - popup_centered(ms); - } - } + EditorInterface::get_singleton()->popup_dialog_centered(this, ms); } void ProgressDialog::add_task(const String &p_task, const String &p_label, int p_steps, bool p_can_cancel) { diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 191a3981cb..ad7e445b5c 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1735,6 +1735,15 @@ Window *Node::get_window() const { return nullptr; } +Window *Node::get_last_exclusive_window() const { + Window *w = get_window(); + while (w && w->get_exclusive_child()) { + w = w->get_exclusive_child(); + } + + return w; +} + bool Node::is_ancestor_of(const Node *p_node) const { ERR_FAIL_NULL_V(p_node, false); Node *p = p_node->data.parent; @@ -3297,6 +3306,7 @@ void Node::_bind_methods() { 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_last_exclusive_window"), &Node::get_last_exclusive_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 01c410ee74..b7462b4468 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -385,6 +385,7 @@ public: Node *find_parent(const String &p_pattern) const; Window *get_window() const; + Window *get_last_exclusive_window() const; _FORCE_INLINE_ SceneTree *get_tree() const { ERR_FAIL_COND_V(!data.tree, nullptr); diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 2c8edec36d..e2f9aa8937 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -1210,12 +1210,6 @@ void Window::_notification(int p_what) { notification(NOTIFICATION_THEME_CHANGED); } break; - case NOTIFICATION_THEME_CHANGED: { - emit_signal(SceneStringNames::get_singleton()->theme_changed); - _invalidate_theme_cache(); - _update_theme_item_cache(); - } break; - case NOTIFICATION_READY: { if (wrap_controls) { // Finish any resizing immediately so it doesn't interfere on stuff overriding _ready(). @@ -1223,6 +1217,12 @@ void Window::_notification(int p_what) { } } break; + case NOTIFICATION_THEME_CHANGED: { + emit_signal(SceneStringNames::get_singleton()->theme_changed); + _invalidate_theme_cache(); + _update_theme_item_cache(); + } break; + case NOTIFICATION_TRANSLATION_CHANGED: { _invalidate_theme_cache(); _update_theme_item_cache(); @@ -1241,6 +1241,15 @@ void Window::_notification(int p_what) { } } break; + case NOTIFICATION_VISIBILITY_CHANGED: { + if (unparent_when_invisible && !is_visible()) { + Node *p = get_parent(); + if (p) { + p->remove_child(this); + } + } + } break; + case NOTIFICATION_EXIT_TREE: { if (transient) { _clear_transient(); @@ -1656,6 +1665,48 @@ void Window::popup(const Rect2i &p_screen_rect) { notification(NOTIFICATION_POST_POPUP); } +bool Window::_try_parent_dialog(Node *p_from_node) { + ERR_FAIL_NULL_V(p_from_node, false); + ERR_FAIL_COND_V_MSG(is_inside_tree(), false, "Attempting to parent and popup a dialog that already has a parent."); + + Window *w = p_from_node->get_last_exclusive_window(); + if (w && w != this) { + w->add_child(this); + return true; + } + return false; +} + +void Window::popup_exclusive(Node *p_from_node, const Rect2i &p_screen_rect) { + if (_try_parent_dialog(p_from_node)) { + popup(p_screen_rect); + } +} + +void Window::popup_exclusive_on_parent(Node *p_from_node, const Rect2i &p_parent_rect) { + if (_try_parent_dialog(p_from_node)) { + popup_on_parent(p_parent_rect); + } +} + +void Window::popup_exclusive_centered(Node *p_from_node, const Size2i &p_minsize) { + if (_try_parent_dialog(p_from_node)) { + popup_centered(p_minsize); + } +} + +void Window::popup_exclusive_centered_ratio(Node *p_from_node, float p_ratio) { + if (_try_parent_dialog(p_from_node)) { + popup_centered_ratio(p_ratio); + } +} + +void Window::popup_exclusive_centered_clamped(Node *p_from_node, const Size2i &p_size, float p_fallback_ratio) { + if (_try_parent_dialog(p_from_node)) { + popup_centered_clamped(p_size, p_fallback_ratio); + } +} + Rect2i Window::fit_rect_in_parent(Rect2i p_rect, const Rect2i &p_parent_rect) const { ERR_READ_THREAD_GUARD_V(Rect2i()); Size2i limit = p_parent_rect.size; @@ -2318,6 +2369,10 @@ bool Window::is_clamped_to_embedder() const { return clamp_to_embedder; } +void Window::set_unparent_when_invisible(bool p_unparent) { + unparent_when_invisible = p_unparent; +} + void Window::set_layout_direction(Window::LayoutDirection p_direction) { ERR_MAIN_THREAD_GUARD; ERR_FAIL_INDEX((int)p_direction, 4); @@ -2469,6 +2524,8 @@ void Window::_bind_methods() { ClassDB::bind_method(D_METHOD("set_exclusive", "exclusive"), &Window::set_exclusive); ClassDB::bind_method(D_METHOD("is_exclusive"), &Window::is_exclusive); + ClassDB::bind_method(D_METHOD("set_unparent_when_invisible", "unparent"), &Window::set_unparent_when_invisible); + ClassDB::bind_method(D_METHOD("can_draw"), &Window::can_draw); ClassDB::bind_method(D_METHOD("has_focus"), &Window::has_focus); ClassDB::bind_method(D_METHOD("grab_focus"), &Window::grab_focus); @@ -2562,10 +2619,16 @@ void Window::_bind_methods() { ClassDB::bind_method(D_METHOD("popup", "rect"), &Window::popup, DEFVAL(Rect2i())); ClassDB::bind_method(D_METHOD("popup_on_parent", "parent_rect"), &Window::popup_on_parent); - ClassDB::bind_method(D_METHOD("popup_centered_ratio", "ratio"), &Window::popup_centered_ratio, DEFVAL(0.8)); ClassDB::bind_method(D_METHOD("popup_centered", "minsize"), &Window::popup_centered, DEFVAL(Size2i())); + ClassDB::bind_method(D_METHOD("popup_centered_ratio", "ratio"), &Window::popup_centered_ratio, DEFVAL(0.8)); ClassDB::bind_method(D_METHOD("popup_centered_clamped", "minsize", "fallback_ratio"), &Window::popup_centered_clamped, DEFVAL(Size2i()), DEFVAL(0.75)); + ClassDB::bind_method(D_METHOD("popup_exclusive", "from_node", "rect"), &Window::popup_exclusive, DEFVAL(Rect2i())); + ClassDB::bind_method(D_METHOD("popup_exclusive_on_parent", "from_node", "parent_rect"), &Window::popup_exclusive_on_parent); + ClassDB::bind_method(D_METHOD("popup_exclusive_centered", "from_node", "minsize"), &Window::popup_exclusive_centered, DEFVAL(Size2i())); + ClassDB::bind_method(D_METHOD("popup_exclusive_centered_ratio", "from_node", "ratio"), &Window::popup_exclusive_centered_ratio, DEFVAL(0.8)); + ClassDB::bind_method(D_METHOD("popup_exclusive_centered_clamped", "from_node", "minsize", "fallback_ratio"), &Window::popup_exclusive_centered_clamped, DEFVAL(Size2i()), DEFVAL(0.75)); + ADD_PROPERTY(PropertyInfo(Variant::INT, "initial_position", PROPERTY_HINT_ENUM, "Absolute,Center of Primary Screen,Center of Other Screen,Center of Screen With Mouse Pointer,Center of Screen With Keyboard Focus"), "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"); diff --git a/scene/main/window.h b/scene/main/window.h index 9ce5fd1b9d..5fce251e33 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -121,6 +121,7 @@ private: bool updating_child_controls = false; bool updating_embedded_window = false; bool clamp_to_embedder = false; + bool unparent_when_invisible = false; LayoutDirection layout_dir = LAYOUT_DIRECTION_INHERITED; @@ -138,6 +139,8 @@ private: void _clear_window(); void _update_from_window(); + bool _try_parent_dialog(Node *p_from_node); + Size2i max_size_used; Size2i _clamp_limit_size(const Size2i &p_limit_size); @@ -272,6 +275,8 @@ public: void set_clamp_to_embedder(bool p_enable); bool is_clamped_to_embedder() const; + void set_unparent_when_invisible(bool p_unparent); + bool is_in_edited_scene_root() const; bool can_draw() const; @@ -307,12 +312,19 @@ public: Window *get_exclusive_child() const { return exclusive_child; }; Window *get_parent_visible_window() const; Viewport *get_parent_viewport() const; - void popup(const Rect2i &p_rect = Rect2i()); + + void popup(const Rect2i &p_screen_rect = Rect2i()); void popup_on_parent(const Rect2i &p_parent_rect); - void popup_centered_ratio(float p_ratio = 0.8); void popup_centered(const Size2i &p_minsize = Size2i()); + void popup_centered_ratio(float p_ratio = 0.8); void popup_centered_clamped(const Size2i &p_size = Size2i(), float p_fallback_ratio = 0.75); + void popup_exclusive(Node *p_from_node, const Rect2i &p_screen_rect = Rect2i()); + void popup_exclusive_on_parent(Node *p_from_node, const Rect2i &p_parent_rect); + void popup_exclusive_centered(Node *p_from_node, const Size2i &p_minsize = Size2i()); + void popup_exclusive_centered_ratio(Node *p_from_node, float p_ratio = 0.8); + void popup_exclusive_centered_clamped(Node *p_from_node, const Size2i &p_size = Size2i(), float p_fallback_ratio = 0.75); + Rect2i fit_rect_in_parent(Rect2i p_rect, const Rect2i &p_parent_rect) const; Size2 get_contents_minimum_size() const; Size2 get_clamped_minimum_size() const; |