diff options
Diffstat (limited to 'scene')
-rw-r--r-- | scene/2d/canvas_item.cpp | 39 | ||||
-rw-r--r-- | scene/2d/canvas_item.h | 3 | ||||
-rw-r--r-- | scene/gui/control.cpp | 451 | ||||
-rw-r--r-- | scene/gui/control.h | 9 | ||||
-rw-r--r-- | scene/gui/dialogs.cpp | 433 | ||||
-rw-r--r-- | scene/gui/dialogs.h | 83 | ||||
-rw-r--r-- | scene/gui/file_dialog.cpp | 147 | ||||
-rw-r--r-- | scene/gui/file_dialog.h | 23 | ||||
-rw-r--r-- | scene/gui/panel.cpp | 16 | ||||
-rw-r--r-- | scene/gui/panel.h | 14 | ||||
-rw-r--r-- | scene/gui/popup.cpp | 8 | ||||
-rw-r--r-- | scene/gui/popup.h | 2 | ||||
-rw-r--r-- | scene/main/node.cpp | 1 | ||||
-rw-r--r-- | scene/main/node.h | 1 | ||||
-rw-r--r-- | scene/main/window.cpp | 378 | ||||
-rw-r--r-- | scene/main/window.h | 51 | ||||
-rw-r--r-- | scene/register_scene_types.cpp | 3 | ||||
-rw-r--r-- | scene/resources/default_theme/default_theme.cpp | 20 | ||||
-rw-r--r-- | scene/scene_string_names.cpp | 2 | ||||
-rw-r--r-- | scene/scene_string_names.h | 3 |
20 files changed, 888 insertions, 799 deletions
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index 4751551371..2d2da005d0 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -348,6 +348,9 @@ bool CanvasItem::is_visible_in_tree() const { while (p) { if (!p->visible) return false; + if (p->window && !p->window->is_visible()) { + return false; + } p = p->get_parent_item(); } @@ -549,10 +552,30 @@ void CanvasItem::_notification(int p_what) { _update_texture_repeat_changed(false); first_draw = true; - if (get_parent()) { - CanvasItem *ci = Object::cast_to<CanvasItem>(get_parent()); + Node *parent = get_parent(); + if (parent) { + CanvasItem *ci = Object::cast_to<CanvasItem>(parent); if (ci) C = ci->children_items.push_back(this); + if (!ci) { + //look for a window + Viewport *viewport = nullptr; + + while (parent) { + viewport = Object::cast_to<Viewport>(parent); + if (viewport) { + break; + } + parent = parent->get_parent(); + } + + ERR_FAIL_COND(!viewport); + + window = Object::cast_to<Window>(viewport); + if (window) { + window->connect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed)); + } + } } _enter_canvas(); if (!block_transform_notify && !xform_change.in_list()) { @@ -581,6 +604,9 @@ void CanvasItem::_notification(int p_what) { Object::cast_to<CanvasItem>(get_parent())->children_items.erase(C); C = NULL; } + if (window) { + window->disconnect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed)); + } global_invalid = true; } break; case NOTIFICATION_DRAW: @@ -601,6 +627,14 @@ void CanvasItem::set_visible(bool p_visible) { else hide(); } + +void CanvasItem::_window_visibility_changed() { + + if (visible) { + _propagate_visibility_changed(window->is_visible()); + } +} + bool CanvasItem::is_visible() const { return visible; @@ -1409,6 +1443,7 @@ CanvasItem::TextureRepeat CanvasItem::get_texture_repeat() const { CanvasItem::CanvasItem() : xform_change(this) { + window = nullptr; canvas_item = VisualServer::get_singleton()->canvas_item_create(); visible = true; pending_update = false; diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index c7f9500ea1..6bfe3cf0c7 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -201,6 +201,7 @@ private: int light_mask; + Window *window; bool first_draw; bool visible; bool pending_update; @@ -232,6 +233,8 @@ private: void _enter_canvas(); void _exit_canvas(); + void _window_visibility_changed(); + void _notify_transform(CanvasItem *p_node); void _set_on_top(bool p_on_top) { set_draw_behind_parent(!p_on_top); } diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index f745cd2da2..55ef2a6bed 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -438,22 +438,30 @@ void Control::_resize(const Size2 &p_size) { void Control::add_child_notify(Node *p_child) { Control *child_c = Object::cast_to<Control>(p_child); - if (!child_c) - return; - if (child_c->data.theme.is_null() && data.theme_owner) { - _propagate_theme_changed(child_c, data.theme_owner); //need to propagate here, since many controls may require setting up stuff + if (child_c && child_c->data.theme.is_null() && (data.theme_owner || data.theme_owner_window)) { + _propagate_theme_changed(child_c, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff + } + + Window *child_w = Object::cast_to<Window>(p_child); + + if (child_w && child_w->theme.is_null() && (data.theme_owner || data.theme_owner_window)) { + _propagate_theme_changed(child_w, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff } } void Control::remove_child_notify(Node *p_child) { Control *child_c = Object::cast_to<Control>(p_child); - if (!child_c) - return; - if (child_c->data.theme_owner && child_c->data.theme.is_null()) { - _propagate_theme_changed(child_c, NULL); + if (child_c && (child_c->data.theme_owner || child_c->data.theme_owner_window) && child_c->data.theme.is_null()) { + _propagate_theme_changed(child_c, NULL, NULL); + } + + Window *child_w = Object::cast_to<Window>(p_child); + + if (child_w && (child_w->theme_owner || child_w->theme_owner_window) && child_w->theme.is_null()) { + _propagate_theme_changed(child_w, NULL, NULL); } } @@ -808,38 +816,112 @@ Size2 Control::get_minimum_size() const { return Size2(); } -Ref<Texture2D> Control::get_icon(const StringName &p_name, const StringName &p_type) const { +template <class T> +bool Control::_find_theme_item(T &r_ret, T (Theme::*get_func)(const StringName &, const StringName &) const, bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_type) const { - if (p_type == StringName() || p_type == get_class_name()) { + // try with custom themes + Control *theme_owner = data.theme_owner; + Window *theme_owner_window = data.theme_owner_window; - const Ref<Texture2D> *tex = data.icon_override.getptr(p_name); - if (tex) - return *tex; + while (theme_owner || theme_owner_window) { + + StringName class_name = p_type; + + while (class_name != StringName()) { + if (theme_owner && (theme_owner->data.theme.operator->()->*has_func)(p_name, class_name)) { + r_ret = (theme_owner->data.theme.operator->()->*get_func)(p_name, class_name); + return true; + } + + if (theme_owner_window && (theme_owner_window->theme.operator->()->*has_func)(p_name, class_name)) { + r_ret = (theme_owner_window->theme.operator->()->*get_func)(p_name, class_name); + return true; + } + + class_name = ClassDB::get_parent_class_nocheck(class_name); + } + + Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent(); + + Control *parent_c = Object::cast_to<Control>(parent); + + if (parent_c) { + theme_owner = parent_c->data.theme_owner; + theme_owner_window = parent_c->data.theme_owner_window; + } else { + Window *parent_w = Object::cast_to<Window>(parent); + if (parent_w) { + theme_owner = parent_w->theme_owner; + theme_owner_window = parent_w->theme_owner_window; + } else { + + theme_owner = NULL; + theme_owner_window = NULL; + } + } } + return false; +} - StringName type = p_type ? p_type : get_class_name(); +bool Control::_has_theme_item(bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_type) const { // try with custom themes Control *theme_owner = data.theme_owner; + Window *theme_owner_window = data.theme_owner_window; - while (theme_owner) { + while (theme_owner || theme_owner_window) { - StringName class_name = type; + StringName class_name = p_type; while (class_name != StringName()) { - if (theme_owner->data.theme->has_icon(p_name, class_name)) { - return theme_owner->data.theme->get_icon(p_name, class_name); + if (theme_owner && (theme_owner->data.theme.operator->()->*has_func)(p_name, class_name)) { + return true; + } + + if (theme_owner_window && (theme_owner_window->theme.operator->()->*has_func)(p_name, class_name)) { + return true; } class_name = ClassDB::get_parent_class_nocheck(class_name); } - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); + Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent(); + + Control *parent_c = Object::cast_to<Control>(parent); + + if (parent_c) { + theme_owner = parent_c->data.theme_owner; + theme_owner_window = parent_c->data.theme_owner_window; + } else { + Window *parent_w = Object::cast_to<Window>(parent); + if (parent_w) { + theme_owner = parent_w->theme_owner; + theme_owner_window = parent_w->theme_owner_window; + } else { + + theme_owner = NULL; + theme_owner_window = NULL; + } + } + } + return false; +} + +Ref<Texture2D> Control::get_icon(const StringName &p_name, const StringName &p_type) const { + + if (p_type == StringName() || p_type == get_class_name()) { + + const Ref<Texture2D> *tex = data.icon_override.getptr(p_name); + if (tex) + return *tex; + } + + StringName type = p_type ? p_type : get_class_name(); + + Ref<Texture2D> icon; - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + if (_find_theme_item(icon, &Theme::get_icon, &Theme::has_icon, p_name, type)) { + return icon; } if (Theme::get_project_default().is_valid()) { @@ -861,27 +943,10 @@ Ref<Shader> Control::get_shader(const StringName &p_name, const StringName &p_ty StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; + Ref<Shader> shader; - while (theme_owner) { - - StringName class_name = type; - - while (class_name != StringName()) { - if (theme_owner->data.theme->has_shader(p_name, class_name)) { - return theme_owner->data.theme->get_shader(p_name, class_name); - } - - class_name = ClassDB::get_parent_class_nocheck(class_name); - } - - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); - - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + if (_find_theme_item(shader, &Theme::get_shader, &Theme::has_shader, p_name, type)) { + return shader; } if (Theme::get_project_default().is_valid()) { @@ -903,40 +968,18 @@ Ref<StyleBox> Control::get_stylebox(const StringName &p_name, const StringName & StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; - - StringName class_name = type; - - while (theme_owner) { - - while (class_name != StringName()) { - if (theme_owner->data.theme->has_stylebox(p_name, class_name)) { - return theme_owner->data.theme->get_stylebox(p_name, class_name); - } - - class_name = ClassDB::get_parent_class_nocheck(class_name); - } - - class_name = type; + Ref<StyleBox> stylebox; - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); - - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + if (_find_theme_item(stylebox, &Theme::get_stylebox, &Theme::has_stylebox, p_name, type)) { + return stylebox; } - while (class_name != StringName()) { - if (Theme::get_project_default().is_valid() && Theme::get_project_default()->has_stylebox(p_name, type)) + if (Theme::get_project_default().is_valid()) { + if (Theme::get_project_default()->has_stylebox(p_name, type)) { return Theme::get_project_default()->get_stylebox(p_name, type); - - if (Theme::get_default()->has_stylebox(p_name, class_name)) - return Theme::get_default()->get_stylebox(p_name, class_name); - - class_name = ClassDB::get_parent_class_nocheck(class_name); + } } + return Theme::get_default()->get_stylebox(p_name, type); } Ref<Font> Control::get_font(const StringName &p_name, const StringName &p_type) const { @@ -949,29 +992,16 @@ Ref<Font> Control::get_font(const StringName &p_name, const StringName &p_type) StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; - - while (theme_owner) { + Ref<Font> font; - StringName class_name = type; - - while (class_name != StringName()) { - if (theme_owner->data.theme->has_font(p_name, class_name)) { - return theme_owner->data.theme->get_font(p_name, class_name); - } + if (_find_theme_item(font, &Theme::get_font, &Theme::has_font, p_name, type)) { + return font; + } - class_name = ClassDB::get_parent_class_nocheck(class_name); + if (Theme::get_project_default().is_valid()) { + if (Theme::get_project_default()->has_font(p_name, type)) { + return Theme::get_project_default()->get_font(p_name, type); } - - if (theme_owner->data.theme->get_default_theme_font().is_valid()) - return theme_owner->data.theme->get_default_theme_font(); - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); - - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; } return Theme::get_default()->get_font(p_name, type); @@ -985,27 +1015,11 @@ Color Control::get_color(const StringName &p_name, const StringName &p_type) con } StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; - - while (theme_owner) { - - StringName class_name = type; - while (class_name != StringName()) { - if (theme_owner->data.theme->has_color(p_name, class_name)) { - return theme_owner->data.theme->get_color(p_name, class_name); - } + Color color; - class_name = ClassDB::get_parent_class_nocheck(class_name); - } - - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); - - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + if (_find_theme_item(color, &Theme::get_color, &Theme::has_color, p_name, type)) { + return color; } if (Theme::get_project_default().is_valid()) { @@ -1025,27 +1039,11 @@ int Control::get_constant(const StringName &p_name, const StringName &p_type) co } StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; - - while (theme_owner) { - StringName class_name = type; + int constant; - while (class_name != StringName()) { - if (theme_owner->data.theme->has_constant(p_name, class_name)) { - return theme_owner->data.theme->get_constant(p_name, class_name); - } - - class_name = ClassDB::get_parent_class_nocheck(class_name); - } - - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); - - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + if (_find_theme_item(constant, &Theme::get_constant, &Theme::has_constant, p_name, type)) { + return constant; } if (Theme::get_project_default().is_valid()) { @@ -1101,26 +1099,8 @@ bool Control::has_icon(const StringName &p_name, const StringName &p_type) const StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; - - while (theme_owner) { - - StringName class_name = type; - - while (class_name != StringName()) { - if (theme_owner->data.theme->has_icon(p_name, class_name)) { - return true; - } - class_name = ClassDB::get_parent_class_nocheck(class_name); - } - - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); - - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + if (_has_theme_item(&Theme::has_icon, p_name, type)) { + return true; } if (Theme::get_project_default().is_valid()) { @@ -1140,26 +1120,8 @@ bool Control::has_shader(const StringName &p_name, const StringName &p_type) con StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; - - while (theme_owner) { - - StringName class_name = type; - - while (class_name != StringName()) { - if (theme_owner->data.theme->has_shader(p_name, class_name)) { - return true; - } - class_name = ClassDB::get_parent_class_nocheck(class_name); - } - - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); - - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + if (_has_theme_item(&Theme::has_shader, p_name, type)) { + return true; } if (Theme::get_project_default().is_valid()) { @@ -1178,26 +1140,8 @@ bool Control::has_stylebox(const StringName &p_name, const StringName &p_type) c StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; - - while (theme_owner) { - - StringName class_name = type; - - while (class_name != StringName()) { - if (theme_owner->data.theme->has_stylebox(p_name, class_name)) { - return true; - } - class_name = ClassDB::get_parent_class_nocheck(class_name); - } - - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); - - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + if (_has_theme_item(&Theme::has_stylebox, p_name, type)) { + return true; } if (Theme::get_project_default().is_valid()) { @@ -1216,26 +1160,8 @@ bool Control::has_font(const StringName &p_name, const StringName &p_type) const StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; - - while (theme_owner) { - - StringName class_name = type; - - while (class_name != StringName()) { - if (theme_owner->data.theme->has_font(p_name, class_name)) { - return true; - } - class_name = ClassDB::get_parent_class_nocheck(class_name); - } - - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); - - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + if (_has_theme_item(&Theme::has_font, p_name, type)) { + return true; } if (Theme::get_project_default().is_valid()) { @@ -1255,26 +1181,8 @@ bool Control::has_color(const StringName &p_name, const StringName &p_type) cons StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; - - while (theme_owner) { - - StringName class_name = type; - - while (class_name != StringName()) { - if (theme_owner->data.theme->has_color(p_name, class_name)) { - return true; - } - class_name = ClassDB::get_parent_class_nocheck(class_name); - } - - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); - - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + if (_has_theme_item(&Theme::has_color, p_name, type)) { + return true; } if (Theme::get_project_default().is_valid()) { @@ -1294,26 +1202,8 @@ bool Control::has_constant(const StringName &p_name, const StringName &p_type) c StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; - - while (theme_owner) { - - StringName class_name = type; - - while (class_name != StringName()) { - if (theme_owner->data.theme->has_constant(p_name, class_name)) { - return true; - } - class_name = ClassDB::get_parent_class_nocheck(class_name); - } - - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); - - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + if (_has_theme_item(&Theme::has_constant, p_name, type)) { + return true; } if (Theme::get_project_default().is_valid()) { @@ -2222,18 +2112,32 @@ void Control::_modal_stack_remove() { data.modal_prev_focus_owner = ObjectID(); } -void Control::_propagate_theme_changed(CanvasItem *p_at, Control *p_owner, bool p_assign) { +void Control::_propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign) { Control *c = Object::cast_to<Control>(p_at); if (c && c != p_owner && c->data.theme.is_valid()) // has a theme, this can't be propagated return; + Window *w = c == nullptr ? Object::cast_to<Window>(p_at) : nullptr; + + if (c && c != p_owner && c->data.theme.is_valid()) // has a theme, this can't be propagated + return; + + if (w && w != p_owner_window && w->theme.is_valid()) // has a theme, this can't be propagated + return; + for (int i = 0; i < p_at->get_child_count(); i++) { CanvasItem *child = Object::cast_to<CanvasItem>(p_at->get_child(i)); if (child) { - _propagate_theme_changed(child, p_owner, p_assign); + _propagate_theme_changed(child, p_owner, p_owner_window, p_assign); + } else { + + Window *window = Object::cast_to<Window>(p_at->get_child(i)); + if (window) { + _propagate_theme_changed(window, p_owner, p_owner_window, p_assign); + } } } @@ -2241,14 +2145,26 @@ void Control::_propagate_theme_changed(CanvasItem *p_at, Control *p_owner, bool if (p_assign) { c->data.theme_owner = p_owner; + c->data.theme_owner_window = p_owner_window; + } + c->notification(Control::NOTIFICATION_THEME_CHANGED); + c->emit_signal(SceneStringNames::get_singleton()->theme_changed); + } + + if (w) { + + if (p_assign) { + w->theme_owner = p_owner; + w->theme_owner_window = p_owner_window; } - c->notification(NOTIFICATION_THEME_CHANGED); + w->notification(Window::NOTIFICATION_THEME_CHANGED); + w->emit_signal(SceneStringNames::get_singleton()->theme_changed); } } void Control::_theme_changed() { - _propagate_theme_changed(this, this, false); + _propagate_theme_changed(this, this, nullptr, false); } void Control::set_theme(const Ref<Theme> &p_theme) { @@ -2264,15 +2180,21 @@ void Control::set_theme(const Ref<Theme> &p_theme) { if (!p_theme.is_null()) { data.theme_owner = this; - _propagate_theme_changed(this, this); + data.theme_owner_window = nullptr; + _propagate_theme_changed(this, this, nullptr); } else { - Control *parent = cast_to<Control>(get_parent()); - if (parent && parent->data.theme_owner) { - _propagate_theme_changed(this, parent->data.theme_owner); - } else { + Control *parent_c = Object::cast_to<Control>(get_parent()); - _propagate_theme_changed(this, NULL); + if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) { + Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window); + } else { + Window *parent_w = cast_to<Window>(get_parent()); + if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) { + Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window); + } else { + Control::_propagate_theme_changed(this, nullptr, nullptr); + } } } @@ -2564,6 +2486,12 @@ void Control::minimum_size_changed() { invalidate->data.minimum_size_valid = false; if (invalidate->is_set_as_toplevel()) break; // do not go further up + if (!invalidate->data.parent && get_parent()) { + Window *parent_window = Object::cast_to<Window>(get_parent()); + if (parent_window && parent_window->is_wrapping_controls()) { + parent_window->child_controls_changed(); + } + } invalidate = invalidate->data.parent; } @@ -2653,6 +2581,7 @@ float Control::get_rotation_degrees() const { void Control::_override_changed() { notification(NOTIFICATION_THEME_CHANGED); + emit_signal(SceneStringNames::get_singleton()->theme_changed); minimum_size_changed(); // overrides are likely to affect minimum size } @@ -3078,6 +3007,7 @@ void Control::_bind_methods() { ADD_SIGNAL(MethodInfo("size_flags_changed")); ADD_SIGNAL(MethodInfo("minimum_size_changed")); ADD_SIGNAL(MethodInfo("modal_closed")); + ADD_SIGNAL(MethodInfo("theme_changed")); BIND_VMETHOD(MethodInfo(Variant::BOOL, "has_point", PropertyInfo(Variant::VECTOR2, "point"))); } @@ -3092,6 +3022,7 @@ Control::Control() { data.MI = NULL; data.RI = NULL; data.theme_owner = NULL; + data.theme_owner_window = NULL; data.modal_exclusive = false; data.default_cursor = CURSOR_ARROW; data.h_size_flags = SIZE_FILL; diff --git a/scene/gui/control.h b/scene/gui/control.h index 15a32b8f67..83b9dd7861 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -183,6 +183,7 @@ private: uint64_t modal_frame; //frame used to put something as modal Ref<Theme> theme; Control *theme_owner; + Window *theme_owner_window; String tooltip; CursorShape default_cursor; @@ -218,7 +219,6 @@ private: void _set_global_position(const Point2 &p_point); void _set_size(const Size2 &p_size); - void _propagate_theme_changed(CanvasItem *p_at, Control *p_owner, bool p_assign = true); void _theme_changed(); void _change_notify_margins(); @@ -244,6 +244,13 @@ private: void _modal_set_prev_focus_owner(ObjectID p_prev); void _update_minimum_size_cache(); + friend class Window; + static void _propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign = true); + + template <class T> + _FORCE_INLINE_ bool _find_theme_item(T &, T (Theme::*get_func)(const StringName &, const StringName &) const, bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_type) const; + + _FORCE_INLINE_ bool _has_theme_item(bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_type) const; protected: virtual void add_child_notify(Node *p_child); diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index 290cff6888..71000847a1 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -29,6 +29,8 @@ /*************************************************************************/ #include "dialogs.h" + +#include "core/os/keyboard.h" #include "core/print_string.h" #include "core/translation.h" #include "line_edit.h" @@ -39,359 +41,51 @@ #include "scene/main/window.h" // Only used to check for more modals when dimming the editor. #endif -// WindowDialog - -void WindowDialog::_post_popup() { - - drag_type = DRAG_NONE; // just in case -} - -void WindowDialog::_fix_size() { - - // Perhaps this should be called when the viewport resizes as well or windows go out of bounds... - - // Ensure the whole window is visible. - Point2i pos = get_global_position(); - Size2i size = get_size(); - Size2i viewport_size = get_viewport_rect().size; - - // Windows require additional padding to keep the window chrome visible. - Ref<StyleBox> panel = get_stylebox("panel", "WindowDialog"); - float top = 0; - float left = 0; - float bottom = 0; - float right = 0; - // Check validity, because the theme could contain a different type of StyleBox. - if (panel->get_class() == "StyleBoxTexture") { - Ref<StyleBoxTexture> panel_texture = Object::cast_to<StyleBoxTexture>(*panel); - top = panel_texture->get_expand_margin_size(MARGIN_TOP); - left = panel_texture->get_expand_margin_size(MARGIN_LEFT); - bottom = panel_texture->get_expand_margin_size(MARGIN_BOTTOM); - right = panel_texture->get_expand_margin_size(MARGIN_RIGHT); - } else if (panel->get_class() == "StyleBoxFlat") { - Ref<StyleBoxFlat> panel_flat = Object::cast_to<StyleBoxFlat>(*panel); - top = panel_flat->get_expand_margin_size(MARGIN_TOP); - left = panel_flat->get_expand_margin_size(MARGIN_LEFT); - bottom = panel_flat->get_expand_margin_size(MARGIN_BOTTOM); - right = panel_flat->get_expand_margin_size(MARGIN_RIGHT); - } - - pos.x = MAX(left, MIN(pos.x, viewport_size.x - size.x - right)); - pos.y = MAX(top, MIN(pos.y, viewport_size.y - size.y - bottom)); - set_global_position(pos); +// AcceptDialog - if (resizable) { - size.x = MIN(size.x, viewport_size.x - left - right); - size.y = MIN(size.y, viewport_size.y - top - bottom); - set_size(size); +void AcceptDialog::_input_from_window(const Ref<InputEvent> &p_event) { + Ref<InputEventKey> key = p_event; + if (key.is_valid() && key->is_pressed() && key->get_keycode() == KEY_ESCAPE) { + _cancel_pressed(); } } -bool WindowDialog::has_point(const Point2 &p_point) const { - - Rect2 r(Point2(), get_size()); - - // Enlarge upwards for title bar. - int title_height = get_constant("title_height", "WindowDialog"); - r.position.y -= title_height; - r.size.y += title_height; - - // Inflate by the resizable border thickness. - if (resizable) { - int scaleborder_size = get_constant("scaleborder_size", "WindowDialog"); - r.position.x -= scaleborder_size; - r.size.width += scaleborder_size * 2; - r.position.y -= scaleborder_size; - r.size.height += scaleborder_size * 2; - } - - return r.has_point(p_point); +void AcceptDialog::_parent_focused() { + _cancel_pressed(); } -void WindowDialog::_gui_input(const Ref<InputEvent> &p_event) { - - Ref<InputEventMouseButton> mb = p_event; - - if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) { - - if (mb->is_pressed()) { - // Begin a possible dragging operation. - drag_type = _drag_hit_test(Point2(mb->get_position().x, mb->get_position().y)); - if (drag_type != DRAG_NONE) - drag_offset = get_global_mouse_position() - get_position(); - drag_offset_far = get_position() + get_size() - get_global_mouse_position(); - } else if (drag_type != DRAG_NONE && !mb->is_pressed()) { - // End a dragging operation. - drag_type = DRAG_NONE; - } - } +void AcceptDialog::_notification(int p_what) { - Ref<InputEventMouseMotion> mm = p_event; - - if (mm.is_valid()) { - - if (drag_type == DRAG_NONE) { - // Update the cursor while moving along the borders. - CursorShape cursor = CURSOR_ARROW; - if (resizable) { - int preview_drag_type = _drag_hit_test(Point2(mm->get_position().x, mm->get_position().y)); - switch (preview_drag_type) { - case DRAG_RESIZE_TOP: - case DRAG_RESIZE_BOTTOM: - cursor = CURSOR_VSIZE; - break; - case DRAG_RESIZE_LEFT: - case DRAG_RESIZE_RIGHT: - cursor = CURSOR_HSIZE; - break; - case DRAG_RESIZE_TOP + DRAG_RESIZE_LEFT: - case DRAG_RESIZE_BOTTOM + DRAG_RESIZE_RIGHT: - cursor = CURSOR_FDIAGSIZE; - break; - case DRAG_RESIZE_TOP + DRAG_RESIZE_RIGHT: - case DRAG_RESIZE_BOTTOM + DRAG_RESIZE_LEFT: - cursor = CURSOR_BDIAGSIZE; - break; + switch (p_what) { + case NOTIFICATION_VISIBILITY_CHANGED: { + if (is_visible()) { + + get_ok()->grab_focus(); + _update_child_rects(); + parent_visible = get_parent_visible_window(); + if (parent_visible) { + parent_visible->connect("focus_entered", callable_mp(this, &AcceptDialog::_parent_focused)); } - } - if (get_cursor_shape() != cursor) - set_default_cursor_shape(cursor); - } else { - // Update while in a dragging operation. - Point2 global_pos = get_global_mouse_position(); - global_pos.y = MAX(global_pos.y, 0); // Ensure title bar stays visible. - - Rect2 rect = get_rect(); - Size2 min_size = get_combined_minimum_size(); - - if (drag_type == DRAG_MOVE) { - rect.position = global_pos - drag_offset; } else { - if (drag_type & DRAG_RESIZE_TOP) { - int bottom = rect.position.y + rect.size.height; - int max_y = bottom - min_size.height; - rect.position.y = MIN(global_pos.y - drag_offset.y, max_y); - rect.size.height = bottom - rect.position.y; - } else if (drag_type & DRAG_RESIZE_BOTTOM) { - rect.size.height = global_pos.y - rect.position.y + drag_offset_far.y; - } - if (drag_type & DRAG_RESIZE_LEFT) { - int right = rect.position.x + rect.size.width; - int max_x = right - min_size.width; - rect.position.x = MIN(global_pos.x - drag_offset.x, max_x); - rect.size.width = right - rect.position.x; - } else if (drag_type & DRAG_RESIZE_RIGHT) { - rect.size.width = global_pos.x - rect.position.x + drag_offset_far.x; + if (parent_visible) { + parent_visible->disconnect("focus_entered", callable_mp(this, &AcceptDialog::_parent_focused)); } } - set_size(rect.size); - set_position(rect.position); - } - } -} - -void WindowDialog::_notification(int p_what) { - - switch (p_what) { - case NOTIFICATION_DRAW: { - RID canvas = get_canvas_item(); - - // Draw the background. - Ref<StyleBox> panel = get_stylebox("panel"); - Size2 size = get_size(); - panel->draw(canvas, Rect2(0, 0, size.x, size.y)); - - // Draw the title bar text. - Ref<Font> title_font = get_font("title_font", "WindowDialog"); - Color title_color = get_color("title_color", "WindowDialog"); - int title_height = get_constant("title_height", "WindowDialog"); - int font_height = title_font->get_height() - title_font->get_descent() * 2; - int x = (size.x - title_font->get_string_size(xl_title).x) / 2; - int y = (-title_height + font_height) / 2; - title_font->draw(canvas, Point2(x, y), xl_title, title_color, size.x - panel->get_minimum_size().x); - } break; - - case NOTIFICATION_THEME_CHANGED: - case NOTIFICATION_ENTER_TREE: { - close_button->set_normal_texture(get_icon("close", "WindowDialog")); - close_button->set_pressed_texture(get_icon("close", "WindowDialog")); - close_button->set_hover_texture(get_icon("close_highlight", "WindowDialog")); - close_button->set_anchor(MARGIN_LEFT, ANCHOR_END); - close_button->set_begin(Point2(-get_constant("close_h_ofs", "WindowDialog"), -get_constant("close_v_ofs", "WindowDialog"))); - } break; - - case NOTIFICATION_TRANSLATION_CHANGED: { - String new_title = tr(title); - if (new_title != xl_title) { - xl_title = new_title; - minimum_size_changed(); - update(); - } - } break; - - case NOTIFICATION_MOUSE_EXIT: { - // Reset the mouse cursor when leaving the resizable window border. - if (resizable && !drag_type) { - if (get_default_cursor_shape() != CURSOR_ARROW) - set_default_cursor_shape(CURSOR_ARROW); - } } break; -#ifdef TOOLS_ENABLED - case NOTIFICATION_POST_POPUP: { - if (get_tree() && Engine::get_singleton()->is_editor_hint() && EditorNode::get_singleton()) { - was_editor_dimmed = EditorNode::get_singleton()->is_editor_dimmed(); - EditorNode::get_singleton()->dim_editor(true); - } + case NOTIFICATION_THEME_CHANGED: { + bg->add_style_override("panel", bg->get_stylebox("panel", "AcceptDialog")); } break; - case NOTIFICATION_POPUP_HIDE: { - if (get_tree() && Engine::get_singleton()->is_editor_hint() && EditorNode::get_singleton() && !was_editor_dimmed) { - EditorNode::get_singleton()->dim_editor(false); - set_pass_on_modal_close_click(false); + case NOTIFICATION_READY: + case NOTIFICATION_WM_SIZE_CHANGED: { + if (is_visible()) { + _update_child_rects(); } } break; -#endif - } -} - -void WindowDialog::_closed() { - - _close_pressed(); - hide(); -} - -int WindowDialog::_drag_hit_test(const Point2 &pos) const { - int drag_type = DRAG_NONE; - - if (resizable) { - int title_height = get_constant("title_height", "WindowDialog"); - int scaleborder_size = get_constant("scaleborder_size", "WindowDialog"); - - Rect2 rect = get_rect(); - - if (pos.y < (-title_height + scaleborder_size)) - drag_type = DRAG_RESIZE_TOP; - else if (pos.y >= (rect.size.height - scaleborder_size)) - drag_type = DRAG_RESIZE_BOTTOM; - if (pos.x < scaleborder_size) - drag_type |= DRAG_RESIZE_LEFT; - else if (pos.x >= (rect.size.width - scaleborder_size)) - drag_type |= DRAG_RESIZE_RIGHT; - } - - if (drag_type == DRAG_NONE && pos.y < 0) - drag_type = DRAG_MOVE; - - return drag_type; -} - -void WindowDialog::set_title(const String &p_title) { - - if (title != p_title) { - title = p_title; - xl_title = tr(p_title); - minimum_size_changed(); - update(); - } -} -String WindowDialog::get_title() const { - - return title; -} - -void WindowDialog::set_resizable(bool p_resizable) { - resizable = p_resizable; -} -bool WindowDialog::get_resizable() const { - return resizable; -} - -Size2 WindowDialog::get_minimum_size() const { - - Ref<Font> font = get_font("title_font", "WindowDialog"); - - const int button_width = close_button->get_combined_minimum_size().x; - const int title_width = font->get_string_size(xl_title).x; - const int padding = button_width / 2; - const int button_area = button_width + padding; - - // As the title gets centered, title_width + close_button_width is not enough. - // We want a width w, such that w / 2 - title_width / 2 >= button_area, i.e. - // w >= 2 * button_area + title_width - - return Size2(2 * button_area + title_width, 1); -} - -TextureButton *WindowDialog::get_close_button() { - - return close_button; -} - -void WindowDialog::_bind_methods() { - - ClassDB::bind_method(D_METHOD("_gui_input"), &WindowDialog::_gui_input); - ClassDB::bind_method(D_METHOD("set_title", "title"), &WindowDialog::set_title); - ClassDB::bind_method(D_METHOD("get_title"), &WindowDialog::get_title); - ClassDB::bind_method(D_METHOD("set_resizable", "resizable"), &WindowDialog::set_resizable); - ClassDB::bind_method(D_METHOD("get_resizable"), &WindowDialog::get_resizable); - ClassDB::bind_method(D_METHOD("get_close_button"), &WindowDialog::get_close_button); - - ADD_PROPERTY(PropertyInfo(Variant::STRING, "window_title", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT_INTL), "set_title", "get_title"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resizable", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT_INTL), "set_resizable", "get_resizable"); -} - -WindowDialog::WindowDialog() { - - drag_type = DRAG_NONE; - resizable = false; - close_button = memnew(TextureButton); - add_child(close_button); - close_button->connect("pressed", callable_mp(this, &WindowDialog::_closed)); - -#ifdef TOOLS_ENABLED - was_editor_dimmed = false; -#endif -} - -WindowDialog::~WindowDialog() { -} - -// PopupDialog - -void PopupDialog::_notification(int p_what) { - - if (p_what == NOTIFICATION_DRAW) { - RID ci = get_canvas_item(); - get_stylebox("panel")->draw(ci, Rect2(Point2(), get_size())); - } -} - -PopupDialog::PopupDialog() { -} - -PopupDialog::~PopupDialog() { -} - -// AcceptDialog - -void AcceptDialog::_post_popup() { - - WindowDialog::_post_popup(); - get_ok()->grab_focus(); -} - -void AcceptDialog::_notification(int p_what) { - - switch (p_what) { - case NOTIFICATION_MODAL_CLOSE: { - cancel_pressed(); - } break; - - case NOTIFICATION_READY: - case NOTIFICATION_RESIZED: { - _update_child_rects(); + case NOTIFICATION_WM_CLOSE_REQUEST: { + _cancel_pressed(); } break; } } @@ -404,20 +98,28 @@ void AcceptDialog::_text_entered(const String &p_text) { void AcceptDialog::_ok_pressed() { if (hide_on_ok) - hide(); + set_visible(false); ok_pressed(); emit_signal("confirmed"); } -void AcceptDialog::_close_pressed() { +void AcceptDialog::_cancel_pressed() { + + Window *parent_window = parent_visible; + if (parent_visible) { + parent_visible->disconnect("focus_entered", callable_mp(this, &AcceptDialog::_parent_focused)); + parent_visible = nullptr; + } + + call_deferred("hide"); + + emit_signal("cancelled"); cancel_pressed(); -} -// FIXME: This is redundant with _closed_pressed, but there's a slight behavior -// change (WindowDialog's _closed() also calls hide()) which should be assessed. -void AcceptDialog::_on_close_pressed() { - _closed(); // From WindowDialog. + if (parent_window) { + //parent_window->grab_focus(); + } } String AcceptDialog::get_text() const { @@ -427,8 +129,10 @@ String AcceptDialog::get_text() const { void AcceptDialog::set_text(String p_text) { label->set_text(p_text); - minimum_size_changed(); - _update_child_rects(); + child_controls_changed(); + if (is_visible()) { + _update_child_rects(); + } } void AcceptDialog::set_hide_on_ok(bool p_hide) { @@ -463,7 +167,7 @@ void AcceptDialog::_update_child_rects() { if (label->get_text().empty()) { label_size.height = 0; } - int margin = get_constant("margin", "Dialogs"); + int margin = hbc->get_constant("margin", "Dialogs"); Size2 size = get_size(); Size2 hminsize = hbc->get_combined_minimum_size(); @@ -475,7 +179,7 @@ void AcceptDialog::_update_child_rects() { if (!c) continue; - if (c == hbc || c == label || c == get_close_button() || c->is_set_as_toplevel()) + if (c == hbc || c == label || c == bg || c->is_set_as_toplevel()) continue; c->set_position(cpos); @@ -487,11 +191,14 @@ void AcceptDialog::_update_child_rects() { hbc->set_position(cpos); hbc->set_size(csize); + + bg->set_position(Point2()); + bg->set_size(size); } -Size2 AcceptDialog::get_minimum_size() const { +Size2 AcceptDialog::_get_contents_minimum_size() const { - int margin = get_constant("margin", "Dialogs"); + int margin = hbc->get_constant("margin", "Dialogs"); Size2 minsize = label->get_combined_minimum_size(); for (int i = 0; i < get_child_count(); i++) { @@ -499,7 +206,7 @@ Size2 AcceptDialog::get_minimum_size() const { if (!c) continue; - if (c == hbc || c == label || c == const_cast<AcceptDialog *>(this)->get_close_button() || c->is_set_as_toplevel()) + if (c == hbc || c == label || c->is_set_as_toplevel()) continue; Size2 cminsize = c->get_combined_minimum_size(); @@ -513,7 +220,7 @@ Size2 AcceptDialog::get_minimum_size() const { minsize.x += margin * 2; minsize.y += margin * 3; //one as separation between hbc and child - Size2 wmsize = WindowDialog::get_minimum_size(); + Size2 wmsize = get_min_size(); minsize.x = MAX(wmsize.x, minsize.x); return minsize; } @@ -551,7 +258,7 @@ Button *AcceptDialog::add_cancel(const String &p_cancel) { if (p_cancel == "") c = RTR("Cancel"); Button *b = swap_ok_cancel ? add_button(c, true) : add_button(c); - b->connect("pressed", callable_mp(this, &AcceptDialog::_on_close_pressed)); + b->connect("pressed", callable_mp(this, &AcceptDialog::_cancel_pressed)); return b; } @@ -570,6 +277,7 @@ void AcceptDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("has_autowrap"), &AcceptDialog::has_autowrap); ADD_SIGNAL(MethodInfo("confirmed")); + ADD_SIGNAL(MethodInfo("cancelled")); ADD_SIGNAL(MethodInfo("custom_action", PropertyInfo(Variant::STRING_NAME, "action"))); ADD_GROUP("Dialog", "dialog"); @@ -586,12 +294,22 @@ void AcceptDialog::set_swap_ok_cancel(bool p_swap) { AcceptDialog::AcceptDialog() { - int margin = get_constant("margin", "Dialogs"); - int button_margin = get_constant("button_margin", "Dialogs"); + parent_visible = nullptr; + + set_visible(false); + set_transient(true); + + bg = memnew(Panel); + add_child(bg); + + hbc = memnew(HBoxContainer); + + int margin = hbc->get_constant("margin", "Dialogs"); + int button_margin = hbc->get_constant("button_margin", "Dialogs"); label = memnew(Label); - label->set_anchor(MARGIN_RIGHT, ANCHOR_END); - label->set_anchor(MARGIN_BOTTOM, ANCHOR_END); + label->set_anchor(MARGIN_RIGHT, Control::ANCHOR_END); + label->set_anchor(MARGIN_BOTTOM, Control::ANCHOR_END); label->set_begin(Point2(margin, margin)); label->set_end(Point2(-margin, -button_margin - 10)); add_child(label); @@ -606,10 +324,11 @@ AcceptDialog::AcceptDialog() { hbc->add_spacer(); ok->connect("pressed", callable_mp(this, &AcceptDialog::_ok_pressed)); - set_as_toplevel(true); hide_on_ok = true; set_title(RTR("Alert!")); + + connect("window_input", callable_mp(this, &AcceptDialog::_input_from_window)); } AcceptDialog::~AcceptDialog() { @@ -631,7 +350,7 @@ ConfirmationDialog::ConfirmationDialog() { set_title(RTR("Please Confirm...")); #ifdef TOOLS_ENABLED - set_custom_minimum_size(Size2(200, 70) * EDSCALE); + set_min_size(Size2(200, 70) * EDSCALE); #endif cancel = add_cancel(); } diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h index c474f7849d..b68b4297d7 100644 --- a/scene/gui/dialogs.h +++ b/scene/gui/dialogs.h @@ -37,91 +37,32 @@ #include "scene/gui/panel.h" #include "scene/gui/popup.h" #include "scene/gui/texture_button.h" - -class WindowDialog : public Popup { - - GDCLASS(WindowDialog, Popup); - - enum DRAG_TYPE { - DRAG_NONE = 0, - DRAG_MOVE = 1, - DRAG_RESIZE_TOP = 1 << 1, - DRAG_RESIZE_RIGHT = 1 << 2, - DRAG_RESIZE_BOTTOM = 1 << 3, - DRAG_RESIZE_LEFT = 1 << 4 - }; - - TextureButton *close_button; - String title; - String xl_title; - int drag_type; - Point2 drag_offset; - Point2 drag_offset_far; - bool resizable; - -#ifdef TOOLS_ENABLED - bool was_editor_dimmed; -#endif - - void _gui_input(const Ref<InputEvent> &p_event); - int _drag_hit_test(const Point2 &pos) const; - -protected: - virtual void _post_popup(); - virtual void _fix_size(); - virtual void _close_pressed() {} - virtual bool has_point(const Point2 &p_point) const; - void _notification(int p_what); - static void _bind_methods(); - - // Not private since used by derived classes signal. - void _closed(); - -public: - TextureButton *get_close_button(); - - void set_title(const String &p_title); - String get_title() const; - void set_resizable(bool p_resizable); - bool get_resizable() const; - - Size2 get_minimum_size() const; - - WindowDialog(); - ~WindowDialog(); -}; - -class PopupDialog : public Popup { - - GDCLASS(PopupDialog, Popup); - -protected: - void _notification(int p_what); - -public: - PopupDialog(); - ~PopupDialog(); -}; +#include "scene/main/window.h" class LineEdit; -class AcceptDialog : public WindowDialog { +class AcceptDialog : public Window { - GDCLASS(AcceptDialog, WindowDialog); + GDCLASS(AcceptDialog, Window); + Window *parent_visible; + Panel *bg; HBoxContainer *hbc; Label *label; Button *ok; bool hide_on_ok; void _custom_action(const String &p_action); - void _close_pressed(); void _update_child_rects(); static bool swap_ok_cancel; + void _input_from_window(const Ref<InputEvent> &p_event); + void _parent_focused(); + protected: - virtual void _post_popup(); + virtual Size2 _get_contents_minimum_size() const; + void _notification(int p_what); static void _bind_methods(); virtual void ok_pressed() {} @@ -131,11 +72,9 @@ protected: // Not private since used by derived classes signal. void _text_entered(const String &p_text); void _ok_pressed(); - void _on_close_pressed(); + void _cancel_pressed(); public: - Size2 get_minimum_size() const; - Label *get_label() { return label; } static void set_swap_ok_cancel(bool p_swap); diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 3be77ff4b3..2f7949ea12 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -44,42 +44,46 @@ VBoxContainer *FileDialog::get_vbox() { return vbox; } -void FileDialog::_notification(int p_what) { +void FileDialog::_theme_changed() { - if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { + Color font_color = vbc->get_color("font_color", "ToolButton"); + Color font_color_hover = vbc->get_color("font_color_hover", "ToolButton"); + Color font_color_pressed = vbc->get_color("font_color_pressed", "ToolButton"); - if (p_what == NOTIFICATION_ENTER_TREE) { - dir_up->set_icon(get_icon("parent_folder")); - refresh->set_icon(get_icon("reload")); - show_hidden->set_icon(get_icon("toggle_hidden")); - } + dir_up->add_color_override("icon_color_normal", font_color); + dir_up->add_color_override("icon_color_hover", font_color_hover); + dir_up->add_color_override("icon_color_pressed", font_color_pressed); - Color font_color = get_color("font_color", "ToolButton"); - Color font_color_hover = get_color("font_color_hover", "ToolButton"); - Color font_color_pressed = get_color("font_color_pressed", "ToolButton"); + refresh->add_color_override("icon_color_normal", font_color); + refresh->add_color_override("icon_color_hover", font_color_hover); + refresh->add_color_override("icon_color_pressed", font_color_pressed); - dir_up->add_color_override("icon_color_normal", font_color); - dir_up->add_color_override("icon_color_hover", font_color_hover); - dir_up->add_color_override("icon_color_pressed", font_color_pressed); + show_hidden->add_color_override("icon_color_normal", font_color); + show_hidden->add_color_override("icon_color_hover", font_color_hover); + show_hidden->add_color_override("icon_color_pressed", font_color_pressed); +} - refresh->add_color_override("icon_color_normal", font_color); - refresh->add_color_override("icon_color_hover", font_color_hover); - refresh->add_color_override("icon_color_pressed", font_color_pressed); +void FileDialog::_notification(int p_what) { - show_hidden->add_color_override("icon_color_normal", font_color); - show_hidden->add_color_override("icon_color_hover", font_color_hover); - show_hidden->add_color_override("icon_color_pressed", font_color_pressed); + if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + if (!is_visible()) { - } else if (p_what == NOTIFICATION_POPUP_HIDE) { + set_process_unhandled_input(false); + } + } + if (p_what == NOTIFICATION_ENTER_TREE) { - set_process_unhandled_input(false); + dir_up->set_icon(vbc->get_icon("parent_folder")); + refresh->set_icon(vbc->get_icon("reload")); + show_hidden->set_icon(vbc->get_icon("toggle_hidden")); + _theme_changed(); } } void FileDialog::_unhandled_input(const Ref<InputEvent> &p_event) { Ref<InputEventKey> k = p_event; - if (k.is_valid() && is_window_modal_on_top()) { + if (k.is_valid() && has_focus()) { if (k->is_pressed()) { @@ -110,7 +114,7 @@ void FileDialog::_unhandled_input(const Ref<InputEvent> &p_event) { } if (handled) - accept_event(); + set_input_as_handled(); } } } @@ -171,7 +175,7 @@ void FileDialog::_post_popup() { update_file_list(); invalidated = false; } - if (mode == MODE_SAVE_FILE) + if (mode == FILE_MODE_SAVE_FILE) file->grab_focus(); else tree->grab_focus(); @@ -179,7 +183,7 @@ void FileDialog::_post_popup() { set_process_unhandled_input(true); // For open dir mode, deselect all items on file dialog open. - if (mode == MODE_OPEN_DIR) { + if (mode == FILE_MODE_OPEN_DIR) { deselect_items(); file_box->set_visible(false); } else { @@ -189,7 +193,7 @@ void FileDialog::_post_popup() { void FileDialog::_action_pressed() { - if (mode == MODE_OPEN_FILES) { + if (mode == FILE_MODE_OPEN_FILES) { TreeItem *ti = tree->get_next_selected(NULL); String fbase = dir_access->get_current_dir(); @@ -211,10 +215,10 @@ void FileDialog::_action_pressed() { String f = dir_access->get_current_dir().plus_file(file->get_text()); - if ((mode == MODE_OPEN_ANY || mode == MODE_OPEN_FILE) && dir_access->file_exists(f)) { + if ((mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_FILE) && dir_access->file_exists(f)) { emit_signal("file_selected", f); hide(); - } else if (mode == MODE_OPEN_ANY || mode == MODE_OPEN_DIR) { + } else if (mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_DIR) { String path = dir_access->get_current_dir(); @@ -231,7 +235,7 @@ void FileDialog::_action_pressed() { hide(); } - if (mode == MODE_SAVE_FILE) { + if (mode == FILE_MODE_SAVE_FILE) { bool valid = false; @@ -283,7 +287,7 @@ void FileDialog::_action_pressed() { if (!valid) { - exterr->popup_centered_minsize(Size2(250, 80)); + exterr->popup_centered(Size2(250, 80)); return; } @@ -307,7 +311,7 @@ void FileDialog::_cancel_pressed() { bool FileDialog::_is_open_should_be_disabled() { - if (mode == MODE_OPEN_ANY || mode == MODE_SAVE_FILE) + if (mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_SAVE_FILE) return false; TreeItem *ti = tree->get_next_selected(tree->get_root()); @@ -319,13 +323,13 @@ bool FileDialog::_is_open_should_be_disabled() { } // We have something that we can't select? if (!ti) - return mode != MODE_OPEN_DIR; // In "Open folder" mode, having nothing selected picks the current folder. + return mode != FILE_MODE_OPEN_DIR; // In "Open folder" mode, having nothing selected picks the current folder. Dictionary d = ti->get_metadata(0); // Opening a file, but selected a folder? Forbidden. - return ((mode == MODE_OPEN_FILE || mode == MODE_OPEN_FILES) && d["dir"]) || // Flipped case, also forbidden. - (mode == MODE_OPEN_DIR && !d["dir"]); + return ((mode == FILE_MODE_OPEN_FILE || mode == FILE_MODE_OPEN_FILES) && d["dir"]) || // Flipped case, also forbidden. + (mode == FILE_MODE_OPEN_DIR && !d["dir"]); } void FileDialog::_go_up() { @@ -346,15 +350,15 @@ void FileDialog::deselect_items() { switch (mode) { - case MODE_OPEN_FILE: - case MODE_OPEN_FILES: + case FILE_MODE_OPEN_FILE: + case FILE_MODE_OPEN_FILES: get_ok()->set_text(RTR("Open")); break; - case MODE_OPEN_DIR: + case FILE_MODE_OPEN_DIR: get_ok()->set_text(RTR("Select Current Folder")); break; - case MODE_OPEN_ANY: - case MODE_SAVE_FILE: + case FILE_MODE_OPEN_ANY: + case FILE_MODE_SAVE_FILE: // FIXME: Implement, or refactor to avoid duplication with set_mode break; } @@ -375,7 +379,7 @@ void FileDialog::_tree_selected() { if (!d["dir"]) { file->set_text(d["name"]); - } else if (mode == MODE_OPEN_DIR) { + } else if (mode == FILE_MODE_OPEN_DIR) { get_ok()->set_text(RTR("Select This Folder")); } @@ -393,7 +397,7 @@ void FileDialog::_tree_item_activated() { if (d["dir"]) { dir_access->change_dir(d["name"]); - if (mode == MODE_OPEN_FILE || mode == MODE_OPEN_FILES || mode == MODE_OPEN_DIR || mode == MODE_OPEN_ANY) + if (mode == FILE_MODE_OPEN_FILE || mode == FILE_MODE_OPEN_FILES || mode == FILE_MODE_OPEN_DIR || mode == FILE_MODE_OPEN_ANY) file->set_text(""); call_deferred("_update_file_list"); call_deferred("_update_dir"); @@ -425,8 +429,8 @@ void FileDialog::update_file_list() { dir_access->list_dir_begin(); TreeItem *root = tree->create_item(); - Ref<Texture2D> folder = get_icon("folder"); - const Color folder_color = get_color("folder_icon_modulate"); + Ref<Texture2D> folder = vbc->get_icon("folder"); + const Color folder_color = vbc->get_color("folder_icon_modulate"); List<String> files; List<String> dirs; @@ -523,8 +527,8 @@ void FileDialog::update_file_list() { ti->set_icon(0, icon); } - if (mode == MODE_OPEN_DIR) { - ti->set_custom_color(0, get_color("files_disabled")); + if (mode == FILE_MODE_OPEN_DIR) { + ti->set_custom_color(0, vbc->get_color("files_disabled")); ti->set_selectable(0, false); } Dictionary d; @@ -661,38 +665,38 @@ bool FileDialog::is_mode_overriding_title() const { return mode_overrides_title; } -void FileDialog::set_mode(Mode p_mode) { +void FileDialog::set_file_mode(FileMode p_mode) { ERR_FAIL_INDEX((int)p_mode, 5); mode = p_mode; switch (mode) { - case MODE_OPEN_FILE: + case FILE_MODE_OPEN_FILE: get_ok()->set_text(RTR("Open")); if (mode_overrides_title) set_title(RTR("Open a File")); makedir->hide(); break; - case MODE_OPEN_FILES: + case FILE_MODE_OPEN_FILES: get_ok()->set_text(RTR("Open")); if (mode_overrides_title) set_title(RTR("Open File(s)")); makedir->hide(); break; - case MODE_OPEN_DIR: + case FILE_MODE_OPEN_DIR: get_ok()->set_text(RTR("Select Current Folder")); if (mode_overrides_title) set_title(RTR("Open a Directory")); makedir->show(); break; - case MODE_OPEN_ANY: + case FILE_MODE_OPEN_ANY: get_ok()->set_text(RTR("Open")); if (mode_overrides_title) set_title(RTR("Open a File or Directory")); makedir->show(); break; - case MODE_SAVE_FILE: + case FILE_MODE_SAVE_FILE: get_ok()->set_text(RTR("Save")); if (mode_overrides_title) set_title(RTR("Save a File")); @@ -700,14 +704,14 @@ void FileDialog::set_mode(Mode p_mode) { break; } - if (mode == MODE_OPEN_FILES) { + if (mode == FILE_MODE_OPEN_FILES) { tree->set_select_mode(Tree::SELECT_MULTI); } else { tree->set_select_mode(Tree::SELECT_SINGLE); } } -FileDialog::Mode FileDialog::get_mode() const { +FileDialog::FileMode FileDialog::get_file_mode() const { return mode; } @@ -741,7 +745,7 @@ void FileDialog::set_access(Access p_access) { void FileDialog::invalidate() { - if (is_visible_in_tree()) { + if (is_visible()) { update_file_list(); invalidated = false; } else { @@ -763,14 +767,14 @@ void FileDialog::_make_dir_confirm() { update_filters(); update_dir(); } else { - mkdirerr->popup_centered_minsize(Size2(250, 50)); + mkdirerr->popup_centered(Size2(250, 50)); } makedirname->set_text(""); // reset label } void FileDialog::_make_dir() { - makedialog->popup_centered_minsize(Size2(250, 80)); + makedialog->popup_centered(Size2(250, 80)); makedirname->grab_focus(); } @@ -826,8 +830,8 @@ void FileDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("set_current_path", "path"), &FileDialog::set_current_path); ClassDB::bind_method(D_METHOD("set_mode_overrides_title", "override"), &FileDialog::set_mode_overrides_title); ClassDB::bind_method(D_METHOD("is_mode_overriding_title"), &FileDialog::is_mode_overriding_title); - ClassDB::bind_method(D_METHOD("set_mode", "mode"), &FileDialog::set_mode); - ClassDB::bind_method(D_METHOD("get_mode"), &FileDialog::get_mode); + ClassDB::bind_method(D_METHOD("set_file_mode", "mode"), &FileDialog::set_file_mode); + ClassDB::bind_method(D_METHOD("get_file_mode"), &FileDialog::get_file_mode); ClassDB::bind_method(D_METHOD("get_vbox"), &FileDialog::get_vbox); ClassDB::bind_method(D_METHOD("get_line_edit"), &FileDialog::get_line_edit); ClassDB::bind_method(D_METHOD("set_access", "access"), &FileDialog::set_access); @@ -842,7 +846,7 @@ void FileDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("invalidate"), &FileDialog::invalidate); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "mode_overrides_title"), "set_mode_overrides_title", "is_mode_overriding_title"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Open File,Open Files,Open Folder,Open Any,Save"), "set_mode", "get_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "file_mode", PROPERTY_HINT_ENUM, "Open File,Open Files,Open Folder,Open Any,Save"), "set_file_mode", "get_file_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"), "set_access", "get_access"); ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "filters"), "set_filters", "get_filters"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_hidden_files"), "set_show_hidden_files", "is_showing_hidden_files"); @@ -854,11 +858,11 @@ void FileDialog::_bind_methods() { ADD_SIGNAL(MethodInfo("files_selected", PropertyInfo(Variant::PACKED_STRING_ARRAY, "paths"))); ADD_SIGNAL(MethodInfo("dir_selected", PropertyInfo(Variant::STRING, "dir"))); - BIND_ENUM_CONSTANT(MODE_OPEN_FILE); - BIND_ENUM_CONSTANT(MODE_OPEN_FILES); - BIND_ENUM_CONSTANT(MODE_OPEN_DIR); - BIND_ENUM_CONSTANT(MODE_OPEN_ANY); - BIND_ENUM_CONSTANT(MODE_SAVE_FILE); + BIND_ENUM_CONSTANT(FILE_MODE_OPEN_FILE); + BIND_ENUM_CONSTANT(FILE_MODE_OPEN_FILES); + BIND_ENUM_CONSTANT(FILE_MODE_OPEN_DIR); + BIND_ENUM_CONSTANT(FILE_MODE_OPEN_ANY); + BIND_ENUM_CONSTANT(FILE_MODE_SAVE_FILE); BIND_ENUM_CONSTANT(ACCESS_RESOURCES); BIND_ENUM_CONSTANT(ACCESS_USERDATA); @@ -884,10 +888,11 @@ FileDialog::FileDialog() { mode_overrides_title = true; - VBoxContainer *vbc = memnew(VBoxContainer); + vbc = memnew(VBoxContainer); add_child(vbc); + vbc->connect("theme_changed", callable_mp(this, &FileDialog::_theme_changed)); - mode = MODE_SAVE_FILE; + mode = FILE_MODE_SAVE_FILE; set_title(RTR("Save a File")); HBoxContainer *hbc = memnew(HBoxContainer); @@ -907,7 +912,7 @@ FileDialog::FileDialog() { dir = memnew(LineEdit); hbc->add_child(dir); - dir->set_h_size_flags(SIZE_EXPAND_FILL); + dir->set_h_size_flags(Control::SIZE_EXPAND_FILL); refresh = memnew(ToolButton); refresh->set_tooltip(RTR("Refresh files.")); @@ -938,11 +943,11 @@ FileDialog::FileDialog() { file_box->add_child(memnew(Label(RTR("File:")))); file = memnew(LineEdit); file->set_stretch_ratio(4); - file->set_h_size_flags(SIZE_EXPAND_FILL); + file->set_h_size_flags(Control::SIZE_EXPAND_FILL); file_box->add_child(file); filter = memnew(OptionButton); filter->set_stretch_ratio(3); - filter->set_h_size_flags(SIZE_EXPAND_FILL); + filter->set_h_size_flags(Control::SIZE_EXPAND_FILL); filter->set_clip_text(true); // too many extensions overflows it file_box->add_child(filter); vbc->add_child(file_box); @@ -961,7 +966,7 @@ FileDialog::FileDialog() { filter->connect("item_selected", callable_mp(this, &FileDialog::_filter_selected)); confirm_save = memnew(ConfirmationDialog); - confirm_save->set_as_toplevel(true); + // confirm_save->set_as_toplevel(true); add_child(confirm_save); confirm_save->connect("confirmed", callable_mp(this, &FileDialog::_save_confirm_pressed)); @@ -1024,7 +1029,7 @@ LineEditFileChooser::LineEditFileChooser() { line_edit = memnew(LineEdit); add_child(line_edit); - line_edit->set_h_size_flags(SIZE_EXPAND_FILL); + line_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL); button = memnew(Button); button->set_text(" .. "); add_child(button); diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index a7dc101d12..295ae023d1 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -50,12 +50,12 @@ public: ACCESS_FILESYSTEM }; - enum Mode { - MODE_OPEN_FILE, - MODE_OPEN_FILES, - MODE_OPEN_DIR, - MODE_OPEN_ANY, - MODE_SAVE_FILE + enum FileMode { + FILE_MODE_OPEN_FILE, + FILE_MODE_OPEN_FILES, + FILE_MODE_OPEN_DIR, + FILE_MODE_OPEN_ANY, + FILE_MODE_SAVE_FILE }; typedef Ref<Texture2D> (*GetIconFunc)(const String &); @@ -70,11 +70,12 @@ private: ConfirmationDialog *makedialog; LineEdit *makedirname; + VBoxContainer *vbc; Button *makedir; Access access; //Button *action; VBoxContainer *vbox; - Mode mode; + FileMode mode; LineEdit *dir; HBoxContainer *drives_container; HBoxContainer *shortcuts_container; @@ -131,6 +132,8 @@ private: virtual void _post_popup(); protected: + void _theme_changed(); + void _notification(int p_what); static void _bind_methods(); //bind helpers @@ -153,8 +156,8 @@ public: void set_mode_overrides_title(bool p_override); bool is_mode_overriding_title() const; - void set_mode(Mode p_mode); - Mode get_mode() const; + void set_file_mode(FileMode p_mode); + FileMode get_file_mode() const; VBoxContainer *get_vbox(); LineEdit *get_line_edit() { return file; } @@ -196,7 +199,7 @@ public: LineEditFileChooser(); }; -VARIANT_ENUM_CAST(FileDialog::Mode); +VARIANT_ENUM_CAST(FileDialog::FileMode); VARIANT_ENUM_CAST(FileDialog::Access); #endif diff --git a/scene/gui/panel.cpp b/scene/gui/panel.cpp index 0356607071..1957e4f271 100644 --- a/scene/gui/panel.cpp +++ b/scene/gui/panel.cpp @@ -36,11 +36,25 @@ void Panel::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW) { RID ci = get_canvas_item(); - Ref<StyleBox> style = get_stylebox("panel"); + Ref<StyleBox> style = mode == MODE_BACKGROUND ? get_stylebox("panel") : get_stylebox("panel_fg"); style->draw(ci, Rect2(Point2(), get_size())); } } +void Panel::set_mode(Mode p_mode) { + mode = p_mode; + update(); +} +Panel::Mode Panel::get_mode() const { + return mode; +} + +void Panel::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_mode", "mode"), &Panel::set_mode); + ClassDB::bind_method(D_METHOD("get_mode"), &Panel::get_mode); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Background,Foreground"), "set_mode", "get_mode"); +} Panel::Panel() { // Has visible stylebox, so stop by default. set_mouse_filter(MOUSE_FILTER_STOP); diff --git a/scene/gui/panel.h b/scene/gui/panel.h index 3538126d22..739c64c0a6 100644 --- a/scene/gui/panel.h +++ b/scene/gui/panel.h @@ -37,12 +37,26 @@ class Panel : public Control { GDCLASS(Panel, Control); +public: + enum Mode { + MODE_BACKGROUND, + MODE_FOREGROUND + }; + +private: + Mode mode = MODE_BACKGROUND; + protected: void _notification(int p_what); + static void _bind_methods(); public: + void set_mode(Mode p_mode); + Mode get_mode() const; + Panel(); ~Panel(); }; +VARIANT_ENUM_CAST(Panel::Mode) #endif diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index 64ef4a01f6..6896d5d609 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -132,17 +132,17 @@ void Popup::popup_centered_clamped(const Size2 &p_size, float p_fallback_ratio) popup_size.x = MIN(window_size.x * p_fallback_ratio, popup_size.x); popup_size.y = MIN(window_size.y * p_fallback_ratio, popup_size.y); - popup_centered(popup_size); + popup_centered_size(popup_size); } void Popup::popup_centered_minsize(const Size2 &p_minsize) { set_custom_minimum_size(p_minsize); _fix_size(); - popup_centered(); + popup_centered_size(); } -void Popup::popup_centered(const Size2 &p_size) { +void Popup::popup_centered_size(const Size2 &p_size) { Rect2 rect; Size2 window_size = get_viewport_rect().size; @@ -208,7 +208,7 @@ bool Popup::is_exclusive() const { void Popup::_bind_methods() { ClassDB::bind_method(D_METHOD("set_as_minsize"), &Popup::set_as_minsize); - ClassDB::bind_method(D_METHOD("popup_centered", "size"), &Popup::popup_centered, DEFVAL(Size2())); + ClassDB::bind_method(D_METHOD("popup_centered_size", "size"), &Popup::popup_centered_size, DEFVAL(Size2())); ClassDB::bind_method(D_METHOD("popup_centered_ratio", "ratio"), &Popup::popup_centered_ratio, DEFVAL(0.75)); ClassDB::bind_method(D_METHOD("popup_centered_minsize", "minsize"), &Popup::popup_centered_minsize, DEFVAL(Size2())); ClassDB::bind_method(D_METHOD("popup_centered_clamped", "size", "fallback_ratio"), &Popup::popup_centered_clamped, DEFVAL(Size2()), DEFVAL(0.75)); diff --git a/scene/gui/popup.h b/scene/gui/popup.h index ff472170b3..fc4158d41c 100644 --- a/scene/gui/popup.h +++ b/scene/gui/popup.h @@ -61,7 +61,7 @@ public: bool is_exclusive() const; void popup_centered_ratio(float p_screen_ratio = 0.75); - void popup_centered(const Size2 &p_size = Size2()); + void popup_centered_size(const Size2 &p_size = Size2()); void popup_centered_minsize(const Size2 &p_minsize = Size2()); void set_as_minsize(); void popup_centered_clamped(const Size2 &p_size = Size2(), float p_fallback_ratio = 0.75); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 578645a676..b882b9ead6 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2952,6 +2952,7 @@ void Node::_bind_methods() { BIND_CONSTANT(NOTIFICATION_WM_FOCUS_OUT); BIND_CONSTANT(NOTIFICATION_WM_CLOSE_REQUEST); BIND_CONSTANT(NOTIFICATION_WM_GO_BACK_REQUEST); + BIND_CONSTANT(NOTIFICATION_WM_SIZE_CHANGED); BIND_CONSTANT(NOTIFICATION_OS_MEMORY_WARNING); BIND_CONSTANT(NOTIFICATION_TRANSLATION_CHANGED); BIND_CONSTANT(NOTIFICATION_WM_ABOUT); diff --git a/scene/main/node.h b/scene/main/node.h index 1b61da9fb1..981477a159 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -251,6 +251,7 @@ public: NOTIFICATION_WM_FOCUS_OUT = 1005, NOTIFICATION_WM_CLOSE_REQUEST = 1006, NOTIFICATION_WM_GO_BACK_REQUEST = 1007, + NOTIFICATION_WM_SIZE_CHANGED = 1008, NOTIFICATION_OS_MEMORY_WARNING = MainLoop::NOTIFICATION_OS_MEMORY_WARNING, NOTIFICATION_TRANSLATION_CHANGED = MainLoop::NOTIFICATION_TRANSLATION_CHANGED, diff --git a/scene/main/window.cpp b/scene/main/window.cpp index b1f2f0cc97..61817f086c 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -32,8 +32,9 @@ #include "core/debugger/engine_debugger.h" #include "core/os/keyboard.h" +#include "scene/gui/control.h" #include "scene/resources/dynamic_font.h" - +#include "scene/scene_string_names.h" void Window::set_title(const String &p_title) { title = p_title; if (window_id == DisplayServer::INVALID_WINDOW_ID) @@ -73,7 +74,7 @@ Point2i Window::get_position() const { void Window::set_size(const Size2i &p_size) { size = p_size; - if (window_id == DisplayServer::INVALID_WINDOW_ID) { + if (window_id != DisplayServer::INVALID_WINDOW_ID) { DisplayServer::get_singleton()->window_set_size(p_size, window_id); } _update_size(); @@ -255,12 +256,14 @@ void Window::_clear_window() { } _update_from_window(); + print_line("deleting window bye"); DisplayServer::get_singleton()->delete_sub_window(window_id); window_id = DisplayServer::INVALID_WINDOW_ID; _update_size(); } void Window::_resize_callback(const Size2i &p_callback) { + size = p_callback; _update_size(); } @@ -289,14 +292,20 @@ void Window::_event_callback(DisplayServer::WindowEvent p_event) { emit_signal("mouse_exited"); } break; case DisplayServer::WINDOW_EVENT_FOCUS_IN: { + focused = true; _propagate_window_notification(this, NOTIFICATION_WM_FOCUS_IN); emit_signal("focus_entered"); + } break; case DisplayServer::WINDOW_EVENT_FOCUS_OUT: { + focused = false; _propagate_window_notification(this, NOTIFICATION_WM_FOCUS_OUT); emit_signal("focus_exited"); } break; case DisplayServer::WINDOW_EVENT_CLOSE_REQUEST: { + if (exclusive_child != nullptr) { + break; //has an exclusive child, can't get events until child is closed + } _propagate_window_notification(this, NOTIFICATION_WM_CLOSE_REQUEST); emit_signal("close_requested"); } break; @@ -307,29 +316,46 @@ void Window::_event_callback(DisplayServer::WindowEvent p_event) { } } +void Window::show() { + set_visible(true); +} +void Window::hide() { + set_visible(false); +} + void Window::set_visible(bool p_visible) { + if (visible == p_visible) { return; } + visible = p_visible; + if (!is_inside_tree()) { return; } - bool subwindow = get_parent() && get_parent()->get_viewport()->is_embedding_subwindows(); + ERR_FAIL_COND_MSG(get_parent() == nullptr, "Can't change visibility of main window."); - visible = p_visible; + bool subwindow = get_parent() && get_parent()->get_viewport()->is_embedding_subwindows(); if (!subwindow) { - if (p_visible && window_id != DisplayServer::INVALID_WINDOW_ID) { + if (!p_visible && window_id != DisplayServer::INVALID_WINDOW_ID) { _clear_window(); } - if (!p_visible && window_id == DisplayServer::INVALID_WINDOW_ID) { + if (p_visible && window_id == DisplayServer::INVALID_WINDOW_ID) { _make_window(); + _update_window_callbacks(); } } else { _update_size(); } + + if (!visible) { + focused = false; + } + notification(NOTIFICATION_VISIBILITY_CHANGED); + emit_signal(SceneStringNames::get_singleton()->visibility_changed); } void Window::_clear_transient() { @@ -338,6 +364,9 @@ void Window::_clear_transient() { DisplayServer::get_singleton()->window_set_transient(window_id, DisplayServer::INVALID_WINDOW_ID); } transient_parent->transient_children.erase(this); + if (transient_parent->exclusive_child == this) { + transient_parent->exclusive_child = nullptr; + } transient_parent = nullptr; } } @@ -365,6 +394,13 @@ void Window::_make_transient() { if (window) { transient_parent = window; window->transient_children.insert(this); + if (exclusive) { + if (transient_parent->exclusive_child == nullptr) { + transient_parent->exclusive_child = this; + } else if (transient_parent->exclusive_child != this) { + ERR_PRINT("Making child transient exclusive, but parent has another exclusive child"); + } + } } //see if we can make transient @@ -394,6 +430,30 @@ bool Window::is_transient() const { return transient; } +void Window::set_exclusive(bool p_exclusive) { + + if (exclusive == p_exclusive) { + return; + } + + exclusive = p_exclusive; + + if (transient_parent) { + if (p_exclusive) { + ERR_FAIL_COND_MSG(transient_parent->exclusive_child && transient_parent->exclusive_child != this, "Transient parent has another exclusive child."); + transient_parent->exclusive_child = nullptr; + } else { + if (transient_parent->exclusive_child == this) { + transient_parent->exclusive_child = nullptr; + } + } + } +} + +bool Window::is_exclusive() const { + return exclusive; +} + bool Window::is_visible() const { return visible; } @@ -524,6 +584,8 @@ void Window::_update_size() { DynamicFont::update_oversampling(); } } + + notification(NOTIFICATION_WM_SIZE_CHANGED); } void Window::_update_window_callbacks() { @@ -541,20 +603,34 @@ void Window::_notification(int p_what) { } else { if (get_parent() == nullptr) { //it's the root window! + visible = true; //always visible window_id = DisplayServer::MAIN_WINDOW_ID; _update_from_window(); _update_size(); _update_window_callbacks(); } else { //create - _make_window(); - _update_window_callbacks(); + if (visible) { + _make_window(); + _update_window_callbacks(); + } } } if (transient) { _make_transient(); } + if (visible) { + notification(NOTIFICATION_VISIBILITY_CHANGED); + emit_signal(SceneStringNames::get_singleton()->visibility_changed); + } + } + + if (p_what == NOTIFICATION_READY) { + + if (wrap_controls) { + _update_child_controls(); + } } if (p_what == NOTIFICATION_EXIT_TREE) { @@ -572,7 +648,7 @@ void Window::_notification(int p_what) { _clear_window(); } } else { - _update_size(); + _update_size(); //called by clear and make, which does not happen here } } } @@ -619,6 +695,58 @@ DisplayServer::WindowID Window::get_window_id() const { return window_id; } +void Window::set_wrap_controls(bool p_enable) { + wrap_controls = p_enable; + if (wrap_controls) { + child_controls_changed(); + } +} + +bool Window::is_wrapping_controls() const { + return wrap_controls; +} + +Size2 Window::_get_contents_minimum_size() const { + Size2 max; + + for (int i = 0; i < get_child_count(); i++) { + Control *c = Object::cast_to<Control>(get_child(i)); + if (c) { + Point2i pos = c->get_position(); + Size2i min = c->get_combined_minimum_size(); + + max.x = MAX(pos.x + min.x, max.x); + max.y = MAX(pos.y + min.y, max.y); + } + } + + return max; +} +void Window::_update_child_controls() { + + Size2 max = _get_contents_minimum_size(); + + Size2 new_size(MAX(max.x, size.x), MAX(max.y, size.y)); + + if (new_size != size) { + set_size(new_size); + } + set_min_size(max); + updating_child_controls = false; +} +void Window::child_controls_changed() { + if (!is_inside_tree()) { + return; + } + + if (updating_child_controls) { + return; + } + + updating_child_controls = true; + call_deferred("_update_child_controls"); +} + void Window::_window_input(const Ref<InputEvent> &p_ev) { if (Engine::get_singleton()->is_editor_hint() && (Object::cast_to<InputEventJoypadButton>(p_ev.ptr()) || Object::cast_to<InputEventJoypadMotion>(*p_ev))) @@ -632,6 +760,11 @@ void Window::_window_input(const Ref<InputEvent> &p_ev) { } } + if (exclusive_child != nullptr) { + exclusive_child->grab_focus(); + return; //has an exclusive child, can't get events until child is closed + } + emit_signal(SceneStringNames::get_singleton()->window_input, p_ev); input(p_ev); if (!is_input_handled()) { unhandled_input(p_ev); @@ -644,6 +777,208 @@ void Window::_window_drop_files(const Vector<String> &p_files) { emit_signal("files_dropped", p_files); } +Viewport *Window::get_parent_viewport() const { + + if (get_parent()) { + return get_parent()->get_viewport(); + } else { + return nullptr; + } +} + +Window *Window::get_parent_visible_window() const { + + Viewport *vp = get_parent_viewport(); + Window *window = nullptr; + while (vp) { + window = Object::cast_to<Window>(vp); + if (window && window->visible) { + break; + } + if (!vp->get_parent()) { + break; + } + + vp = vp->get_parent()->get_viewport(); + } + return window; +} + +void Window::popup_on_parent(const Rect2 &p_parent_rect) { + + ERR_FAIL_COND(!is_inside_tree()); + ERR_FAIL_COND_MSG(window_id == DisplayServer::MAIN_WINDOW_ID, "Can't popup the main window."); + + if (!is_embedded()) { + Window *window = get_parent_visible_window(); + + if (!window) { + popup(p_parent_rect); + } else { + popup(Rect2(window->get_position() + p_parent_rect.position, p_parent_rect.size)); + } + } else { + popup(p_parent_rect); + } +} + +void Window::popup_centered_clamped(const Size2 &p_size, float p_fallback_ratio) { + + ERR_FAIL_COND(!is_inside_tree()); + ERR_FAIL_COND_MSG(window_id == DisplayServer::MAIN_WINDOW_ID, "Can't popup the main window."); + + Rect2 parent_rect; + + if (is_embedded()) { + parent_rect = get_parent_viewport()->get_visible_rect(); + } else { + DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id(); + int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id); + parent_rect.position = DisplayServer::get_singleton()->screen_get_position(parent_screen); + parent_rect.size = DisplayServer::get_singleton()->screen_get_size(parent_screen); + } + + Vector2 size_ratio = parent_rect.size * p_fallback_ratio; + + Rect2 popup_rect; + popup_rect.size = Vector2(MIN(size_ratio.x, p_size.x), MIN(size_ratio.y, p_size.y)); + popup_rect.position = (parent_rect.size - popup_rect.size) / 2; + + popup(popup_rect); +} + +void Window::popup_centered(const Size2 &p_minsize) { + ERR_FAIL_COND(!is_inside_tree()); + ERR_FAIL_COND_MSG(window_id == DisplayServer::MAIN_WINDOW_ID, "Can't popup the main window."); + + Rect2 parent_rect; + + if (is_embedded()) { + parent_rect = get_parent_viewport()->get_visible_rect(); + } else { + DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id(); + int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id); + parent_rect.position = DisplayServer::get_singleton()->screen_get_position(parent_screen); + parent_rect.size = DisplayServer::get_singleton()->screen_get_size(parent_screen); + } + + Rect2 popup_rect; + if (p_minsize == Size2()) { + popup_rect.size = _get_contents_minimum_size(); + } else { + popup_rect.size = p_minsize; + } + popup_rect.position = (parent_rect.size - popup_rect.size) / 2; + + popup(popup_rect); +} + +void Window::popup_centered_ratio(float p_ratio) { + + ERR_FAIL_COND(!is_inside_tree()); + ERR_FAIL_COND_MSG(window_id == DisplayServer::MAIN_WINDOW_ID, "Can't popup the main window."); + + Rect2 parent_rect; + + if (is_embedded()) { + parent_rect = get_parent_viewport()->get_visible_rect(); + } else { + DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id(); + int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id); + parent_rect.position = DisplayServer::get_singleton()->screen_get_position(parent_screen); + parent_rect.size = DisplayServer::get_singleton()->screen_get_size(parent_screen); + } + + Rect2 popup_rect; + popup_rect.size = parent_rect.size * p_ratio; + popup_rect.position = (parent_rect.size - popup_rect.size) / 2; + + popup(popup_rect); +} + +void Window::popup(const Rect2 &p_screen_rect) { + if (p_screen_rect != Rect2()) { + set_position(p_screen_rect.position); + set_size(p_screen_rect.size); + } + + set_transient(true); + set_visible(true); + _post_popup(); + notification(NOTIFICATION_POST_POPUP); +} + +void Window::grab_focus() { + if (window_id != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_move_to_foreground(window_id); + } +} + +bool Window::has_focus() const { + return focused; +} + +void Window::add_child_notify(Node *p_child) { + + Control *child_c = Object::cast_to<Control>(p_child); + + if (child_c && child_c->data.theme.is_null() && (theme_owner || theme_owner_window)) { + Control::_propagate_theme_changed(child_c, theme_owner, theme_owner_window); //need to propagate here, since many controls may require setting up stuff + } + + Window *child_w = Object::cast_to<Window>(p_child); + + if (child_w && child_w->theme.is_null() && (theme_owner || theme_owner_window)) { + Control::_propagate_theme_changed(child_w, theme_owner, theme_owner_window); //need to propagate here, since many controls may require setting up stuff + } +} + +void Window::remove_child_notify(Node *p_child) { + + Control *child_c = Object::cast_to<Control>(p_child); + + if (child_c && (child_c->data.theme_owner || child_c->data.theme_owner_window) && child_c->data.theme.is_null()) { + Control::_propagate_theme_changed(child_c, NULL, NULL); + } + + Window *child_w = Object::cast_to<Window>(p_child); + + if (child_w && (child_w->theme_owner || child_w->theme_owner_window) && child_w->theme.is_null()) { + Control::_propagate_theme_changed(child_w, NULL, NULL); + } +} + +void Window::set_theme(const Ref<Theme> &p_theme) { + + if (theme == p_theme) + return; + + theme = p_theme; + + if (!p_theme.is_null()) { + + theme_owner = nullptr; + theme_owner_window = this; + Control::_propagate_theme_changed(this, nullptr, this); + } else { + + Control *parent_c = cast_to<Control>(get_parent()); + if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) { + Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window); + } else { + Window *parent_w = cast_to<Window>(get_parent()); + if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) { + Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window); + } else { + Control::_propagate_theme_changed(this, nullptr, nullptr); + } + } + } +} +Ref<Theme> Window::get_theme() const { + return theme; +} + void Window::_bind_methods() { ClassDB::bind_method(D_METHOD("set_title", "title"), &Window::set_title); @@ -681,10 +1016,18 @@ void Window::_bind_methods() { ClassDB::bind_method(D_METHOD("set_visible", "visible"), &Window::set_visible); ClassDB::bind_method(D_METHOD("is_visible"), &Window::is_visible); + ClassDB::bind_method(D_METHOD("hide"), &Window::hide); + ClassDB::bind_method(D_METHOD("show"), &Window::show); + ClassDB::bind_method(D_METHOD("set_transient", "transient"), &Window::set_transient); ClassDB::bind_method(D_METHOD("is_transient"), &Window::is_transient); + 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("can_draw"), &Window::is_transient); + ClassDB::bind_method(D_METHOD("has_focus"), &Window::has_focus); + ClassDB::bind_method(D_METHOD("grab_focus"), &Window::grab_focus); ClassDB::bind_method(D_METHOD("set_ime_active"), &Window::set_ime_active); ClassDB::bind_method(D_METHOD("set_ime_position"), &Window::set_ime_position); @@ -703,6 +1046,15 @@ void Window::_bind_methods() { ClassDB::bind_method(D_METHOD("set_use_font_oversampling", "enable"), &Window::set_use_font_oversampling); ClassDB::bind_method(D_METHOD("is_using_font_oversampling"), &Window::is_using_font_oversampling); + ClassDB::bind_method(D_METHOD("set_wrap_controls", "enable"), &Window::set_wrap_controls); + ClassDB::bind_method(D_METHOD("is_wrapping_controls"), &Window::is_wrapping_controls); + ClassDB::bind_method(D_METHOD("child_controls_changed"), &Window::child_controls_changed); + + ClassDB::bind_method(D_METHOD("_update_child_controls"), &Window::_update_child_controls); + + ClassDB::bind_method(D_METHOD("set_theme", "theme"), &Window::set_theme); + ClassDB::bind_method(D_METHOD("get_theme"), &Window::get_theme); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "position"), "set_position", "get_position"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size"), "set_size", "get_size"); @@ -710,7 +1062,9 @@ void Window::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_screen"), "set_current_screen", "get_current_screen"); ADD_GROUP("Flags", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "wrap_controls"), "set_wrap_controls", "is_wrapping_controls"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "transient"), "set_transient", "is_transient"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclusive"), "set_exclusive", "is_exclusive"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "unresizable"), "set_flag", "get_flag", FLAG_RESIZE_DISABLED); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "borderless"), "set_flag", "get_flag", FLAG_BORDERLESS); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "always_on_top"), "set_flag", "get_flag", FLAG_ALWAYS_ON_TOP); @@ -722,7 +1076,10 @@ void Window::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "content_scale_size"), "set_content_scale_size", "get_content_scale_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_mode", PROPERTY_HINT_ENUM, "Disabled,Object,Pixels"), "set_content_scale_mode", "get_content_scale_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_aspect", PROPERTY_HINT_ENUM, "Ignore,Keep,KeepWidth,KeepHeight,Expand"), "set_content_scale_aspect", "get_content_scale_aspect"); + ADD_GROUP("Theme", ""); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme"); + ADD_SIGNAL(MethodInfo("window_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); ADD_SIGNAL(MethodInfo("files_dropped")); ADD_SIGNAL(MethodInfo("mouse_entered")); ADD_SIGNAL(MethodInfo("mouse_exited")); @@ -730,6 +1087,9 @@ void Window::_bind_methods() { ADD_SIGNAL(MethodInfo("focus_exited")); ADD_SIGNAL(MethodInfo("close_requested")); ADD_SIGNAL(MethodInfo("go_back_requested")); + ADD_SIGNAL(MethodInfo("visibility_changed")); + + BIND_CONSTANT(NOTIFICATION_VISIBILITY_CHANGED); } Window::Window() { diff --git a/scene/main/window.h b/scene/main/window.h index 795e415396..acc3e11fdc 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -32,8 +32,10 @@ #define WINDOW_H #include "scene/main/viewport.h" +#include "scene/resources/theme.h" #include "servers/display_server.h" +class Control; class Window : public Viewport { GDCLASS(Window, Viewport) public: @@ -83,9 +85,15 @@ private: mutable Mode mode = MODE_WINDOWED; mutable bool flags[FLAG_MAX]; bool visible = true; + bool focused = false; bool use_font_oversampling = false; bool transient = false; + bool exclusive = false; + bool wrap_controls = false; + bool updating_child_controls = false; + + void _update_child_controls(); Size2i content_scale_size; ContentScaleMode content_scale_mode; @@ -114,13 +122,31 @@ private: void _clear_transient(); void _make_transient(); Window *transient_parent = nullptr; + Window *exclusive_child = nullptr; Set<Window *> transient_children; + friend class Control; + Ref<Theme> theme; + Control *theme_owner = nullptr; + Window *theme_owner_window = nullptr; + protected: + virtual void _post_popup() {} + virtual Size2 _get_contents_minimum_size() const; static void _bind_methods(); void _notification(int p_what); + virtual void add_child_notify(Node *p_child); + virtual void remove_child_notify(Node *p_child); + public: + enum { + + NOTIFICATION_VISIBILITY_CHANGED = 30, + NOTIFICATION_POST_POPUP = 31, + NOTIFICATION_THEME_CHANGED = 32, + }; + void set_title(const String &p_title); String get_title() const; @@ -155,9 +181,15 @@ public: void set_visible(bool p_visible); bool is_visible() const; + void show(); + void hide(); + void set_transient(bool p_transient); bool is_transient() const; + void set_exclusive(bool p_exclusive); + bool is_exclusive() const; + bool can_draw() const; void set_ime_active(bool p_active); @@ -176,6 +208,25 @@ public: void set_use_font_oversampling(bool p_oversampling); bool is_using_font_oversampling() const; + + void set_wrap_controls(bool p_enable); + bool is_wrapping_controls() const; + void child_controls_changed(); + + Window *get_parent_visible_window() const; + Viewport *get_parent_viewport() const; + void popup(const Rect2 &p_rect = Rect2()); + void popup_on_parent(const Rect2 &p_parent_rect); + void popup_centered_ratio(float p_ratio = 0.8); + void popup_centered(const Size2 &p_minsize = Size2()); + void popup_centered_clamped(const Size2 &p_size = Size2(), float p_fallback_ratio = 0.75); + + void set_theme(const Ref<Theme> &p_theme); + Ref<Theme> get_theme() const; + + void grab_focus(); + bool has_focus() const; + Window(); ~Window(); }; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 8c4bff16a0..41c43a586b 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -350,8 +350,7 @@ void register_scene_types() { ClassDB::register_class<RichTextLabel>(); ClassDB::register_class<RichTextEffect>(); ClassDB::register_class<CharFXTransform>(); - ClassDB::register_class<PopupDialog>(); - ClassDB::register_class<WindowDialog>(); + ; ClassDB::register_class<AcceptDialog>(); ClassDB::register_class<ConfirmationDialog>(); ClassDB::register_class<MarginContainer>(); diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 9f5b49c4c3..2449f1adf0 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -188,6 +188,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // Panel theme->set_stylebox("panel", "Panel", make_stylebox(panel_bg_png, 0, 0, 0, 0)); + theme->set_stylebox("panel_fg", "Panel", make_stylebox(panel_bg_png, 0, 0, 0, 0)); // Focus @@ -523,17 +524,18 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // WindowDialog - theme->set_stylebox("panel", "WindowDialog", sb_expand(make_stylebox(popup_window_png, 10, 26, 10, 8), 8, 24, 8, 6)); - theme->set_constant("scaleborder_size", "WindowDialog", 4 * scale); + theme->set_stylebox("panel", "AcceptDialog", default_style); + theme->set_stylebox("window_panel", "AcceptDialog", sb_expand(make_stylebox(popup_window_png, 10, 26, 10, 8), 8, 24, 8, 6)); + theme->set_constant("scaleborder_size", "AcceptDialog", 4 * scale); - theme->set_font("title_font", "WindowDialog", large_font); - theme->set_color("title_color", "WindowDialog", Color(0, 0, 0)); - theme->set_constant("title_height", "WindowDialog", 20 * scale); + theme->set_font("title_font", "AcceptDialog", large_font); + theme->set_color("title_color", "AcceptDialog", Color(0, 0, 0)); + theme->set_constant("title_height", "AcceptDialog", 20 * scale); - theme->set_icon("close", "WindowDialog", make_icon(close_png)); - theme->set_icon("close_highlight", "WindowDialog", make_icon(close_hl_png)); - theme->set_constant("close_h_ofs", "WindowDialog", 18 * scale); - theme->set_constant("close_v_ofs", "WindowDialog", 18 * scale); + theme->set_icon("close", "AcceptDialog", make_icon(close_png)); + theme->set_icon("close_highlight", "AcceptDialog", make_icon(close_hl_png)); + theme->set_constant("close_h_ofs", "AcceptDialog", 18 * scale); + theme->set_constant("close_v_ofs", "AcceptDialog", 18 * scale); // File Dialog diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp index 443817b3eb..1f0365dab9 100644 --- a/scene/scene_string_names.cpp +++ b/scene/scene_string_names.cpp @@ -195,8 +195,10 @@ SceneStringNames::SceneStringNames() { _window_group = StaticCString::create("_window_group"); _window_input = StaticCString::create("_window_input"); + window_input = StaticCString::create("window_input"); _window_unhandled_input = StaticCString::create("_window_unhandled_input"); + theme_changed = StaticCString::create("theme_changed"); parameters_base_path = "parameters/"; tracks_changed = "tracks_changed"; diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h index d7cef5449a..e255ebb3cb 100644 --- a/scene/scene_string_names.h +++ b/scene/scene_string_names.h @@ -204,6 +204,9 @@ public: StringName _window_group; StringName _window_input; StringName _window_unhandled_input; + StringName window_input; + + StringName theme_changed; enum { MAX_MATERIALS = 32 |