summaryrefslogtreecommitdiffstats
path: root/scene/gui
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui')
-rw-r--r--scene/gui/base_button.cpp9
-rw-r--r--scene/gui/box_container.cpp4
-rw-r--r--scene/gui/button.cpp117
-rw-r--r--scene/gui/button.h12
-rw-r--r--scene/gui/check_box.cpp8
-rw-r--r--scene/gui/check_button.cpp8
-rw-r--r--scene/gui/code_edit.cpp2
-rw-r--r--scene/gui/color_picker.cpp50
-rw-r--r--scene/gui/container.cpp18
-rw-r--r--scene/gui/control.cpp41
-rw-r--r--scene/gui/dialogs.cpp44
-rw-r--r--scene/gui/dialogs.h2
-rw-r--r--scene/gui/file_dialog.cpp11
-rw-r--r--scene/gui/graph_edit.cpp85
-rw-r--r--scene/gui/graph_edit.h2
-rw-r--r--scene/gui/graph_node.cpp13
-rw-r--r--scene/gui/graph_node.h5
-rw-r--r--scene/gui/item_list.cpp3
-rw-r--r--scene/gui/line_edit.cpp4
-rw-r--r--scene/gui/margin_container.cpp4
-rw-r--r--scene/gui/menu_button.cpp1
-rw-r--r--scene/gui/nine_patch_rect.cpp3
-rw-r--r--scene/gui/option_button.cpp3
-rw-r--r--scene/gui/popup.cpp20
-rw-r--r--scene/gui/popup_menu.cpp10
-rw-r--r--scene/gui/range.cpp2
-rw-r--r--scene/gui/rich_text_label.cpp31
-rw-r--r--scene/gui/scroll_bar.cpp18
-rw-r--r--scene/gui/spin_box.cpp6
-rw-r--r--scene/gui/split_container.cpp22
-rw-r--r--scene/gui/split_container.h3
-rw-r--r--scene/gui/subviewport_container.cpp2
-rw-r--r--scene/gui/tab_bar.cpp3
-rw-r--r--scene/gui/tab_container.cpp6
-rw-r--r--scene/gui/text_edit.cpp139
-rw-r--r--scene/gui/texture_button.cpp31
-rw-r--r--scene/gui/tree.cpp28
-rw-r--r--scene/gui/tree.h1
-rw-r--r--scene/gui/video_stream_player.cpp5
39 files changed, 487 insertions, 289 deletions
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 66b14dc967..01e3cce78b 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -33,7 +33,6 @@
#include "core/config/project_settings.h"
#include "core/os/keyboard.h"
#include "scene/main/window.h"
-#include "scene/scene_string_names.h"
void BaseButton::_unpress_group() {
if (!button_group.is_valid()) {
@@ -135,7 +134,7 @@ void BaseButton::_notification(int p_what) {
void BaseButton::_pressed() {
GDVIRTUAL_CALL(_pressed);
pressed();
- emit_signal(SNAME("pressed"));
+ emit_signal(SceneStringName(pressed));
}
void BaseButton::_toggled(bool p_pressed) {
@@ -162,7 +161,7 @@ void BaseButton::on_action_event(Ref<InputEvent> p_event) {
status.pressed = !status.pressed;
_unpress_group();
if (button_group.is_valid()) {
- button_group->emit_signal(SNAME("pressed"), this);
+ button_group->emit_signal(SceneStringName(pressed), this);
}
_toggled(status.pressed);
_pressed();
@@ -226,7 +225,7 @@ void BaseButton::set_pressed(bool p_pressed) {
if (p_pressed) {
_unpress_group();
if (button_group.is_valid()) {
- button_group->emit_signal(SNAME("pressed"), this);
+ button_group->emit_signal(SceneStringName(pressed), this);
}
}
_toggled(status.pressed);
@@ -368,7 +367,7 @@ void BaseButton::shortcut_input(const Ref<InputEvent> &p_event) {
_unpress_group();
if (button_group.is_valid()) {
- button_group->emit_signal(SNAME("pressed"), this);
+ button_group->emit_signal(SceneStringName(pressed), this);
}
_toggled(status.pressed);
diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp
index 88f65ca1bc..d8fcbbb883 100644
--- a/scene/gui/box_container.cpp
+++ b/scene/gui/box_container.cpp
@@ -243,8 +243,8 @@ Size2 BoxContainer::get_minimum_size() const {
bool first = true;
for (int i = 0; i < get_child_count(); i++) {
- Control *c = as_sortable_control(get_child(i));
- if (!c) {
+ Control *c = Object::cast_to<Control>(get_child(i));
+ if (!c || !c->is_visible() || c->is_set_as_top_level()) {
continue;
}
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index ad3f607661..3bf9d79c7f 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -50,6 +50,83 @@ void Button::_set_internal_margin(Side p_side, float p_value) {
void Button::_queue_update_size_cache() {
}
+void Button::_update_theme_item_cache() {
+ Control::_update_theme_item_cache();
+
+ const bool rtl = is_layout_rtl();
+ if (rtl && has_theme_stylebox(SNAME("normal_mirrored"))) {
+ theme_cache.max_style_size = theme_cache.normal_mirrored->get_minimum_size();
+ theme_cache.style_margin_left = theme_cache.normal_mirrored->get_margin(SIDE_LEFT);
+ theme_cache.style_margin_right = theme_cache.normal_mirrored->get_margin(SIDE_RIGHT);
+ theme_cache.style_margin_top = theme_cache.normal_mirrored->get_margin(SIDE_TOP);
+ theme_cache.style_margin_bottom = theme_cache.normal_mirrored->get_margin(SIDE_BOTTOM);
+ } else {
+ theme_cache.max_style_size = theme_cache.normal->get_minimum_size();
+ theme_cache.style_margin_left = theme_cache.normal->get_margin(SIDE_LEFT);
+ theme_cache.style_margin_right = theme_cache.normal->get_margin(SIDE_RIGHT);
+ theme_cache.style_margin_top = theme_cache.normal->get_margin(SIDE_TOP);
+ theme_cache.style_margin_bottom = theme_cache.normal->get_margin(SIDE_BOTTOM);
+ }
+ if (has_theme_stylebox("hover_pressed")) {
+ if (rtl && has_theme_stylebox(SNAME("hover_pressed_mirrored"))) {
+ theme_cache.max_style_size = theme_cache.max_style_size.max(theme_cache.hover_pressed_mirrored->get_minimum_size());
+ theme_cache.style_margin_left = MAX(theme_cache.style_margin_left, theme_cache.hover_pressed_mirrored->get_margin(SIDE_LEFT));
+ theme_cache.style_margin_right = MAX(theme_cache.style_margin_right, theme_cache.hover_pressed_mirrored->get_margin(SIDE_RIGHT));
+ theme_cache.style_margin_top = MAX(theme_cache.style_margin_top, theme_cache.hover_pressed_mirrored->get_margin(SIDE_TOP));
+ theme_cache.style_margin_bottom = MAX(theme_cache.style_margin_bottom, theme_cache.hover_pressed_mirrored->get_margin(SIDE_BOTTOM));
+ } else {
+ theme_cache.max_style_size = theme_cache.max_style_size.max(theme_cache.hover_pressed->get_minimum_size());
+ theme_cache.style_margin_left = MAX(theme_cache.style_margin_left, theme_cache.hover_pressed->get_margin(SIDE_LEFT));
+ theme_cache.style_margin_right = MAX(theme_cache.style_margin_right, theme_cache.hover_pressed->get_margin(SIDE_RIGHT));
+ theme_cache.style_margin_top = MAX(theme_cache.style_margin_top, theme_cache.hover_pressed->get_margin(SIDE_TOP));
+ theme_cache.style_margin_bottom = MAX(theme_cache.style_margin_bottom, theme_cache.hover_pressed->get_margin(SIDE_BOTTOM));
+ }
+ }
+ if (rtl && has_theme_stylebox(SNAME("pressed_mirrored"))) {
+ theme_cache.max_style_size = theme_cache.max_style_size.max(theme_cache.pressed_mirrored->get_minimum_size());
+ theme_cache.style_margin_left = MAX(theme_cache.style_margin_left, theme_cache.pressed_mirrored->get_margin(SIDE_LEFT));
+ theme_cache.style_margin_right = MAX(theme_cache.style_margin_right, theme_cache.pressed_mirrored->get_margin(SIDE_RIGHT));
+ theme_cache.style_margin_top = MAX(theme_cache.style_margin_top, theme_cache.pressed_mirrored->get_margin(SIDE_TOP));
+ theme_cache.style_margin_bottom = MAX(theme_cache.style_margin_bottom, theme_cache.pressed_mirrored->get_margin(SIDE_BOTTOM));
+ } else {
+ theme_cache.max_style_size = theme_cache.max_style_size.max(theme_cache.pressed->get_minimum_size());
+ theme_cache.style_margin_left = MAX(theme_cache.style_margin_left, theme_cache.pressed->get_margin(SIDE_LEFT));
+ theme_cache.style_margin_right = MAX(theme_cache.style_margin_right, theme_cache.pressed->get_margin(SIDE_RIGHT));
+ theme_cache.style_margin_top = MAX(theme_cache.style_margin_top, theme_cache.pressed->get_margin(SIDE_TOP));
+ theme_cache.style_margin_bottom = MAX(theme_cache.style_margin_bottom, theme_cache.pressed->get_margin(SIDE_BOTTOM));
+ }
+ if (rtl && has_theme_stylebox(SNAME("hover_mirrored"))) {
+ theme_cache.max_style_size = theme_cache.max_style_size.max(theme_cache.hover_mirrored->get_minimum_size());
+ theme_cache.style_margin_left = MAX(theme_cache.style_margin_left, theme_cache.hover_mirrored->get_margin(SIDE_LEFT));
+ theme_cache.style_margin_right = MAX(theme_cache.style_margin_right, theme_cache.hover_mirrored->get_margin(SIDE_RIGHT));
+ theme_cache.style_margin_top = MAX(theme_cache.style_margin_top, theme_cache.hover_mirrored->get_margin(SIDE_TOP));
+ theme_cache.style_margin_bottom = MAX(theme_cache.style_margin_bottom, theme_cache.hover_mirrored->get_margin(SIDE_BOTTOM));
+ } else {
+ theme_cache.max_style_size = theme_cache.max_style_size.max(theme_cache.hover->get_minimum_size());
+ theme_cache.style_margin_left = MAX(theme_cache.style_margin_left, theme_cache.hover->get_margin(SIDE_LEFT));
+ theme_cache.style_margin_right = MAX(theme_cache.style_margin_right, theme_cache.hover->get_margin(SIDE_RIGHT));
+ theme_cache.style_margin_top = MAX(theme_cache.style_margin_top, theme_cache.hover->get_margin(SIDE_TOP));
+ theme_cache.style_margin_bottom = MAX(theme_cache.style_margin_bottom, theme_cache.hover->get_margin(SIDE_BOTTOM));
+ }
+ if (rtl && has_theme_stylebox(SNAME("disabled_mirrored"))) {
+ theme_cache.max_style_size = theme_cache.max_style_size.max(theme_cache.disabled_mirrored->get_minimum_size());
+ theme_cache.style_margin_left = MAX(theme_cache.style_margin_left, theme_cache.disabled_mirrored->get_margin(SIDE_LEFT));
+ theme_cache.style_margin_right = MAX(theme_cache.style_margin_right, theme_cache.disabled_mirrored->get_margin(SIDE_RIGHT));
+ theme_cache.style_margin_top = MAX(theme_cache.style_margin_top, theme_cache.disabled_mirrored->get_margin(SIDE_TOP));
+ theme_cache.style_margin_bottom = MAX(theme_cache.style_margin_bottom, theme_cache.disabled_mirrored->get_margin(SIDE_BOTTOM));
+ } else {
+ theme_cache.max_style_size = theme_cache.max_style_size.max(theme_cache.disabled->get_minimum_size());
+ theme_cache.style_margin_left = MAX(theme_cache.style_margin_left, theme_cache.disabled->get_margin(SIDE_LEFT));
+ theme_cache.style_margin_right = MAX(theme_cache.style_margin_right, theme_cache.disabled->get_margin(SIDE_RIGHT));
+ theme_cache.style_margin_top = MAX(theme_cache.style_margin_top, theme_cache.disabled->get_margin(SIDE_TOP));
+ theme_cache.style_margin_bottom = MAX(theme_cache.style_margin_bottom, theme_cache.disabled->get_margin(SIDE_BOTTOM));
+ }
+}
+
+Size2 Button::_get_largest_stylebox_size() const {
+ return theme_cache.max_style_size;
+}
+
Ref<StyleBox> Button::_get_current_stylebox() const {
Ref<StyleBox> stylebox = theme_cache.normal;
const bool rtl = is_layout_rtl();
@@ -137,16 +214,13 @@ void Button::_notification(int p_what) {
const RID ci = get_canvas_item();
const Size2 size = get_size();
- const Ref<StyleBox> style = _get_current_stylebox();
- { // Draws the stylebox in the current state.
- if (!flat) {
- style->draw(ci, Rect2(Point2(), size));
- }
+ // Draws the stylebox in the current state.
+ if (!flat) {
+ _get_current_stylebox()->draw(ci, Rect2(Point2(), size));
+ }
- if (has_focus()) {
- Ref<StyleBox> style2 = theme_cache.focus;
- style2->draw(ci, Rect2(Point2(), size));
- }
+ if (has_focus()) {
+ theme_cache.focus->draw(ci, Rect2(Point2(), size));
}
Ref<Texture2D> _icon = icon;
@@ -158,16 +232,11 @@ void Button::_notification(int p_what) {
break;
}
- const float style_margin_left = style->get_margin(SIDE_LEFT);
- const float style_margin_right = style->get_margin(SIDE_RIGHT);
- const float style_margin_top = style->get_margin(SIDE_TOP);
- const float style_margin_bottom = style->get_margin(SIDE_BOTTOM);
-
Size2 drawable_size_remained = size;
{ // The size after the stelybox is stripped.
- drawable_size_remained.width -= style_margin_left + style_margin_right;
- drawable_size_remained.height -= style_margin_top + style_margin_bottom;
+ drawable_size_remained.width -= theme_cache.style_margin_left + theme_cache.style_margin_right;
+ drawable_size_remained.height -= theme_cache.style_margin_top + theme_cache.style_margin_bottom;
}
const int h_separation = MAX(0, theme_cache.h_separation);
@@ -298,6 +367,7 @@ void Button::_notification(int p_what) {
icon_size = Size2(icon_width, icon_height);
}
icon_size = _fit_icon_size(icon_size);
+ icon_size = icon_size.round();
}
if (icon_size.width > 0.0f) {
@@ -311,12 +381,12 @@ void Button::_notification(int p_what) {
[[fallthrough]];
case HORIZONTAL_ALIGNMENT_FILL:
case HORIZONTAL_ALIGNMENT_LEFT: {
- icon_ofs.x += style_margin_left;
+ icon_ofs.x += theme_cache.style_margin_left;
icon_ofs.x += left_internal_margin_with_h_separation;
} break;
case HORIZONTAL_ALIGNMENT_RIGHT: {
- icon_ofs.x = size.x - style_margin_right;
+ icon_ofs.x = size.x - theme_cache.style_margin_right;
icon_ofs.x -= right_internal_margin_with_h_separation;
icon_ofs.x -= icon_size.width;
} break;
@@ -329,13 +399,14 @@ void Button::_notification(int p_what) {
[[fallthrough]];
case VERTICAL_ALIGNMENT_FILL:
case VERTICAL_ALIGNMENT_TOP: {
- icon_ofs.y += style_margin_top;
+ icon_ofs.y += theme_cache.style_margin_top;
} break;
case VERTICAL_ALIGNMENT_BOTTOM: {
- icon_ofs.y = size.y - style_margin_bottom - icon_size.height;
+ icon_ofs.y = size.y - theme_cache.style_margin_bottom - icon_size.height;
} break;
}
+ icon_ofs = icon_ofs.floor();
Rect2 icon_region = Rect2(icon_ofs, icon_size);
draw_texture_rect(_icon, icon_region, false, icon_modulate_color);
@@ -371,7 +442,7 @@ void Button::_notification(int p_what) {
case HORIZONTAL_ALIGNMENT_FILL:
case HORIZONTAL_ALIGNMENT_LEFT:
case HORIZONTAL_ALIGNMENT_RIGHT: {
- text_ofs.x += style_margin_left;
+ text_ofs.x += theme_cache.style_margin_left;
text_ofs.x += left_internal_margin_with_h_separation;
if (icon_align_rtl_checked == HORIZONTAL_ALIGNMENT_LEFT) {
// Offset by the space's width that occupied by icon and h_separation together.
@@ -380,7 +451,7 @@ void Button::_notification(int p_what) {
} break;
}
- text_ofs.y = (drawable_size_remained.height - text_buf->get_size().height) / 2.0f + style_margin_top;
+ text_ofs.y = (drawable_size_remained.height - text_buf->get_size().height) / 2.0f + theme_cache.style_margin_top;
if (vertical_icon_alignment == VERTICAL_ALIGNMENT_TOP) {
text_ofs.y += custom_element_size.height - drawable_size_remained.height; // Offset by the icon's height.
}
@@ -450,7 +521,7 @@ Size2 Button::get_minimum_size_for_text_and_icon(const String &p_text, Ref<Textu
}
}
- return _get_current_stylebox()->get_minimum_size() + minsize;
+ return _get_largest_stylebox_size() + minsize;
}
void Button::_shape(Ref<TextParagraph> p_paragraph, String p_text) {
diff --git a/scene/gui/button.h b/scene/gui/button.h
index 86fdbd35d5..eefb690913 100644
--- a/scene/gui/button.h
+++ b/scene/gui/button.h
@@ -69,6 +69,12 @@ private:
Ref<StyleBox> disabled_mirrored;
Ref<StyleBox> focus;
+ Size2 max_style_size;
+ float style_margin_left = 0;
+ float style_margin_right = 0;
+ float style_margin_top = 0;
+ float style_margin_bottom = 0;
+
Color font_color;
Color font_focus_color;
Color font_pressed_color;
@@ -94,16 +100,18 @@ private:
int icon_max_width = 0;
} theme_cache;
- Size2 _fit_icon_size(const Size2 &p_size) const;
-
void _shape(Ref<TextParagraph> p_paragraph = Ref<TextParagraph>(), String p_text = "");
void _texture_changed();
protected:
+ virtual void _update_theme_item_cache() override;
+
void _set_internal_margin(Side p_side, float p_value);
virtual void _queue_update_size_cache();
+ Size2 _fit_icon_size(const Size2 &p_size) const;
Ref<StyleBox> _get_current_stylebox() const;
+ Size2 _get_largest_stylebox_size() const;
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp
index af6696834e..99937aaf41 100644
--- a/scene/gui/check_box.cpp
+++ b/scene/gui/check_box.cpp
@@ -59,14 +59,14 @@ Size2 CheckBox::get_icon_size() const {
if (!theme_cache.radio_unchecked_disabled.is_null()) {
tex_size = tex_size.max(theme_cache.radio_unchecked_disabled->get_size());
}
- return tex_size;
+ return _fit_icon_size(tex_size);
}
Size2 CheckBox::get_minimum_size() const {
Size2 minsize = Button::get_minimum_size();
const Size2 tex_size = get_icon_size();
if (tex_size.width > 0 || tex_size.height > 0) {
- const Size2 padding = _get_current_stylebox()->get_minimum_size();
+ const Size2 padding = _get_largest_stylebox_size();
Size2 content_size = minsize - padding;
if (content_size.width > 0 && tex_size.width > 0) {
content_size.width += MAX(0, theme_cache.h_separation);
@@ -127,9 +127,9 @@ void CheckBox::_notification(int p_what) {
ofs.y = int((get_size().height - get_icon_size().height) / 2) + theme_cache.check_v_offset;
if (is_pressed()) {
- on_tex->draw(ci, ofs);
+ on_tex->draw_rect(ci, Rect2(ofs, _fit_icon_size(on_tex->get_size())));
} else {
- off_tex->draw(ci, ofs);
+ off_tex->draw_rect(ci, Rect2(ofs, _fit_icon_size(off_tex->get_size())));
}
} break;
}
diff --git a/scene/gui/check_button.cpp b/scene/gui/check_button.cpp
index ab3b74a3c3..29b9504776 100644
--- a/scene/gui/check_button.cpp
+++ b/scene/gui/check_button.cpp
@@ -63,14 +63,14 @@ Size2 CheckButton::get_icon_size() const {
tex_size = tex_size.max(off_tex->get_size());
}
- return tex_size;
+ return _fit_icon_size(tex_size);
}
Size2 CheckButton::get_minimum_size() const {
Size2 minsize = Button::get_minimum_size();
const Size2 tex_size = get_icon_size();
if (tex_size.width > 0 || tex_size.height > 0) {
- const Size2 padding = _get_current_stylebox()->get_minimum_size();
+ const Size2 padding = _get_largest_stylebox_size();
Size2 content_size = minsize - padding;
if (content_size.width > 0 && tex_size.width > 0) {
content_size.width += MAX(0, theme_cache.h_separation);
@@ -134,9 +134,9 @@ void CheckButton::_notification(int p_what) {
ofs.y = (get_size().height - tex_size.height) / 2 + theme_cache.check_v_offset;
if (is_pressed()) {
- on_tex->draw(ci, ofs);
+ on_tex->draw_rect(ci, Rect2(ofs, _fit_icon_size(on_tex->get_size())));
} else {
- off_tex->draw(ci, ofs);
+ off_tex->draw_rect(ci, Rect2(ofs, _fit_icon_size(off_tex->get_size())));
}
} break;
}
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index 8131fe7aaa..c843bb8c44 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -3050,7 +3050,7 @@ void CodeEdit::_update_delimiter_cache(int p_from_line, int p_to_line) {
}
int CodeEdit::_is_in_delimiter(int p_line, int p_column, DelimiterType p_type) const {
- if (delimiters.size() == 0) {
+ if (delimiters.size() == 0 || p_line >= delimiter_cache.size()) {
return -1;
}
ERR_FAIL_INDEX_V(p_line, get_line_count(), 0);
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index aeaaac1efc..245a086dda 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -95,8 +95,8 @@ void ColorPicker::_notification(int p_what) {
for (int i = 0; i < MODE_BUTTON_COUNT; i++) {
mode_btns[i]->begin_bulk_theme_override();
- mode_btns[i]->add_theme_style_override(SNAME("pressed"), theme_cache.mode_button_pressed);
- mode_btns[i]->add_theme_style_override(SNAME("normal"), theme_cache.mode_button_normal);
+ mode_btns[i]->add_theme_style_override(SceneStringName(pressed), theme_cache.mode_button_pressed);
+ mode_btns[i]->add_theme_style_override(CoreStringName(normal), theme_cache.mode_button_normal);
mode_btns[i]->add_theme_style_override(SNAME("hover"), theme_cache.mode_button_hover);
mode_btns[i]->end_bulk_theme_override();
}
@@ -420,18 +420,18 @@ void ColorPicker::create_slider(GridContainer *gc, int idx) {
LineEdit *vle = val->get_line_edit();
vle->connect("text_changed", callable_mp(this, &ColorPicker::_text_changed));
- vle->connect("gui_input", callable_mp(this, &ColorPicker::_line_edit_input));
+ vle->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_line_edit_input));
vle->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT);
- val->connect("gui_input", callable_mp(this, &ColorPicker::_slider_or_spin_input));
+ val->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_slider_or_spin_input));
slider->set_h_size_flags(SIZE_EXPAND_FILL);
slider->connect("drag_started", callable_mp(this, &ColorPicker::_slider_drag_started));
slider->connect("value_changed", callable_mp(this, &ColorPicker::_slider_value_changed).unbind(1));
slider->connect("drag_ended", callable_mp(this, &ColorPicker::_slider_drag_ended).unbind(1));
- slider->connect("draw", callable_mp(this, &ColorPicker::_slider_draw).bind(idx));
- slider->connect("gui_input", callable_mp(this, &ColorPicker::_slider_or_spin_input));
+ slider->connect(SceneStringName(draw), callable_mp(this, &ColorPicker::_slider_draw).bind(idx));
+ slider->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_slider_or_spin_input));
if (idx < SLIDER_COUNT) {
sliders[idx] = slider;
@@ -761,7 +761,7 @@ void ColorPicker::_add_preset_button(int p_size, const Color &p_color) {
btn_preset_new->set_button_group(preset_group);
preset_container->add_child(btn_preset_new);
btn_preset_new->set_pressed(true);
- btn_preset_new->connect("gui_input", callable_mp(this, &ColorPicker::_preset_input).bind(p_color));
+ btn_preset_new->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_preset_input).bind(p_color));
}
void ColorPicker::_add_recent_preset_button(int p_size, const Color &p_color) {
@@ -1510,7 +1510,7 @@ void ColorPicker::_pick_button_pressed() {
if (!picker_window) {
picker_window = memnew(Popup);
picker_window->set_size(Vector2i(1, 1));
- picker_window->connect("visibility_changed", callable_mp(this, &ColorPicker::_pick_finished));
+ picker_window->connect(SceneStringName(visibility_changed), callable_mp(this, &ColorPicker::_pick_finished));
add_child(picker_window, false, INTERNAL_MODE_FRONT);
}
picker_window->popup();
@@ -1546,7 +1546,7 @@ void ColorPicker::_pick_button_pressed_legacy() {
picker_texture_rect->set_anchors_preset(Control::PRESET_FULL_RECT);
picker_window->add_child(picker_texture_rect);
picker_texture_rect->set_default_cursor_shape(CURSOR_POINTING_HAND);
- picker_texture_rect->connect("gui_input", callable_mp(this, &ColorPicker::_picker_texture_input));
+ picker_texture_rect->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_picker_texture_input));
picker_preview = memnew(Panel);
picker_preview->set_anchors_preset(Control::PRESET_CENTER_TOP);
@@ -1823,11 +1823,11 @@ ColorPicker::ColorPicker() {
uv_edit = memnew(Control);
hb_edit->add_child(uv_edit);
- uv_edit->connect("gui_input", callable_mp(this, &ColorPicker::_uv_input).bind(uv_edit));
+ uv_edit->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_uv_input).bind(uv_edit));
uv_edit->set_mouse_filter(MOUSE_FILTER_PASS);
uv_edit->set_h_size_flags(SIZE_EXPAND_FILL);
uv_edit->set_v_size_flags(SIZE_EXPAND_FILL);
- uv_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw).bind(0, uv_edit));
+ uv_edit->connect(SceneStringName(draw), callable_mp(this, &ColorPicker::_hsv_draw).bind(0, uv_edit));
sample_hbc = memnew(HBoxContainer);
real_vbox->add_child(sample_hbc);
@@ -1836,18 +1836,18 @@ ColorPicker::ColorPicker() {
sample_hbc->add_child(btn_pick);
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_SCREEN_CAPTURE)) {
btn_pick->set_tooltip_text(ETR("Pick a color from the screen."));
- btn_pick->connect(SNAME("pressed"), callable_mp(this, &ColorPicker::_pick_button_pressed));
+ btn_pick->connect(SceneStringName(pressed), callable_mp(this, &ColorPicker::_pick_button_pressed));
} else {
// On unsupported platforms, use a legacy method for color picking.
btn_pick->set_tooltip_text(ETR("Pick a color from the application window."));
- btn_pick->connect(SNAME("pressed"), callable_mp(this, &ColorPicker::_pick_button_pressed_legacy));
+ btn_pick->connect(SceneStringName(pressed), callable_mp(this, &ColorPicker::_pick_button_pressed_legacy));
}
sample = memnew(TextureRect);
sample_hbc->add_child(sample);
sample->set_h_size_flags(SIZE_EXPAND_FILL);
- sample->connect("gui_input", callable_mp(this, &ColorPicker::_sample_input));
- sample->connect("draw", callable_mp(this, &ColorPicker::_sample_draw));
+ sample->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_sample_input));
+ sample->connect(SceneStringName(draw), callable_mp(this, &ColorPicker::_sample_draw));
btn_shape = memnew(MenuButton);
btn_shape->set_flat(false);
@@ -1883,7 +1883,7 @@ ColorPicker::ColorPicker() {
mode_btns[i]->set_toggle_mode(true);
mode_btns[i]->set_text(modes[i]->get_name());
mode_btns[i]->set_button_group(mode_group);
- mode_btns[i]->connect("pressed", callable_mp(this, &ColorPicker::set_color_mode).bind((ColorModeType)i));
+ mode_btns[i]->connect(SceneStringName(pressed), callable_mp(this, &ColorPicker::set_color_mode).bind((ColorModeType)i));
}
mode_btns[0]->set_pressed(true);
@@ -1936,7 +1936,7 @@ ColorPicker::ColorPicker() {
text_type->set_text("#");
text_type->set_tooltip_text(RTR("Switch between hexadecimal and code values."));
if (Engine::get_singleton()->is_editor_hint()) {
- text_type->connect("pressed", callable_mp(this, &ColorPicker::_text_type_toggled));
+ text_type->connect(SceneStringName(pressed), callable_mp(this, &ColorPicker::_text_type_toggled));
} else {
text_type->set_flat(true);
text_type->set_mouse_filter(MOUSE_FILTER_IGNORE);
@@ -1950,7 +1950,7 @@ ColorPicker::ColorPicker() {
c_text->set_placeholder(ETR("Hex code or named color"));
c_text->connect("text_submitted", callable_mp(this, &ColorPicker::_html_submitted));
c_text->connect("text_changed", callable_mp(this, &ColorPicker::_text_changed));
- c_text->connect("focus_exited", callable_mp(this, &ColorPicker::_html_focus_exit));
+ c_text->connect(SceneStringName(focus_exited), callable_mp(this, &ColorPicker::_html_focus_exit));
wheel_edit = memnew(AspectRatioContainer);
wheel_edit->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -1969,19 +1969,19 @@ ColorPicker::ColorPicker() {
wheel = memnew(Control);
wheel_margin->add_child(wheel);
wheel->set_mouse_filter(MOUSE_FILTER_PASS);
- wheel->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw).bind(2, wheel));
+ wheel->connect(SceneStringName(draw), callable_mp(this, &ColorPicker::_hsv_draw).bind(2, wheel));
wheel_uv = memnew(Control);
wheel_margin->add_child(wheel_uv);
- wheel_uv->connect("gui_input", callable_mp(this, &ColorPicker::_uv_input).bind(wheel_uv));
- wheel_uv->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw).bind(0, wheel_uv));
+ wheel_uv->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_uv_input).bind(wheel_uv));
+ wheel_uv->connect(SceneStringName(draw), callable_mp(this, &ColorPicker::_hsv_draw).bind(0, wheel_uv));
w_edit = memnew(Control);
hb_edit->add_child(w_edit);
w_edit->set_h_size_flags(SIZE_FILL);
w_edit->set_v_size_flags(SIZE_EXPAND_FILL);
- w_edit->connect("gui_input", callable_mp(this, &ColorPicker::_w_input));
- w_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw).bind(1, w_edit));
+ w_edit->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_w_input));
+ w_edit->connect(SceneStringName(draw), callable_mp(this, &ColorPicker::_hsv_draw).bind(1, w_edit));
_update_controls();
updating = false;
@@ -2026,7 +2026,7 @@ ColorPicker::ColorPicker() {
btn_add_preset = memnew(Button);
btn_add_preset->set_icon_alignment(HORIZONTAL_ALIGNMENT_CENTER);
btn_add_preset->set_tooltip_text(ETR("Add current color as a preset."));
- btn_add_preset->connect("pressed", callable_mp(this, &ColorPicker::_add_preset_pressed));
+ btn_add_preset->connect(SceneStringName(pressed), callable_mp(this, &ColorPicker::_add_preset_pressed));
preset_container->add_child(btn_add_preset);
}
@@ -2171,7 +2171,7 @@ void ColorPickerButton::_update_picker() {
picker->connect("color_changed", callable_mp(this, &ColorPickerButton::_color_changed));
popup->connect("about_to_popup", callable_mp(this, &ColorPickerButton::_about_to_popup));
popup->connect("popup_hide", callable_mp(this, &ColorPickerButton::_modal_closed));
- picker->connect("minimum_size_changed", callable_mp((Window *)popup, &Window::reset_size));
+ picker->connect(SceneStringName(minimum_size_changed), callable_mp((Window *)popup, &Window::reset_size));
picker->set_pick_color(color);
picker->set_edit_alpha(edit_alpha);
picker->set_display_old_color(true);
diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp
index 5db8d69eef..f1faf3e899 100644
--- a/scene/gui/container.cpp
+++ b/scene/gui/container.cpp
@@ -30,8 +30,6 @@
#include "container.h"
-#include "scene/scene_string_names.h"
-
void Container::_child_minsize_changed() {
update_minimum_size();
queue_sort();
@@ -45,9 +43,9 @@ void Container::add_child_notify(Node *p_child) {
return;
}
- control->connect(SNAME("size_flags_changed"), callable_mp(this, &Container::queue_sort));
- control->connect(SNAME("minimum_size_changed"), callable_mp(this, &Container::_child_minsize_changed));
- control->connect(SNAME("visibility_changed"), callable_mp(this, &Container::_child_minsize_changed));
+ control->connect(SceneStringName(size_flags_changed), callable_mp(this, &Container::queue_sort));
+ control->connect(SceneStringName(minimum_size_changed), callable_mp(this, &Container::_child_minsize_changed));
+ control->connect(SceneStringName(visibility_changed), callable_mp(this, &Container::_child_minsize_changed));
update_minimum_size();
queue_sort();
@@ -72,9 +70,9 @@ void Container::remove_child_notify(Node *p_child) {
return;
}
- control->disconnect("size_flags_changed", callable_mp(this, &Container::queue_sort));
- control->disconnect("minimum_size_changed", callable_mp(this, &Container::_child_minsize_changed));
- control->disconnect("visibility_changed", callable_mp(this, &Container::_child_minsize_changed));
+ control->disconnect(SceneStringName(size_flags_changed), callable_mp(this, &Container::queue_sort));
+ control->disconnect(SceneStringName(minimum_size_changed), callable_mp(this, &Container::_child_minsize_changed));
+ control->disconnect(SceneStringName(visibility_changed), callable_mp(this, &Container::_child_minsize_changed));
update_minimum_size();
queue_sort();
@@ -86,10 +84,10 @@ void Container::_sort_children() {
}
notification(NOTIFICATION_PRE_SORT_CHILDREN);
- emit_signal(SceneStringNames::get_singleton()->pre_sort_children);
+ emit_signal(SceneStringName(pre_sort_children));
notification(NOTIFICATION_SORT_CHILDREN);
- emit_signal(SceneStringNames::get_singleton()->sort_children);
+ emit_signal(SceneStringName(sort_children));
pending_sort = false;
}
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 2dd12b92f3..0d5c69b207 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -42,7 +42,6 @@
#include "scene/gui/panel.h"
#include "scene/main/canvas_layer.h"
#include "scene/main/window.h"
-#include "scene/scene_string_names.h"
#include "scene/theme/theme_db.h"
#include "scene/theme/theme_owner.h"
#include "servers/rendering_server.h"
@@ -212,17 +211,17 @@ void Control::get_argument_options(const StringName &p_function, int p_idx, List
const String pf = p_function;
Theme::DataType type = Theme::DATA_TYPE_MAX;
- if (pf == "add_theme_color_override" || pf == "has_theme_color" || pf == "has_theme_color_override" || pf == "get_theme_color") {
+ if (pf == "add_theme_color_override" || pf == "has_theme_color" || pf == "has_theme_color_override" || pf == "get_theme_color" || pf == "remove_theme_color_override") {
type = Theme::DATA_TYPE_COLOR;
- } else if (pf == "add_theme_constant_override" || pf == "has_theme_constant" || pf == "has_theme_constant_override" || pf == "get_theme_constant") {
+ } else if (pf == "add_theme_constant_override" || pf == "has_theme_constant" || pf == "has_theme_constant_override" || pf == "get_theme_constant" || pf == "remove_theme_constant_override") {
type = Theme::DATA_TYPE_CONSTANT;
- } else if (pf == "add_theme_font_override" || pf == "has_theme_font" || pf == "has_theme_font_override" || pf == "get_theme_font") {
+ } else if (pf == "add_theme_font_override" || pf == "has_theme_font" || pf == "has_theme_font_override" || pf == "get_theme_font" || pf == "remove_theme_font_override") {
type = Theme::DATA_TYPE_FONT;
- } else if (pf == "add_theme_font_size_override" || pf == "has_theme_font_size" || pf == "has_theme_font_size_override" || pf == "get_theme_font_size") {
+ } else if (pf == "add_theme_font_size_override" || pf == "has_theme_font_size" || pf == "has_theme_font_size_override" || pf == "get_theme_font_size" || pf == "remove_theme_font_size_override") {
type = Theme::DATA_TYPE_FONT_SIZE;
- } else if (pf == "add_theme_icon_override" || pf == "has_theme_icon" || pf == "has_theme_icon_override" || pf == "get_theme_icon") {
+ } else if (pf == "add_theme_icon_override" || pf == "has_theme_icon" || pf == "has_theme_icon_override" || pf == "get_theme_icon" || pf == "remove_theme_icon_override") {
type = Theme::DATA_TYPE_ICON;
- } else if (pf == "add_theme_style_override" || pf == "has_theme_style" || pf == "has_theme_style_override" || pf == "get_theme_style") {
+ } else if (pf == "add_theme_stylebox_override" || pf == "has_theme_stylebox" || pf == "has_theme_stylebox_override" || pf == "get_theme_stylebox" || pf == "remove_theme_stylebox_override") {
type = Theme::DATA_TYPE_STYLEBOX;
}
@@ -1606,7 +1605,7 @@ void Control::_update_minimum_size() {
if (minsize != data.last_minimum_size) {
data.last_minimum_size = minsize;
_size_changed();
- emit_signal(SceneStringNames::get_singleton()->minimum_size_changed);
+ emit_signal(SceneStringName(minimum_size_changed));
}
}
@@ -1770,7 +1769,7 @@ void Control::set_h_size_flags(BitField<SizeFlags> p_flags) {
return;
}
data.h_size_flags = p_flags;
- emit_signal(SceneStringNames::get_singleton()->size_flags_changed);
+ emit_signal(SceneStringName(size_flags_changed));
}
BitField<Control::SizeFlags> Control::get_h_size_flags() const {
@@ -1784,7 +1783,7 @@ void Control::set_v_size_flags(BitField<SizeFlags> p_flags) {
return;
}
data.v_size_flags = p_flags;
- emit_signal(SceneStringNames::get_singleton()->size_flags_changed);
+ emit_signal(SceneStringName(size_flags_changed));
}
BitField<Control::SizeFlags> Control::get_v_size_flags() const {
@@ -1799,7 +1798,7 @@ void Control::set_stretch_ratio(real_t p_ratio) {
}
data.expand = p_ratio;
- emit_signal(SceneStringNames::get_singleton()->size_flags_changed);
+ emit_signal(SceneStringName(size_flags_changed));
}
real_t Control::get_stretch_ratio() const {
@@ -1811,7 +1810,7 @@ real_t Control::get_stretch_ratio() const {
void Control::_call_gui_input(const Ref<InputEvent> &p_event) {
if (p_event->get_device() != InputEvent::DEVICE_ID_INTERNAL) {
- emit_signal(SceneStringNames::get_singleton()->gui_input, p_event); // Signal should be first, so it's possible to override an event (and then accept it).
+ emit_signal(SceneStringName(gui_input), p_event); // Signal should be first, so it's possible to override an event (and then accept it).
}
if (!is_inside_tree() || get_viewport()->is_input_handled()) {
return; // Input was handled, abort.
@@ -3223,7 +3222,7 @@ void Control::_notification(int p_notification) {
case NOTIFICATION_READY: {
#ifdef DEBUG_ENABLED
- connect("ready", callable_mp(this, &Control::_clear_size_warning), CONNECT_DEFERRED | CONNECT_ONE_SHOT);
+ connect(SceneStringName(ready), callable_mp(this, &Control::_clear_size_warning), CONNECT_DEFERRED | CONNECT_ONE_SHOT);
#endif
} break;
@@ -3262,7 +3261,7 @@ void Control::_notification(int p_notification) {
data.parent_canvas_item = get_parent_item();
if (data.parent_canvas_item) {
- data.parent_canvas_item->connect("item_rect_changed", callable_mp(this, &Control::_size_changed));
+ data.parent_canvas_item->connect(SceneStringName(item_rect_changed), callable_mp(this, &Control::_size_changed));
} else {
// Connect viewport.
Viewport *viewport = get_viewport();
@@ -3273,7 +3272,7 @@ void Control::_notification(int p_notification) {
case NOTIFICATION_EXIT_CANVAS: {
if (data.parent_canvas_item) {
- data.parent_canvas_item->disconnect("item_rect_changed", callable_mp(this, &Control::_size_changed));
+ data.parent_canvas_item->disconnect(SceneStringName(item_rect_changed), callable_mp(this, &Control::_size_changed));
data.parent_canvas_item = nullptr;
} else {
// Disconnect viewport.
@@ -3299,7 +3298,7 @@ void Control::_notification(int p_notification) {
} break;
case NOTIFICATION_RESIZED: {
- emit_signal(SceneStringNames::get_singleton()->resized);
+ emit_signal(SceneStringName(resized));
} break;
case NOTIFICATION_DRAW: {
@@ -3309,25 +3308,25 @@ void Control::_notification(int p_notification) {
} break;
case NOTIFICATION_MOUSE_ENTER: {
- emit_signal(SceneStringNames::get_singleton()->mouse_entered);
+ emit_signal(SceneStringName(mouse_entered));
} break;
case NOTIFICATION_MOUSE_EXIT: {
- emit_signal(SceneStringNames::get_singleton()->mouse_exited);
+ emit_signal(SceneStringName(mouse_exited));
} break;
case NOTIFICATION_FOCUS_ENTER: {
- emit_signal(SceneStringNames::get_singleton()->focus_entered);
+ emit_signal(SceneStringName(focus_entered));
queue_redraw();
} break;
case NOTIFICATION_FOCUS_EXIT: {
- emit_signal(SceneStringNames::get_singleton()->focus_exited);
+ emit_signal(SceneStringName(focus_exited));
queue_redraw();
} break;
case NOTIFICATION_THEME_CHANGED: {
- emit_signal(SceneStringNames::get_singleton()->theme_changed);
+ emit_signal(SceneStringName(theme_changed));
_invalidate_theme_cache();
_update_theme_item_cache();
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index 4d2080dda2..3d8be38fbd 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -47,7 +47,7 @@ void AcceptDialog::_input_from_window(const Ref<InputEvent> &p_event) {
}
void AcceptDialog::_parent_focused() {
- if (!is_exclusive() && get_flag(FLAG_POPUP)) {
+ if (popped_up && !is_exclusive() && get_flag(FLAG_POPUP)) {
_cancel_pressed();
}
}
@@ -68,16 +68,25 @@ void AcceptDialog::_notification(int p_what) {
parent_visible = get_parent_visible_window();
if (parent_visible) {
- parent_visible->connect("focus_entered", callable_mp(this, &AcceptDialog::_parent_focused));
+ parent_visible->connect(SceneStringName(focus_entered), callable_mp(this, &AcceptDialog::_parent_focused));
}
} else {
+ popped_up = false;
if (parent_visible) {
- parent_visible->disconnect("focus_entered", callable_mp(this, &AcceptDialog::_parent_focused));
+ parent_visible->disconnect(SceneStringName(focus_entered), callable_mp(this, &AcceptDialog::_parent_focused));
parent_visible = nullptr;
}
}
} break;
+ case NOTIFICATION_WM_WINDOW_FOCUS_IN: {
+ if (!is_in_edited_scene_root()) {
+ if (has_focus()) {
+ popped_up = true;
+ }
+ }
+ } break;
+
case NOTIFICATION_THEME_CHANGED: {
bg_panel->add_theme_style_override("panel", theme_cache.panel_style);
@@ -89,7 +98,7 @@ void AcceptDialog::_notification(int p_what) {
case NOTIFICATION_EXIT_TREE: {
if (parent_visible) {
- parent_visible->disconnect("focus_entered", callable_mp(this, &AcceptDialog::_parent_focused));
+ parent_visible->disconnect(SceneStringName(focus_entered), callable_mp(this, &AcceptDialog::_parent_focused));
parent_visible = nullptr;
}
} break;
@@ -114,8 +123,14 @@ void AcceptDialog::_text_submitted(const String &p_text) {
_ok_pressed();
}
+void AcceptDialog::_post_popup() {
+ Window::_post_popup();
+ popped_up = true;
+}
+
void AcceptDialog::_ok_pressed() {
if (hide_on_ok) {
+ popped_up = false;
set_visible(false);
}
ok_pressed();
@@ -124,9 +139,10 @@ void AcceptDialog::_ok_pressed() {
}
void AcceptDialog::_cancel_pressed() {
+ popped_up = false;
Window *parent_window = parent_visible;
if (parent_visible) {
- parent_visible->disconnect("focus_entered", callable_mp(this, &AcceptDialog::_parent_focused));
+ parent_visible->disconnect(SceneStringName(focus_entered), callable_mp(this, &AcceptDialog::_parent_focused));
parent_visible = nullptr;
}
@@ -308,7 +324,7 @@ Button *AcceptDialog::add_button(const String &p_text, bool p_right, const Strin
}
button->set_meta("__right_spacer", right_spacer);
- button->connect("visibility_changed", callable_mp(this, &AcceptDialog::_custom_button_visibility_changed).bind(button));
+ button->connect(SceneStringName(visibility_changed), callable_mp(this, &AcceptDialog::_custom_button_visibility_changed).bind(button));
child_controls_changed();
if (is_visible()) {
@@ -316,7 +332,7 @@ Button *AcceptDialog::add_button(const String &p_text, bool p_right, const Strin
}
if (!p_action.is_empty()) {
- button->connect("pressed", callable_mp(this, &AcceptDialog::_custom_action).bind(p_action));
+ button->connect(SceneStringName(pressed), callable_mp(this, &AcceptDialog::_custom_action).bind(p_action));
}
return button;
@@ -330,7 +346,7 @@ Button *AcceptDialog::add_cancel_button(const String &p_cancel) {
Button *b = swap_cancel_ok ? add_button(c, true) : add_button(c);
- b->connect("pressed", callable_mp(this, &AcceptDialog::_cancel_pressed));
+ b->connect(SceneStringName(pressed), callable_mp(this, &AcceptDialog::_cancel_pressed));
return b;
}
@@ -345,12 +361,12 @@ void AcceptDialog::remove_button(Button *p_button) {
ERR_FAIL_COND_MSG(right_spacer->get_parent() != buttons_hbox, vformat("Cannot remove button %s as its associated spacer does not belong to this dialog.", p_button->get_name()));
}
- p_button->disconnect("visibility_changed", callable_mp(this, &AcceptDialog::_custom_button_visibility_changed));
- if (p_button->is_connected("pressed", callable_mp(this, &AcceptDialog::_custom_action))) {
- p_button->disconnect("pressed", callable_mp(this, &AcceptDialog::_custom_action));
+ p_button->disconnect(SceneStringName(visibility_changed), callable_mp(this, &AcceptDialog::_custom_button_visibility_changed));
+ if (p_button->is_connected(SceneStringName(pressed), callable_mp(this, &AcceptDialog::_custom_action))) {
+ p_button->disconnect(SceneStringName(pressed), callable_mp(this, &AcceptDialog::_custom_action));
}
- if (p_button->is_connected("pressed", callable_mp(this, &AcceptDialog::_cancel_pressed))) {
- p_button->disconnect("pressed", callable_mp(this, &AcceptDialog::_cancel_pressed));
+ if (p_button->is_connected(SceneStringName(pressed), callable_mp(this, &AcceptDialog::_cancel_pressed))) {
+ p_button->disconnect(SceneStringName(pressed), callable_mp(this, &AcceptDialog::_cancel_pressed));
}
if (right_spacer) {
@@ -433,7 +449,7 @@ AcceptDialog::AcceptDialog() {
buttons_hbox->add_child(ok_button);
buttons_hbox->add_spacer();
- ok_button->connect("pressed", callable_mp(this, &AcceptDialog::_ok_pressed));
+ ok_button->connect(SceneStringName(pressed), callable_mp(this, &AcceptDialog::_ok_pressed));
set_title(ETR("Alert!"));
}
diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h
index 12b48c903a..404237bfd8 100644
--- a/scene/gui/dialogs.h
+++ b/scene/gui/dialogs.h
@@ -51,6 +51,7 @@ class AcceptDialog : public Window {
HBoxContainer *buttons_hbox = nullptr;
Button *ok_button = nullptr;
+ bool popped_up = false;
bool hide_on_ok = true;
bool close_on_escape = true;
@@ -72,6 +73,7 @@ class AcceptDialog : public Window {
protected:
virtual Size2 _get_contents_minimum_size() const override;
virtual void _input_from_window(const Ref<InputEvent> &p_event) override;
+ virtual void _post_popup() override;
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 97a2917dc1..0c146ce173 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -1344,6 +1344,7 @@ void FileDialog::_bind_methods() {
Option defaults;
base_property_helper.set_prefix("option_");
+ base_property_helper.set_array_length_getter(&FileDialog::get_option_count);
base_property_helper.register_property(PropertyInfo(Variant::STRING, "name"), defaults.name, &FileDialog::set_option_name, &FileDialog::get_option_name);
base_property_helper.register_property(PropertyInfo(Variant::PACKED_STRING_ARRAY, "values"), defaults.values, &FileDialog::set_option_values, &FileDialog::get_option_values);
base_property_helper.register_property(PropertyInfo(Variant::INT, "default"), defaults.default_idx, &FileDialog::set_option_default, &FileDialog::get_option_default);
@@ -1408,9 +1409,9 @@ FileDialog::FileDialog() {
hbc->add_child(dir_prev);
hbc->add_child(dir_next);
hbc->add_child(dir_up);
- dir_prev->connect("pressed", callable_mp(this, &FileDialog::_go_back));
- dir_next->connect("pressed", callable_mp(this, &FileDialog::_go_forward));
- dir_up->connect("pressed", callable_mp(this, &FileDialog::_go_up));
+ dir_prev->connect(SceneStringName(pressed), callable_mp(this, &FileDialog::_go_back));
+ dir_next->connect(SceneStringName(pressed), callable_mp(this, &FileDialog::_go_forward));
+ dir_up->connect(SceneStringName(pressed), callable_mp(this, &FileDialog::_go_up));
hbc->add_child(memnew(Label(ETR("Path:"))));
@@ -1429,7 +1430,7 @@ FileDialog::FileDialog() {
refresh = memnew(Button);
refresh->set_theme_type_variation("FlatButton");
refresh->set_tooltip_text(ETR("Refresh files."));
- refresh->connect("pressed", callable_mp(this, &FileDialog::update_file_list));
+ refresh->connect(SceneStringName(pressed), callable_mp(this, &FileDialog::update_file_list));
hbc->add_child(refresh);
show_hidden = memnew(Button);
@@ -1446,7 +1447,7 @@ FileDialog::FileDialog() {
makedir = memnew(Button);
makedir->set_theme_type_variation("FlatButton");
makedir->set_tooltip_text(ETR("Create a new folder."));
- makedir->connect("pressed", callable_mp(this, &FileDialog::_make_dir));
+ makedir->connect(SceneStringName(pressed), callable_mp(this, &FileDialog::_make_dir));
hbc->add_child(makedir);
vbox->add_child(hbc);
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 646e45b27a..6c2a61d255 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -601,7 +601,7 @@ void GraphEdit::add_child_notify(Node *p_child) {
GraphNode *graph_node = Object::cast_to<GraphNode>(graph_element);
if (graph_node) {
graph_node->connect("slot_updated", callable_mp(this, &GraphEdit::_graph_node_slot_updated).bind(graph_element));
- graph_node->connect("item_rect_changed", callable_mp(this, &GraphEdit::_graph_node_rect_changed).bind(graph_node));
+ graph_node->connect(SceneStringName(item_rect_changed), callable_mp(this, &GraphEdit::_graph_node_rect_changed).bind(graph_node));
_ensure_node_order_from(graph_node);
}
@@ -618,8 +618,8 @@ void GraphEdit::add_child_notify(Node *p_child) {
}
graph_element->connect("raise_request", callable_mp(this, &GraphEdit::_ensure_node_order_from).bind(graph_element));
graph_element->connect("resize_request", callable_mp(this, &GraphEdit::_graph_element_resize_request).bind(graph_element));
- graph_element->connect("item_rect_changed", callable_mp((CanvasItem *)connections_layer, &CanvasItem::queue_redraw));
- graph_element->connect("item_rect_changed", callable_mp((CanvasItem *)minimap, &GraphEditMinimap::queue_redraw));
+ graph_element->connect(SceneStringName(item_rect_changed), callable_mp((CanvasItem *)connections_layer, &CanvasItem::queue_redraw));
+ graph_element->connect(SceneStringName(item_rect_changed), callable_mp((CanvasItem *)minimap, &GraphEditMinimap::queue_redraw));
graph_element->set_scale(Vector2(zoom, zoom));
_graph_element_moved(graph_element);
@@ -651,7 +651,7 @@ void GraphEdit::remove_child_notify(Node *p_child) {
GraphNode *graph_node = Object::cast_to<GraphNode>(graph_element);
if (graph_node) {
graph_node->disconnect("slot_updated", callable_mp(this, &GraphEdit::_graph_node_slot_updated));
- graph_node->disconnect("item_rect_changed", callable_mp(this, &GraphEdit::_graph_node_rect_changed));
+ graph_node->disconnect(SceneStringName(item_rect_changed), callable_mp(this, &GraphEdit::_graph_node_rect_changed));
// Invalidate all adjacent connections, so that they are removed before the next redraw.
for (const Ref<Connection> &conn : connection_map[graph_node->get_name()]) {
@@ -692,7 +692,7 @@ void GraphEdit::remove_child_notify(Node *p_child) {
// In case of the whole GraphEdit being destroyed these references can already be freed.
if (minimap != nullptr && minimap->is_inside_tree()) {
- graph_element->disconnect("item_rect_changed", callable_mp((CanvasItem *)minimap, &GraphEditMinimap::queue_redraw));
+ graph_element->disconnect(SceneStringName(item_rect_changed), callable_mp((CanvasItem *)minimap, &GraphEditMinimap::queue_redraw));
}
}
}
@@ -898,6 +898,12 @@ bool GraphEdit::_filter_input(const Point2 &p_point) {
return true;
}
}
+
+ // This prevents interactions with a port hotzone that is behind another node.
+ Rect2 graph_node_rect = Rect2(graph_node->get_position(), graph_node->get_size() * zoom);
+ if (graph_node_rect.has_point(click_pos * zoom)) {
+ break;
+ }
}
return false;
@@ -1027,6 +1033,12 @@ void GraphEdit::_top_connection_layer_input(const Ref<InputEvent> &p_ev) {
return;
}
}
+
+ // This prevents interactions with a port hotzone that is behind another node.
+ Rect2 graph_node_rect = Rect2(graph_node->get_position(), graph_node->get_size() * zoom);
+ if (graph_node_rect.has_point(click_pos * zoom)) {
+ break;
+ }
}
}
@@ -1059,7 +1071,7 @@ void GraphEdit::_top_connection_layer_input(const Ref<InputEvent> &p_ev) {
port_size.height = MAX(port_size.height, child ? child->get_size().y : 0);
int type = graph_node->get_output_port_type(j);
- if ((type == connecting_type ||
+ if ((type == connecting_type || graph_node->is_ignoring_valid_connection_type() ||
valid_connection_types.has(ConnectionType(type, connecting_type))) &&
is_in_output_hotzone(graph_node, j, mpos, port_size)) {
if (!is_node_hover_valid(graph_node->get_name(), j, connecting_from_node, connecting_from_port_index)) {
@@ -1084,7 +1096,7 @@ void GraphEdit::_top_connection_layer_input(const Ref<InputEvent> &p_ev) {
port_size.height = MAX(port_size.height, child ? child->get_size().y : 0);
int type = graph_node->get_input_port_type(j);
- if ((type == connecting_type || valid_connection_types.has(ConnectionType(connecting_type, type))) &&
+ if ((type == connecting_type || graph_node->is_ignoring_valid_connection_type() || valid_connection_types.has(ConnectionType(connecting_type, type))) &&
is_in_input_hotzone(graph_node, j, mpos, port_size)) {
if (!is_node_hover_valid(connecting_from_node, connecting_from_port_index, graph_node->get_name(), j)) {
continue;
@@ -1117,6 +1129,8 @@ void GraphEdit::_top_connection_layer_input(const Ref<InputEvent> &p_ev) {
emit_signal(SNAME("connection_from_empty"), connecting_from_node, connecting_from_port_index, mb->get_position());
}
}
+ } else {
+ set_selected(get_node_or_null(NodePath(connecting_from_node)));
}
if (connecting) {
@@ -1285,18 +1299,26 @@ List<Ref<GraphEdit::Connection>> GraphEdit::get_connections_intersecting_with_re
return intersecting_connections;
}
-void GraphEdit::_draw_minimap_connection_line(CanvasItem *p_where, const Vector2 &p_from, const Vector2 &p_to, const Color &p_from_color, const Color &p_to_color) {
- const Vector<Vector2> &points = get_connection_line(p_from, p_to);
+void GraphEdit::_draw_minimap_connection_line(const Vector2 &p_from_graph_position, const Vector2 &p_to_graph_position, const Color &p_from_color, const Color &p_to_color) {
+ Vector<Vector2> points = get_connection_line(p_from_graph_position, p_to_graph_position);
+ ERR_FAIL_COND_MSG(points.size() < 2, "\"_get_connection_line()\" returned an invalid line.");
+ // Convert to minimap points.
+ for (Vector2 &point : points) {
+ point = minimap->_convert_from_graph_position(point) + minimap->minimap_offset;
+ }
+
+ // Setup polyline colors.
LocalVector<Color> colors;
colors.reserve(points.size());
-
- float length_inv = 1.0 / (p_from).distance_to(p_to);
+ const Vector2 &from = points[0];
+ const Vector2 &to = points[points.size() - 1];
+ float length_inv = 1.0 / (from).distance_to(to);
for (const Vector2 &point : points) {
- float normalized_curve_position = (p_from).distance_to(point) * length_inv;
+ float normalized_curve_position = from.distance_to(point) * length_inv;
colors.push_back(p_from_color.lerp(p_to_color, normalized_curve_position));
}
- p_where->draw_polyline_colors(points, colors, 0.5, lines_antialiased);
+ minimap->draw_polyline_colors(points, colors, 0.5, lines_antialiased);
}
void GraphEdit::_update_connections() {
@@ -1551,8 +1573,8 @@ void GraphEdit::_minimap_draw() {
// Draw node connections.
for (const Ref<Connection> &c : connections) {
- Vector2 from_position = minimap->_convert_from_graph_position(c->_cache.from_pos * zoom - graph_offset) + minimap_offset;
- Vector2 to_position = minimap->_convert_from_graph_position(c->_cache.to_pos * zoom - graph_offset) + minimap_offset;
+ Vector2 from_graph_position = c->_cache.from_pos * zoom - graph_offset;
+ Vector2 to_graph_position = c->_cache.to_pos * zoom - graph_offset;
Color from_color = c->_cache.from_color;
Color to_color = c->_cache.to_color;
@@ -1560,7 +1582,8 @@ void GraphEdit::_minimap_draw() {
from_color = from_color.lerp(theme_cache.activity_color, c->activity);
to_color = to_color.lerp(theme_cache.activity_color, c->activity);
}
- _draw_minimap_connection_line(minimap, from_position, to_position, from_color, to_color);
+
+ _draw_minimap_connection_line(from_graph_position, to_graph_position, from_color, to_color);
}
// Draw the "camera" viewport.
@@ -1636,12 +1659,12 @@ void GraphEdit::_draw_grid() {
void GraphEdit::set_selected(Node *p_child) {
for (int i = get_child_count() - 1; i >= 0; i--) {
- GraphNode *graph_node = Object::cast_to<GraphNode>(get_child(i));
- if (!graph_node) {
+ GraphElement *graph_element = Object::cast_to<GraphElement>(get_child(i));
+ if (!graph_element) {
continue;
}
- graph_node->set_selected(graph_node == p_child);
+ graph_element->set_selected(graph_element == p_child);
}
}
@@ -2755,12 +2778,12 @@ GraphEdit::GraphEdit() {
add_child(top_layer, false, INTERNAL_MODE_BACK);
top_layer->set_mouse_filter(MOUSE_FILTER_IGNORE);
top_layer->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
- top_layer->connect("draw", callable_mp(this, &GraphEdit::_top_layer_draw));
- top_layer->connect("focus_exited", callable_mp(panner.ptr(), &ViewPanner::release_pan_key));
+ top_layer->connect(SceneStringName(draw), callable_mp(this, &GraphEdit::_top_layer_draw));
+ top_layer->connect(SceneStringName(focus_exited), callable_mp(panner.ptr(), &ViewPanner::release_pan_key));
connections_layer = memnew(Control);
add_child(connections_layer, false);
- connections_layer->connect("draw", callable_mp(this, &GraphEdit::_update_connections));
+ connections_layer->connect(SceneStringName(draw), callable_mp(this, &GraphEdit::_update_connections));
connections_layer->set_name("_connection_layer");
connections_layer->set_disable_visibility_clip(true); // Necessary, so it can draw freely and be offset.
connections_layer->set_mouse_filter(MOUSE_FILTER_IGNORE);
@@ -2772,7 +2795,7 @@ GraphEdit::GraphEdit() {
top_connection_layer->set_mouse_filter(MOUSE_FILTER_PASS);
top_connection_layer->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
- top_connection_layer->connect("gui_input", callable_mp(this, &GraphEdit::_top_connection_layer_input));
+ top_connection_layer->connect(SceneStringName(gui_input), callable_mp(this, &GraphEdit::_top_connection_layer_input));
dragged_connection_line = memnew(Line2D);
dragged_connection_line->set_texture_mode(Line2D::LINE_TEXTURE_STRETCH);
@@ -2822,7 +2845,7 @@ GraphEdit::GraphEdit() {
zoom_minus_button->set_tooltip_text(ETR("Zoom Out"));
zoom_minus_button->set_focus_mode(FOCUS_NONE);
menu_hbox->add_child(zoom_minus_button);
- zoom_minus_button->connect("pressed", callable_mp(this, &GraphEdit::_zoom_minus));
+ zoom_minus_button->connect(SceneStringName(pressed), callable_mp(this, &GraphEdit::_zoom_minus));
zoom_reset_button = memnew(Button);
zoom_reset_button->set_theme_type_variation("FlatButton");
@@ -2830,7 +2853,7 @@ GraphEdit::GraphEdit() {
zoom_reset_button->set_tooltip_text(ETR("Zoom Reset"));
zoom_reset_button->set_focus_mode(FOCUS_NONE);
menu_hbox->add_child(zoom_reset_button);
- zoom_reset_button->connect("pressed", callable_mp(this, &GraphEdit::_zoom_reset));
+ zoom_reset_button->connect(SceneStringName(pressed), callable_mp(this, &GraphEdit::_zoom_reset));
zoom_plus_button = memnew(Button);
zoom_plus_button->set_theme_type_variation("FlatButton");
@@ -2838,7 +2861,7 @@ GraphEdit::GraphEdit() {
zoom_plus_button->set_tooltip_text(ETR("Zoom In"));
zoom_plus_button->set_focus_mode(FOCUS_NONE);
menu_hbox->add_child(zoom_plus_button);
- zoom_plus_button->connect("pressed", callable_mp(this, &GraphEdit::_zoom_plus));
+ zoom_plus_button->connect(SceneStringName(pressed), callable_mp(this, &GraphEdit::_zoom_plus));
// Grid controls.
@@ -2850,7 +2873,7 @@ GraphEdit::GraphEdit() {
toggle_grid_button->set_tooltip_text(ETR("Toggle the visual grid."));
toggle_grid_button->set_focus_mode(FOCUS_NONE);
menu_hbox->add_child(toggle_grid_button);
- toggle_grid_button->connect("pressed", callable_mp(this, &GraphEdit::_show_grid_toggled));
+ toggle_grid_button->connect(SceneStringName(pressed), callable_mp(this, &GraphEdit::_show_grid_toggled));
toggle_snapping_button = memnew(Button);
toggle_snapping_button->set_theme_type_variation("FlatButton");
@@ -2860,7 +2883,7 @@ GraphEdit::GraphEdit() {
toggle_snapping_button->set_pressed(snapping_enabled);
toggle_snapping_button->set_focus_mode(FOCUS_NONE);
menu_hbox->add_child(toggle_snapping_button);
- toggle_snapping_button->connect("pressed", callable_mp(this, &GraphEdit::_snapping_toggled));
+ toggle_snapping_button->connect(SceneStringName(pressed), callable_mp(this, &GraphEdit::_snapping_toggled));
snapping_distance_spinbox = memnew(SpinBox);
snapping_distance_spinbox->set_visible(show_grid_buttons);
@@ -2882,12 +2905,12 @@ GraphEdit::GraphEdit() {
minimap_button->set_pressed(show_grid);
minimap_button->set_focus_mode(FOCUS_NONE);
menu_hbox->add_child(minimap_button);
- minimap_button->connect("pressed", callable_mp(this, &GraphEdit::_minimap_toggled));
+ minimap_button->connect(SceneStringName(pressed), callable_mp(this, &GraphEdit::_minimap_toggled));
arrange_button = memnew(Button);
arrange_button->set_theme_type_variation("FlatButton");
arrange_button->set_visible(show_arrange_button);
- arrange_button->connect("pressed", callable_mp(this, &GraphEdit::arrange_nodes));
+ arrange_button->connect(SceneStringName(pressed), callable_mp(this, &GraphEdit::arrange_nodes));
arrange_button->set_focus_mode(FOCUS_NONE);
menu_hbox->add_child(arrange_button);
arrange_button->set_tooltip_text(ETR("Automatically arrange selected nodes."));
@@ -2909,7 +2932,7 @@ GraphEdit::GraphEdit() {
minimap->set_offset(Side::SIDE_TOP, -minimap_size.height - MINIMAP_OFFSET);
minimap->set_offset(Side::SIDE_RIGHT, -MINIMAP_OFFSET);
minimap->set_offset(Side::SIDE_BOTTOM, -MINIMAP_OFFSET);
- minimap->connect("draw", callable_mp(this, &GraphEdit::_minimap_draw));
+ minimap->connect(SceneStringName(draw), callable_mp(this, &GraphEdit::_minimap_draw));
set_clip_contents(true);
diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h
index eeda9ae200..20c98c462c 100644
--- a/scene/gui/graph_edit.h
+++ b/scene/gui/graph_edit.h
@@ -328,7 +328,7 @@ private:
void _top_connection_layer_input(const Ref<InputEvent> &p_ev);
float _get_shader_line_width();
- void _draw_minimap_connection_line(CanvasItem *p_where, const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, const Color &p_to_color);
+ void _draw_minimap_connection_line(const Vector2 &p_from_graph_position, const Vector2 &p_to_graph_position, const Color &p_from_color, const Color &p_to_color);
void _invalidate_connection_line_cache();
void _update_top_connection_layer();
void _update_connections();
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 75ac5c5135..d804f83e1c 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -604,6 +604,14 @@ void GraphNode::set_slot_draw_stylebox(int p_slot_index, bool p_enable) {
emit_signal(SNAME("slot_updated"), p_slot_index);
}
+void GraphNode::set_ignore_invalid_connection_type(bool p_ignore) {
+ ignore_invalid_connection_type = p_ignore;
+}
+
+bool GraphNode::is_ignoring_valid_connection_type() const {
+ return ignore_invalid_connection_type;
+}
+
Size2 GraphNode::get_minimum_size() const {
Ref<StyleBox> sb_panel = theme_cache.panel;
Ref<StyleBox> sb_titlebar = theme_cache.titlebar;
@@ -859,6 +867,9 @@ void GraphNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_slot_draw_stylebox", "slot_index"), &GraphNode::is_slot_draw_stylebox);
ClassDB::bind_method(D_METHOD("set_slot_draw_stylebox", "slot_index", "enable"), &GraphNode::set_slot_draw_stylebox);
+ ClassDB::bind_method(D_METHOD("set_ignore_invalid_connection_type", "ignore"), &GraphNode::set_ignore_invalid_connection_type);
+ ClassDB::bind_method(D_METHOD("is_ignoring_valid_connection_type"), &GraphNode::is_ignoring_valid_connection_type);
+
ClassDB::bind_method(D_METHOD("get_input_port_count"), &GraphNode::get_input_port_count);
ClassDB::bind_method(D_METHOD("get_input_port_position", "port_idx"), &GraphNode::get_input_port_position);
ClassDB::bind_method(D_METHOD("get_input_port_type", "port_idx"), &GraphNode::get_input_port_type);
@@ -874,6 +885,8 @@ void GraphNode::_bind_methods() {
GDVIRTUAL_BIND(_draw_port, "slot_index", "position", "left", "color")
ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_invalid_connection_type"), "set_ignore_invalid_connection_type", "is_ignoring_valid_connection_type");
+
ADD_SIGNAL(MethodInfo("slot_updated", PropertyInfo(Variant::INT, "slot_index")));
BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, GraphNode, panel);
diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h
index 71cc322baa..27af3192c8 100644
--- a/scene/gui/graph_node.h
+++ b/scene/gui/graph_node.h
@@ -95,6 +95,8 @@ class GraphNode : public GraphElement {
bool port_pos_dirty = true;
+ bool ignore_invalid_connection_type = false;
+
void _port_pos_update();
protected:
@@ -147,6 +149,9 @@ public:
bool is_slot_draw_stylebox(int p_slot_index) const;
void set_slot_draw_stylebox(int p_slot_index, bool p_enable);
+ void set_ignore_invalid_connection_type(bool p_ignore);
+ bool is_ignoring_valid_connection_type() const;
+
int get_input_port_count();
Vector2 get_input_port_position(int p_port_idx);
int get_input_port_type(int p_port_idx);
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 8376ef48b6..cfb46aebc8 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -1882,6 +1882,7 @@ void ItemList::_bind_methods() {
Item defaults(true);
base_property_helper.set_prefix("item_");
+ base_property_helper.set_array_length_getter(&ItemList::get_item_count);
base_property_helper.register_property(PropertyInfo(Variant::STRING, "text"), defaults.text, &ItemList::set_item_text, &ItemList::get_item_text);
base_property_helper.register_property(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), defaults.icon, &ItemList::set_item_icon, &ItemList::get_item_icon);
base_property_helper.register_property(PropertyInfo(Variant::BOOL, "selectable"), defaults.selectable, &ItemList::set_item_selectable, &ItemList::is_item_selectable);
@@ -1893,7 +1894,7 @@ ItemList::ItemList() {
add_child(scroll_bar, false, INTERNAL_MODE_FRONT);
scroll_bar->connect("value_changed", callable_mp(this, &ItemList::_scroll_changed));
- connect("mouse_exited", callable_mp(this, &ItemList::_mouse_exited));
+ connect(SceneStringName(mouse_exited), callable_mp(this, &ItemList::_mouse_exited));
set_focus_mode(FOCUS_ALL);
set_clip_contents(true);
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index c263e14b8a..729e219825 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -2473,8 +2473,8 @@ void LineEdit::_generate_context_menu() {
menu_dir->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));
menu_ctl->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));
- menu->connect(SNAME("focus_entered"), callable_mp(this, &LineEdit::_validate_caret_can_draw));
- menu->connect(SNAME("focus_exited"), callable_mp(this, &LineEdit::_validate_caret_can_draw));
+ menu->connect(SceneStringName(focus_entered), callable_mp(this, &LineEdit::_validate_caret_can_draw));
+ menu->connect(SceneStringName(focus_exited), callable_mp(this, &LineEdit::_validate_caret_can_draw));
}
void LineEdit::_update_context_menu() {
diff --git a/scene/gui/margin_container.cpp b/scene/gui/margin_container.cpp
index 91e6c1f092..06e4a7cc13 100644
--- a/scene/gui/margin_container.cpp
+++ b/scene/gui/margin_container.cpp
@@ -36,8 +36,8 @@ Size2 MarginContainer::get_minimum_size() const {
Size2 max;
for (int i = 0; i < get_child_count(); i++) {
- Control *c = as_sortable_control(get_child(i));
- if (!c) {
+ Control *c = Object::cast_to<Control>(get_child(i));
+ if (!c || !c->is_visible() || c->is_set_as_top_level()) {
continue;
}
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index e83d9c7c1b..998f99b2f9 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -190,6 +190,7 @@ void MenuButton::_bind_methods() {
PopupMenu::Item defaults(true);
base_property_helper.set_prefix("popup/item_");
+ base_property_helper.set_array_length_getter(&MenuButton::get_item_count);
base_property_helper.register_property(PropertyInfo(Variant::STRING, "text"), defaults.text);
base_property_helper.register_property(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), defaults.icon);
base_property_helper.register_property(PropertyInfo(Variant::INT, "checkable", PROPERTY_HINT_ENUM, "No,As Checkbox,As Radio Button"), defaults.checkable_type);
diff --git a/scene/gui/nine_patch_rect.cpp b/scene/gui/nine_patch_rect.cpp
index e2ae824e60..f9181d2a2d 100644
--- a/scene/gui/nine_patch_rect.cpp
+++ b/scene/gui/nine_patch_rect.cpp
@@ -30,7 +30,6 @@
#include "nine_patch_rect.h"
-#include "scene/scene_string_names.h"
#include "servers/rendering_server.h"
void NinePatchRect::_notification(int p_what) {
@@ -111,7 +110,7 @@ void NinePatchRect::set_texture(const Ref<Texture2D> &p_tex) {
queue_redraw();
update_minimum_size();
- emit_signal(SceneStringNames::get_singleton()->texture_changed);
+ emit_signal(SceneStringName(texture_changed));
}
Ref<Texture2D> NinePatchRect::get_texture() const {
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index 509c6aca99..68e72ea996 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -60,7 +60,7 @@ Size2 OptionButton::get_minimum_size() const {
}
if (has_theme_icon(SNAME("arrow"))) {
- const Size2 padding = _get_current_stylebox()->get_minimum_size();
+ const Size2 padding = _get_largest_stylebox_size();
const Size2 arrow_size = theme_cache.arrow_icon->get_size();
Size2 content_size = minsize - padding;
@@ -571,6 +571,7 @@ void OptionButton::_bind_methods() {
PopupMenu::Item defaults(true);
base_property_helper.set_prefix("popup/item_");
+ base_property_helper.set_array_length_getter(&OptionButton::get_item_count);
base_property_helper.register_property(PropertyInfo(Variant::STRING, "text"), defaults.text, &OptionButton::_dummy_setter, &OptionButton::get_item_text);
base_property_helper.register_property(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), defaults.icon, &OptionButton::_dummy_setter, &OptionButton::get_item_icon);
base_property_helper.register_property(PropertyInfo(Variant::INT, "id", PROPERTY_HINT_RANGE, "0,10,1,or_greater"), defaults.id, &OptionButton::_dummy_setter, &OptionButton::get_item_id);
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp
index 97b33c4f74..38204af6d5 100644
--- a/scene/gui/popup.cpp
+++ b/scene/gui/popup.cpp
@@ -37,6 +37,7 @@
void Popup::_input_from_window(const Ref<InputEvent> &p_event) {
if (get_flag(FLAG_POPUP) && p_event->is_action_pressed(SNAME("ui_cancel"), false, true)) {
+ hide_reason = HIDE_REASON_CANCELED; // ESC pressed, mark as canceled unconditionally.
_close_pressed();
}
Window::_input_from_window(p_event);
@@ -51,8 +52,8 @@ void Popup::_initialize_visible_parents() {
parent_window = parent_window->get_parent_visible_window();
if (parent_window) {
visible_parents.push_back(parent_window);
- parent_window->connect("focus_entered", callable_mp(this, &Popup::_parent_focused));
- parent_window->connect("tree_exited", callable_mp(this, &Popup::_deinitialize_visible_parents));
+ parent_window->connect(SceneStringName(focus_entered), callable_mp(this, &Popup::_parent_focused));
+ parent_window->connect(SceneStringName(tree_exited), callable_mp(this, &Popup::_deinitialize_visible_parents));
}
}
}
@@ -61,8 +62,8 @@ void Popup::_initialize_visible_parents() {
void Popup::_deinitialize_visible_parents() {
if (is_embedded()) {
for (Window *parent_window : visible_parents) {
- parent_window->disconnect("focus_entered", callable_mp(this, &Popup::_parent_focused));
- parent_window->disconnect("tree_exited", callable_mp(this, &Popup::_deinitialize_visible_parents));
+ parent_window->disconnect(SceneStringName(focus_entered), callable_mp(this, &Popup::_parent_focused));
+ parent_window->disconnect(SceneStringName(tree_exited), callable_mp(this, &Popup::_deinitialize_visible_parents));
}
visible_parents.clear();
@@ -104,13 +105,18 @@ void Popup::_notification(int p_what) {
case NOTIFICATION_WM_CLOSE_REQUEST: {
if (!is_in_edited_scene_root()) {
- hide_reason = HIDE_REASON_UNFOCUSED;
+ if (hide_reason == HIDE_REASON_NONE) {
+ hide_reason = HIDE_REASON_UNFOCUSED;
+ }
_close_pressed();
}
} break;
case NOTIFICATION_APPLICATION_FOCUS_OUT: {
if (!is_in_edited_scene_root() && get_flag(FLAG_POPUP)) {
+ if (hide_reason == HIDE_REASON_NONE) {
+ hide_reason = HIDE_REASON_UNFOCUSED;
+ }
_close_pressed();
}
} break;
@@ -119,7 +125,9 @@ void Popup::_notification(int p_what) {
void Popup::_parent_focused() {
if (popped_up && get_flag(FLAG_POPUP)) {
- hide_reason = HIDE_REASON_UNFOCUSED;
+ if (hide_reason == HIDE_REASON_NONE) {
+ hide_reason = HIDE_REASON_UNFOCUSED;
+ }
_close_pressed();
}
}
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 9b991972be..bdd0102b63 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -1014,9 +1014,6 @@ void PopupMenu::_notification(int p_what) {
float pm_delay = pm->get_submenu_popup_delay();
set_submenu_popup_delay(pm_delay);
}
- if (!is_embedded()) {
- set_flag(FLAG_NO_FOCUS, true);
- }
if (system_menu_id != NativeMenu::INVALID_MENU_ID) {
bind_global_menu();
}
@@ -2808,6 +2805,7 @@ void PopupMenu::_bind_methods() {
Item defaults(true);
base_property_helper.set_prefix("item_");
+ base_property_helper.set_array_length_getter(&PopupMenu::get_item_count);
base_property_helper.register_property(PropertyInfo(Variant::STRING, "text"), defaults.text, &PopupMenu::set_item_text, &PopupMenu::get_item_text);
base_property_helper.register_property(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), defaults.icon, &PopupMenu::set_item_icon, &PopupMenu::get_item_icon);
base_property_helper.register_property(PropertyInfo(Variant::INT, "checkable", PROPERTY_HINT_ENUM, "No,As checkbox,As radio button"), defaults.checkable_type, &PopupMenu::_set_item_checkable_type, &PopupMenu::_get_item_checkable_type);
@@ -2828,6 +2826,8 @@ void PopupMenu::popup(const Rect2i &p_bounds) {
if (native) {
NativeMenu::get_singleton()->popup(global_menu, (p_bounds != Rect2i()) ? p_bounds.position : get_position());
} else {
+ set_flag(FLAG_NO_FOCUS, !is_embedded());
+
moved = Vector2();
popup_time_msec = OS::get_singleton()->get_ticks_msec();
if (!is_embedded()) {
@@ -2855,6 +2855,8 @@ void PopupMenu::set_visible(bool p_visible) {
NativeMenu::get_singleton()->popup(global_menu, get_position());
}
} else {
+ set_flag(FLAG_NO_FOCUS, !is_embedded());
+
Popup::set_visible(p_visible);
}
}
@@ -2873,7 +2875,7 @@ PopupMenu::PopupMenu() {
control->set_h_size_flags(Control::SIZE_EXPAND_FILL);
control->set_v_size_flags(Control::SIZE_EXPAND_FILL);
scroll_container->add_child(control, false, INTERNAL_MODE_FRONT);
- control->connect("draw", callable_mp(this, &PopupMenu::_draw_items));
+ control->connect(SceneStringName(draw), callable_mp(this, &PopupMenu::_draw_items));
submenu_timer = memnew(Timer);
submenu_timer->set_wait_time(0.3);
diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp
index 236dfcc864..00f4a1089a 100644
--- a/scene/gui/range.cpp
+++ b/scene/gui/range.cpp
@@ -60,7 +60,7 @@ void Range::Shared::emit_value_changed() {
}
void Range::_changed_notify(const char *p_what) {
- emit_signal(SNAME("changed"));
+ emit_signal(CoreStringName(changed));
queue_redraw();
}
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 19b02f33c6..f6942ca206 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -39,7 +39,6 @@
#include "scene/gui/label.h"
#include "scene/gui/rich_text_effect.h"
#include "scene/resources/atlas_texture.h"
-#include "scene/scene_string_names.h"
#include "scene/theme/theme_db.h"
#include "servers/display_server.h"
@@ -1608,8 +1607,34 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
if (p_meta) {
int64_t glyph_idx = TS->shaped_text_hit_test_grapheme(rid, p_click.x - rect.position.x);
if (glyph_idx >= 0) {
+ float baseline_y = rect.position.y + TS->shaped_text_get_ascent(rid);
const Glyph *glyphs = TS->shaped_text_get_glyphs(rid);
- char_pos = glyphs[glyph_idx].start;
+ if (glyphs[glyph_idx].flags & TextServer::GRAPHEME_IS_EMBEDDED_OBJECT) {
+ // Emebedded object.
+ for (int i = 0; i < objects.size(); i++) {
+ if (TS->shaped_text_get_object_glyph(rid, objects[i]) == glyph_idx) {
+ Rect2 obj_rect = TS->shaped_text_get_object_rect(rid, objects[i]);
+ obj_rect.position.y += baseline_y;
+ if (p_click.y >= obj_rect.position.y && p_click.y <= obj_rect.position.y + obj_rect.size.y) {
+ char_pos = glyphs[glyph_idx].start;
+ }
+ break;
+ }
+ }
+ } else if (glyphs[glyph_idx].font_rid != RID()) {
+ // Normal glyph.
+ float fa = TS->font_get_ascent(glyphs[glyph_idx].font_rid, glyphs[glyph_idx].font_size);
+ float fd = TS->font_get_descent(glyphs[glyph_idx].font_rid, glyphs[glyph_idx].font_size);
+ if (p_click.y >= baseline_y - fa && p_click.y <= baseline_y + fd) {
+ char_pos = glyphs[glyph_idx].start;
+ }
+ } else if (!(glyphs[glyph_idx].flags & TextServer::GRAPHEME_IS_VIRTUAL)) {
+ // Hex code box.
+ Vector2 gl_size = TS->get_hex_code_box_size(glyphs[glyph_idx].font_size, glyphs[glyph_idx].index);
+ if (p_click.y >= baseline_y - gl_size.y * 0.9 && p_click.y <= baseline_y + gl_size.y * 0.2) {
+ char_pos = glyphs[glyph_idx].start;
+ }
+ }
}
} else {
char_pos = TS->shaped_text_hit_test_position(rid, p_click.x - rect.position.x);
@@ -2993,7 +3018,7 @@ void RichTextLabel::_process_line_caches() {
if (fit_content) {
update_minimum_size();
}
- emit_signal(SNAME("finished"));
+ emit_signal(SceneStringName(finished));
}
void RichTextLabel::_invalidate_current_line(ItemFrame *p_frame) {
diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp
index b35c4e9308..af9f08e389 100644
--- a/scene/gui/scroll_bar.cpp
+++ b/scene/gui/scroll_bar.cpp
@@ -310,15 +310,15 @@ void ScrollBar::_notification(int p_what) {
}
if (drag_node) {
- drag_node->connect("gui_input", callable_mp(this, &ScrollBar::_drag_node_input));
- drag_node->connect("tree_exiting", callable_mp(this, &ScrollBar::_drag_node_exit), CONNECT_ONE_SHOT);
+ drag_node->connect(SceneStringName(gui_input), callable_mp(this, &ScrollBar::_drag_node_input));
+ drag_node->connect(SceneStringName(tree_exiting), callable_mp(this, &ScrollBar::_drag_node_exit), CONNECT_ONE_SHOT);
}
} break;
case NOTIFICATION_EXIT_TREE: {
if (drag_node) {
- drag_node->disconnect("gui_input", callable_mp(this, &ScrollBar::_drag_node_input));
- drag_node->disconnect("tree_exiting", callable_mp(this, &ScrollBar::_drag_node_exit));
+ drag_node->disconnect(SceneStringName(gui_input), callable_mp(this, &ScrollBar::_drag_node_input));
+ drag_node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &ScrollBar::_drag_node_exit));
}
drag_node = nullptr;
@@ -522,7 +522,7 @@ float ScrollBar::get_custom_step() const {
void ScrollBar::_drag_node_exit() {
if (drag_node) {
- drag_node->disconnect("gui_input", callable_mp(this, &ScrollBar::_drag_node_input));
+ drag_node->disconnect(SceneStringName(gui_input), callable_mp(this, &ScrollBar::_drag_node_input));
}
drag_node = nullptr;
}
@@ -591,8 +591,8 @@ void ScrollBar::_drag_node_input(const Ref<InputEvent> &p_input) {
void ScrollBar::set_drag_node(const NodePath &p_path) {
if (is_inside_tree()) {
if (drag_node) {
- drag_node->disconnect("gui_input", callable_mp(this, &ScrollBar::_drag_node_input));
- drag_node->disconnect("tree_exiting", callable_mp(this, &ScrollBar::_drag_node_exit));
+ drag_node->disconnect(SceneStringName(gui_input), callable_mp(this, &ScrollBar::_drag_node_input));
+ drag_node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &ScrollBar::_drag_node_exit));
}
}
@@ -606,8 +606,8 @@ void ScrollBar::set_drag_node(const NodePath &p_path) {
}
if (drag_node) {
- drag_node->connect("gui_input", callable_mp(this, &ScrollBar::_drag_node_input));
- drag_node->connect("tree_exiting", callable_mp(this, &ScrollBar::_drag_node_exit), CONNECT_ONE_SHOT);
+ drag_node->connect(SceneStringName(gui_input), callable_mp(this, &ScrollBar::_drag_node_input));
+ drag_node->connect(SceneStringName(tree_exiting), callable_mp(this, &ScrollBar::_drag_node_exit), CONNECT_ONE_SHOT);
}
}
}
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index 70acaf7adf..bfea7b0fbe 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -409,9 +409,9 @@ SpinBox::SpinBox() {
line_edit->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_LEFT);
line_edit->connect("text_submitted", callable_mp(this, &SpinBox::_text_submitted), CONNECT_DEFERRED);
- line_edit->connect("focus_entered", callable_mp(this, &SpinBox::_line_edit_focus_enter), CONNECT_DEFERRED);
- line_edit->connect("focus_exited", callable_mp(this, &SpinBox::_line_edit_focus_exit), CONNECT_DEFERRED);
- line_edit->connect("gui_input", callable_mp(this, &SpinBox::_line_edit_input));
+ line_edit->connect(SceneStringName(focus_entered), callable_mp(this, &SpinBox::_line_edit_focus_enter), CONNECT_DEFERRED);
+ line_edit->connect(SceneStringName(focus_exited), callable_mp(this, &SpinBox::_line_edit_focus_exit), CONNECT_DEFERRED);
+ line_edit->connect(SceneStringName(gui_input), callable_mp(this, &SpinBox::_line_edit_input));
range_click_timer = memnew(Timer);
range_click_timer->connect("timeout", callable_mp(this, &SpinBox::_range_click_timeout));
diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp
index 98b1db4a96..925600756a 100644
--- a/scene/gui/split_container.cpp
+++ b/scene/gui/split_container.cpp
@@ -39,7 +39,7 @@ void SplitContainerDragger::gui_input(const Ref<InputEvent> &p_event) {
SplitContainer *sc = Object::cast_to<SplitContainer>(get_parent());
- if (sc->collapsed || !sc->get_containable_child(0) || !sc->get_containable_child(1) || sc->dragger_visibility != SplitContainer::DRAGGER_VISIBLE) {
+ if (sc->collapsed || !sc->_get_sortable_child(0) || !sc->_get_sortable_child(1) || sc->dragger_visibility != SplitContainer::DRAGGER_VISIBLE) {
return;
}
@@ -122,12 +122,12 @@ void SplitContainerDragger::_notification(int p_what) {
}
}
-Control *SplitContainer::get_containable_child(int p_idx) const {
+Control *SplitContainer::_get_sortable_child(int p_idx) const {
int idx = 0;
for (int i = 0; i < get_child_count(false); i++) {
- Control *c = Object::cast_to<Control>(get_child(i, false));
- if (!c || !c->is_visible() || c->is_set_as_top_level()) {
+ Control *c = as_sortable_control(get_child(i, false));
+ if (!c) {
continue;
}
@@ -154,8 +154,8 @@ Ref<Texture2D> SplitContainer::_get_grabber_icon() const {
}
void SplitContainer::_compute_middle_sep(bool p_clamp) {
- Control *first = get_containable_child(0);
- Control *second = get_containable_child(1);
+ Control *first = _get_sortable_child(0);
+ Control *second = _get_sortable_child(1);
// Determine expanded children.
bool first_expanded = (vertical ? first->get_v_size_flags() : first->get_h_size_flags()) & SIZE_EXPAND;
@@ -196,8 +196,8 @@ void SplitContainer::_compute_middle_sep(bool p_clamp) {
}
void SplitContainer::_resort() {
- Control *first = get_containable_child(0);
- Control *second = get_containable_child(1);
+ Control *first = _get_sortable_child(0);
+ Control *second = _get_sortable_child(1);
// If we have only one element.
if (!first || !second) {
@@ -258,7 +258,7 @@ Size2 SplitContainer::get_minimum_size() const {
int sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(theme_cache.separation, vertical ? g->get_height() : g->get_width()) : 0;
for (int i = 0; i < 2; i++) {
- if (!get_containable_child(i)) {
+ if (!_get_sortable_child(i)) {
break;
}
@@ -270,7 +270,7 @@ Size2 SplitContainer::get_minimum_size() const {
}
}
- Size2 ms = get_containable_child(i)->get_combined_minimum_size();
+ Size2 ms = _get_sortable_child(i)->get_combined_minimum_size();
if (vertical) {
minimum.height += ms.height;
@@ -322,7 +322,7 @@ int SplitContainer::get_split_offset() const {
}
void SplitContainer::clamp_split_offset() {
- if (!get_containable_child(0) || !get_containable_child(1)) {
+ if (!_get_sortable_child(0) || !_get_sortable_child(1)) {
return;
}
diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h
index 0f45ef166d..95f26f5e0b 100644
--- a/scene/gui/split_container.h
+++ b/scene/gui/split_container.h
@@ -82,12 +82,11 @@ private:
Ref<Texture2D> _get_grabber_icon() const;
void _compute_middle_sep(bool p_clamp);
void _resort();
+ Control *_get_sortable_child(int p_idx) const;
protected:
bool is_fixed = false;
- Control *get_containable_child(int p_idx) const;
-
void _notification(int p_what);
void _validate_property(PropertyInfo &p_property) const;
static void _bind_methods();
diff --git a/scene/gui/subviewport_container.cpp b/scene/gui/subviewport_container.cpp
index f6cfe6ab18..c715aceb0b 100644
--- a/scene/gui/subviewport_container.cpp
+++ b/scene/gui/subviewport_container.cpp
@@ -287,7 +287,7 @@ void SubViewportContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_stretch_shrink"), &SubViewportContainer::get_stretch_shrink);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stretch"), "set_stretch", "is_stretch_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "stretch_shrink"), "set_stretch_shrink", "get_stretch_shrink");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "stretch_shrink", PROPERTY_HINT_RANGE, "1,32,1,or_greater"), "set_stretch_shrink", "get_stretch_shrink");
GDVIRTUAL_BIND(_propagate_input_event, "event");
}
diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp
index 0e130d60af..ddc757c452 100644
--- a/scene/gui/tab_bar.cpp
+++ b/scene/gui/tab_bar.cpp
@@ -1868,6 +1868,7 @@ void TabBar::_bind_methods() {
Tab defaults(true);
base_property_helper.set_prefix("tab_");
+ base_property_helper.set_array_length_getter(&TabBar::get_tab_count);
base_property_helper.register_property(PropertyInfo(Variant::STRING, "title"), defaults.text, &TabBar::set_tab_title, &TabBar::get_tab_title);
base_property_helper.register_property(PropertyInfo(Variant::STRING, "tooltip"), defaults.tooltip, &TabBar::set_tab_tooltip, &TabBar::get_tab_tooltip);
base_property_helper.register_property(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), defaults.icon, &TabBar::set_tab_icon, &TabBar::get_tab_icon);
@@ -1877,7 +1878,7 @@ void TabBar::_bind_methods() {
TabBar::TabBar() {
set_size(Size2(get_size().width, get_minimum_size().height));
set_focus_mode(FOCUS_ALL);
- connect("mouse_exited", callable_mp(this, &TabBar::_on_mouse_exited));
+ connect(SceneStringName(mouse_exited), callable_mp(this, &TabBar::_on_mouse_exited));
property_helper.setup_for_instance(base_property_helper, this);
}
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index dc53cf82e6..d0c3f3d65e 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -554,7 +554,7 @@ void TabContainer::add_child_notify(Node *p_child) {
}
p_child->connect("renamed", callable_mp(this, &TabContainer::_refresh_tab_names));
- p_child->connect(SNAME("visibility_changed"), callable_mp(this, &TabContainer::_on_tab_visibility_changed).bind(c));
+ p_child->connect(SceneStringName(visibility_changed), callable_mp(this, &TabContainer::_on_tab_visibility_changed).bind(c));
// TabBar won't emit the "tab_changed" signal when not inside the tree.
if (!is_inside_tree()) {
@@ -607,7 +607,7 @@ void TabContainer::remove_child_notify(Node *p_child) {
p_child->remove_meta("_tab_index");
p_child->remove_meta("_tab_name");
p_child->disconnect("renamed", callable_mp(this, &TabContainer::_refresh_tab_names));
- p_child->disconnect(SNAME("visibility_changed"), callable_mp(this, &TabContainer::_on_tab_visibility_changed));
+ p_child->disconnect(SceneStringName(visibility_changed), callable_mp(this, &TabContainer::_on_tab_visibility_changed));
// TabBar won't emit the "tab_changed" signal when not inside the tree.
if (!is_inside_tree()) {
@@ -1121,5 +1121,5 @@ TabContainer::TabContainer() {
tab_bar->connect("tab_button_pressed", callable_mp(this, &TabContainer::_on_tab_button_pressed));
tab_bar->connect("active_tab_rearranged", callable_mp(this, &TabContainer::_on_active_tab_rearranged));
- connect("mouse_exited", callable_mp(this, &TabContainer::_on_mouse_exited));
+ connect(SceneStringName(mouse_exited), callable_mp(this, &TabContainer::_on_mouse_exited));
}
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 49cfa8a030..1dd00fab4d 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -558,8 +558,6 @@ void TextEdit::_notification(int p_what) {
int visible_rows = get_visible_line_count() + 1;
- Color color = !editable ? theme_cache.font_readonly_color : theme_cache.font_color;
-
if (theme_cache.background_color.a > 0.01) {
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(), get_size()), theme_cache.background_color);
}
@@ -734,7 +732,7 @@ void TextEdit::_notification(int p_what) {
if (draw_minimap) {
int minimap_visible_lines = get_minimap_visible_lines();
int minimap_line_height = (minimap_char_size.y + minimap_line_spacing);
- int minimap_tab_size = minimap_char_size.x * text.get_tab_size();
+ int tab_size = text.get_tab_size();
// Calculate viewport size and y offset.
int viewport_height = (draw_amount - 1) * minimap_line_height;
@@ -839,68 +837,74 @@ void TextEdit::_notification(int p_what) {
}
}
- Color previous_color;
+ Color next_color = current_color;
int characters = 0;
- int tabs = 0;
+ int tab_alignment = 0;
+ int xpos = xmargin_end + 2 + indent_px;
for (int j = 0; j < str.length(); j++) {
- const Variant *color_data = color_map.getptr(last_wrap_column + j);
- if (color_data != nullptr) {
- current_color = (color_data->operator Dictionary()).get("color", theme_cache.font_color);
- if (!editable) {
- current_color.a = theme_cache.font_readonly_color.a;
+ bool next_is_whitespace = false;
+ bool next_is_tab = false;
+ // Get the number of characters to draw together.
+ for (characters = 0; j + characters < str.length(); characters++) {
+ int next_char_index = j + characters;
+ const Variant *color_data = color_map.getptr(last_wrap_column + next_char_index);
+ if (color_data != nullptr) {
+ next_color = (color_data->operator Dictionary()).get("color", theme_cache.font_color);
+ if (!editable) {
+ next_color.a = theme_cache.font_readonly_color.a;
+ }
+ next_color.a *= 0.6;
}
- }
- color = current_color;
-
- if (j == 0) {
- previous_color = color;
- }
-
- int xpos = indent_px + ((xmargin_end + minimap_char_size.x) + (minimap_char_size.x * j)) + tabs;
- bool out_of_bounds = (xpos >= xmargin_end + minimap_width);
-
- bool whitespace = is_whitespace(str[j]);
- if (!whitespace) {
- characters++;
-
- if (j < str.length() - 1 && color == previous_color && !out_of_bounds) {
- continue;
+ if (characters == 0) {
+ current_color = next_color;
}
-
- // If we've changed color we are at the start of a new section, therefore we need to go back to the end
- // of the previous section to draw it, we'll also add the character back on.
- if (color != previous_color) {
- characters--;
- j--;
-
- if (str[j] == '\t') {
- tabs -= minimap_tab_size;
+ if (next_color != current_color) {
+ break;
+ }
+ next_is_whitespace = is_whitespace(str[next_char_index]);
+ if (next_is_whitespace) {
+ if (str[next_char_index] == '\t') {
+ next_is_tab = true;
}
+ break;
+ }
+ bool out_of_bounds = xpos + minimap_char_size.x * characters >= xmargin_end + minimap_width;
+ if (out_of_bounds) {
+ break;
}
}
+ if (!next_is_whitespace && characters == 0) {
+ break;
+ }
if (characters > 0) {
- previous_color.a *= 0.6;
- // Take one for zero indexing, and if we hit whitespace / the end of a word.
- int chars = MAX(0, (j - (characters - 1)) - (whitespace ? 1 : 0)) + 1;
- int char_x_ofs = indent_px + ((xmargin_end + minimap_char_size.x) + (minimap_char_size.x * chars)) + tabs;
if (rtl) {
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(size.width - char_x_ofs - minimap_char_size.x * characters, minimap_line_height * i), Point2(minimap_char_size.x * characters, minimap_char_size.y)), previous_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(size.width - xpos - minimap_char_size.x * characters, minimap_line_height * i), Point2(minimap_char_size.x * characters, minimap_char_size.y)), current_color);
} else {
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_x_ofs, minimap_line_height * i), Point2(minimap_char_size.x * characters, minimap_char_size.y)), previous_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(xpos, minimap_line_height * i), Point2(minimap_char_size.x * characters, minimap_char_size.y)), current_color);
}
}
- if (out_of_bounds) {
- break;
- }
+ j += characters - 1;
+ xpos += minimap_char_size.x * characters;
+ tab_alignment += characters;
- if (str[j] == '\t') {
- tabs += minimap_tab_size;
+ if (next_is_whitespace) {
+ if (next_is_tab) {
+ tab_alignment %= tab_size;
+ xpos += minimap_char_size.x * (tab_size - tab_alignment);
+ tab_alignment = 0;
+ } else {
+ xpos += minimap_char_size.x;
+ tab_alignment += 1;
+ }
+ j += 1;
}
- previous_color = color;
- characters = 0;
+ if (xpos >= xmargin_end + minimap_width) {
+ // Out of bounds.
+ break;
+ }
}
}
}
@@ -999,23 +1003,12 @@ void TextEdit::_notification(int p_what) {
}
}
- if (str.length() == 0) {
- // Draw line background if empty as we won't loop at all.
- if (caret_line_wrap_index_map.has(line) && caret_line_wrap_index_map[line].has(line_wrap_index) && highlight_current_line) {
- if (rtl) {
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - ofs_x - xmargin_end, ofs_y, xmargin_end, row_height), theme_cache.current_line_color);
- } else {
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(ofs_x, ofs_y, xmargin_end, row_height), theme_cache.current_line_color);
- }
- }
- } else {
- // If it has text, then draw current line marker in the margin, as line number etc will draw over it, draw the rest of line marker later.
- if (caret_line_wrap_index_map.has(line) && caret_line_wrap_index_map[line].has(line_wrap_index) && highlight_current_line) {
- if (rtl) {
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - ofs_x - xmargin_end, ofs_y, xmargin_end, row_height), theme_cache.current_line_color);
- } else {
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(ofs_x, ofs_y, xmargin_end, row_height), theme_cache.current_line_color);
- }
+ // Draw current line highlight.
+ if (highlight_current_line && caret_line_wrap_index_map.has(line) && caret_line_wrap_index_map[line].has(line_wrap_index)) {
+ if (rtl) {
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - ofs_x - xmargin_end, ofs_y, xmargin_end, row_height), theme_cache.current_line_color);
+ } else {
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(ofs_x, ofs_y, xmargin_end, row_height), theme_cache.current_line_color);
}
}
@@ -1188,6 +1181,7 @@ void TextEdit::_notification(int p_what) {
if (!clipped && lookup_symbol_word.length() != 0) { // Highlight word
if (is_ascii_alphabet_char(lookup_symbol_word[0]) || lookup_symbol_word[0] == '_' || lookup_symbol_word[0] == '.') {
+ Color highlight_underline_color = !editable ? theme_cache.font_readonly_color : theme_cache.font_color;
int lookup_symbol_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, 0);
int lookup_symbol_word_len = lookup_symbol_word.length();
while (lookup_symbol_word_col != -1) {
@@ -1205,7 +1199,7 @@ void TextEdit::_notification(int p_what) {
}
rect.position.y += ceil(TS->shaped_text_get_ascent(rid)) + ceil(theme_cache.font->get_underline_position(theme_cache.font_size));
rect.size.y = MAX(1, theme_cache.font->get_underline_thickness(theme_cache.font_size));
- draw_rect(rect, color);
+ draw_rect(rect, highlight_underline_color);
}
lookup_symbol_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, lookup_symbol_word_col + lookup_symbol_word_len);
@@ -4243,8 +4237,11 @@ String TextEdit::get_word_at_pos(const Vector2 &p_pos) const {
}
Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_of_bounds) const {
- float rows = p_pos.y;
- rows -= theme_cache.style_normal->get_margin(SIDE_TOP);
+ float rows = p_pos.y - theme_cache.style_normal->get_margin(SIDE_TOP);
+ if (!editable) {
+ rows -= theme_cache.style_readonly->get_offset().y / 2;
+ rows += theme_cache.style_normal->get_offset().y / 2;
+ }
rows /= get_line_height();
rows += _get_v_scroll_offset();
int first_vis_line = get_first_visible_line();
@@ -4275,6 +4272,10 @@ Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_
int col = 0;
int colx = p_pos.x - (theme_cache.style_normal->get_margin(SIDE_LEFT) + gutters_width + gutter_padding);
colx += first_visible_col;
+ if (!editable) {
+ colx -= theme_cache.style_readonly->get_offset().x / 2;
+ colx += theme_cache.style_normal->get_offset().x / 2;
+ }
col = _get_char_pos_for_line(colx, row, wrap_index);
if (get_line_wrapping_mode() != LineWrappingMode::LINE_WRAPPING_NONE && wrap_index < get_line_wrap_count(row)) {
// Move back one if we are at the end of the row.
@@ -7973,7 +7974,7 @@ void TextEdit::_update_minimap_click() {
Point2 mp = get_local_mouse_pos();
int xmargin_end = get_size().width - theme_cache.style_normal->get_margin(SIDE_RIGHT);
- if (!dragging_minimap && (mp.x < xmargin_end - minimap_width || mp.y > xmargin_end)) {
+ if (!dragging_minimap && (mp.x < xmargin_end - minimap_width || mp.x > xmargin_end)) {
minimap_clicked = false;
return;
}
diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp
index df90257e03..c267ff93c6 100644
--- a/scene/gui/texture_button.cpp
+++ b/scene/gui/texture_button.cpp
@@ -178,13 +178,14 @@ void TextureButton::_notification(int p_what) {
texdraw = focused;
}
- if (texdraw.is_valid()) {
- size = texdraw->get_size();
- _texture_region = Rect2(Point2(), texdraw->get_size());
+ if (texdraw.is_valid() || click_mask.is_valid()) {
+ const Size2 texdraw_size = texdraw.is_valid() ? texdraw->get_size() : Size2(click_mask->get_size());
+
+ size = texdraw_size;
+ _texture_region = Rect2(Point2(), texdraw_size);
_tile = false;
switch (stretch_mode) {
case STRETCH_KEEP:
- size = texdraw->get_size();
break;
case STRETCH_SCALE:
size = get_size();
@@ -194,18 +195,17 @@ void TextureButton::_notification(int p_what) {
_tile = true;
break;
case STRETCH_KEEP_CENTERED:
- ofs = (get_size() - texdraw->get_size()) / 2;
- size = texdraw->get_size();
+ ofs = (get_size() - texdraw_size) / 2;
break;
case STRETCH_KEEP_ASPECT_CENTERED:
case STRETCH_KEEP_ASPECT: {
Size2 _size = get_size();
- float tex_width = texdraw->get_width() * _size.height / texdraw->get_height();
+ float tex_width = texdraw_size.width * _size.height / texdraw_size.height;
float tex_height = _size.height;
if (tex_width > _size.width) {
tex_width = _size.width;
- tex_height = texdraw->get_height() * tex_width / texdraw->get_width();
+ tex_height = texdraw_size.height * tex_width / texdraw_size.width;
}
if (stretch_mode == STRETCH_KEEP_ASPECT_CENTERED) {
@@ -217,10 +217,9 @@ void TextureButton::_notification(int p_what) {
} break;
case STRETCH_KEEP_ASPECT_COVERED: {
size = get_size();
- Size2 tex_size = texdraw->get_size();
- Size2 scale_size(size.width / tex_size.width, size.height / tex_size.height);
+ Size2 scale_size = size / texdraw_size;
float scale = scale_size.width > scale_size.height ? scale_size.width : scale_size.height;
- Size2 scaled_tex_size = tex_size * scale;
+ Size2 scaled_tex_size = texdraw_size * scale;
Point2 ofs2 = ((scaled_tex_size - size) / scale).abs() / 2.0f;
_texture_region = Rect2(ofs2, size / scale);
} break;
@@ -233,10 +232,12 @@ void TextureButton::_notification(int p_what) {
if (draw_focus_only) {
// Do nothing, we only needed to calculate the rectangle.
- } else if (_tile) {
- draw_texture_rect(texdraw, Rect2(ofs, size), _tile);
- } else {
- draw_texture_rect_region(texdraw, Rect2(ofs, size), _texture_region);
+ } else if (texdraw.is_valid()) {
+ if (_tile) {
+ draw_texture_rect(texdraw, Rect2(ofs, size), _tile);
+ } else {
+ draw_texture_rect_region(texdraw, Rect2(ofs, size), _texture_region);
+ }
}
} else {
_position_rect = Rect2();
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index e2de585a69..fc5b942918 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -3152,8 +3152,12 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
}
void Tree::_text_editor_popup_modal_close() {
+ if (popup_edit_commited) {
+ return; // Already processed by LineEdit/TextEdit commit.
+ }
+
if (popup_editor->get_hide_reason() == Popup::HIDE_REASON_CANCELED) {
- return;
+ return; // ESC pressed, app focus lost, or forced close from code.
}
if (value_editor->has_point(value_editor->get_local_mouse_position())) {
@@ -3172,9 +3176,18 @@ void Tree::_text_editor_popup_modal_close() {
}
void Tree::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
+ if (popup_edit_commited) {
+ return; // Already processed by _text_editor_popup_modal_close
+ }
+
+ if (popup_editor->get_hide_reason() == Popup::HIDE_REASON_CANCELED) {
+ return; // ESC pressed, app focus lost, or forced close from code.
+ }
+
if (p_event->is_action_pressed("ui_text_newline_blank", true)) {
accept_event();
} else if (p_event->is_action_pressed("ui_text_newline")) {
+ popup_edit_commited = true; // End edit popup processing.
popup_editor->hide();
_apply_multiline_edit();
accept_event();
@@ -3205,6 +3218,15 @@ void Tree::_apply_multiline_edit() {
}
void Tree::_line_editor_submit(String p_text) {
+ if (popup_edit_commited) {
+ return; // Already processed by _text_editor_popup_modal_close
+ }
+
+ if (popup_editor->get_hide_reason() == Popup::HIDE_REASON_CANCELED) {
+ return; // ESC pressed, app focus lost, or forced close from code.
+ }
+
+ popup_edit_commited = true; // End edit popup processing.
popup_editor->hide();
if (!popup_edited_item) {
@@ -4072,6 +4094,7 @@ bool Tree::edit_selected(bool p_force_edit) {
if (!popup_editor->is_embedded()) {
popup_editor->set_content_scale_factor(popup_scale);
}
+ popup_edit_commited = false; // Start edit popup processing.
popup_editor->popup();
popup_editor->child_controls_changed();
@@ -4091,6 +4114,7 @@ bool Tree::edit_selected(bool p_force_edit) {
if (!popup_editor->is_embedded()) {
popup_editor->set_content_scale_factor(popup_scale);
}
+ popup_edit_commited = false; // Start edit popup processing.
popup_editor->popup();
popup_editor->child_controls_changed();
@@ -5795,7 +5819,7 @@ Tree::Tree() {
h_scroll->connect("value_changed", callable_mp(this, &Tree::_scroll_moved));
v_scroll->connect("value_changed", callable_mp(this, &Tree::_scroll_moved));
line_editor->connect("text_submitted", callable_mp(this, &Tree::_line_editor_submit));
- text_editor->connect("gui_input", callable_mp(this, &Tree::_text_editor_gui_input));
+ text_editor->connect(SceneStringName(gui_input), callable_mp(this, &Tree::_text_editor_gui_input));
popup_editor->connect("popup_hide", callable_mp(this, &Tree::_text_editor_popup_modal_close));
popup_menu->connect("id_pressed", callable_mp(this, &Tree::popup_select));
value_editor->connect("value_changed", callable_mp(this, &Tree::value_editor_changed));
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 311055a2f8..e9c93c6e03 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -479,6 +479,7 @@ private:
VBoxContainer *popup_editor_vb = nullptr;
+ bool popup_edit_commited = true;
Popup *popup_editor = nullptr;
LineEdit *line_editor = nullptr;
TextEdit *text_editor = nullptr;
diff --git a/scene/gui/video_stream_player.cpp b/scene/gui/video_stream_player.cpp
index 687a9e46a0..0b521f926d 100644
--- a/scene/gui/video_stream_player.cpp
+++ b/scene/gui/video_stream_player.cpp
@@ -31,7 +31,6 @@
#include "video_stream_player.h"
#include "core/os/os.h"
-#include "scene/scene_string_names.h"
#include "servers/audio_server.h"
int VideoStreamPlayer::sp_get_channel_count() const {
@@ -163,7 +162,7 @@ void VideoStreamPlayer::_notification(int p_notification) {
play();
return;
}
- emit_signal(SceneStringNames::get_singleton()->finished);
+ emit_signal(SceneStringName(finished));
}
} break;
@@ -460,7 +459,7 @@ StringName VideoStreamPlayer::get_bus() const {
return bus;
}
}
- return SceneStringNames::get_singleton()->Master;
+ return SceneStringName(Master);
}
void VideoStreamPlayer::_validate_property(PropertyInfo &p_property) const {