summaryrefslogtreecommitdiff
path: root/scene/gui
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui')
-rw-r--r--scene/gui/base_button.cpp27
-rw-r--r--scene/gui/box_container.cpp16
-rw-r--r--scene/gui/box_container.h7
-rw-r--r--scene/gui/button.cpp160
-rw-r--r--scene/gui/button.h38
-rw-r--r--scene/gui/check_box.cpp96
-rw-r--r--scene/gui/check_box.h17
-rw-r--r--scene/gui/check_button.cpp90
-rw-r--r--scene/gui/check_button.h17
-rw-r--r--scene/gui/code_edit.cpp56
-rw-r--r--scene/gui/color_picker.cpp28
-rw-r--r--scene/gui/color_rect.cpp2
-rw-r--r--scene/gui/control.cpp127
-rw-r--r--scene/gui/control.h8
-rw-r--r--scene/gui/dialogs.cpp31
-rw-r--r--scene/gui/dialogs.h7
-rw-r--r--scene/gui/file_dialog.cpp133
-rw-r--r--scene/gui/file_dialog.h21
-rw-r--r--scene/gui/flow_container.cpp30
-rw-r--r--scene/gui/flow_container.h8
-rw-r--r--scene/gui/gradient_edit.cpp446
-rw-r--r--scene/gui/gradient_edit.h86
-rw-r--r--scene/gui/graph_edit.cpp216
-rw-r--r--scene/gui/graph_edit.h5
-rw-r--r--scene/gui/graph_node.cpp68
-rw-r--r--scene/gui/graph_node.h8
-rw-r--r--scene/gui/grid_container.cpp27
-rw-r--r--scene/gui/grid_container.h7
-rw-r--r--scene/gui/item_list.cpp215
-rw-r--r--scene/gui/item_list.h28
-rw-r--r--scene/gui/label.cpp104
-rw-r--r--scene/gui/label.h17
-rw-r--r--scene/gui/line_edit.cpp169
-rw-r--r--scene/gui/line_edit.h26
-rw-r--r--scene/gui/link_button.cpp62
-rw-r--r--scene/gui/link_button.h19
-rw-r--r--scene/gui/margin_container.cpp29
-rw-r--r--scene/gui/margin_container.h9
-rw-r--r--scene/gui/menu_bar.cpp135
-rw-r--r--scene/gui/menu_bar.h31
-rw-r--r--scene/gui/menu_button.cpp14
-rw-r--r--scene/gui/nine_patch_rect.cpp10
-rw-r--r--scene/gui/option_button.cpp89
-rw-r--r--scene/gui/option_button.h18
-rw-r--r--scene/gui/panel.cpp9
-rw-r--r--scene/gui/panel.h6
-rw-r--r--scene/gui/panel_container.cpp42
-rw-r--r--scene/gui/panel_container.h5
-rw-r--r--scene/gui/popup.cpp30
-rw-r--r--scene/gui/popup.h11
-rw-r--r--scene/gui/popup_menu.cpp459
-rw-r--r--scene/gui/popup_menu.h45
-rw-r--r--scene/gui/progress_bar.cpp64
-rw-r--r--scene/gui/progress_bar.h13
-rw-r--r--scene/gui/range.cpp4
-rw-r--r--scene/gui/reference_rect.cpp6
-rw-r--r--scene/gui/rich_text_label.cpp98
-rw-r--r--scene/gui/scroll_bar.cpp88
-rw-r--r--scene/gui/scroll_bar.h19
-rw-r--r--scene/gui/scroll_container.cpp22
-rw-r--r--scene/gui/scroll_container.h5
-rw-r--r--scene/gui/separator.cpp18
-rw-r--r--scene/gui/separator.h8
-rw-r--r--scene/gui/slider.cpp69
-rw-r--r--scene/gui/slider.h15
-rw-r--r--scene/gui/spin_box.cpp20
-rw-r--r--scene/gui/spin_box.h5
-rw-r--r--scene/gui/split_container.cpp50
-rw-r--r--scene/gui/split_container.h8
-rw-r--r--scene/gui/subviewport_container.cpp4
-rw-r--r--scene/gui/tab_bar.cpp290
-rw-r--r--scene/gui/tab_bar.h29
-rw-r--r--scene/gui/tab_container.cpp154
-rw-r--r--scene/gui/tab_container.h35
-rw-r--r--scene/gui/text_edit.cpp124
-rw-r--r--scene/gui/texture_button.cpp18
-rw-r--r--scene/gui/texture_progress_bar.cpp26
-rw-r--r--scene/gui/texture_rect.cpp12
-rw-r--r--scene/gui/tree.cpp626
-rw-r--r--scene/gui/tree.h18
-rw-r--r--scene/gui/video_stream_player.cpp4
81 files changed, 2804 insertions, 2412 deletions
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 87a7355bb2..cf467ceafb 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -65,8 +65,9 @@ void BaseButton::gui_input(const Ref<InputEvent> &p_event) {
bool button_masked = mouse_button.is_valid() && (mouse_button_to_mask(mouse_button->get_button_index()) & button_mask) != MouseButton::NONE;
if (button_masked || ui_accept) {
was_mouse_pressed = button_masked;
-
on_action_event(p_event);
+ was_mouse_pressed = false;
+
return;
}
@@ -76,7 +77,7 @@ void BaseButton::gui_input(const Ref<InputEvent> &p_event) {
bool last_press_inside = status.pressing_inside;
status.pressing_inside = has_point(mouse_motion->get_position());
if (last_press_inside != status.pressing_inside) {
- update();
+ queue_redraw();
}
}
}
@@ -86,32 +87,32 @@ void BaseButton::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_MOUSE_ENTER: {
status.hovering = true;
- update();
+ queue_redraw();
} break;
case NOTIFICATION_MOUSE_EXIT: {
status.hovering = false;
- update();
+ queue_redraw();
} break;
case NOTIFICATION_DRAG_BEGIN:
case NOTIFICATION_SCROLL_BEGIN: {
if (status.press_attempt) {
status.press_attempt = false;
- update();
+ queue_redraw();
}
} break;
case NOTIFICATION_FOCUS_ENTER: {
- update();
+ queue_redraw();
} break;
case NOTIFICATION_FOCUS_EXIT: {
if (status.press_attempt) {
status.press_attempt = false;
- update();
+ queue_redraw();
} else if (status.hovering) {
- update();
+ queue_redraw();
}
} break;
@@ -187,7 +188,7 @@ void BaseButton::on_action_event(Ref<InputEvent> p_event) {
emit_signal(SNAME("button_up"));
}
- update();
+ queue_redraw();
}
void BaseButton::pressed() {
@@ -209,7 +210,7 @@ void BaseButton::set_disabled(bool p_disabled) {
status.press_attempt = false;
status.pressing_inside = false;
}
- update();
+ queue_redraw();
}
bool BaseButton::is_disabled() const {
@@ -233,7 +234,7 @@ void BaseButton::set_pressed(bool p_pressed) {
}
_toggled(status.pressed);
- update();
+ queue_redraw();
}
void BaseButton::set_pressed_no_signal(bool p_pressed) {
@@ -245,7 +246,7 @@ void BaseButton::set_pressed_no_signal(bool p_pressed) {
}
status.pressed = p_pressed;
- update();
+ queue_redraw();
}
bool BaseButton::is_pressing() const {
@@ -384,7 +385,7 @@ void BaseButton::set_button_group(const Ref<ButtonGroup> &p_group) {
button_group->buttons.insert(this);
}
- update(); //checkbox changes to radio if set a buttongroup
+ queue_redraw(); //checkbox changes to radio if set a buttongroup
}
Ref<ButtonGroup> BaseButton::get_button_group() const {
diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp
index a56a51a547..22c8f2cd4e 100644
--- a/scene/gui/box_container.cpp
+++ b/scene/gui/box_container.cpp
@@ -44,7 +44,6 @@ void BoxContainer::_resort() {
Size2i new_size = get_size();
- int sep = get_theme_constant(SNAME("separation")); //,vertical?"VBoxContainer":"HBoxContainer");
bool rtl = is_layout_rtl();
bool first = true;
@@ -90,7 +89,7 @@ void BoxContainer::_resort() {
return;
}
- int stretch_max = (vertical ? new_size.height : new_size.width) - (children_count - 1) * sep;
+ int stretch_max = (vertical ? new_size.height : new_size.width) - (children_count - 1) * theme_cache.separation;
int stretch_diff = stretch_max - stretch_min;
if (stretch_diff < 0) {
//avoid negative stretch space
@@ -214,7 +213,7 @@ void BoxContainer::_resort() {
if (first) {
first = false;
} else {
- ofs += sep;
+ ofs += theme_cache.separation;
}
int from = ofs;
@@ -248,7 +247,6 @@ Size2 BoxContainer::get_minimum_size() const {
/* Calculate MINIMUM SIZE */
Size2i minimum;
- int sep = get_theme_constant(SNAME("separation")); //,vertical?"VBoxContainer":"HBoxContainer");
bool first = true;
@@ -273,7 +271,7 @@ Size2 BoxContainer::get_minimum_size() const {
minimum.width = size.width;
}
- minimum.height += size.height + (first ? 0 : sep);
+ minimum.height += size.height + (first ? 0 : theme_cache.separation);
} else { /* HORIZONTAL */
@@ -281,7 +279,7 @@ Size2 BoxContainer::get_minimum_size() const {
minimum.height = size.height;
}
- minimum.width += size.width + (first ? 0 : sep);
+ minimum.width += size.width + (first ? 0 : theme_cache.separation);
}
first = false;
@@ -290,6 +288,12 @@ Size2 BoxContainer::get_minimum_size() const {
return minimum;
}
+void BoxContainer::_update_theme_item_cache() {
+ Container::_update_theme_item_cache();
+
+ theme_cache.separation = get_theme_constant(SNAME("separation")); //,vertical?"VBoxContainer":"HBoxContainer");
+}
+
void BoxContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_SORT_CHILDREN: {
diff --git a/scene/gui/box_container.h b/scene/gui/box_container.h
index 3043c3ea45..55dfb2ada7 100644
--- a/scene/gui/box_container.h
+++ b/scene/gui/box_container.h
@@ -47,11 +47,16 @@ private:
bool vertical = false;
AlignmentMode alignment = ALIGNMENT_BEGIN;
+ struct ThemeCache {
+ int separation = 0;
+ } theme_cache;
+
void _resort();
protected:
- void _notification(int p_what);
+ virtual void _update_theme_item_cache() override;
+ void _notification(int p_what);
static void _bind_methods();
public:
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index e163f4355c..c2b82e01d1 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -36,7 +36,7 @@
Size2 Button::get_minimum_size() const {
Ref<Texture2D> _icon = icon;
if (_icon.is_null() && has_theme_icon(SNAME("icon"))) {
- _icon = Control::get_theme_icon(SNAME("icon"));
+ _icon = theme_cache.icon;
}
return get_minimum_size_for_text_and_icon("", _icon);
@@ -46,10 +46,49 @@ void Button::_set_internal_margin(Side p_side, float p_value) {
_internal_margin[p_side] = p_value;
}
+void Button::_update_theme_item_cache() {
+ BaseButton::_update_theme_item_cache();
+
+ theme_cache.normal = get_theme_stylebox(SNAME("normal"));
+ theme_cache.normal_mirrored = get_theme_stylebox(SNAME("normal_mirrored"));
+ theme_cache.pressed = get_theme_stylebox(SNAME("pressed"));
+ theme_cache.pressed_mirrored = get_theme_stylebox(SNAME("pressed_mirrored"));
+ theme_cache.hover = get_theme_stylebox(SNAME("hover"));
+ theme_cache.hover_mirrored = get_theme_stylebox(SNAME("hover_mirrored"));
+ theme_cache.hover_pressed = get_theme_stylebox(SNAME("hover_pressed"));
+ theme_cache.hover_pressed_mirrored = get_theme_stylebox(SNAME("hover_pressed_mirrored"));
+ theme_cache.disabled = get_theme_stylebox(SNAME("disabled"));
+ theme_cache.disabled_mirrored = get_theme_stylebox(SNAME("disabled_mirrored"));
+ theme_cache.focus = get_theme_stylebox(SNAME("focus"));
+
+ theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_focus_color = get_theme_color(SNAME("font_focus_color"));
+ theme_cache.font_pressed_color = get_theme_color(SNAME("font_pressed_color"));
+ theme_cache.font_hover_color = get_theme_color(SNAME("font_hover_color"));
+ theme_cache.font_hover_pressed_color = get_theme_color(SNAME("font_hover_pressed_color"));
+ theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
+
+ theme_cache.font = get_theme_font(SNAME("font"));
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
+ theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+
+ theme_cache.icon_normal_color = get_theme_color(SNAME("icon_normal_color"));
+ theme_cache.icon_focus_color = get_theme_color(SNAME("icon_focus_color"));
+ theme_cache.icon_pressed_color = get_theme_color(SNAME("icon_pressed_color"));
+ theme_cache.icon_hover_color = get_theme_color(SNAME("icon_hover_color"));
+ theme_cache.icon_hover_pressed_color = get_theme_color(SNAME("icon_hover_pressed_color"));
+ theme_cache.icon_disabled_color = get_theme_color(SNAME("icon_disabled_color"));
+
+ theme_cache.icon = get_theme_icon(SNAME("icon"));
+
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
+}
+
void Button::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
- update();
+ queue_redraw();
} break;
case NOTIFICATION_TRANSLATION_CHANGED: {
@@ -57,14 +96,14 @@ void Button::_notification(int p_what) {
_shape();
update_minimum_size();
- update();
+ queue_redraw();
} break;
case NOTIFICATION_THEME_CHANGED: {
_shape();
update_minimum_size();
- update();
+ queue_redraw();
} break;
case NOTIFICATION_DRAW: {
@@ -73,15 +112,15 @@ void Button::_notification(int p_what) {
Color color;
Color color_icon(1, 1, 1, 1);
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
+ Ref<StyleBox> style = theme_cache.normal;
bool rtl = is_layout_rtl();
switch (get_draw_mode()) {
case DRAW_NORMAL: {
if (rtl && has_theme_stylebox(SNAME("normal_mirrored"))) {
- style = get_theme_stylebox(SNAME("normal_mirrored"));
+ style = theme_cache.normal_mirrored;
} else {
- style = get_theme_stylebox(SNAME("normal"));
+ style = theme_cache.normal;
}
if (!flat) {
@@ -90,14 +129,14 @@ void Button::_notification(int p_what) {
// Focus colors only take precedence over normal state.
if (has_focus()) {
- color = get_theme_color(SNAME("font_focus_color"));
+ color = theme_cache.font_focus_color;
if (has_theme_color(SNAME("icon_focus_color"))) {
- color_icon = get_theme_color(SNAME("icon_focus_color"));
+ color_icon = theme_cache.icon_focus_color;
}
} else {
- color = get_theme_color(SNAME("font_color"));
+ color = theme_cache.font_color;
if (has_theme_color(SNAME("icon_normal_color"))) {
- color_icon = get_theme_color(SNAME("icon_normal_color"));
+ color_icon = theme_cache.icon_normal_color;
}
}
} break;
@@ -105,19 +144,19 @@ void Button::_notification(int p_what) {
// Edge case for CheckButton and CheckBox.
if (has_theme_stylebox("hover_pressed")) {
if (rtl && has_theme_stylebox(SNAME("hover_pressed_mirrored"))) {
- style = get_theme_stylebox(SNAME("hover_pressed_mirrored"));
+ style = theme_cache.hover_pressed_mirrored;
} else {
- style = get_theme_stylebox(SNAME("hover_pressed"));
+ style = theme_cache.hover_pressed;
}
if (!flat) {
style->draw(ci, Rect2(Point2(0, 0), size));
}
if (has_theme_color(SNAME("font_hover_pressed_color"))) {
- color = get_theme_color(SNAME("font_hover_pressed_color"));
+ color = theme_cache.font_hover_pressed_color;
}
if (has_theme_color(SNAME("icon_hover_pressed_color"))) {
- color_icon = get_theme_color(SNAME("icon_hover_pressed_color"));
+ color_icon = theme_cache.icon_hover_pressed_color;
}
break;
@@ -126,53 +165,53 @@ void Button::_notification(int p_what) {
}
case DRAW_PRESSED: {
if (rtl && has_theme_stylebox(SNAME("pressed_mirrored"))) {
- style = get_theme_stylebox(SNAME("pressed_mirrored"));
+ style = theme_cache.pressed_mirrored;
} else {
- style = get_theme_stylebox(SNAME("pressed"));
+ style = theme_cache.pressed;
}
if (!flat) {
style->draw(ci, Rect2(Point2(0, 0), size));
}
if (has_theme_color(SNAME("font_pressed_color"))) {
- color = get_theme_color(SNAME("font_pressed_color"));
+ color = theme_cache.font_pressed_color;
} else {
- color = get_theme_color(SNAME("font_color"));
+ color = theme_cache.font_color;
}
if (has_theme_color(SNAME("icon_pressed_color"))) {
- color_icon = get_theme_color(SNAME("icon_pressed_color"));
+ color_icon = theme_cache.icon_pressed_color;
}
} break;
case DRAW_HOVER: {
if (rtl && has_theme_stylebox(SNAME("hover_mirrored"))) {
- style = get_theme_stylebox(SNAME("hover_mirrored"));
+ style = theme_cache.hover_mirrored;
} else {
- style = get_theme_stylebox(SNAME("hover"));
+ style = theme_cache.hover;
}
if (!flat) {
style->draw(ci, Rect2(Point2(0, 0), size));
}
- color = get_theme_color(SNAME("font_hover_color"));
+ color = theme_cache.font_hover_color;
if (has_theme_color(SNAME("icon_hover_color"))) {
- color_icon = get_theme_color(SNAME("icon_hover_color"));
+ color_icon = theme_cache.icon_hover_color;
}
} break;
case DRAW_DISABLED: {
if (rtl && has_theme_stylebox(SNAME("disabled_mirrored"))) {
- style = get_theme_stylebox(SNAME("disabled_mirrored"));
+ style = theme_cache.disabled_mirrored;
} else {
- style = get_theme_stylebox(SNAME("disabled"));
+ style = theme_cache.disabled;
}
if (!flat) {
style->draw(ci, Rect2(Point2(0, 0), size));
}
- color = get_theme_color(SNAME("font_disabled_color"));
+ color = theme_cache.font_disabled_color;
if (has_theme_color(SNAME("icon_disabled_color"))) {
- color_icon = get_theme_color(SNAME("icon_disabled_color"));
+ color_icon = theme_cache.icon_disabled_color;
} else {
color_icon.a = 0.4;
}
@@ -181,13 +220,13 @@ void Button::_notification(int p_what) {
}
if (has_focus()) {
- Ref<StyleBox> style2 = get_theme_stylebox(SNAME("focus"));
+ Ref<StyleBox> style2 = theme_cache.focus;
style2->draw(ci, Rect2(Point2(), size));
}
Ref<Texture2D> _icon;
if (icon.is_null() && has_theme_icon(SNAME("icon"))) {
- _icon = Control::get_theme_icon(SNAME("icon"));
+ _icon = theme_cache.icon;
} else {
_icon = icon;
}
@@ -217,21 +256,21 @@ void Button::_notification(int p_what) {
if (icon_align_rtl_checked == HORIZONTAL_ALIGNMENT_LEFT) {
style_offset.x = style->get_margin(SIDE_LEFT);
if (_internal_margin[SIDE_LEFT] > 0) {
- icon_ofs_region = _internal_margin[SIDE_LEFT] + get_theme_constant(SNAME("h_separation"));
+ icon_ofs_region = _internal_margin[SIDE_LEFT] + theme_cache.h_separation;
}
} else if (icon_align_rtl_checked == HORIZONTAL_ALIGNMENT_CENTER) {
style_offset.x = 0.0;
} else if (icon_align_rtl_checked == HORIZONTAL_ALIGNMENT_RIGHT) {
style_offset.x = -style->get_margin(SIDE_RIGHT);
if (_internal_margin[SIDE_RIGHT] > 0) {
- icon_ofs_region = -_internal_margin[SIDE_RIGHT] - get_theme_constant(SNAME("h_separation"));
+ icon_ofs_region = -_internal_margin[SIDE_RIGHT] - theme_cache.h_separation;
}
}
style_offset.y = style->get_margin(SIDE_TOP);
if (expand_icon) {
Size2 _size = get_size() - style->get_offset() * 2;
- int icon_text_separation = text.is_empty() ? 0 : get_theme_constant(SNAME("h_separation"));
+ int icon_text_separation = text.is_empty() ? 0 : theme_cache.h_separation;
_size.width -= icon_text_separation + icon_ofs_region;
if (!clip_text && icon_align_rtl_checked != HORIZONTAL_ALIGNMENT_CENTER) {
_size.width -= text_buf->get_size().width;
@@ -261,7 +300,7 @@ void Button::_notification(int p_what) {
}
}
- Point2 icon_ofs = !_icon.is_null() ? Point2(icon_region.size.width + get_theme_constant(SNAME("h_separation")), 0) : Point2();
+ Point2 icon_ofs = !_icon.is_null() ? Point2(icon_region.size.width + theme_cache.h_separation, 0) : Point2();
if (align_rtl_checked == HORIZONTAL_ALIGNMENT_CENTER && icon_align_rtl_checked == HORIZONTAL_ALIGNMENT_CENTER) {
icon_ofs.x = 0.0;
}
@@ -271,10 +310,10 @@ void Button::_notification(int p_what) {
int text_width = MAX(1, (clip_text || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) ? MIN(text_clip, text_buf->get_size().x) : text_buf->get_size().x);
if (_internal_margin[SIDE_LEFT] > 0) {
- text_clip -= _internal_margin[SIDE_LEFT] + get_theme_constant(SNAME("h_separation"));
+ text_clip -= _internal_margin[SIDE_LEFT] + theme_cache.h_separation;
}
if (_internal_margin[SIDE_RIGHT] > 0) {
- text_clip -= _internal_margin[SIDE_RIGHT] + get_theme_constant(SNAME("h_separation"));
+ text_clip -= _internal_margin[SIDE_RIGHT] + theme_cache.h_separation;
}
Point2 text_ofs = (size - style->get_minimum_size() - icon_ofs - text_buf->get_size() - Point2(_internal_margin[SIDE_RIGHT] - _internal_margin[SIDE_LEFT], 0)) / 2.0;
@@ -288,7 +327,7 @@ void Button::_notification(int p_what) {
icon_ofs.x = 0.0;
}
if (_internal_margin[SIDE_LEFT] > 0) {
- text_ofs.x = style->get_margin(SIDE_LEFT) + icon_ofs.x + _internal_margin[SIDE_LEFT] + get_theme_constant(SNAME("h_separation"));
+ text_ofs.x = style->get_margin(SIDE_LEFT) + icon_ofs.x + _internal_margin[SIDE_LEFT] + theme_cache.h_separation;
} else {
text_ofs.x = style->get_margin(SIDE_LEFT) + icon_ofs.x;
}
@@ -305,7 +344,7 @@ void Button::_notification(int p_what) {
} break;
case HORIZONTAL_ALIGNMENT_RIGHT: {
if (_internal_margin[SIDE_RIGHT] > 0) {
- text_ofs.x = size.x - style->get_margin(SIDE_RIGHT) - text_width - _internal_margin[SIDE_RIGHT] - get_theme_constant(SNAME("h_separation"));
+ text_ofs.x = size.x - style->get_margin(SIDE_RIGHT) - text_width - _internal_margin[SIDE_RIGHT] - theme_cache.h_separation;
} else {
text_ofs.x = size.x - style->get_margin(SIDE_RIGHT) - text_width;
}
@@ -316,8 +355,8 @@ void Button::_notification(int p_what) {
} break;
}
- Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
+ Color font_outline_color = theme_cache.font_outline_color;
+ int outline_size = theme_cache.outline_size;
if (outline_size > 0 && font_outline_color.a > 0) {
text_buf->draw_outline(ci, text_ofs, outline_size, font_outline_color);
}
@@ -346,7 +385,7 @@ Size2 Button::get_minimum_size_for_text_and_icon(const String &p_text, Ref<Textu
if (icon_alignment != HORIZONTAL_ALIGNMENT_CENTER) {
minsize.width += p_icon->get_width();
if (!xl_text.is_empty() || !p_text.is_empty()) {
- minsize.width += MAX(0, get_theme_constant(SNAME("h_separation")));
+ minsize.width += MAX(0, theme_cache.h_separation);
}
} else {
minsize.width = MAX(minsize.width, p_icon->get_width());
@@ -354,12 +393,12 @@ Size2 Button::get_minimum_size_for_text_and_icon(const String &p_text, Ref<Textu
}
if (!xl_text.is_empty() || !p_text.is_empty()) {
- Ref<Font> font = get_theme_font(SNAME("font"));
- float font_height = font->get_height(get_theme_font_size(SNAME("font_size")));
+ Ref<Font> font = theme_cache.font;
+ float font_height = font->get_height(theme_cache.font_size);
minsize.height = MAX(font_height, minsize.height);
}
- return get_theme_stylebox(SNAME("normal"))->get_minimum_size() + minsize;
+ return theme_cache.normal->get_minimum_size() + minsize;
}
void Button::_shape(Ref<TextParagraph> p_paragraph, String p_text) {
@@ -371,10 +410,15 @@ void Button::_shape(Ref<TextParagraph> p_paragraph, String p_text) {
p_text = xl_text;
}
- Ref<Font> font = get_theme_font(SNAME("font"));
- int font_size = get_theme_font_size(SNAME("font_size"));
-
p_paragraph->clear();
+
+ Ref<Font> font = theme_cache.font;
+ int font_size = theme_cache.font_size;
+ if (font.is_null() || font_size == 0) {
+ // Can't shape without a valid font and a non-zero size.
+ return;
+ }
+
if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
p_paragraph->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
} else {
@@ -389,7 +433,7 @@ void Button::set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior) {
overrun_behavior = p_behavior;
_shape();
- update();
+ queue_redraw();
update_minimum_size();
}
}
@@ -404,7 +448,7 @@ void Button::set_text(const String &p_text) {
xl_text = atr(text);
_shape();
- update();
+ queue_redraw();
update_minimum_size();
}
}
@@ -418,7 +462,7 @@ void Button::set_text_direction(Control::TextDirection p_text_direction) {
if (text_direction != p_text_direction) {
text_direction = p_text_direction;
_shape();
- update();
+ queue_redraw();
}
}
@@ -430,7 +474,7 @@ void Button::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
_shape();
- update();
+ queue_redraw();
}
}
@@ -441,7 +485,7 @@ String Button::get_language() const {
void Button::set_icon(const Ref<Texture2D> &p_icon) {
if (icon != p_icon) {
icon = p_icon;
- update();
+ queue_redraw();
update_minimum_size();
}
}
@@ -453,7 +497,7 @@ Ref<Texture2D> Button::get_icon() const {
void Button::set_expand_icon(bool p_enabled) {
if (expand_icon != p_enabled) {
expand_icon = p_enabled;
- update();
+ queue_redraw();
update_minimum_size();
}
}
@@ -465,7 +509,7 @@ bool Button::is_expand_icon() const {
void Button::set_flat(bool p_enabled) {
if (flat != p_enabled) {
flat = p_enabled;
- update();
+ queue_redraw();
}
}
@@ -476,7 +520,7 @@ bool Button::is_flat() const {
void Button::set_clip_text(bool p_enabled) {
if (clip_text != p_enabled) {
clip_text = p_enabled;
- update();
+ queue_redraw();
update_minimum_size();
}
}
@@ -488,7 +532,7 @@ bool Button::get_clip_text() const {
void Button::set_text_alignment(HorizontalAlignment p_alignment) {
if (alignment != p_alignment) {
alignment = p_alignment;
- update();
+ queue_redraw();
}
}
@@ -499,7 +543,7 @@ HorizontalAlignment Button::get_text_alignment() const {
void Button::set_icon_alignment(HorizontalAlignment p_alignment) {
icon_alignment = p_alignment;
update_minimum_size();
- update();
+ queue_redraw();
}
HorizontalAlignment Button::get_icon_alignment() const {
@@ -544,7 +588,7 @@ void Button::_bind_methods() {
Button::Button(const String &p_text) {
text_buf.instantiate();
- text_buf->set_break_flags(TextServer::BREAK_MANDATORY);
+ text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_TRIM_EDGE_SPACES);
set_mouse_filter(MOUSE_FILTER_STOP);
set_text(p_text);
diff --git a/scene/gui/button.h b/scene/gui/button.h
index 23b5c78166..9d9f9763db 100644
--- a/scene/gui/button.h
+++ b/scene/gui/button.h
@@ -54,10 +54,48 @@ private:
HorizontalAlignment icon_alignment = HORIZONTAL_ALIGNMENT_LEFT;
float _internal_margin[4] = {};
+ struct ThemeCache {
+ Ref<StyleBox> normal;
+ Ref<StyleBox> normal_mirrored;
+ Ref<StyleBox> pressed;
+ Ref<StyleBox> pressed_mirrored;
+ Ref<StyleBox> hover;
+ Ref<StyleBox> hover_mirrored;
+ Ref<StyleBox> hover_pressed;
+ Ref<StyleBox> hover_pressed_mirrored;
+ Ref<StyleBox> disabled;
+ Ref<StyleBox> disabled_mirrored;
+ Ref<StyleBox> focus;
+
+ Color font_color;
+ Color font_focus_color;
+ Color font_pressed_color;
+ Color font_hover_color;
+ Color font_hover_pressed_color;
+ Color font_disabled_color;
+
+ Ref<Font> font;
+ int font_size = 0;
+ int outline_size = 0;
+ Color font_outline_color;
+
+ Color icon_normal_color;
+ Color icon_focus_color;
+ Color icon_pressed_color;
+ Color icon_hover_color;
+ Color icon_hover_pressed_color;
+ Color icon_disabled_color;
+
+ Ref<Texture2D> icon;
+
+ int h_separation = 0;
+ } theme_cache;
+
void _shape(Ref<TextParagraph> p_paragraph = Ref<TextParagraph>(), String p_text = "");
protected:
void _set_internal_margin(Side p_side, float p_value);
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp
index 26edc1f1b0..37db7d53f0 100644
--- a/scene/gui/check_box.cpp
+++ b/scene/gui/check_box.cpp
@@ -33,39 +33,30 @@
#include "servers/rendering_server.h"
Size2 CheckBox::get_icon_size() const {
- Ref<Texture2D> checked = Control::get_theme_icon(SNAME("checked"));
- Ref<Texture2D> unchecked = Control::get_theme_icon(SNAME("unchecked"));
- Ref<Texture2D> radio_checked = Control::get_theme_icon(SNAME("radio_checked"));
- Ref<Texture2D> radio_unchecked = Control::get_theme_icon(SNAME("radio_unchecked"));
- Ref<Texture2D> checked_disabled = Control::get_theme_icon(SNAME("checked_disabled"));
- Ref<Texture2D> unchecked_disabled = Control::get_theme_icon(SNAME("unchecked_disabled"));
- Ref<Texture2D> radio_checked_disabled = Control::get_theme_icon(SNAME("radio_checked_disabled"));
- Ref<Texture2D> radio_unchecked_disabled = Control::get_theme_icon(SNAME("radio_unchecked_disabled"));
-
Size2 tex_size = Size2(0, 0);
- if (!checked.is_null()) {
- tex_size = Size2(checked->get_width(), checked->get_height());
+ if (!theme_cache.checked.is_null()) {
+ tex_size = Size2(theme_cache.checked->get_width(), theme_cache.checked->get_height());
}
- if (!unchecked.is_null()) {
- tex_size = Size2(MAX(tex_size.width, unchecked->get_width()), MAX(tex_size.height, unchecked->get_height()));
+ if (!theme_cache.unchecked.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, theme_cache.unchecked->get_width()), MAX(tex_size.height, theme_cache.unchecked->get_height()));
}
- if (!radio_checked.is_null()) {
- tex_size = Size2(MAX(tex_size.width, radio_checked->get_width()), MAX(tex_size.height, radio_checked->get_height()));
+ if (!theme_cache.radio_checked.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, theme_cache.radio_checked->get_width()), MAX(tex_size.height, theme_cache.radio_checked->get_height()));
}
- if (!radio_unchecked.is_null()) {
- tex_size = Size2(MAX(tex_size.width, radio_unchecked->get_width()), MAX(tex_size.height, radio_unchecked->get_height()));
+ if (!theme_cache.radio_unchecked.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, theme_cache.radio_unchecked->get_width()), MAX(tex_size.height, theme_cache.radio_unchecked->get_height()));
}
- if (!checked_disabled.is_null()) {
- tex_size = Size2(MAX(tex_size.width, checked_disabled->get_width()), MAX(tex_size.height, checked_disabled->get_height()));
+ if (!theme_cache.checked_disabled.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, theme_cache.checked_disabled->get_width()), MAX(tex_size.height, theme_cache.checked_disabled->get_height()));
}
- if (!unchecked_disabled.is_null()) {
- tex_size = Size2(MAX(tex_size.width, unchecked_disabled->get_width()), MAX(tex_size.height, unchecked_disabled->get_height()));
+ if (!theme_cache.unchecked_disabled.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, theme_cache.unchecked_disabled->get_width()), MAX(tex_size.height, theme_cache.unchecked_disabled->get_height()));
}
- if (!radio_checked_disabled.is_null()) {
- tex_size = Size2(MAX(tex_size.width, radio_checked_disabled->get_width()), MAX(tex_size.height, radio_checked_disabled->get_height()));
+ if (!theme_cache.radio_checked_disabled.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, theme_cache.radio_checked_disabled->get_width()), MAX(tex_size.height, theme_cache.radio_checked_disabled->get_height()));
}
- if (!radio_unchecked_disabled.is_null()) {
- tex_size = Size2(MAX(tex_size.width, radio_unchecked_disabled->get_width()), MAX(tex_size.height, radio_unchecked_disabled->get_height()));
+ if (!theme_cache.radio_unchecked_disabled.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, theme_cache.radio_unchecked_disabled->get_width()), MAX(tex_size.height, theme_cache.radio_unchecked_disabled->get_height()));
}
return tex_size;
}
@@ -75,14 +66,30 @@ Size2 CheckBox::get_minimum_size() const {
Size2 tex_size = get_icon_size();
minsize.width += tex_size.width;
if (get_text().length() > 0) {
- minsize.width += MAX(0, get_theme_constant(SNAME("h_separation")));
+ minsize.width += MAX(0, theme_cache.h_separation);
}
- Ref<StyleBox> sb = get_theme_stylebox(SNAME("normal"));
- minsize.height = MAX(minsize.height, tex_size.height + sb->get_margin(SIDE_TOP) + sb->get_margin(SIDE_BOTTOM));
+ minsize.height = MAX(minsize.height, tex_size.height + theme_cache.normal_style->get_margin(SIDE_TOP) + theme_cache.normal_style->get_margin(SIDE_BOTTOM));
return minsize;
}
+void CheckBox::_update_theme_item_cache() {
+ Button::_update_theme_item_cache();
+
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
+ theme_cache.check_v_adjust = get_theme_constant(SNAME("check_v_adjust"));
+ theme_cache.normal_style = get_theme_stylebox(SNAME("normal"));
+
+ theme_cache.checked = get_theme_icon(SNAME("checked"));
+ theme_cache.unchecked = get_theme_icon(SNAME("unchecked"));
+ theme_cache.radio_checked = get_theme_icon(SNAME("radio_checked"));
+ theme_cache.radio_unchecked = get_theme_icon(SNAME("radio_unchecked"));
+ theme_cache.checked_disabled = get_theme_icon(SNAME("checked_disabled"));
+ theme_cache.unchecked_disabled = get_theme_icon(SNAME("unchecked_disabled"));
+ theme_cache.radio_checked_disabled = get_theme_icon(SNAME("radio_checked_disabled"));
+ theme_cache.radio_unchecked_disabled = get_theme_icon(SNAME("radio_unchecked_disabled"));
+}
+
void CheckBox::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED:
@@ -100,22 +107,39 @@ void CheckBox::_notification(int p_what) {
case NOTIFICATION_DRAW: {
RID ci = get_canvas_item();
- Ref<Texture2D> on = Control::get_theme_icon(vformat("%s%s", is_radio() ? "radio_checked" : "checked", is_disabled() ? "_disabled" : ""));
- Ref<Texture2D> off = Control::get_theme_icon(vformat("%s%s", is_radio() ? "radio_unchecked" : "unchecked", is_disabled() ? "_disabled" : ""));
- Ref<StyleBox> sb = get_theme_stylebox(SNAME("normal"));
+ Ref<Texture2D> on_tex;
+ Ref<Texture2D> off_tex;
+
+ if (is_radio()) {
+ if (is_disabled()) {
+ on_tex = theme_cache.radio_checked_disabled;
+ off_tex = theme_cache.radio_unchecked_disabled;
+ } else {
+ on_tex = theme_cache.radio_checked;
+ off_tex = theme_cache.radio_unchecked;
+ }
+ } else {
+ if (is_disabled()) {
+ on_tex = theme_cache.checked_disabled;
+ off_tex = theme_cache.unchecked_disabled;
+ } else {
+ on_tex = theme_cache.checked;
+ off_tex = theme_cache.unchecked;
+ }
+ }
Vector2 ofs;
if (is_layout_rtl()) {
- ofs.x = get_size().x - sb->get_margin(SIDE_RIGHT) - get_icon_size().width;
+ ofs.x = get_size().x - theme_cache.normal_style->get_margin(SIDE_RIGHT) - get_icon_size().width;
} else {
- ofs.x = sb->get_margin(SIDE_LEFT);
+ ofs.x = theme_cache.normal_style->get_margin(SIDE_LEFT);
}
- ofs.y = int((get_size().height - get_icon_size().height) / 2) + get_theme_constant(SNAME("check_v_adjust"));
+ ofs.y = int((get_size().height - get_icon_size().height) / 2) + theme_cache.check_v_adjust;
if (is_pressed()) {
- on->draw(ci, ofs);
+ on_tex->draw(ci, ofs);
} else {
- off->draw(ci, ofs);
+ off_tex->draw(ci, ofs);
}
} break;
}
diff --git a/scene/gui/check_box.h b/scene/gui/check_box.h
index fcdb2ce08c..beafece3dc 100644
--- a/scene/gui/check_box.h
+++ b/scene/gui/check_box.h
@@ -36,9 +36,26 @@
class CheckBox : public Button {
GDCLASS(CheckBox, Button);
+ struct ThemeCache {
+ int h_separation = 0;
+ int check_v_adjust = 0;
+ Ref<StyleBox> normal_style;
+
+ Ref<Texture2D> checked;
+ Ref<Texture2D> unchecked;
+ Ref<Texture2D> radio_checked;
+ Ref<Texture2D> radio_unchecked;
+ Ref<Texture2D> checked_disabled;
+ Ref<Texture2D> unchecked_disabled;
+ Ref<Texture2D> radio_checked_disabled;
+ Ref<Texture2D> radio_unchecked_disabled;
+ } theme_cache;
+
protected:
Size2 get_icon_size() const;
Size2 get_minimum_size() const override;
+
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
bool is_radio();
diff --git a/scene/gui/check_button.cpp b/scene/gui/check_button.cpp
index b9674ca41e..b01081e31b 100644
--- a/scene/gui/check_button.cpp
+++ b/scene/gui/check_button.cpp
@@ -34,14 +34,33 @@
#include "servers/rendering_server.h"
Size2 CheckButton::get_icon_size() const {
- Ref<Texture2D> on = Control::get_theme_icon(is_disabled() ? "on_disabled" : "on");
- Ref<Texture2D> off = Control::get_theme_icon(is_disabled() ? "off_disabled" : "off");
+ Ref<Texture2D> on_tex;
+ Ref<Texture2D> off_tex;
+
+ if (is_layout_rtl()) {
+ if (is_disabled()) {
+ on_tex = theme_cache.checked_disabled_mirrored;
+ off_tex = theme_cache.unchecked_disabled_mirrored;
+ } else {
+ on_tex = theme_cache.checked_mirrored;
+ off_tex = theme_cache.unchecked_mirrored;
+ }
+ } else {
+ if (is_disabled()) {
+ on_tex = theme_cache.checked_disabled;
+ off_tex = theme_cache.unchecked_disabled;
+ } else {
+ on_tex = theme_cache.checked;
+ off_tex = theme_cache.unchecked;
+ }
+ }
+
Size2 tex_size = Size2(0, 0);
- if (!on.is_null()) {
- tex_size = Size2(on->get_width(), on->get_height());
+ if (!on_tex.is_null()) {
+ tex_size = Size2(on_tex->get_width(), on_tex->get_height());
}
- if (!off.is_null()) {
- tex_size = Size2(MAX(tex_size.width, off->get_width()), MAX(tex_size.height, off->get_height()));
+ if (!off_tex.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, off_tex->get_width()), MAX(tex_size.height, off_tex->get_height()));
}
return tex_size;
@@ -52,14 +71,30 @@ Size2 CheckButton::get_minimum_size() const {
Size2 tex_size = get_icon_size();
minsize.width += tex_size.width;
if (get_text().length() > 0) {
- minsize.width += MAX(0, get_theme_constant(SNAME("h_separation")));
+ minsize.width += MAX(0, theme_cache.h_separation);
}
- Ref<StyleBox> sb = get_theme_stylebox(SNAME("normal"));
- minsize.height = MAX(minsize.height, tex_size.height + sb->get_margin(SIDE_TOP) + sb->get_margin(SIDE_BOTTOM));
+ minsize.height = MAX(minsize.height, tex_size.height + theme_cache.normal_style->get_margin(SIDE_TOP) + theme_cache.normal_style->get_margin(SIDE_BOTTOM));
return minsize;
}
+void CheckButton::_update_theme_item_cache() {
+ Button::_update_theme_item_cache();
+
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
+ theme_cache.check_v_adjust = get_theme_constant(SNAME("check_v_adjust"));
+ theme_cache.normal_style = get_theme_stylebox(SNAME("normal"));
+
+ theme_cache.checked = get_theme_icon(SNAME("on"));
+ theme_cache.unchecked = get_theme_icon(SNAME("off"));
+ theme_cache.checked_disabled = get_theme_icon(SNAME("on_disabled"));
+ theme_cache.unchecked_disabled = get_theme_icon(SNAME("off_disabled"));
+ theme_cache.checked_mirrored = get_theme_icon(SNAME("on_mirrored"));
+ theme_cache.unchecked_mirrored = get_theme_icon(SNAME("off_mirrored"));
+ theme_cache.checked_disabled_mirrored = get_theme_icon(SNAME("on_disabled_mirrored"));
+ theme_cache.unchecked_disabled_mirrored = get_theme_icon(SNAME("off_disabled_mirrored"));
+}
+
void CheckButton::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED:
@@ -78,34 +113,41 @@ void CheckButton::_notification(int p_what) {
RID ci = get_canvas_item();
bool rtl = is_layout_rtl();
- Ref<Texture2D> on;
- if (rtl) {
- on = Control::get_theme_icon(is_disabled() ? "on_disabled_mirrored" : "on_mirrored");
- } else {
- on = Control::get_theme_icon(is_disabled() ? "on_disabled" : "on");
- }
- Ref<Texture2D> off;
+ Ref<Texture2D> on_tex;
+ Ref<Texture2D> off_tex;
+
if (rtl) {
- off = Control::get_theme_icon(is_disabled() ? "off_disabled_mirrored" : "off_mirrored");
+ if (is_disabled()) {
+ on_tex = theme_cache.checked_disabled_mirrored;
+ off_tex = theme_cache.unchecked_disabled_mirrored;
+ } else {
+ on_tex = theme_cache.checked_mirrored;
+ off_tex = theme_cache.unchecked_mirrored;
+ }
} else {
- off = Control::get_theme_icon(is_disabled() ? "off_disabled" : "off");
+ if (is_disabled()) {
+ on_tex = theme_cache.checked_disabled;
+ off_tex = theme_cache.unchecked_disabled;
+ } else {
+ on_tex = theme_cache.checked;
+ off_tex = theme_cache.unchecked;
+ }
}
- Ref<StyleBox> sb = get_theme_stylebox(SNAME("normal"));
Vector2 ofs;
Size2 tex_size = get_icon_size();
if (rtl) {
- ofs.x = sb->get_margin(SIDE_LEFT);
+ ofs.x = theme_cache.normal_style->get_margin(SIDE_LEFT);
} else {
- ofs.x = get_size().width - (tex_size.width + sb->get_margin(SIDE_RIGHT));
+ ofs.x = get_size().width - (tex_size.width + theme_cache.normal_style->get_margin(SIDE_RIGHT));
}
- ofs.y = (get_size().height - tex_size.height) / 2 + get_theme_constant(SNAME("check_v_adjust"));
+ ofs.y = (get_size().height - tex_size.height) / 2 + theme_cache.check_v_adjust;
if (is_pressed()) {
- on->draw(ci, ofs);
+ on_tex->draw(ci, ofs);
} else {
- off->draw(ci, ofs);
+ off_tex->draw(ci, ofs);
}
} break;
}
diff --git a/scene/gui/check_button.h b/scene/gui/check_button.h
index 7d4bb8bdfc..e71472c870 100644
--- a/scene/gui/check_button.h
+++ b/scene/gui/check_button.h
@@ -36,9 +36,26 @@
class CheckButton : public Button {
GDCLASS(CheckButton, Button);
+ struct ThemeCache {
+ int h_separation = 0;
+ int check_v_adjust = 0;
+ Ref<StyleBox> normal_style;
+
+ Ref<Texture2D> checked;
+ Ref<Texture2D> unchecked;
+ Ref<Texture2D> checked_disabled;
+ Ref<Texture2D> unchecked_disabled;
+ Ref<Texture2D> checked_mirrored;
+ Ref<Texture2D> unchecked_mirrored;
+ Ref<Texture2D> checked_disabled_mirrored;
+ Ref<Texture2D> unchecked_disabled_mirrored;
+ } theme_cache;
+
protected:
Size2 get_icon_size() const;
virtual Size2 get_minimum_size() const override;
+
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
public:
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index e54ba7ce13..1ef1801457 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -268,7 +268,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
if (is_code_completion_scroll_pressed && mb->get_button_index() == MouseButton::LEFT) {
is_code_completion_scroll_pressed = false;
- update();
+ queue_redraw();
return;
}
@@ -281,13 +281,13 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
case MouseButton::WHEEL_UP: {
if (code_completion_current_selected > 0) {
code_completion_current_selected--;
- update();
+ queue_redraw();
}
} break;
case MouseButton::WHEEL_DOWN: {
if (code_completion_current_selected < code_completion_options.size() - 1) {
code_completion_current_selected++;
- update();
+ queue_redraw();
}
} break;
case MouseButton::LEFT: {
@@ -295,7 +295,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
if (mb->is_double_click()) {
confirm_code_completion();
}
- update();
+ queue_redraw();
} break;
default:
break;
@@ -310,7 +310,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
is_code_completion_scroll_pressed = true;
_update_scroll_selected_line(mb->get_position().y);
- update();
+ queue_redraw();
}
return;
@@ -384,12 +384,12 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
bool scroll_hovered = code_completion_scroll_rect.has_point(mpos);
if (is_code_completion_scroll_hovered != scroll_hovered) {
is_code_completion_scroll_hovered = scroll_hovered;
- update();
+ queue_redraw();
}
if (is_code_completion_scroll_pressed) {
_update_scroll_selected_line(mpos.y);
- update();
+ queue_redraw();
return;
}
}
@@ -448,7 +448,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
} else {
code_completion_current_selected = code_completion_options.size() - 1;
}
- update();
+ queue_redraw();
accept_event();
return;
}
@@ -458,31 +458,31 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
} else {
code_completion_current_selected = 0;
}
- update();
+ queue_redraw();
accept_event();
return;
}
if (k->is_action("ui_page_up", true)) {
code_completion_current_selected = MAX(0, code_completion_current_selected - code_completion_max_lines);
- update();
+ queue_redraw();
accept_event();
return;
}
if (k->is_action("ui_page_down", true)) {
code_completion_current_selected = MIN(code_completion_options.size() - 1, code_completion_current_selected + code_completion_max_lines);
- update();
+ queue_redraw();
accept_event();
return;
}
if (k->is_action("ui_home", true)) {
code_completion_current_selected = 0;
- update();
+ queue_redraw();
accept_event();
return;
}
if (k->is_action("ui_end", true)) {
code_completion_current_selected = code_completion_options.size() - 1;
- update();
+ queue_redraw();
accept_event();
return;
}
@@ -1106,7 +1106,7 @@ bool CodeEdit::is_auto_brace_completion_enabled() const {
void CodeEdit::set_highlight_matching_braces_enabled(bool p_enabled) {
highlight_matching_braces_enabled = p_enabled;
- update();
+ queue_redraw();
}
bool CodeEdit::is_highlight_matching_braces_enabled() const {
@@ -1265,7 +1265,7 @@ void CodeEdit::set_line_as_breakpoint(int p_line, bool p_breakpointed) {
breakpointed_lines.erase(p_line);
}
emit_signal(SNAME("breakpoint_toggled"), p_line);
- update();
+ queue_redraw();
}
bool CodeEdit::is_line_breakpointed(int p_line) const {
@@ -1294,7 +1294,7 @@ PackedInt32Array CodeEdit::get_breakpointed_lines() const {
void CodeEdit::set_line_as_bookmarked(int p_line, bool p_bookmarked) {
int mask = get_line_gutter_metadata(p_line, main_gutter);
set_line_gutter_metadata(p_line, main_gutter, p_bookmarked ? mask | MAIN_GUTTER_BOOKMARK : mask & ~MAIN_GUTTER_BOOKMARK);
- update();
+ queue_redraw();
}
bool CodeEdit::is_line_bookmarked(int p_line) const {
@@ -1323,7 +1323,7 @@ PackedInt32Array CodeEdit::get_bookmarked_lines() const {
void CodeEdit::set_line_as_executing(int p_line, bool p_executing) {
int mask = get_line_gutter_metadata(p_line, main_gutter);
set_line_gutter_metadata(p_line, main_gutter, p_executing ? mask | MAIN_GUTTER_EXECUTING : mask & ~MAIN_GUTTER_EXECUTING);
- update();
+ queue_redraw();
}
bool CodeEdit::is_line_executing(int p_line) const {
@@ -1359,7 +1359,7 @@ bool CodeEdit::is_draw_line_numbers_enabled() const {
void CodeEdit::set_line_numbers_zero_padded(bool p_zero_padded) {
p_zero_padded ? line_number_padding = "0" : line_number_padding = " ";
- update();
+ queue_redraw();
}
bool CodeEdit::is_line_numbers_zero_padded() const {
@@ -1529,7 +1529,7 @@ void CodeEdit::fold_line(int p_line) {
set_caret_line(p_line, false, false);
set_caret_column(get_line(p_line).length(), false);
}
- update();
+ queue_redraw();
}
void CodeEdit::unfold_line(int p_line) {
@@ -1552,14 +1552,14 @@ void CodeEdit::unfold_line(int p_line) {
}
_set_line_as_hidden(i, false);
}
- update();
+ queue_redraw();
}
void CodeEdit::fold_all_lines() {
for (int i = 0; i < get_line_count(); i++) {
fold_line(i);
}
- update();
+ queue_redraw();
}
void CodeEdit::unfold_all_lines() {
@@ -1765,12 +1765,12 @@ Point2 CodeEdit::get_delimiter_end_position(int p_line, int p_column) const {
void CodeEdit::set_code_hint(const String &p_hint) {
code_hint = p_hint;
code_hint_xpos = -0xFFFF;
- update();
+ queue_redraw();
}
void CodeEdit::set_code_hint_draw_below(bool p_below) {
code_hint_draw_below = p_below;
- update();
+ queue_redraw();
}
/* Code Completion */
@@ -1929,7 +1929,7 @@ void CodeEdit::set_code_completion_selected_index(int p_index) {
}
ERR_FAIL_INDEX(p_index, code_completion_options.size());
code_completion_current_selected = p_index;
- update();
+ queue_redraw();
}
void CodeEdit::confirm_code_completion(bool p_replace) {
@@ -2043,13 +2043,13 @@ void CodeEdit::cancel_code_completion() {
}
code_completion_forced = false;
code_completion_active = false;
- update();
+ queue_redraw();
}
/* Line length guidelines */
void CodeEdit::set_line_length_guidelines(TypedArray<int> p_guideline_columns) {
line_length_guideline_columns = p_guideline_columns;
- update();
+ queue_redraw();
}
TypedArray<int> CodeEdit::get_line_length_guidelines() const {
@@ -2802,7 +2802,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() {
code_completion_longest_line = MIN(max_width, code_completion_max_width * font_size);
code_completion_current_selected = 0;
code_completion_active = true;
- update();
+ queue_redraw();
return;
}
@@ -3052,7 +3052,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() {
code_completion_longest_line = MIN(max_width, code_completion_max_width * font_size);
code_completion_current_selected = 0;
code_completion_active = true;
- update();
+ queue_redraw();
}
void CodeEdit::_lines_edited_from(int p_from_line, int p_to_line) {
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 9eef45f412..3030fdff8d 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -303,7 +303,7 @@ void ColorPicker::set_edit_alpha(bool p_show) {
}
_update_color();
- sample->update();
+ sample->queue_redraw();
}
bool ColorPicker::is_editing_alpha() const {
@@ -458,15 +458,15 @@ void ColorPicker::_update_color(bool p_update_sliders) {
_update_text_value();
- sample->update();
- uv_edit->update();
- w_edit->update();
+ sample->queue_redraw();
+ uv_edit->queue_redraw();
+ w_edit->queue_redraw();
for (int i = 0; i < current_slider_count; i++) {
- sliders[i]->update();
+ sliders[i]->queue_redraw();
}
- alpha_slider->update();
- wheel->update();
- wheel_uv->update();
+ alpha_slider->queue_redraw();
+ wheel->queue_redraw();
+ wheel_uv->queue_redraw();
updating = false;
}
@@ -536,7 +536,7 @@ void ColorPicker::_add_preset_button(int p_size, const Color &p_color) {
btn_preset->set_preset_color(p_color);
btn_preset->set_custom_minimum_size(Size2(p_size, p_size));
btn_preset->connect("gui_input", callable_mp(this, &ColorPicker::_preset_input).bind(p_color));
- btn_preset->set_tooltip(vformat(RTR("Color: #%s\nLMB: Apply color\nRMB: Remove preset"), p_color.to_html(p_color.a < 1)));
+ btn_preset->set_tooltip_text(vformat(RTR("Color: #%s\nLMB: Apply color\nRMB: Remove preset"), p_color.to_html(p_color.a < 1)));
preset_container->add_child(btn_preset);
}
@@ -1236,7 +1236,7 @@ ColorPicker::ColorPicker() :
btn_pick->set_flat(true);
hb_smpl->add_child(btn_pick);
btn_pick->set_toggle_mode(true);
- btn_pick->set_tooltip(RTR("Pick a color from the editor window."));
+ btn_pick->set_tooltip_text(RTR("Pick a color from the editor window."));
btn_pick->connect("pressed", callable_mp(this, &ColorPicker::_screen_pick_pressed));
VBoxContainer *vbl = memnew(VBoxContainer);
@@ -1276,7 +1276,7 @@ ColorPicker::ColorPicker() :
text_type = memnew(Button);
hhb->add_child(text_type);
text_type->set_text("#");
- text_type->set_tooltip(RTR("Switch between hexadecimal and code values."));
+ 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));
} else {
@@ -1337,7 +1337,7 @@ ColorPicker::ColorPicker() :
btn_add_preset = memnew(Button);
btn_add_preset->set_icon_alignment(HORIZONTAL_ALIGNMENT_CENTER);
- btn_add_preset->set_tooltip(RTR("Add current color as a preset."));
+ btn_add_preset->set_tooltip_text(RTR("Add current color as a preset."));
btn_add_preset->connect("pressed", callable_mp(this, &ColorPicker::_add_preset_pressed));
preset_container->add_child(btn_add_preset);
}
@@ -1359,7 +1359,7 @@ void ColorPickerButton::_about_to_popup() {
void ColorPickerButton::_color_changed(const Color &p_color) {
color = p_color;
- update();
+ queue_redraw();
emit_signal(SNAME("color_changed"), color);
}
@@ -1439,7 +1439,7 @@ void ColorPickerButton::set_pick_color(const Color &p_color) {
picker->set_pick_color(p_color);
}
- update();
+ queue_redraw();
}
Color ColorPickerButton::get_pick_color() const {
diff --git a/scene/gui/color_rect.cpp b/scene/gui/color_rect.cpp
index c30fa8461a..143662efc6 100644
--- a/scene/gui/color_rect.cpp
+++ b/scene/gui/color_rect.cpp
@@ -35,7 +35,7 @@ void ColorRect::set_color(const Color &p_color) {
return;
}
color = p_color;
- update();
+ queue_redraw();
}
Color ColorRect::get_color() const {
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 9b6a19c50a..06819283fa 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -43,6 +43,7 @@
#include "scene/main/canvas_layer.h"
#include "scene/main/window.h"
#include "scene/scene_string_names.h"
+#include "scene/theme/theme_db.h"
#include "servers/rendering_server.h"
#include "servers/text_server.h"
@@ -193,15 +194,15 @@ void Control::get_argument_options(const StringName &p_function, int p_idx, List
List<StringName> sn;
String pf = p_function;
if (pf == "add_theme_color_override" || pf == "has_theme_color" || pf == "has_theme_color_override" || pf == "get_theme_color") {
- Theme::get_default()->get_color_list(get_class(), &sn);
+ ThemeDB::get_singleton()->get_default_theme()->get_color_list(get_class(), &sn);
} else if (pf == "add_theme_style_override" || pf == "has_theme_style" || pf == "has_theme_style_override" || pf == "get_theme_style") {
- Theme::get_default()->get_stylebox_list(get_class(), &sn);
+ ThemeDB::get_singleton()->get_default_theme()->get_stylebox_list(get_class(), &sn);
} else if (pf == "add_theme_font_override" || pf == "has_theme_font" || pf == "has_theme_font_override" || pf == "get_theme_font") {
- Theme::get_default()->get_font_list(get_class(), &sn);
+ ThemeDB::get_singleton()->get_default_theme()->get_font_list(get_class(), &sn);
} else if (pf == "add_theme_font_size_override" || pf == "has_theme_font_size" || pf == "has_theme_font_size_override" || pf == "get_theme_font_size") {
- Theme::get_default()->get_font_size_list(get_class(), &sn);
+ ThemeDB::get_singleton()->get_default_theme()->get_font_size_list(get_class(), &sn);
} else if (pf == "add_theme_constant_override" || pf == "has_theme_constant" || pf == "has_theme_constant_override" || pf == "get_theme_constant") {
- Theme::get_default()->get_constant_list(get_class(), &sn);
+ ThemeDB::get_singleton()->get_default_theme()->get_constant_list(get_class(), &sn);
}
sn.sort_custom<StringName::AlphCompare>();
@@ -344,7 +345,7 @@ bool Control::_get(const StringName &p_name, Variant &r_ret) const {
}
void Control::_get_property_list(List<PropertyInfo> *p_list) const {
- Ref<Theme> theme = Theme::get_default();
+ Ref<Theme> theme = ThemeDB::get_singleton()->get_default_theme();
p_list->push_back(PropertyInfo(Variant::NIL, TTRC("Theme Overrides"), PROPERTY_HINT_NONE, "theme_override_", PROPERTY_USAGE_GROUP));
@@ -429,9 +430,9 @@ void Control::_validate_property(PropertyInfo &p_property) const {
// Only the default theme and the project theme are used for the list of options.
// This is an imposed limitation to simplify the logic needed to leverage those options.
- Theme::get_default()->get_type_variation_list(get_class_name(), &names);
- if (Theme::get_project_default().is_valid()) {
- Theme::get_project_default()->get_type_variation_list(get_class_name(), &names);
+ ThemeDB::get_singleton()->get_default_theme()->get_type_variation_list(get_class_name(), &names);
+ if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
+ ThemeDB::get_singleton()->get_project_theme()->get_type_variation_list(get_class_name(), &names);
}
names.sort_custom<StringName::AlphCompare>();
@@ -712,7 +713,7 @@ void Control::set_anchor(Side p_side, real_t p_anchor, bool p_keep_offset, bool
_size_changed();
}
- update();
+ queue_redraw();
}
real_t Control::get_anchor(Side p_side) const {
@@ -1458,7 +1459,7 @@ void Control::set_scale(const Vector2 &p_scale) {
if (data.scale.y == 0) {
data.scale.y = CMP_EPSILON;
}
- update();
+ queue_redraw();
_notify_transform();
}
@@ -1472,7 +1473,7 @@ void Control::set_rotation(real_t p_radians) {
}
data.rotation = p_radians;
- update();
+ queue_redraw();
_notify_transform();
}
@@ -1486,7 +1487,7 @@ void Control::set_pivot_offset(const Vector2 &p_pivot) {
}
data.pivot_offset = p_pivot;
- update();
+ queue_redraw();
_notify_transform();
}
@@ -2239,7 +2240,7 @@ void Control::set_disable_visibility_clip(bool p_ignore) {
return;
}
data.disable_visibility_clip = p_ignore;
- update();
+ queue_redraw();
}
bool Control::is_visibility_clip_disabled() const {
@@ -2251,7 +2252,7 @@ void Control::set_clip_contents(bool p_clip) {
return;
}
data.clip_contents = p_clip;
- update();
+ queue_redraw();
}
bool Control::is_clipping_contents() {
@@ -2329,6 +2330,9 @@ void Control::_invalidate_theme_cache() {
data.theme_constant_cache.clear();
}
+void Control::_update_theme_item_cache() {
+}
+
void Control::set_theme(const Ref<Theme> &p_theme) {
if (data.theme == p_theme) {
return;
@@ -2419,22 +2423,22 @@ T Control::get_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner
}
// Secondly, check the project-defined Theme resource.
- if (Theme::get_project_default().is_valid()) {
+ if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
for (const StringName &E : p_theme_types) {
- if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E)) {
- return Theme::get_project_default()->get_theme_item(p_data_type, p_name, E);
+ if (ThemeDB::get_singleton()->get_project_theme()->has_theme_item(p_data_type, p_name, E)) {
+ return ThemeDB::get_singleton()->get_project_theme()->get_theme_item(p_data_type, p_name, E);
}
}
}
// Lastly, fall back on the items defined in the default Theme, if they exist.
for (const StringName &E : p_theme_types) {
- if (Theme::get_default()->has_theme_item(p_data_type, p_name, E)) {
- return Theme::get_default()->get_theme_item(p_data_type, p_name, E);
+ if (ThemeDB::get_singleton()->get_default_theme()->has_theme_item(p_data_type, p_name, E)) {
+ return ThemeDB::get_singleton()->get_default_theme()->get_theme_item(p_data_type, p_name, E);
}
}
// If they don't exist, use any type to return the default/empty value.
- return Theme::get_default()->get_theme_item(p_data_type, p_name, p_theme_types[0]);
+ return ThemeDB::get_singleton()->get_default_theme()->get_theme_item(p_data_type, p_name, p_theme_types[0]);
}
bool Control::has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types) {
@@ -2475,9 +2479,9 @@ bool Control::has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_ow
}
// Secondly, check the project-defined Theme resource.
- if (Theme::get_project_default().is_valid()) {
+ if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
for (const StringName &E : p_theme_types) {
- if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E)) {
+ if (ThemeDB::get_singleton()->get_project_theme()->has_theme_item(p_data_type, p_name, E)) {
return true;
}
}
@@ -2485,7 +2489,7 @@ bool Control::has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_ow
// Lastly, fall back on the items defined in the default Theme, if they exist.
for (const StringName &E : p_theme_types) {
- if (Theme::get_default()->has_theme_item(p_data_type, p_name, E)) {
+ if (ThemeDB::get_singleton()->get_default_theme()->has_theme_item(p_data_type, p_name, E)) {
return true;
}
}
@@ -2494,13 +2498,13 @@ bool Control::has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_ow
void Control::_get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const {
if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
- if (Theme::get_project_default().is_valid() && Theme::get_project_default()->get_type_variation_base(data.theme_type_variation) != StringName()) {
- Theme::get_project_default()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list);
+ if (ThemeDB::get_singleton()->get_project_theme().is_valid() && ThemeDB::get_singleton()->get_project_theme()->get_type_variation_base(data.theme_type_variation) != StringName()) {
+ ThemeDB::get_singleton()->get_project_theme()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list);
} else {
- Theme::get_default()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list);
+ ThemeDB::get_singleton()->get_default_theme()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list);
}
} else {
- Theme::get_default()->get_type_dependencies(p_theme_type, StringName(), p_list);
+ ThemeDB::get_singleton()->get_default_theme()->get_type_dependencies(p_theme_type, StringName(), p_list);
}
}
@@ -2851,17 +2855,17 @@ float Control::fetch_theme_default_base_scale(Control *p_theme_owner, Window *p_
}
// Secondly, check the project-defined Theme resource.
- if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_default_base_scale()) {
- return Theme::get_project_default()->get_default_base_scale();
+ if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
+ if (ThemeDB::get_singleton()->get_project_theme()->has_default_base_scale()) {
+ return ThemeDB::get_singleton()->get_project_theme()->get_default_base_scale();
}
}
// Lastly, fall back on the default Theme.
- if (Theme::get_default()->has_default_base_scale()) {
- return Theme::get_default()->get_default_base_scale();
+ if (ThemeDB::get_singleton()->get_default_theme()->has_default_base_scale()) {
+ return ThemeDB::get_singleton()->get_default_theme()->get_default_base_scale();
}
- return Theme::get_fallback_base_scale();
+ return ThemeDB::get_singleton()->get_fallback_base_scale();
}
float Control::get_theme_default_base_scale() const {
@@ -2902,17 +2906,17 @@ Ref<Font> Control::fetch_theme_default_font(Control *p_theme_owner, Window *p_th
}
// Secondly, check the project-defined Theme resource.
- if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_default_font()) {
- return Theme::get_project_default()->get_default_font();
+ if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
+ if (ThemeDB::get_singleton()->get_project_theme()->has_default_font()) {
+ return ThemeDB::get_singleton()->get_project_theme()->get_default_font();
}
}
// Lastly, fall back on the default Theme.
- if (Theme::get_default()->has_default_font()) {
- return Theme::get_default()->get_default_font();
+ if (ThemeDB::get_singleton()->get_default_theme()->has_default_font()) {
+ return ThemeDB::get_singleton()->get_default_theme()->get_default_font();
}
- return Theme::get_fallback_font();
+ return ThemeDB::get_singleton()->get_fallback_font();
}
Ref<Font> Control::get_theme_default_font() const {
@@ -2953,17 +2957,17 @@ int Control::fetch_theme_default_font_size(Control *p_theme_owner, Window *p_the
}
// Secondly, check the project-defined Theme resource.
- if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_default_font_size()) {
- return Theme::get_project_default()->get_default_font_size();
+ if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
+ if (ThemeDB::get_singleton()->get_project_theme()->has_default_font_size()) {
+ return ThemeDB::get_singleton()->get_project_theme()->get_default_font_size();
}
}
// Lastly, fall back on the default Theme.
- if (Theme::get_default()->has_default_font_size()) {
- return Theme::get_default()->get_default_font_size();
+ if (ThemeDB::get_singleton()->get_default_theme()->has_default_font_size()) {
+ return ThemeDB::get_singleton()->get_default_theme()->get_default_font_size();
}
- return Theme::get_fallback_font_size();
+ return ThemeDB::get_singleton()->get_fallback_font_size();
}
int Control::get_theme_default_font_size() const {
@@ -3062,12 +3066,12 @@ bool Control::is_auto_translating() const {
// Extra properties.
-void Control::set_tooltip(const String &p_tooltip) {
- data.tooltip = p_tooltip;
+void Control::set_tooltip_text(const String &p_hint) {
+ data.tooltip = p_hint;
update_configuration_warnings();
}
-String Control::_get_tooltip() const {
+String Control::get_tooltip_text() const {
return data.tooltip;
}
@@ -3102,6 +3106,11 @@ void Control::remove_child_notify(Node *p_child) {
void Control::_notification(int p_notification) {
switch (p_notification) {
+ case NOTIFICATION_POSTINITIALIZE: {
+ _invalidate_theme_cache();
+ _update_theme_item_cache();
+ } break;
+
case NOTIFICATION_ENTER_TREE: {
// Need to defer here, because theme owner information might be set in
// add_child_notify, which doesn't get called until right after this.
@@ -3195,9 +3204,9 @@ void Control::_notification(int p_notification) {
// some parents need to know the order of the children to draw (like TabContainer)
// update if necessary
if (data.parent) {
- data.parent->update();
+ data.parent->queue_redraw();
}
- update();
+ queue_redraw();
if (data.RI) {
get_viewport()->_gui_set_root_order_dirty();
@@ -3224,19 +3233,20 @@ void Control::_notification(int p_notification) {
case NOTIFICATION_FOCUS_ENTER: {
emit_signal(SceneStringNames::get_singleton()->focus_entered);
- update();
+ queue_redraw();
} break;
case NOTIFICATION_FOCUS_EXIT: {
emit_signal(SceneStringNames::get_singleton()->focus_exited);
- update();
+ queue_redraw();
} break;
case NOTIFICATION_THEME_CHANGED: {
emit_signal(SceneStringNames::get_singleton()->theme_changed);
_invalidate_theme_cache();
+ _update_theme_item_cache();
update_minimum_size();
- update();
+ queue_redraw();
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -3256,6 +3266,7 @@ void Control::_notification(int p_notification) {
if (is_inside_tree()) {
data.is_rtl_dirty = true;
_invalidate_theme_cache();
+ _update_theme_item_cache();
_size_changed();
}
} break;
@@ -3383,9 +3394,9 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_v_grow_direction", "direction"), &Control::set_v_grow_direction);
ClassDB::bind_method(D_METHOD("get_v_grow_direction"), &Control::get_v_grow_direction);
- ClassDB::bind_method(D_METHOD("set_tooltip", "tooltip"), &Control::set_tooltip);
+ ClassDB::bind_method(D_METHOD("set_tooltip_text", "hint"), &Control::set_tooltip_text);
+ ClassDB::bind_method(D_METHOD("get_tooltip_text"), &Control::get_tooltip_text);
ClassDB::bind_method(D_METHOD("get_tooltip", "at_position"), &Control::get_tooltip, DEFVAL(Point2()));
- ClassDB::bind_method(D_METHOD("_get_tooltip"), &Control::_get_tooltip);
ClassDB::bind_method(D_METHOD("set_default_cursor_shape", "shape"), &Control::set_default_cursor_shape);
ClassDB::bind_method(D_METHOD("get_default_cursor_shape"), &Control::get_default_cursor_shape);
@@ -3475,8 +3486,8 @@ void Control::_bind_methods() {
ADD_GROUP("Auto Translate", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_translate"), "set_auto_translate", "is_auto_translating");
- ADD_GROUP("Hint", "hint_");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "hint_tooltip", PROPERTY_HINT_MULTILINE_TEXT), "set_tooltip", "_get_tooltip");
+ ADD_GROUP("Tooltip", "tooltip_");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "tooltip_text", PROPERTY_HINT_MULTILINE_TEXT), "set_tooltip_text", "get_tooltip_text");
ADD_GROUP("Focus", "focus_");
ADD_PROPERTYI(PropertyInfo(Variant::NODE_PATH, "focus_neighbor_left", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Control"), "set_focus_neighbor", "get_focus_neighbor", SIDE_LEFT);
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 82d3d8d24a..ac5d481f3a 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -312,7 +312,7 @@ private:
// Extra properties.
- String _get_tooltip() const;
+ String get_tooltip_text() const;
protected:
// Dynamic properties.
@@ -325,6 +325,10 @@ protected:
bool _property_can_revert(const StringName &p_name) const;
bool _property_get_revert(const StringName &p_name, Variant &r_property) const;
+ // Theming.
+
+ virtual void _update_theme_item_cache();
+
// Internationalization.
virtual TypedArray<Vector2i> structured_text_parser(TextServer::StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
@@ -604,7 +608,7 @@ public:
// Extra properties.
- void set_tooltip(const String &p_tooltip);
+ void set_tooltip_text(const String &text);
virtual String get_tooltip(const Point2 &p_pos) const;
virtual Control *make_custom_tooltip(const String &p_text) const;
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index b4e0747ab8..0a1aeeda71 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -50,6 +50,14 @@ void AcceptDialog::_parent_focused() {
}
}
+void AcceptDialog::_update_theme_item_cache() {
+ Window::_update_theme_item_cache();
+
+ theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
+ theme_cache.margin = get_theme_constant(SNAME("margin"));
+ theme_cache.button_margin = get_theme_constant(SNAME("button_margin"));
+}
+
void AcceptDialog::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -69,7 +77,10 @@ void AcceptDialog::_notification(int p_what) {
} break;
case NOTIFICATION_THEME_CHANGED: {
- bg->add_theme_style_override("panel", bg->get_theme_stylebox(SNAME("panel"), SNAME("AcceptDialog")));
+ bg->add_theme_style_override("panel", theme_cache.panel_style);
+
+ label->set_begin(Point2(theme_cache.margin, theme_cache.margin));
+ label->set_end(Point2(-theme_cache.margin, -theme_cache.button_margin - 10));
} break;
case NOTIFICATION_EXIT_TREE: {
@@ -185,12 +196,12 @@ void AcceptDialog::_update_child_rects() {
if (label->get_text().is_empty()) {
label_size.height = 0;
}
- int margin = hbc->get_theme_constant(SNAME("margin"), SNAME("Dialogs"));
+
Size2 size = get_size();
Size2 hminsize = hbc->get_combined_minimum_size();
- Vector2 cpos(margin, margin + label_size.height);
- Vector2 csize(size.x - margin * 2, size.y - margin * 3 - hminsize.y - label_size.height);
+ Vector2 cpos(theme_cache.margin, theme_cache.margin + label_size.height);
+ Vector2 csize(size.x - theme_cache.margin * 2, size.y - theme_cache.margin * 3 - hminsize.y - label_size.height);
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
@@ -206,7 +217,7 @@ void AcceptDialog::_update_child_rects() {
c->set_size(csize);
}
- cpos.y += csize.y + margin;
+ cpos.y += csize.y + theme_cache.margin;
csize.y = hminsize.y;
hbc->set_position(cpos);
@@ -217,7 +228,6 @@ void AcceptDialog::_update_child_rects() {
}
Size2 AcceptDialog::_get_contents_minimum_size() const {
- int margin = hbc->get_theme_constant(SNAME("margin"), SNAME("Dialogs"));
Size2 minsize = label->get_combined_minimum_size();
for (int i = 0; i < get_child_count(); i++) {
@@ -238,8 +248,8 @@ Size2 AcceptDialog::_get_contents_minimum_size() const {
Size2 hminsize = hbc->get_combined_minimum_size();
minsize.x = MAX(hminsize.x, minsize.x);
minsize.y += hminsize.y;
- minsize.x += margin * 2;
- minsize.y += margin * 3; //one as separation between hbc and child
+ minsize.x += theme_cache.margin * 2;
+ minsize.y += theme_cache.margin * 3; //one as separation between hbc and child
Size2 wmsize = get_min_size();
minsize.x = MAX(wmsize.x, minsize.x);
@@ -350,14 +360,9 @@ AcceptDialog::AcceptDialog() {
hbc = memnew(HBoxContainer);
- int margin = hbc->get_theme_constant(SNAME("margin"), SNAME("Dialogs"));
- int button_margin = hbc->get_theme_constant(SNAME("button_margin"), SNAME("Dialogs"));
-
label = memnew(Label);
label->set_anchor(SIDE_RIGHT, Control::ANCHOR_END);
label->set_anchor(SIDE_BOTTOM, Control::ANCHOR_END);
- label->set_begin(Point2(margin, margin));
- label->set_end(Point2(-margin, -button_margin - 10));
add_child(label, false, INTERNAL_MODE_FRONT);
add_child(hbc, false, INTERNAL_MODE_FRONT);
diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h
index 9ebf5ddfb2..8ba9c93861 100644
--- a/scene/gui/dialogs.h
+++ b/scene/gui/dialogs.h
@@ -52,6 +52,12 @@ class AcceptDialog : public Window {
bool hide_on_ok = true;
bool close_on_escape = true;
+ struct ThemeCache {
+ Ref<StyleBox> panel_style;
+ int margin = 0;
+ int button_margin = 0;
+ } theme_cache;
+
void _custom_action(const String &p_action);
void _update_child_rects();
@@ -62,6 +68,7 @@ class AcceptDialog : public Window {
protected:
virtual Size2 _get_contents_minimum_size() const override;
+ virtual void _update_theme_item_cache() 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 7965b12edd..a0cf5f5970 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -59,36 +59,26 @@ VBoxContainer *FileDialog::get_vbox() {
return vbox;
}
-void FileDialog::_theme_changed() {
- Color font_color = vbox->get_theme_color(SNAME("font_color"), SNAME("Button"));
- Color font_hover_color = vbox->get_theme_color(SNAME("font_hover_color"), SNAME("Button"));
- Color font_focus_color = vbox->get_theme_color(SNAME("font_focus_color"), SNAME("Button"));
- Color font_pressed_color = vbox->get_theme_color(SNAME("font_pressed_color"), SNAME("Button"));
-
- dir_up->add_theme_color_override("icon_normal_color", font_color);
- dir_up->add_theme_color_override("icon_hover_color", font_hover_color);
- dir_up->add_theme_color_override("icon_focus_color", font_focus_color);
- dir_up->add_theme_color_override("icon_pressed_color", font_pressed_color);
-
- dir_prev->add_theme_color_override("icon_color_normal", font_color);
- dir_prev->add_theme_color_override("icon_color_hover", font_hover_color);
- dir_prev->add_theme_color_override("icon_focus_color", font_focus_color);
- dir_prev->add_theme_color_override("icon_color_pressed", font_pressed_color);
-
- dir_next->add_theme_color_override("icon_color_normal", font_color);
- dir_next->add_theme_color_override("icon_color_hover", font_hover_color);
- dir_next->add_theme_color_override("icon_focus_color", font_focus_color);
- dir_next->add_theme_color_override("icon_color_pressed", font_pressed_color);
-
- refresh->add_theme_color_override("icon_normal_color", font_color);
- refresh->add_theme_color_override("icon_hover_color", font_hover_color);
- refresh->add_theme_color_override("icon_focus_color", font_focus_color);
- refresh->add_theme_color_override("icon_pressed_color", font_pressed_color);
-
- show_hidden->add_theme_color_override("icon_normal_color", font_color);
- show_hidden->add_theme_color_override("icon_hover_color", font_hover_color);
- show_hidden->add_theme_color_override("icon_focus_color", font_focus_color);
- show_hidden->add_theme_color_override("icon_pressed_color", font_pressed_color);
+void FileDialog::_update_theme_item_cache() {
+ ConfirmationDialog::_update_theme_item_cache();
+
+ theme_cache.parent_folder = get_theme_icon(SNAME("parent_folder"));
+ theme_cache.forward_folder = get_theme_icon(SNAME("forward_folder"));
+ theme_cache.back_folder = get_theme_icon(SNAME("back_folder"));
+ theme_cache.reload = get_theme_icon(SNAME("reload"));
+ theme_cache.toggle_hidden = get_theme_icon(SNAME("toggle_hidden"));
+ theme_cache.folder = get_theme_icon(SNAME("folder"));
+ theme_cache.file = get_theme_icon(SNAME("file"));
+
+ theme_cache.folder_icon_modulate = get_theme_color(SNAME("folder_icon_modulate"));
+ theme_cache.file_icon_modulate = get_theme_color(SNAME("file_icon_modulate"));
+ theme_cache.files_disabled = get_theme_color(SNAME("files_disabled"));
+
+ // TODO: Define own colors?
+ theme_cache.icon_normal_color = get_theme_color(SNAME("font_color"), SNAME("Button"));
+ theme_cache.icon_hover_color = get_theme_color(SNAME("font_hover_color"), SNAME("Button"));
+ theme_cache.icon_focus_color = get_theme_color(SNAME("font_focus_color"), SNAME("Button"));
+ theme_cache.icon_pressed_color = get_theme_color(SNAME("font_pressed_color"), SNAME("Button"));
}
void FileDialog::_notification(int p_what) {
@@ -99,18 +89,42 @@ void FileDialog::_notification(int p_what) {
}
} break;
- case NOTIFICATION_ENTER_TREE: {
- dir_up->set_icon(vbox->get_theme_icon(SNAME("parent_folder"), SNAME("FileDialog")));
+ case NOTIFICATION_THEME_CHANGED: {
+ dir_up->set_icon(theme_cache.parent_folder);
if (vbox->is_layout_rtl()) {
- dir_prev->set_icon(vbox->get_theme_icon(SNAME("forward_folder"), SNAME("FileDialog")));
- dir_next->set_icon(vbox->get_theme_icon(SNAME("back_folder"), SNAME("FileDialog")));
+ dir_prev->set_icon(theme_cache.forward_folder);
+ dir_next->set_icon(theme_cache.back_folder);
} else {
- dir_prev->set_icon(vbox->get_theme_icon(SNAME("back_folder"), SNAME("FileDialog")));
- dir_next->set_icon(vbox->get_theme_icon(SNAME("forward_folder"), SNAME("FileDialog")));
+ dir_prev->set_icon(theme_cache.back_folder);
+ dir_next->set_icon(theme_cache.forward_folder);
}
- refresh->set_icon(vbox->get_theme_icon(SNAME("reload"), SNAME("FileDialog")));
- show_hidden->set_icon(vbox->get_theme_icon(SNAME("toggle_hidden"), SNAME("FileDialog")));
- _theme_changed();
+ refresh->set_icon(theme_cache.reload);
+ show_hidden->set_icon(theme_cache.toggle_hidden);
+
+ dir_up->add_theme_color_override("icon_normal_color", theme_cache.icon_normal_color);
+ dir_up->add_theme_color_override("icon_hover_color", theme_cache.icon_hover_color);
+ dir_up->add_theme_color_override("icon_focus_color", theme_cache.icon_focus_color);
+ dir_up->add_theme_color_override("icon_pressed_color", theme_cache.icon_pressed_color);
+
+ dir_prev->add_theme_color_override("icon_color_normal", theme_cache.icon_normal_color);
+ dir_prev->add_theme_color_override("icon_color_hover", theme_cache.icon_hover_color);
+ dir_prev->add_theme_color_override("icon_focus_color", theme_cache.icon_focus_color);
+ dir_prev->add_theme_color_override("icon_color_pressed", theme_cache.icon_pressed_color);
+
+ dir_next->add_theme_color_override("icon_color_normal", theme_cache.icon_normal_color);
+ dir_next->add_theme_color_override("icon_color_hover", theme_cache.icon_hover_color);
+ dir_next->add_theme_color_override("icon_focus_color", theme_cache.icon_focus_color);
+ dir_next->add_theme_color_override("icon_color_pressed", theme_cache.icon_pressed_color);
+
+ refresh->add_theme_color_override("icon_normal_color", theme_cache.icon_normal_color);
+ refresh->add_theme_color_override("icon_hover_color", theme_cache.icon_hover_color);
+ refresh->add_theme_color_override("icon_focus_color", theme_cache.icon_focus_color);
+ refresh->add_theme_color_override("icon_pressed_color", theme_cache.icon_pressed_color);
+
+ show_hidden->add_theme_color_override("icon_normal_color", theme_cache.icon_normal_color);
+ show_hidden->add_theme_color_override("icon_hover_color", theme_cache.icon_hover_color);
+ show_hidden->add_theme_color_override("icon_focus_color", theme_cache.icon_focus_color);
+ show_hidden->add_theme_color_override("icon_pressed_color", theme_cache.icon_pressed_color);
} break;
case NOTIFICATION_TRANSLATION_CHANGED: {
@@ -163,7 +177,7 @@ Vector<String> FileDialog::get_selected_files() const {
TreeItem *item = tree->get_root();
while ((item = tree->get_next_selected(item))) {
- list.push_back(dir_access->get_current_dir().plus_file(item->get_text(0)));
+ list.push_back(dir_access->get_current_dir().path_join(item->get_text(0)));
};
return list;
@@ -192,7 +206,7 @@ void FileDialog::update_dir() {
}
void FileDialog::_dir_submitted(String p_dir) {
- _change_dir(root_prefix.plus_file(p_dir));
+ _change_dir(root_prefix.path_join(p_dir));
file->set_text("");
_push_history();
}
@@ -202,7 +216,7 @@ void FileDialog::_file_submitted(const String &p_file) {
}
void FileDialog::_save_confirm_pressed() {
- String f = dir_access->get_current_dir().plus_file(file->get_text());
+ String f = dir_access->get_current_dir().path_join(file->get_text());
emit_signal(SNAME("file_selected"), f);
hide();
}
@@ -252,7 +266,7 @@ void FileDialog::_action_pressed() {
Vector<String> files;
while (ti) {
- files.push_back(fbase.plus_file(ti->get_text(0)));
+ files.push_back(fbase.path_join(ti->get_text(0)));
ti = tree->get_next_selected(ti);
}
@@ -265,7 +279,7 @@ void FileDialog::_action_pressed() {
}
String file_text = file->get_text();
- String f = file_text.is_absolute_path() ? file_text : dir_access->get_current_dir().plus_file(file_text);
+ String f = file_text.is_absolute_path() ? file_text : dir_access->get_current_dir().path_join(file_text);
if ((mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_FILE) && dir_access->file_exists(f)) {
emit_signal(SNAME("file_selected"), f);
@@ -278,7 +292,7 @@ void FileDialog::_action_pressed() {
if (item) {
Dictionary d = item->get_metadata(0);
if (d["dir"] && d["name"] != "..") {
- path = path.plus_file(d["name"]);
+ path = path.path_join(d["name"]);
}
}
@@ -506,10 +520,6 @@ void FileDialog::update_file_list() {
}
TreeItem *root = tree->create_item();
- Ref<Texture2D> folder = vbox->get_theme_icon(SNAME("folder"), SNAME("FileDialog"));
- Ref<Texture2D> file_icon = vbox->get_theme_icon(SNAME("file"), SNAME("FileDialog"));
- const Color folder_color = vbox->get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog"));
- const Color file_color = vbox->get_theme_color(SNAME("file_icon_modulate"), SNAME("FileDialog"));
List<String> files;
List<String> dirs;
@@ -541,8 +551,8 @@ void FileDialog::update_file_list() {
String &dir_name = dirs.front()->get();
TreeItem *ti = tree->create_item(root);
ti->set_text(0, dir_name);
- ti->set_icon(0, folder);
- ti->set_icon_modulate(0, folder_color);
+ ti->set_icon(0, theme_cache.folder);
+ ti->set_icon_modulate(0, theme_cache.folder_icon_modulate);
Dictionary d;
d["name"] = dir_name;
@@ -598,15 +608,15 @@ void FileDialog::update_file_list() {
ti->set_text(0, files.front()->get());
if (get_icon_func) {
- Ref<Texture2D> icon = get_icon_func(base_dir.plus_file(files.front()->get()));
+ Ref<Texture2D> icon = get_icon_func(base_dir.path_join(files.front()->get()));
ti->set_icon(0, icon);
} else {
- ti->set_icon(0, file_icon);
+ ti->set_icon(0, theme_cache.file);
}
- ti->set_icon_modulate(0, file_color);
+ ti->set_icon_modulate(0, theme_cache.file_icon_modulate);
if (mode == FILE_MODE_OPEN_DIR) {
- ti->set_custom_color(0, vbox->get_theme_color(SNAME("files_disabled"), SNAME("FileDialog")));
+ ti->set_custom_color(0, theme_cache.files_disabled);
ti->set_selectable(0, false);
}
Dictionary d;
@@ -706,7 +716,7 @@ String FileDialog::get_current_file() const {
}
String FileDialog::get_current_path() const {
- return dir->get_text().plus_file(file->get_text());
+ return dir->get_text().path_join(file->get_text());
}
void FileDialog::set_current_dir(const String &p_dir) {
@@ -1006,7 +1016,6 @@ FileDialog::FileDialog() {
vbox = memnew(VBoxContainer);
add_child(vbox, false, INTERNAL_MODE_FRONT);
- vbox->connect("theme_changed", callable_mp(this, &FileDialog::_theme_changed));
mode = FILE_MODE_SAVE_FILE;
set_title(TTRC("Save a File"));
@@ -1015,13 +1024,13 @@ FileDialog::FileDialog() {
dir_prev = memnew(Button);
dir_prev->set_flat(true);
- dir_prev->set_tooltip(RTR("Go to previous folder."));
+ dir_prev->set_tooltip_text(RTR("Go to previous folder."));
dir_next = memnew(Button);
dir_next->set_flat(true);
- dir_next->set_tooltip(RTR("Go to next folder."));
+ dir_next->set_tooltip_text(RTR("Go to next folder."));
dir_up = memnew(Button);
dir_up->set_flat(true);
- dir_up->set_tooltip(RTR("Go to parent folder."));
+ dir_up->set_tooltip_text(RTR("Go to parent folder."));
hbc->add_child(dir_prev);
hbc->add_child(dir_next);
hbc->add_child(dir_up);
@@ -1045,7 +1054,7 @@ FileDialog::FileDialog() {
refresh = memnew(Button);
refresh->set_flat(true);
- refresh->set_tooltip(RTR("Refresh files."));
+ refresh->set_tooltip_text(RTR("Refresh files."));
refresh->connect("pressed", callable_mp(this, &FileDialog::update_file_list));
hbc->add_child(refresh);
@@ -1053,7 +1062,7 @@ FileDialog::FileDialog() {
show_hidden->set_flat(true);
show_hidden->set_toggle_mode(true);
show_hidden->set_pressed(is_showing_hidden_files());
- show_hidden->set_tooltip(RTR("Toggle the visibility of hidden files."));
+ show_hidden->set_tooltip_text(RTR("Toggle the visibility of hidden files."));
show_hidden->connect("toggled", callable_mp(this, &FileDialog::set_show_hidden_files));
hbc->add_child(show_hidden);
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index 4945094086..5c892288b5 100644
--- a/scene/gui/file_dialog.h
+++ b/scene/gui/file_dialog.h
@@ -109,6 +109,25 @@ private:
bool invalidated = true;
+ struct ThemeCache {
+ Ref<Texture2D> parent_folder;
+ Ref<Texture2D> forward_folder;
+ Ref<Texture2D> back_folder;
+ Ref<Texture2D> reload;
+ Ref<Texture2D> toggle_hidden;
+ Ref<Texture2D> folder;
+ Ref<Texture2D> file;
+
+ Color folder_icon_modulate;
+ Color file_icon_modulate;
+ Color files_disabled;
+
+ Color icon_normal_color;
+ Color icon_hover_color;
+ Color icon_focus_color;
+ Color icon_pressed_color;
+ } theme_cache;
+
void update_dir();
void update_file_name();
void update_file_list();
@@ -143,7 +162,7 @@ private:
virtual void _post_popup() override;
protected:
- void _theme_changed();
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/flow_container.cpp b/scene/gui/flow_container.cpp
index 30b694da76..ca230b8e81 100644
--- a/scene/gui/flow_container.cpp
+++ b/scene/gui/flow_container.cpp
@@ -44,9 +44,6 @@ void FlowContainer::_resort() {
return;
}
- int separation_horizontal = get_theme_constant(SNAME("h_separation"));
- int separation_vertical = get_theme_constant(SNAME("v_separation"));
-
bool rtl = is_layout_rtl();
HashMap<Control *, Size2i> children_minsize_cache;
@@ -74,14 +71,14 @@ void FlowContainer::_resort() {
if (vertical) { /* VERTICAL */
if (children_in_current_line > 0) {
- ofs.y += separation_vertical;
+ ofs.y += theme_cache.v_separation;
}
if (ofs.y + child_msc.y > current_container_size) {
- line_length = ofs.y - separation_vertical;
+ line_length = ofs.y - theme_cache.v_separation;
lines_data.push_back(_LineData{ children_in_current_line, line_height, line_length, current_container_size - line_length, line_stretch_ratio_total });
// Move in new column (vertical line).
- ofs.x += line_height + separation_horizontal;
+ ofs.x += line_height + theme_cache.h_separation;
ofs.y = 0;
line_height = 0;
line_stretch_ratio_total = 0;
@@ -96,14 +93,14 @@ void FlowContainer::_resort() {
} else { /* HORIZONTAL */
if (children_in_current_line > 0) {
- ofs.x += separation_horizontal;
+ ofs.x += theme_cache.h_separation;
}
if (ofs.x + child_msc.x > current_container_size) {
- line_length = ofs.x - separation_horizontal;
+ line_length = ofs.x - theme_cache.h_separation;
lines_data.push_back(_LineData{ children_in_current_line, line_height, line_length, current_container_size - line_length, line_stretch_ratio_total });
// Move in new line.
- ofs.y += line_height + separation_vertical;
+ ofs.y += line_height + theme_cache.v_separation;
ofs.x = 0;
line_height = 0;
line_stretch_ratio_total = 0;
@@ -146,11 +143,11 @@ void FlowContainer::_resort() {
current_line_idx++;
child_idx_in_line = 0;
if (vertical) {
- ofs.x += line_data.min_line_height + separation_horizontal;
+ ofs.x += line_data.min_line_height + theme_cache.h_separation;
ofs.y = 0;
} else {
ofs.x = 0;
- ofs.y += line_data.min_line_height + separation_vertical;
+ ofs.y += line_data.min_line_height + theme_cache.v_separation;
}
line_data = lines_data[current_line_idx];
}
@@ -184,9 +181,9 @@ void FlowContainer::_resort() {
fit_child_in_rect(child, child_rect);
if (vertical) { /* VERTICAL */
- ofs.y += child_size.height + separation_vertical;
+ ofs.y += child_size.height + theme_cache.v_separation;
} else { /* HORIZONTAL */
- ofs.x += child_size.width + separation_horizontal;
+ ofs.x += child_size.width + theme_cache.h_separation;
}
child_idx_in_line++;
@@ -250,6 +247,13 @@ Vector<int> FlowContainer::get_allowed_size_flags_vertical() const {
return flags;
}
+void FlowContainer::_update_theme_item_cache() {
+ Container::_update_theme_item_cache();
+
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
+ theme_cache.v_separation = get_theme_constant(SNAME("v_separation"));
+}
+
void FlowContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_SORT_CHILDREN: {
diff --git a/scene/gui/flow_container.h b/scene/gui/flow_container.h
index a2da43e071..2cdf7d7c37 100644
--- a/scene/gui/flow_container.h
+++ b/scene/gui/flow_container.h
@@ -42,11 +42,17 @@ private:
bool vertical = false;
+ struct ThemeCache {
+ int h_separation = 0;
+ int v_separation = 0;
+ } theme_cache;
+
void _resort();
protected:
- void _notification(int p_what);
+ virtual void _update_theme_item_cache() override;
+ void _notification(int p_what);
static void _bind_methods();
public:
diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp
deleted file mode 100644
index cc27a6b7c2..0000000000
--- a/scene/gui/gradient_edit.cpp
+++ /dev/null
@@ -1,446 +0,0 @@
-/*************************************************************************/
-/* gradient_edit.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "gradient_edit.h"
-
-#include "core/os/keyboard.h"
-
-GradientEdit::GradientEdit() {
- set_focus_mode(FOCUS_ALL);
-
- popup = memnew(PopupPanel);
- picker = memnew(ColorPicker);
- popup->add_child(picker);
-
- gradient_cache.instantiate();
- preview_texture.instantiate();
-
- preview_texture->set_width(1024);
- add_child(popup, false, INTERNAL_MODE_FRONT);
-}
-
-int GradientEdit::_get_point_from_pos(int x) {
- int result = -1;
- int total_w = get_size().width - get_size().height - draw_spacing;
- float min_distance = 1e20;
- for (int i = 0; i < points.size(); i++) {
- // Check if we clicked at point.
- float distance = ABS(x - points[i].offset * total_w);
- float min = (draw_point_width / 2 * 1.7); //make it easier to grab
- if (distance <= min && distance < min_distance) {
- result = i;
- min_distance = distance;
- }
- }
- return result;
-}
-
-void GradientEdit::_show_color_picker() {
- if (grabbed == -1) {
- return;
- }
- picker->set_pick_color(points[grabbed].color);
- Size2 minsize = popup->get_contents_minimum_size();
- bool show_above = false;
- if (get_global_position().y + get_size().y + minsize.y > get_viewport_rect().size.y) {
- show_above = true;
- }
- if (show_above) {
- popup->set_position(get_screen_position() - Vector2(0, minsize.y));
- } else {
- popup->set_position(get_screen_position() + Vector2(0, get_size().y));
- }
- popup->popup();
-}
-
-GradientEdit::~GradientEdit() {
-}
-
-void GradientEdit::gui_input(const Ref<InputEvent> &p_event) {
- ERR_FAIL_COND(p_event.is_null());
-
- Ref<InputEventKey> k = p_event;
-
- if (k.is_valid() && k->is_pressed() && k->get_keycode() == Key::KEY_DELETE && grabbed != -1) {
- points.remove_at(grabbed);
- grabbed = -1;
- grabbing = false;
- update();
- emit_signal(SNAME("ramp_changed"));
- accept_event();
- }
-
- Ref<InputEventMouseButton> mb = p_event;
- // Show color picker on double click.
- if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_double_click() && mb->is_pressed()) {
- grabbed = _get_point_from_pos(mb->get_position().x);
- _show_color_picker();
- accept_event();
- }
-
- // Delete point on right click.
- if (mb.is_valid() && mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) {
- grabbed = _get_point_from_pos(mb->get_position().x);
- if (grabbed != -1) {
- points.remove_at(grabbed);
- grabbed = -1;
- grabbing = false;
- update();
- emit_signal(SNAME("ramp_changed"));
- accept_event();
- }
- }
-
- // Hold alt key to duplicate selected color.
- if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed() && mb->is_alt_pressed()) {
- int x = mb->get_position().x;
- grabbed = _get_point_from_pos(x);
-
- if (grabbed != -1) {
- int total_w = get_size().width - get_size().height - draw_spacing;
- Gradient::Point new_point = points[grabbed];
- new_point.offset = CLAMP(x / float(total_w), 0, 1);
-
- points.push_back(new_point);
- points.sort();
- for (int i = 0; i < points.size(); ++i) {
- if (points[i].offset == new_point.offset) {
- grabbed = i;
- break;
- }
- }
-
- emit_signal(SNAME("ramp_changed"));
- update();
- }
- }
-
- // Select.
- if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) {
- update();
- int x = mb->get_position().x;
- int total_w = get_size().width - get_size().height - draw_spacing;
-
- //Check if color selector was clicked.
- if (x > total_w + draw_spacing) {
- _show_color_picker();
- return;
- }
-
- grabbing = true;
-
- grabbed = _get_point_from_pos(x);
- //grab or select
- if (grabbed != -1) {
- return;
- }
-
- // Insert point.
- Gradient::Point new_point;
- new_point.offset = CLAMP(x / float(total_w), 0, 1);
-
- Gradient::Point prev;
- Gradient::Point next;
-
- int pos = -1;
- for (int i = 0; i < points.size(); i++) {
- if (points[i].offset < new_point.offset) {
- pos = i;
- }
- }
-
- if (pos == -1) {
- prev.color = Color(0, 0, 0);
- prev.offset = 0;
- if (points.size()) {
- next = points[0];
- } else {
- next.color = Color(1, 1, 1);
- next.offset = 1.0;
- }
- } else {
- if (pos == points.size() - 1) {
- next.color = Color(1, 1, 1);
- next.offset = 1.0;
- } else {
- next = points[pos + 1];
- }
- prev = points[pos];
- }
-
- new_point.color = prev.color.lerp(next.color, (new_point.offset - prev.offset) / (next.offset - prev.offset));
-
- points.push_back(new_point);
- points.sort();
- for (int i = 0; i < points.size(); i++) {
- if (points[i].offset == new_point.offset) {
- grabbed = i;
- break;
- }
- }
-
- emit_signal(SNAME("ramp_changed"));
- }
-
- if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && !mb->is_pressed()) {
- if (grabbing) {
- grabbing = false;
- emit_signal(SNAME("ramp_changed"));
- }
- update();
- }
-
- Ref<InputEventMouseMotion> mm = p_event;
-
- if (mm.is_valid() && grabbing) {
- int total_w = get_size().width - get_size().height - draw_spacing;
-
- int x = mm->get_position().x;
-
- float newofs = CLAMP(x / float(total_w), 0, 1);
-
- // Snap to "round" coordinates if holding Ctrl.
- // Be more precise if holding Shift as well.
- if (mm->is_ctrl_pressed()) {
- newofs = Math::snapped(newofs, mm->is_shift_pressed() ? 0.025 : 0.1);
- } else if (mm->is_shift_pressed()) {
- // Snap to nearest point if holding just Shift
- const float snap_threshold = 0.03;
- float smallest_ofs = snap_threshold;
- bool found = false;
- int nearest_point = 0;
- for (int i = 0; i < points.size(); ++i) {
- if (i != grabbed) {
- float temp_ofs = ABS(points[i].offset - newofs);
- if (temp_ofs < smallest_ofs) {
- smallest_ofs = temp_ofs;
- nearest_point = i;
- if (found) {
- break;
- }
- found = true;
- }
- }
- }
- if (found) {
- if (points[nearest_point].offset < newofs) {
- newofs = points[nearest_point].offset + 0.00001;
- } else {
- newofs = points[nearest_point].offset - 0.00001;
- }
- newofs = CLAMP(newofs, 0, 1);
- }
- }
-
- bool valid = true;
- for (int i = 0; i < points.size(); i++) {
- if (points[i].offset == newofs && i != grabbed) {
- valid = false;
- break;
- }
- }
-
- if (!valid || grabbed == -1) {
- return;
- }
- points.write[grabbed].offset = newofs;
-
- points.sort();
- for (int i = 0; i < points.size(); i++) {
- if (points[i].offset == newofs) {
- grabbed = i;
- break;
- }
- }
-
- emit_signal(SNAME("ramp_changed"));
-
- update();
- }
-}
-
-void GradientEdit::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
- if (!picker->is_connected("color_changed", callable_mp(this, &GradientEdit::_color_changed))) {
- picker->connect("color_changed", callable_mp(this, &GradientEdit::_color_changed));
- }
- [[fallthrough]];
- }
- case NOTIFICATION_THEME_CHANGED: {
- draw_spacing = BASE_SPACING * get_theme_default_base_scale();
- draw_point_width = BASE_POINT_WIDTH * get_theme_default_base_scale();
- } break;
-
- case NOTIFICATION_DRAW: {
- int w = get_size().x;
- int h = get_size().y;
-
- if (w == 0 || h == 0) {
- return; // Safety check. We have division by 'h'. And in any case there is nothing to draw with such size.
- }
-
- int total_w = get_size().width - get_size().height - draw_spacing;
-
- // Draw checker pattern for ramp.
- draw_texture_rect(get_theme_icon(SNAME("GuiMiniCheckerboard"), SNAME("EditorIcons")), Rect2(0, 0, total_w, h), true);
-
- // Draw color ramp.
- gradient_cache->set_points(points);
- gradient_cache->set_interpolation_mode(interpolation_mode);
- preview_texture->set_gradient(gradient_cache);
- draw_texture_rect(preview_texture, Rect2(0, 0, total_w, h));
-
- // Draw point markers.
- for (int i = 0; i < points.size(); i++) {
- Color col = points[i].color.inverted();
- col.a = 0.9;
-
- draw_line(Vector2(points[i].offset * total_w, 0), Vector2(points[i].offset * total_w, h / 2), col);
- Rect2 rect = Rect2(points[i].offset * total_w - draw_point_width / 2, h / 2, draw_point_width, h / 2);
- draw_rect(rect, points[i].color, true);
- draw_rect(rect, col, false);
- if (grabbed == i) {
- rect = rect.grow(-1);
- if (has_focus()) {
- draw_rect(rect, Color(1, 0, 0, 0.9), false);
- } else {
- draw_rect(rect, Color(0.6, 0, 0, 0.9), false);
- }
-
- rect = rect.grow(-1);
- draw_rect(rect, col, false);
- }
- }
-
- // Draw "button" for color selector.
- draw_texture_rect(get_theme_icon(SNAME("GuiMiniCheckerboard"), SNAME("EditorIcons")), Rect2(total_w + draw_spacing, 0, h, h), true);
- if (grabbed != -1) {
- // Draw with selection color.
- draw_rect(Rect2(total_w + draw_spacing, 0, h, h), points[grabbed].color);
- } else {
- // If no color selected draw grey color with 'X' on top.
- draw_rect(Rect2(total_w + draw_spacing, 0, h, h), Color(0.5, 0.5, 0.5, 1));
- draw_line(Vector2(total_w + draw_spacing, 0), Vector2(total_w + draw_spacing + h, h), Color(1, 1, 1, 0.6));
- draw_line(Vector2(total_w + draw_spacing, h), Vector2(total_w + draw_spacing + h, 0), Color(1, 1, 1, 0.6));
- }
-
- // Draw borders around color ramp if in focus.
- if (has_focus()) {
- draw_line(Vector2(-1, -1), Vector2(total_w + 1, -1), Color(1, 1, 1, 0.6));
- draw_line(Vector2(total_w + 1, -1), Vector2(total_w + 1, h + 1), Color(1, 1, 1, 0.6));
- draw_line(Vector2(total_w + 1, h + 1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6));
- draw_line(Vector2(-1, -1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6));
- }
- } break;
-
- case NOTIFICATION_VISIBILITY_CHANGED: {
- if (!is_visible()) {
- grabbing = false;
- }
- } break;
- }
-}
-
-Size2 GradientEdit::get_minimum_size() const {
- return Vector2(0, 16);
-}
-
-void GradientEdit::_color_changed(const Color &p_color) {
- if (grabbed == -1) {
- return;
- }
- points.write[grabbed].color = p_color;
- update();
- emit_signal(SNAME("ramp_changed"));
-}
-
-void GradientEdit::set_ramp(const Vector<float> &p_offsets, const Vector<Color> &p_colors) {
- ERR_FAIL_COND(p_offsets.size() != p_colors.size());
- points.clear();
- for (int i = 0; i < p_offsets.size(); i++) {
- Gradient::Point p;
- p.offset = p_offsets[i];
- p.color = p_colors[i];
- points.push_back(p);
- }
-
- points.sort();
- update();
-}
-
-Vector<float> GradientEdit::get_offsets() const {
- Vector<float> ret;
- for (int i = 0; i < points.size(); i++) {
- ret.push_back(points[i].offset);
- }
- return ret;
-}
-
-Vector<Color> GradientEdit::get_colors() const {
- Vector<Color> ret;
- for (int i = 0; i < points.size(); i++) {
- ret.push_back(points[i].color);
- }
- return ret;
-}
-
-void GradientEdit::set_points(Vector<Gradient::Point> &p_points) {
- if (points.size() != p_points.size()) {
- grabbed = -1;
- }
- points.clear();
- points = p_points;
- points.sort();
-}
-
-Vector<Gradient::Point> &GradientEdit::get_points() {
- return points;
-}
-
-void GradientEdit::set_interpolation_mode(Gradient::InterpolationMode p_interp_mode) {
- interpolation_mode = p_interp_mode;
-}
-
-Gradient::InterpolationMode GradientEdit::get_interpolation_mode() {
- return interpolation_mode;
-}
-
-ColorPicker *GradientEdit::get_picker() {
- return picker;
-}
-
-PopupPanel *GradientEdit::get_popup() {
- return popup;
-}
-
-void GradientEdit::_bind_methods() {
- ADD_SIGNAL(MethodInfo("ramp_changed"));
-}
diff --git a/scene/gui/gradient_edit.h b/scene/gui/gradient_edit.h
deleted file mode 100644
index b7c99f1f1c..0000000000
--- a/scene/gui/gradient_edit.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*************************************************************************/
-/* gradient_edit.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef GRADIENT_EDIT_H
-#define GRADIENT_EDIT_H
-
-#include "scene/gui/color_picker.h"
-#include "scene/gui/popup.h"
-#include "scene/resources/gradient.h"
-
-class GradientEdit : public Control {
- GDCLASS(GradientEdit, Control);
-
- PopupPanel *popup = nullptr;
- ColorPicker *picker = nullptr;
-
- bool grabbing = false;
- int grabbed = -1;
- Vector<Gradient::Point> points;
- Gradient::InterpolationMode interpolation_mode = Gradient::GRADIENT_INTERPOLATE_LINEAR;
-
- Ref<Gradient> gradient_cache;
- Ref<GradientTexture1D> preview_texture;
-
- // Make sure to use the scaled value below.
- const int BASE_SPACING = 3;
- const int BASE_POINT_WIDTH = 8;
-
- int draw_spacing = BASE_SPACING;
- int draw_point_width = BASE_POINT_WIDTH;
-
- void _draw_checker(int x, int y, int w, int h);
- void _color_changed(const Color &p_color);
- int _get_point_from_pos(int x);
- void _show_color_picker();
-
-protected:
- virtual void gui_input(const Ref<InputEvent> &p_event) override;
- void _notification(int p_what);
- static void _bind_methods();
-
-public:
- void set_ramp(const Vector<float> &p_offsets, const Vector<Color> &p_colors);
- Vector<float> get_offsets() const;
- Vector<Color> get_colors() const;
- void set_points(Vector<Gradient::Point> &p_points);
- Vector<Gradient::Point> &get_points();
- void set_interpolation_mode(Gradient::InterpolationMode p_interp_mode);
- Gradient::InterpolationMode get_interpolation_mode();
- ColorPicker *get_picker();
- PopupPanel *get_popup();
-
- virtual Size2 get_minimum_size() const override;
-
- GradientEdit();
- virtual ~GradientEdit();
-};
-
-#endif // GRADIENT_EDIT_H
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index e6198b44ff..8c16f8ca26 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -176,7 +176,7 @@ void GraphEditMinimap::gui_input(const Ref<InputEvent> &p_ev) {
new_minimap_size.y = MIN(get_size().y - mm->get_relative().y, ge->get_size().y - 2.0 * minimap_padding.y);
ge->set_minimap_size(new_minimap_size);
- update();
+ queue_redraw();
} else {
Vector2 click_position = _convert_to_graph_position(mm->get_position() - minimap_padding) - graph_padding;
_adjust_graph_scroll(click_position);
@@ -201,10 +201,10 @@ Error GraphEdit::connect_node(const StringName &p_from, int p_from_port, const S
c.to_port = p_to_port;
c.activity = 0;
connections.push_back(c);
- top_layer->update();
- minimap->update();
- update();
- connections_layer->update();
+ top_layer->queue_redraw();
+ minimap->queue_redraw();
+ queue_redraw();
+ connections_layer->queue_redraw();
return OK;
}
@@ -223,10 +223,10 @@ void GraphEdit::disconnect_node(const StringName &p_from, int p_from_port, const
for (const List<Connection>::Element *E = connections.front(); E; E = E->next()) {
if (E->get().from == p_from && E->get().from_port == p_from_port && E->get().to == p_to && E->get().to_port == p_to_port) {
connections.erase(E);
- top_layer->update();
- minimap->update();
- update();
- connections_layer->update();
+ top_layer->queue_redraw();
+ minimap->queue_redraw();
+ queue_redraw();
+ connections_layer->queue_redraw();
return;
}
}
@@ -253,9 +253,9 @@ void GraphEdit::_scroll_moved(double) {
call_deferred(SNAME("_update_scroll_offset"));
awaiting_scroll_offset_update = true;
}
- top_layer->update();
- minimap->update();
- update();
+ top_layer->queue_redraw();
+ minimap->queue_redraw();
+ queue_redraw();
if (!setting_scroll_ofs) { //in godot, signals on change value are avoided as a convention
emit_signal(SNAME("scroll_offset_changed"), get_scroll_ofs());
@@ -359,19 +359,19 @@ void GraphEdit::_graph_node_raised(Node *p_gn) {
void GraphEdit::_graph_node_moved(Node *p_gn) {
GraphNode *gn = Object::cast_to<GraphNode>(p_gn);
ERR_FAIL_COND(!gn);
- top_layer->update();
- minimap->update();
- update();
- connections_layer->update();
+ top_layer->queue_redraw();
+ minimap->queue_redraw();
+ queue_redraw();
+ connections_layer->queue_redraw();
}
void GraphEdit::_graph_node_slot_updated(int p_index, Node *p_gn) {
GraphNode *gn = Object::cast_to<GraphNode>(p_gn);
ERR_FAIL_COND(!gn);
- top_layer->update();
- minimap->update();
- update();
- connections_layer->update();
+ top_layer->queue_redraw();
+ minimap->queue_redraw();
+ queue_redraw();
+ connections_layer->queue_redraw();
}
void GraphEdit::add_child_notify(Node *p_child) {
@@ -385,8 +385,8 @@ void GraphEdit::add_child_notify(Node *p_child) {
gn->connect("position_offset_changed", callable_mp(this, &GraphEdit::_graph_node_moved).bind(gn));
gn->connect("slot_updated", callable_mp(this, &GraphEdit::_graph_node_slot_updated).bind(gn));
gn->connect("raise_request", callable_mp(this, &GraphEdit::_graph_node_raised).bind(gn));
- gn->connect("item_rect_changed", callable_mp((CanvasItem *)connections_layer, &CanvasItem::update));
- gn->connect("item_rect_changed", callable_mp((CanvasItem *)minimap, &GraphEditMinimap::update));
+ gn->connect("item_rect_changed", callable_mp((CanvasItem *)connections_layer, &CanvasItem::queue_redraw));
+ gn->connect("item_rect_changed", callable_mp((CanvasItem *)minimap, &GraphEditMinimap::queue_redraw));
_graph_node_moved(gn);
gn->set_mouse_filter(MOUSE_FILTER_PASS);
}
@@ -414,10 +414,10 @@ void GraphEdit::remove_child_notify(Node *p_child) {
// In case of the whole GraphEdit being destroyed these references can already be freed.
if (connections_layer != nullptr && connections_layer->is_inside_tree()) {
- gn->disconnect("item_rect_changed", callable_mp((CanvasItem *)connections_layer, &CanvasItem::update));
+ gn->disconnect("item_rect_changed", callable_mp((CanvasItem *)connections_layer, &CanvasItem::queue_redraw));
}
if (minimap != nullptr && minimap->is_inside_tree()) {
- gn->disconnect("item_rect_changed", callable_mp((CanvasItem *)minimap, &GraphEditMinimap::update));
+ gn->disconnect("item_rect_changed", callable_mp((CanvasItem *)minimap, &GraphEditMinimap::queue_redraw));
}
}
}
@@ -500,8 +500,8 @@ void GraphEdit::_notification(int p_what) {
case NOTIFICATION_RESIZED: {
_update_scroll();
- top_layer->update();
- minimap->update();
+ top_layer->queue_redraw();
+ minimap->queue_redraw();
} break;
}
}
@@ -607,13 +607,16 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
connecting_color = Object::cast_to<GraphNode>(to)->get_connection_input_color(E.to_port);
connecting_target = false;
connecting_to = pos;
- just_disconnected = true;
- emit_signal(SNAME("disconnection_request"), E.from, E.from_port, E.to, E.to_port);
- to = get_node(String(connecting_from)); //maybe it was erased
- if (Object::cast_to<GraphNode>(to)) {
- connecting = true;
- emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, false);
+ if (connecting_type >= 0) {
+ just_disconnected = true;
+
+ emit_signal(SNAME("disconnection_request"), E.from, E.from_port, E.to, E.to_port);
+ to = get_node(String(connecting_from)); //maybe it was erased
+ if (Object::cast_to<GraphNode>(to)) {
+ connecting = true;
+ emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, false);
+ }
}
return;
}
@@ -621,7 +624,6 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
}
}
- connecting = true;
connecting_from = gn->get_name();
connecting_index = j;
connecting_out = true;
@@ -629,8 +631,11 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
connecting_color = gn->get_connection_output_color(j);
connecting_target = false;
connecting_to = pos;
- just_disconnected = false;
- emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, true);
+ if (connecting_type >= 0) {
+ connecting = true;
+ just_disconnected = false;
+ emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, true);
+ }
return;
}
}
@@ -657,11 +662,13 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
connecting_to = pos;
just_disconnected = true;
- emit_signal(SNAME("disconnection_request"), E.from, E.from_port, E.to, E.to_port);
- fr = get_node(String(connecting_from)); //maybe it was erased
- if (Object::cast_to<GraphNode>(fr)) {
- connecting = true;
- emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, true);
+ if (connecting_type >= 0) {
+ emit_signal(SNAME("disconnection_request"), E.from, E.from_port, E.to, E.to_port);
+ fr = get_node(String(connecting_from)); //maybe it was erased
+ if (Object::cast_to<GraphNode>(fr)) {
+ connecting = true;
+ emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, true);
+ }
}
return;
}
@@ -669,7 +676,6 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
}
}
- connecting = true;
connecting_from = gn->get_name();
connecting_index = j;
connecting_out = false;
@@ -677,8 +683,11 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
connecting_color = gn->get_connection_input_color(j);
connecting_target = false;
connecting_to = pos;
- just_disconnected = false;
- emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, false);
+ if (connecting_type >= 0) {
+ connecting = true;
+ just_disconnected = false;
+ emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, false);
+ }
return;
}
}
@@ -689,8 +698,8 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
if (mm.is_valid() && connecting) {
connecting_to = mm->get_position();
connecting_target = false;
- top_layer->update();
- minimap->update();
+ top_layer->queue_redraw();
+ minimap->queue_redraw();
connecting_valid = just_disconnected || click_pos.distance_to(connecting_to / zoom) > 20.0;
if (connecting_valid) {
@@ -1127,7 +1136,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
drag_accum += mm->get_relative();
for (int i = get_child_count() - 1; i >= 0; i--) {
GraphNode *gn = Object::cast_to<GraphNode>(get_child(i));
- if (gn && gn->is_selected()) {
+ if (gn && gn->is_selected() && gn->is_draggable()) {
Vector2 pos = (gn->get_drag_from() * zoom + drag_accum) / zoom;
// Snapping can be toggled temporarily by holding down Ctrl.
@@ -1166,7 +1175,9 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
} else if (gn->is_selected() && !box_selection_mode_additive) {
emit_signal(SNAME("node_deselected"), gn);
}
- gn->set_selected(box_selection_mode_additive);
+ if (gn->is_selectable()) {
+ gn->set_selected(box_selection_mode_additive);
+ }
} else {
bool select = (previous_selected.find(gn) != nullptr);
if (gn->is_selected() && !select) {
@@ -1174,12 +1185,14 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
} else if (!gn->is_selected() && select) {
emit_signal(SNAME("node_selected"), gn);
}
- gn->set_selected(select);
+ if (gn->is_selectable()) {
+ gn->set_selected(select);
+ }
}
}
- top_layer->update();
- minimap->update();
+ top_layer->queue_redraw();
+ minimap->queue_redraw();
}
Ref<InputEventMouseButton> b = p_ev;
@@ -1193,7 +1206,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
continue;
}
- bool select = (previous_selected.find(gn) != nullptr);
+ bool select = (gn->is_selectable() && previous_selected.find(gn) != nullptr);
if (gn->is_selected() && !select) {
emit_signal(SNAME("node_deselected"), gn);
} else if (!gn->is_selected() && select) {
@@ -1201,8 +1214,8 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
}
gn->set_selected(select);
}
- top_layer->update();
- minimap->update();
+ top_layer->queue_redraw();
+ minimap->queue_redraw();
} else {
if (connecting) {
force_connection_drag_end();
@@ -1248,10 +1261,10 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
dragging = false;
- top_layer->update();
- minimap->update();
- update();
- connections_layer->update();
+ top_layer->queue_redraw();
+ minimap->queue_redraw();
+ queue_redraw();
+ connections_layer->queue_redraw();
}
if (b->get_button_index() == MouseButton::LEFT && b->is_pressed()) {
@@ -1285,7 +1298,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
GraphNode *o_gn = Object::cast_to<GraphNode>(get_child(i));
if (o_gn) {
if (o_gn == gn) {
- o_gn->set_selected(true);
+ o_gn->set_selected(o_gn->is_selectable());
} else {
if (o_gn->is_selected()) {
emit_signal(SNAME("node_deselected"), o_gn);
@@ -1296,7 +1309,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
}
}
- gn->set_selected(true);
+ gn->set_selected(gn->is_selectable());
for (int i = 0; i < get_child_count(); i++) {
GraphNode *o_gn = Object::cast_to<GraphNode>(get_child(i));
if (!o_gn) {
@@ -1364,8 +1377,8 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
box_selecting = false;
box_selecting_rect = Rect2();
previous_selected.clear();
- top_layer->update();
- minimap->update();
+ top_layer->queue_redraw();
+ minimap->queue_redraw();
}
}
@@ -1431,9 +1444,9 @@ void GraphEdit::set_connection_activity(const StringName &p_from, int p_from_por
if (E.from == p_from && E.from_port == p_from_port && E.to == p_to && E.to_port == p_to_port) {
if (Math::is_equal_approx(E.activity, p_activity)) {
//update only if changed
- top_layer->update();
- minimap->update();
- connections_layer->update();
+ top_layer->queue_redraw();
+ minimap->queue_redraw();
+ connections_layer->queue_redraw();
}
E.activity = p_activity;
return;
@@ -1443,19 +1456,19 @@ void GraphEdit::set_connection_activity(const StringName &p_from, int p_from_por
void GraphEdit::clear_connections() {
connections.clear();
- minimap->update();
- update();
- connections_layer->update();
+ minimap->queue_redraw();
+ queue_redraw();
+ connections_layer->queue_redraw();
}
void GraphEdit::force_connection_drag_end() {
ERR_FAIL_COND_MSG(!connecting, "Drag end requested without active drag!");
connecting = false;
connecting_valid = false;
- top_layer->update();
- minimap->update();
- update();
- connections_layer->update();
+ top_layer->queue_redraw();
+ minimap->queue_redraw();
+ queue_redraw();
+ connections_layer->queue_redraw();
emit_signal(SNAME("connection_drag_ended"));
}
@@ -1489,14 +1502,14 @@ void GraphEdit::set_zoom_custom(float p_zoom, const Vector2 &p_center) {
Vector2 sbofs = (Vector2(h_scroll->get_value(), v_scroll->get_value()) + p_center) / zoom;
zoom = p_zoom;
- top_layer->update();
+ top_layer->queue_redraw();
zoom_minus->set_disabled(zoom == zoom_min);
zoom_plus->set_disabled(zoom == zoom_max);
_update_scroll();
- minimap->update();
- connections_layer->update();
+ minimap->queue_redraw();
+ connections_layer->queue_redraw();
if (is_visible_in_tree()) {
Vector2 ofs = sbofs * zoom - p_center;
@@ -1505,7 +1518,7 @@ void GraphEdit::set_zoom_custom(float p_zoom, const Vector2 &p_center) {
}
_update_zoom_label();
- update();
+ queue_redraw();
}
float GraphEdit::get_zoom() const {
@@ -1644,7 +1657,7 @@ void GraphEdit::set_use_snap(bool p_enable) {
return;
}
snap_button->set_pressed(p_enable);
- update();
+ queue_redraw();
}
bool GraphEdit::is_using_snap() const {
@@ -1658,15 +1671,15 @@ int GraphEdit::get_snap() const {
void GraphEdit::set_snap(int p_snap) {
ERR_FAIL_COND(p_snap < 5);
snap_amount->set_value(p_snap);
- update();
+ queue_redraw();
}
void GraphEdit::_snap_toggled() {
- update();
+ queue_redraw();
}
void GraphEdit::_snap_value_changed(double) {
- update();
+ queue_redraw();
}
void GraphEdit::set_minimap_size(Vector2 p_size) {
@@ -1678,7 +1691,7 @@ void GraphEdit::set_minimap_size(Vector2 p_size) {
minimap->set_offset(Side::SIDE_TOP, -minimap_size.y - MINIMAP_OFFSET);
minimap->set_offset(Side::SIDE_RIGHT, -MINIMAP_OFFSET);
minimap->set_offset(Side::SIDE_BOTTOM, -MINIMAP_OFFSET);
- minimap->update();
+ minimap->queue_redraw();
}
Vector2 GraphEdit::get_minimap_size() const {
@@ -1690,7 +1703,7 @@ void GraphEdit::set_minimap_opacity(float p_opacity) {
return;
}
minimap->set_modulate(Color(1, 1, 1, p_opacity));
- minimap->update();
+ minimap->queue_redraw();
}
float GraphEdit::get_minimap_opacity() const {
@@ -1704,17 +1717,30 @@ void GraphEdit::set_minimap_enabled(bool p_enable) {
}
minimap_button->set_pressed(p_enable);
_minimap_toggled();
- minimap->update();
+ minimap->queue_redraw();
}
bool GraphEdit::is_minimap_enabled() const {
return minimap_button->is_pressed();
}
+void GraphEdit::set_arrange_nodes_button_hidden(bool p_enable) {
+ arrange_nodes_button_hidden = p_enable;
+ if (arrange_nodes_button_hidden) {
+ layout_button->hide();
+ } else {
+ layout_button->show();
+ }
+}
+
+bool GraphEdit::is_arrange_nodes_button_hidden() const {
+ return arrange_nodes_button_hidden;
+}
+
void GraphEdit::_minimap_toggled() {
if (is_minimap_enabled()) {
minimap->set_visible(true);
- minimap->update();
+ minimap->queue_redraw();
} else {
minimap->set_visible(false);
}
@@ -1722,7 +1748,7 @@ void GraphEdit::_minimap_toggled() {
void GraphEdit::set_connection_lines_curvature(float p_curvature) {
lines_curvature = p_curvature;
- update();
+ queue_redraw();
}
float GraphEdit::get_connection_lines_curvature() const {
@@ -1734,7 +1760,7 @@ void GraphEdit::set_connection_lines_thickness(float p_thickness) {
return;
}
lines_thickness = p_thickness;
- update();
+ queue_redraw();
}
float GraphEdit::get_connection_lines_thickness() const {
@@ -1746,7 +1772,7 @@ void GraphEdit::set_connection_lines_antialiased(bool p_antialiased) {
return;
}
lines_antialiased = p_antialiased;
- update();
+ queue_redraw();
}
bool GraphEdit::is_connection_lines_antialiased() const {
@@ -2343,6 +2369,9 @@ void GraphEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_minimap_enabled", "enable"), &GraphEdit::set_minimap_enabled);
ClassDB::bind_method(D_METHOD("is_minimap_enabled"), &GraphEdit::is_minimap_enabled);
+ ClassDB::bind_method(D_METHOD("set_arrange_nodes_button_hidden", "enable"), &GraphEdit::set_arrange_nodes_button_hidden);
+ ClassDB::bind_method(D_METHOD("is_arrange_nodes_button_hidden"), &GraphEdit::is_arrange_nodes_button_hidden);
+
ClassDB::bind_method(D_METHOD("set_right_disconnects", "enable"), &GraphEdit::set_right_disconnects);
ClassDB::bind_method(D_METHOD("is_right_disconnects_enabled"), &GraphEdit::is_right_disconnects_enabled);
@@ -2382,6 +2411,9 @@ void GraphEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "minimap_size", PROPERTY_HINT_NONE, "suffix:px"), "set_minimap_size", "get_minimap_size");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "minimap_opacity"), "set_minimap_opacity", "get_minimap_opacity");
+ ADD_GROUP("UI", "");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "arrange_nodes_button_hidden"), "set_arrange_nodes_button_hidden", "is_arrange_nodes_button_hidden");
+
ADD_SIGNAL(MethodInfo("connection_request", PropertyInfo(Variant::STRING_NAME, "from"), PropertyInfo(Variant::INT, "from_slot"), PropertyInfo(Variant::STRING_NAME, "to"), PropertyInfo(Variant::INT, "to_slot")));
ADD_SIGNAL(MethodInfo("disconnection_request", PropertyInfo(Variant::STRING_NAME, "from"), PropertyInfo(Variant::INT, "from_slot"), PropertyInfo(Variant::STRING_NAME, "to"), PropertyInfo(Variant::INT, "to_slot")));
ADD_SIGNAL(MethodInfo("popup_request", PropertyInfo(Variant::VECTOR2, "position")));
@@ -2464,28 +2496,28 @@ GraphEdit::GraphEdit() {
zoom_minus = memnew(Button);
zoom_minus->set_flat(true);
zoom_hb->add_child(zoom_minus);
- zoom_minus->set_tooltip(RTR("Zoom Out"));
+ zoom_minus->set_tooltip_text(RTR("Zoom Out"));
zoom_minus->connect("pressed", callable_mp(this, &GraphEdit::_zoom_minus));
zoom_minus->set_focus_mode(FOCUS_NONE);
zoom_reset = memnew(Button);
zoom_reset->set_flat(true);
zoom_hb->add_child(zoom_reset);
- zoom_reset->set_tooltip(RTR("Zoom Reset"));
+ zoom_reset->set_tooltip_text(RTR("Zoom Reset"));
zoom_reset->connect("pressed", callable_mp(this, &GraphEdit::_zoom_reset));
zoom_reset->set_focus_mode(FOCUS_NONE);
zoom_plus = memnew(Button);
zoom_plus->set_flat(true);
zoom_hb->add_child(zoom_plus);
- zoom_plus->set_tooltip(RTR("Zoom In"));
+ zoom_plus->set_tooltip_text(RTR("Zoom In"));
zoom_plus->connect("pressed", callable_mp(this, &GraphEdit::_zoom_plus));
zoom_plus->set_focus_mode(FOCUS_NONE);
snap_button = memnew(Button);
snap_button->set_flat(true);
snap_button->set_toggle_mode(true);
- snap_button->set_tooltip(RTR("Enable snap and show grid."));
+ snap_button->set_tooltip_text(RTR("Enable snap and show grid."));
snap_button->connect("pressed", callable_mp(this, &GraphEdit::_snap_toggled));
snap_button->set_pressed(true);
snap_button->set_focus_mode(FOCUS_NONE);
@@ -2502,7 +2534,7 @@ GraphEdit::GraphEdit() {
minimap_button = memnew(Button);
minimap_button->set_flat(true);
minimap_button->set_toggle_mode(true);
- minimap_button->set_tooltip(RTR("Enable grid minimap."));
+ minimap_button->set_tooltip_text(RTR("Enable grid minimap."));
minimap_button->connect("pressed", callable_mp(this, &GraphEdit::_minimap_toggled));
minimap_button->set_pressed(true);
minimap_button->set_focus_mode(FOCUS_NONE);
@@ -2511,7 +2543,7 @@ GraphEdit::GraphEdit() {
layout_button = memnew(Button);
layout_button->set_flat(true);
zoom_hb->add_child(layout_button);
- layout_button->set_tooltip(RTR("Arrange nodes."));
+ layout_button->set_tooltip_text(RTR("Arrange nodes."));
layout_button->connect("pressed", callable_mp(this, &GraphEdit::arrange_nodes));
layout_button->set_focus_mode(FOCUS_NONE);
diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h
index b8c9be9983..0a0676699f 100644
--- a/scene/gui/graph_edit.h
+++ b/scene/gui/graph_edit.h
@@ -133,6 +133,8 @@ private:
void _pan_callback(Vector2 p_scroll_vec);
void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
+ bool arrange_nodes_button_hidden = false;
+
bool connecting = false;
String connecting_from;
bool connecting_out = false;
@@ -323,6 +325,9 @@ public:
void set_minimap_enabled(bool p_enable);
bool is_minimap_enabled() const;
+ void set_arrange_nodes_button_hidden(bool p_enable);
+ bool is_arrange_nodes_button_hidden() const;
+
GraphEditFilter *get_top_layer() const { return top_layer; }
GraphEditMinimap *get_minimap() const { return minimap; }
void get_connection_list(List<Connection> *r_connections) const;
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 7d31e929dc..5976d9fc37 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -78,7 +78,7 @@ bool GraphNode::_set(const StringName &p_name, const Variant &p_value) {
}
set_slot(idx, si.enable_left, si.type_left, si.color_left, si.enable_right, si.type_right, si.color_right, si.custom_slot_left, si.custom_slot_right, si.draw_stylebox);
- update();
+ queue_redraw();
return true;
}
@@ -288,7 +288,7 @@ void GraphNode::_resort() {
idx++;
}
- update();
+ queue_redraw();
connpos_dirty = true;
}
@@ -416,7 +416,7 @@ void GraphNode::_notification(int p_what) {
_shape();
update_minimum_size();
- update();
+ queue_redraw();
} break;
}
}
@@ -475,7 +475,7 @@ void GraphNode::set_slot(int p_idx, bool p_enable_left, int p_type_left, const C
s.custom_slot_right = p_custom_right;
s.draw_stylebox = p_draw_stylebox;
slot_info[p_idx] = s;
- update();
+ queue_redraw();
connpos_dirty = true;
emit_signal(SNAME("slot_updated"), p_idx);
@@ -483,13 +483,13 @@ void GraphNode::set_slot(int p_idx, bool p_enable_left, int p_type_left, const C
void GraphNode::clear_slot(int p_idx) {
slot_info.erase(p_idx);
- update();
+ queue_redraw();
connpos_dirty = true;
}
void GraphNode::clear_all_slots() {
slot_info.clear();
- update();
+ queue_redraw();
connpos_dirty = true;
}
@@ -508,7 +508,7 @@ void GraphNode::set_slot_enabled_left(int p_idx, bool p_enable_left) {
}
slot_info[p_idx].enable_left = p_enable_left;
- update();
+ queue_redraw();
connpos_dirty = true;
emit_signal(SNAME("slot_updated"), p_idx);
@@ -522,7 +522,7 @@ void GraphNode::set_slot_type_left(int p_idx, int p_type_left) {
}
slot_info[p_idx].type_left = p_type_left;
- update();
+ queue_redraw();
connpos_dirty = true;
emit_signal(SNAME("slot_updated"), p_idx);
@@ -543,7 +543,7 @@ void GraphNode::set_slot_color_left(int p_idx, const Color &p_color_left) {
}
slot_info[p_idx].color_left = p_color_left;
- update();
+ queue_redraw();
connpos_dirty = true;
emit_signal(SNAME("slot_updated"), p_idx);
@@ -571,7 +571,7 @@ void GraphNode::set_slot_enabled_right(int p_idx, bool p_enable_right) {
}
slot_info[p_idx].enable_right = p_enable_right;
- update();
+ queue_redraw();
connpos_dirty = true;
emit_signal(SNAME("slot_updated"), p_idx);
@@ -585,7 +585,7 @@ void GraphNode::set_slot_type_right(int p_idx, int p_type_right) {
}
slot_info[p_idx].type_right = p_type_right;
- update();
+ queue_redraw();
connpos_dirty = true;
emit_signal(SNAME("slot_updated"), p_idx);
@@ -606,7 +606,7 @@ void GraphNode::set_slot_color_right(int p_idx, const Color &p_color_right) {
}
slot_info[p_idx].color_right = p_color_right;
- update();
+ queue_redraw();
connpos_dirty = true;
emit_signal(SNAME("slot_updated"), p_idx);
@@ -630,7 +630,7 @@ void GraphNode::set_slot_draw_stylebox(int p_idx, bool p_enable) {
ERR_FAIL_COND_MSG(p_idx < 0, vformat("Cannot set draw_stylebox for the slot with p_idx (%d) lesser than zero.", p_idx));
slot_info[p_idx].draw_stylebox = p_enable;
- update();
+ queue_redraw();
connpos_dirty = true;
emit_signal(SNAME("slot_updated"), p_idx);
@@ -688,7 +688,7 @@ void GraphNode::set_title(const String &p_title) {
title = p_title;
_shape();
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -701,7 +701,7 @@ void GraphNode::set_text_direction(Control::TextDirection p_text_direction) {
if (text_direction != p_text_direction) {
text_direction = p_text_direction;
_shape();
- update();
+ queue_redraw();
}
}
@@ -713,7 +713,7 @@ void GraphNode::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
_shape();
- update();
+ queue_redraw();
}
}
@@ -728,7 +728,7 @@ void GraphNode::set_position_offset(const Vector2 &p_offset) {
position_offset = p_offset;
emit_signal(SNAME("position_offset_changed"));
- update();
+ queue_redraw();
}
Vector2 GraphNode::get_position_offset() const {
@@ -741,7 +741,7 @@ void GraphNode::set_selected(bool p_selected) {
}
selected = p_selected;
- update();
+ queue_redraw();
}
bool GraphNode::is_selected() {
@@ -766,7 +766,7 @@ void GraphNode::set_show_close_button(bool p_enable) {
}
show_close = p_enable;
- update();
+ queue_redraw();
}
bool GraphNode::is_close_button_visible() const {
@@ -970,7 +970,7 @@ void GraphNode::set_overlay(Overlay p_overlay) {
}
overlay = p_overlay;
- update();
+ queue_redraw();
}
GraphNode::Overlay GraphNode::get_overlay() const {
@@ -983,7 +983,7 @@ void GraphNode::set_comment(bool p_enable) {
}
comment = p_enable;
- update();
+ queue_redraw();
}
bool GraphNode::is_comment() const {
@@ -996,13 +996,29 @@ void GraphNode::set_resizable(bool p_enable) {
}
resizable = p_enable;
- update();
+ queue_redraw();
}
bool GraphNode::is_resizable() const {
return resizable;
}
+void GraphNode::set_draggable(bool p_draggable) {
+ draggable = p_draggable;
+}
+
+bool GraphNode::is_draggable() {
+ return draggable;
+}
+
+void GraphNode::set_selectable(bool p_selectable) {
+ selectable = p_selectable;
+}
+
+bool GraphNode::is_selectable() {
+ return selectable;
+}
+
Vector<int> GraphNode::get_allowed_size_flags_horizontal() const {
Vector<int> flags;
flags.append(SIZE_FILL);
@@ -1064,6 +1080,12 @@ void GraphNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_resizable", "resizable"), &GraphNode::set_resizable);
ClassDB::bind_method(D_METHOD("is_resizable"), &GraphNode::is_resizable);
+ ClassDB::bind_method(D_METHOD("set_draggable", "draggable"), &GraphNode::set_draggable);
+ ClassDB::bind_method(D_METHOD("is_draggable"), &GraphNode::is_draggable);
+
+ ClassDB::bind_method(D_METHOD("set_selectable", "selectable"), &GraphNode::set_selectable);
+ ClassDB::bind_method(D_METHOD("is_selectable"), &GraphNode::is_selectable);
+
ClassDB::bind_method(D_METHOD("set_selected", "selected"), &GraphNode::set_selected);
ClassDB::bind_method(D_METHOD("is_selected"), &GraphNode::is_selected);
@@ -1089,6 +1111,8 @@ void GraphNode::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_position_offset", "get_position_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_close"), "set_show_close_button", "is_close_button_visible");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resizable"), "set_resizable", "is_resizable");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draggable"), "set_draggable", "is_draggable");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selectable"), "set_selectable", "is_selectable");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selected"), "set_selected", "is_selected");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "comment"), "set_comment", "is_comment");
ADD_PROPERTY(PropertyInfo(Variant::INT, "overlay", PROPERTY_HINT_ENUM, "Disabled,Breakpoint,Position"), "set_overlay", "get_overlay");
diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h
index d575b6ceed..9c8f926403 100644
--- a/scene/gui/graph_node.h
+++ b/scene/gui/graph_node.h
@@ -67,6 +67,8 @@ private:
Vector2 position_offset;
bool comment = false;
bool resizable = false;
+ bool draggable = true;
+ bool selectable = true;
bool resizing = false;
Vector2 resizing_from;
@@ -183,6 +185,12 @@ public:
void set_resizable(bool p_enable);
bool is_resizable() const;
+ void set_draggable(bool p_draggable);
+ bool is_draggable();
+
+ void set_selectable(bool p_selectable);
+ bool is_selectable();
+
virtual Size2 get_minimum_size() const override;
virtual Vector<int> get_allowed_size_flags_horizontal() const override;
diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp
index 3163d17846..8dc890eccb 100644
--- a/scene/gui/grid_container.cpp
+++ b/scene/gui/grid_container.cpp
@@ -31,6 +31,13 @@
#include "grid_container.h"
#include "core/templates/rb_set.h"
+void GridContainer::_update_theme_item_cache() {
+ Container::_update_theme_item_cache();
+
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
+ theme_cache.v_separation = get_theme_constant(SNAME("v_separation"));
+}
+
void GridContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_SORT_CHILDREN: {
@@ -39,9 +46,6 @@ void GridContainer::_notification(int p_what) {
RBSet<int> col_expanded; // Columns which have the SIZE_EXPAND flag set.
RBSet<int> row_expanded; // Rows which have the SIZE_EXPAND flag set.
- int hsep = get_theme_constant(SNAME("h_separation"));
- int vsep = get_theme_constant(SNAME("v_separation"));
-
// Compute the per-column/per-row data.
int valid_controls_index = 0;
for (int i = 0; i < get_child_count(); i++) {
@@ -98,8 +102,8 @@ void GridContainer::_notification(int p_what) {
remaining_space.height -= E.value;
}
}
- remaining_space.height -= vsep * MAX(max_row - 1, 0);
- remaining_space.width -= hsep * MAX(max_col - 1, 0);
+ remaining_space.height -= theme_cache.v_separation * MAX(max_row - 1, 0);
+ remaining_space.width -= theme_cache.h_separation * MAX(max_col - 1, 0);
bool can_fit = false;
while (!can_fit && col_expanded.size() > 0) {
@@ -202,7 +206,7 @@ void GridContainer::_notification(int p_what) {
col_ofs = 0;
}
if (row > 0) {
- row_ofs += (row_expanded.has(row - 1) ? row_expand : row_minh[row - 1]) + vsep;
+ row_ofs += (row_expanded.has(row - 1) ? row_expand : row_minh[row - 1]) + theme_cache.v_separation;
if (row_expanded.has(row - 1) && row - 1 < row_remaining_pixel_index) {
// Apply the remaining pixel of the previous row.
@@ -224,11 +228,11 @@ void GridContainer::_notification(int p_what) {
if (rtl) {
Point2 p(col_ofs - s.width, row_ofs);
fit_child_in_rect(c, Rect2(p, s));
- col_ofs -= s.width + hsep;
+ col_ofs -= s.width + theme_cache.h_separation;
} else {
Point2 p(col_ofs, row_ofs);
fit_child_in_rect(c, Rect2(p, s));
- col_ofs += s.width + hsep;
+ col_ofs += s.width + theme_cache.h_separation;
}
}
} break;
@@ -271,9 +275,6 @@ Size2 GridContainer::get_minimum_size() const {
RBMap<int, int> col_minw;
RBMap<int, int> row_minh;
- int hsep = get_theme_constant(SNAME("h_separation"));
- int vsep = get_theme_constant(SNAME("v_separation"));
-
int max_row = 0;
int max_col = 0;
@@ -313,8 +314,8 @@ Size2 GridContainer::get_minimum_size() const {
ms.height += E.value;
}
- ms.height += vsep * max_row;
- ms.width += hsep * max_col;
+ ms.height += theme_cache.v_separation * max_row;
+ ms.width += theme_cache.h_separation * max_col;
return ms;
}
diff --git a/scene/gui/grid_container.h b/scene/gui/grid_container.h
index 9d77f90ab3..522046f694 100644
--- a/scene/gui/grid_container.h
+++ b/scene/gui/grid_container.h
@@ -38,7 +38,14 @@ class GridContainer : public Container {
int columns = 1;
+ struct ThemeCache {
+ int h_separation = 0;
+ int v_separation = 0;
+ } theme_cache;
+
protected:
+ virtual void _update_theme_item_cache() override;
+
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 086f729603..8c49353105 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -43,9 +43,9 @@ void ItemList::_shape(int p_idx) {
} else {
item.text_buf->set_direction((TextServer::Direction)item.text_direction);
}
- item.text_buf->add_string(item.text, get_theme_font(SNAME("font")), get_theme_font_size(SNAME("font_size")), item.language);
+ item.text_buf->add_string(item.text, theme_cache.font, theme_cache.font_size, item.language);
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
- item.text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
+ item.text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_TRIM_EDGE_SPACES);
} else {
item.text_buf->set_break_flags(TextServer::BREAK_NONE);
}
@@ -63,7 +63,7 @@ int ItemList::add_item(const String &p_item, const Ref<Texture2D> &p_texture, bo
_shape(items.size() - 1);
- update();
+ queue_redraw();
shape_changed = true;
notify_property_list_changed();
return item_id;
@@ -76,7 +76,7 @@ int ItemList::add_icon_item(const Ref<Texture2D> &p_item, bool p_selectable) {
items.push_back(item);
int item_id = items.size() - 1;
- update();
+ queue_redraw();
shape_changed = true;
notify_property_list_changed();
return item_id;
@@ -94,7 +94,7 @@ void ItemList::set_item_text(int p_idx, const String &p_text) {
items.write[p_idx].text = p_text;
_shape(p_idx);
- update();
+ queue_redraw();
shape_changed = true;
}
@@ -112,7 +112,7 @@ void ItemList::set_item_text_direction(int p_idx, Control::TextDirection p_text_
if (items[p_idx].text_direction != p_text_direction) {
items.write[p_idx].text_direction = p_text_direction;
_shape(p_idx);
- update();
+ queue_redraw();
}
}
@@ -129,7 +129,7 @@ void ItemList::set_item_language(int p_idx, const String &p_language) {
if (items[p_idx].language != p_language) {
items.write[p_idx].language = p_language;
_shape(p_idx);
- update();
+ queue_redraw();
}
}
@@ -162,7 +162,7 @@ void ItemList::set_item_tooltip(int p_idx, const String &p_tooltip) {
}
items.write[p_idx].tooltip = p_tooltip;
- update();
+ queue_redraw();
shape_changed = true;
}
@@ -182,7 +182,7 @@ void ItemList::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) {
}
items.write[p_idx].icon = p_icon;
- update();
+ queue_redraw();
shape_changed = true;
}
@@ -203,7 +203,7 @@ void ItemList::set_item_icon_transposed(int p_idx, const bool p_transposed) {
}
items.write[p_idx].icon_transposed = p_transposed;
- update();
+ queue_redraw();
shape_changed = true;
}
@@ -224,7 +224,7 @@ void ItemList::set_item_icon_region(int p_idx, const Rect2 &p_region) {
}
items.write[p_idx].icon_region = p_region;
- update();
+ queue_redraw();
shape_changed = true;
}
@@ -245,7 +245,7 @@ void ItemList::set_item_icon_modulate(int p_idx, const Color &p_modulate) {
}
items.write[p_idx].icon_modulate = p_modulate;
- update();
+ queue_redraw();
}
Color ItemList::get_item_icon_modulate(int p_idx) const {
@@ -265,7 +265,7 @@ void ItemList::set_item_custom_bg_color(int p_idx, const Color &p_custom_bg_colo
}
items.write[p_idx].custom_bg = p_custom_bg_color;
- update();
+ queue_redraw();
}
Color ItemList::get_item_custom_bg_color(int p_idx) const {
@@ -285,7 +285,7 @@ void ItemList::set_item_custom_fg_color(int p_idx, const Color &p_custom_fg_colo
}
items.write[p_idx].custom_fg = p_custom_fg_color;
- update();
+ queue_redraw();
}
Color ItemList::get_item_custom_fg_color(int p_idx) const {
@@ -305,7 +305,7 @@ void ItemList::set_item_tag_icon(int p_idx, const Ref<Texture2D> &p_tag_icon) {
}
items.write[p_idx].tag_icon = p_tag_icon;
- update();
+ queue_redraw();
shape_changed = true;
}
@@ -340,7 +340,7 @@ void ItemList::set_item_disabled(int p_idx, bool p_disabled) {
}
items.write[p_idx].disabled = p_disabled;
- update();
+ queue_redraw();
}
bool ItemList::is_item_disabled(int p_idx) const {
@@ -359,7 +359,7 @@ void ItemList::set_item_metadata(int p_idx, const Variant &p_metadata) {
}
items.write[p_idx].metadata = p_metadata;
- update();
+ queue_redraw();
shape_changed = true;
}
@@ -387,7 +387,7 @@ void ItemList::select(int p_idx, bool p_single) {
items.write[p_idx].selected = true;
}
}
- update();
+ queue_redraw();
}
void ItemList::deselect(int p_idx) {
@@ -399,7 +399,7 @@ void ItemList::deselect(int p_idx) {
} else {
items.write[p_idx].selected = false;
}
- update();
+ queue_redraw();
}
void ItemList::deselect_all() {
@@ -411,7 +411,7 @@ void ItemList::deselect_all() {
items.write[i].selected = false;
}
current = -1;
- update();
+ queue_redraw();
}
bool ItemList::is_selected(int p_idx) const {
@@ -431,7 +431,7 @@ void ItemList::set_current(int p_current) {
select(p_current, true);
} else {
current = p_current;
- update();
+ queue_redraw();
}
}
@@ -451,7 +451,7 @@ void ItemList::move_item(int p_from_idx, int p_to_idx) {
items.remove_at(p_from_idx);
items.insert(p_to_idx, item);
- update();
+ queue_redraw();
shape_changed = true;
notify_property_list_changed();
}
@@ -464,7 +464,7 @@ void ItemList::set_item_count(int p_count) {
}
items.resize(p_count);
- update();
+ queue_redraw();
shape_changed = true;
notify_property_list_changed();
}
@@ -480,7 +480,7 @@ void ItemList::remove_item(int p_idx) {
if (current == p_idx) {
current = -1;
}
- update();
+ queue_redraw();
shape_changed = true;
defer_select_single = -1;
notify_property_list_changed();
@@ -490,7 +490,7 @@ void ItemList::clear() {
items.clear();
current = -1;
ensure_selected_visible = false;
- update();
+ queue_redraw();
shape_changed = true;
defer_select_single = -1;
notify_property_list_changed();
@@ -504,7 +504,7 @@ void ItemList::set_fixed_column_width(int p_size) {
}
fixed_column_width = p_size;
- update();
+ queue_redraw();
shape_changed = true;
}
@@ -518,7 +518,7 @@ void ItemList::set_same_column_width(bool p_enable) {
}
same_column_width = p_enable;
- update();
+ queue_redraw();
shape_changed = true;
}
@@ -532,14 +532,14 @@ void ItemList::set_max_text_lines(int p_lines) {
max_text_lines = p_lines;
for (int i = 0; i < items.size(); i++) {
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
- items.write[i].text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
+ items.write[i].text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_TRIM_EDGE_SPACES);
items.write[i].text_buf->set_max_lines_visible(p_lines);
} else {
items.write[i].text_buf->set_break_flags(TextServer::BREAK_NONE);
}
}
shape_changed = true;
- update();
+ queue_redraw();
}
}
@@ -555,7 +555,7 @@ void ItemList::set_max_columns(int p_amount) {
}
max_columns = p_amount;
- update();
+ queue_redraw();
shape_changed = true;
}
@@ -569,7 +569,7 @@ void ItemList::set_select_mode(SelectMode p_mode) {
}
select_mode = p_mode;
- update();
+ queue_redraw();
}
ItemList::SelectMode ItemList::get_select_mode() const {
@@ -582,13 +582,13 @@ void ItemList::set_icon_mode(IconMode p_mode) {
icon_mode = p_mode;
for (int i = 0; i < items.size(); i++) {
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
- items.write[i].text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
+ items.write[i].text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_TRIM_EDGE_SPACES);
} else {
items.write[i].text_buf->set_break_flags(TextServer::BREAK_NONE);
}
}
shape_changed = true;
- update();
+ queue_redraw();
}
}
@@ -602,7 +602,7 @@ void ItemList::set_fixed_icon_size(const Size2 &p_size) {
}
fixed_icon_size = p_size;
- update();
+ queue_redraw();
}
Size2 ItemList::get_fixed_icon_size() const {
@@ -655,8 +655,7 @@ void ItemList::gui_input(const Ref<InputEvent> &p_event) {
if (mb.is_valid() && mb->is_pressed()) {
search_string = ""; //any mousepress cancels
Vector2 pos = mb->get_position();
- Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
- pos -= bg->get_offset();
+ pos -= theme_cache.bg_style->get_offset();
pos.y += scroll_bar->get_value();
if (is_layout_rtl()) {
@@ -961,7 +960,7 @@ void ItemList::gui_input(const Ref<InputEvent> &p_event) {
void ItemList::ensure_current_is_visible() {
ensure_selected_visible = true;
- update();
+ queue_redraw();
}
static Rect2 _adjust_to_max_size(Size2 p_size, Size2 p_max_size) {
@@ -980,11 +979,36 @@ static Rect2 _adjust_to_max_size(Size2 p_size, Size2 p_max_size) {
return Rect2(ofs_x, ofs_y, tex_width, tex_height);
}
+void ItemList::_update_theme_item_cache() {
+ Control::_update_theme_item_cache();
+
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
+ theme_cache.v_separation = get_theme_constant(SNAME("v_separation"));
+
+ theme_cache.bg_style = get_theme_stylebox(SNAME("bg"));
+ theme_cache.bg_focus_style = get_theme_stylebox(SNAME("bg_focus"));
+
+ theme_cache.font = get_theme_font(SNAME("font"));
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
+ theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
+ theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+
+ theme_cache.line_separation = get_theme_constant(SNAME("line_separation"));
+ theme_cache.icon_margin = get_theme_constant(SNAME("icon_margin"));
+ theme_cache.selected_style = get_theme_stylebox(SNAME("selected"));
+ theme_cache.selected_focus_style = get_theme_stylebox(SNAME("selected_focus"));
+ theme_cache.cursor_style = get_theme_stylebox(SNAME("cursor_unfocused"));
+ theme_cache.cursor_focus_style = get_theme_stylebox(SNAME("cursor"));
+ theme_cache.guide_color = get_theme_color(SNAME("guide_color"));
+}
+
void ItemList::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_RESIZED: {
shape_changed = true;
- update();
+ queue_redraw();
} break;
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
@@ -994,41 +1018,36 @@ void ItemList::_notification(int p_what) {
_shape(i);
}
shape_changed = true;
- update();
+ queue_redraw();
} break;
case NOTIFICATION_DRAW: {
- Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
-
int mw = scroll_bar->get_minimum_size().x;
scroll_bar->set_anchor_and_offset(SIDE_LEFT, ANCHOR_END, -mw);
scroll_bar->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, 0);
- scroll_bar->set_anchor_and_offset(SIDE_TOP, ANCHOR_BEGIN, bg->get_margin(SIDE_TOP));
- scroll_bar->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, -bg->get_margin(SIDE_BOTTOM));
+ scroll_bar->set_anchor_and_offset(SIDE_TOP, ANCHOR_BEGIN, theme_cache.bg_style->get_margin(SIDE_TOP));
+ scroll_bar->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, -theme_cache.bg_style->get_margin(SIDE_BOTTOM));
Size2 size = get_size();
- int width = size.width - bg->get_minimum_size().width;
+ int width = size.width - theme_cache.bg_style->get_minimum_size().width;
- draw_style_box(bg, Rect2(Point2(), size));
+ draw_style_box(theme_cache.bg_style, Rect2(Point2(), size));
- int hseparation = get_theme_constant(SNAME("h_separation"));
- int vseparation = get_theme_constant(SNAME("v_separation"));
- int icon_margin = get_theme_constant(SNAME("icon_margin"));
- int line_separation = get_theme_constant(SNAME("line_separation"));
- Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
+ Ref<StyleBox> sbsel;
+ Ref<StyleBox> cursor;
- Ref<StyleBox> sbsel = has_focus() ? get_theme_stylebox(SNAME("selected_focus")) : get_theme_stylebox(SNAME("selected"));
- Ref<StyleBox> cursor = has_focus() ? get_theme_stylebox(SNAME("cursor")) : get_theme_stylebox(SNAME("cursor_unfocused"));
+ if (has_focus()) {
+ sbsel = theme_cache.selected_focus_style;
+ cursor = theme_cache.cursor_focus_style;
+ } else {
+ sbsel = theme_cache.selected_style;
+ cursor = theme_cache.cursor_style;
+ }
bool rtl = is_layout_rtl();
- Color guide_color = get_theme_color(SNAME("guide_color"));
- Color font_color = get_theme_color(SNAME("font_color"));
- Color font_selected_color = get_theme_color(SNAME("font_selected_color"));
-
if (has_focus()) {
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(), true);
- draw_style_box(get_theme_stylebox(SNAME("bg_focus")), Rect2(Point2(), size));
+ draw_style_box(theme_cache.bg_focus_style, Rect2(Point2(), size));
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(), false);
}
@@ -1047,9 +1066,9 @@ void ItemList::_notification(int p_what) {
if (!items[i].text.is_empty()) {
if (icon_mode == ICON_MODE_TOP) {
- minsize.y += icon_margin;
+ minsize.y += theme_cache.icon_margin;
} else {
- minsize.x += icon_margin;
+ minsize.x += theme_cache.icon_margin;
}
}
}
@@ -1067,7 +1086,7 @@ void ItemList::_notification(int p_what) {
if (icon_mode == ICON_MODE_TOP) {
minsize.x = MAX(minsize.x, s.width);
if (max_text_lines > 0) {
- minsize.y += s.height + line_separation * max_text_lines;
+ minsize.y += s.height + theme_cache.line_separation * max_text_lines;
} else {
minsize.y += s.height;
}
@@ -1084,13 +1103,13 @@ void ItemList::_notification(int p_what) {
max_column_width = MAX(max_column_width, minsize.x);
// elements need to adapt to the selected size
- minsize.y += vseparation;
- minsize.x += hseparation;
+ minsize.y += theme_cache.v_separation;
+ minsize.x += theme_cache.h_separation;
items.write[i].rect_cache.size = minsize;
items.write[i].min_rect_cache.size = minsize;
}
- int fit_size = size.x - bg->get_minimum_size().width - mw;
+ int fit_size = size.x - theme_cache.bg_style->get_minimum_size().width - mw;
//2-attempt best fit
current_columns = 0x7FFFFFFF;
@@ -1118,11 +1137,11 @@ void ItemList::_notification(int p_what) {
}
items.write[i].rect_cache.position = ofs;
max_h = MAX(max_h, items[i].rect_cache.size.y);
- ofs.x += items[i].rect_cache.size.x + hseparation;
+ ofs.x += items[i].rect_cache.size.x + theme_cache.h_separation;
col++;
if (col == current_columns) {
if (i < items.size() - 1) {
- separators.push_back(ofs.y + max_h + vseparation / 2);
+ separators.push_back(ofs.y + max_h + theme_cache.v_separation / 2);
}
for (int j = i; j >= 0 && col > 0; j--, col--) {
@@ -1130,7 +1149,7 @@ void ItemList::_notification(int p_what) {
}
ofs.x = 0;
- ofs.y += max_h + vseparation;
+ ofs.y += max_h + theme_cache.v_separation;
col = 0;
max_h = 0;
}
@@ -1141,10 +1160,10 @@ void ItemList::_notification(int p_what) {
}
if (all_fit) {
- float page = MAX(0, size.height - bg->get_minimum_size().height);
+ float page = MAX(0, size.height - theme_cache.bg_style->get_minimum_size().height);
float max = MAX(page, ofs.y + max_h);
if (auto_height) {
- auto_height_value = ofs.y + max_h + bg->get_minimum_size().height;
+ auto_height_value = ofs.y + max_h + theme_cache.bg_style->get_minimum_size().height;
}
scroll_bar->set_max(max);
scroll_bar->set_page(page);
@@ -1185,7 +1204,7 @@ void ItemList::_notification(int p_what) {
ensure_selected_visible = false;
- Vector2 base_ofs = bg->get_offset();
+ Vector2 base_ofs = theme_cache.bg_style->get_offset();
base_ofs.y -= int(scroll_bar->get_value());
const Rect2 clip(-base_ofs, size); // visible frame, don't need to draw outside of there
@@ -1229,10 +1248,10 @@ void ItemList::_notification(int p_what) {
if (items[i].selected) {
Rect2 r = rcache;
r.position += base_ofs;
- r.position.y -= vseparation / 2;
- r.size.y += vseparation;
- r.position.x -= hseparation / 2;
- r.size.x += hseparation;
+ r.position.y -= theme_cache.v_separation / 2;
+ r.size.y += theme_cache.v_separation;
+ r.position.x -= theme_cache.h_separation / 2;
+ r.size.x += theme_cache.h_separation;
if (rtl) {
r.position.x = size.width - r.position.x - r.size.x;
@@ -1245,10 +1264,10 @@ void ItemList::_notification(int p_what) {
r.position += base_ofs;
// Size rect to make the align the temperature colors
- r.position.y -= vseparation / 2;
- r.size.y += vseparation;
- r.position.x -= hseparation / 2;
- r.size.x += hseparation;
+ r.position.y -= theme_cache.v_separation / 2;
+ r.size.y += theme_cache.v_separation;
+ r.position.x -= theme_cache.h_separation / 2;
+ r.size.x += theme_cache.h_separation;
if (rtl) {
r.position.x = size.width - r.position.x - r.size.x;
@@ -1274,11 +1293,11 @@ void ItemList::_notification(int p_what) {
if (icon_mode == ICON_MODE_TOP) {
pos.x += Math::floor((items[i].rect_cache.size.width - icon_size.width) / 2);
- pos.y += icon_margin;
- text_ofs.y = icon_size.height + icon_margin * 2;
+ pos.y += theme_cache.icon_margin;
+ text_ofs.y = icon_size.height + theme_cache.icon_margin * 2;
} else {
pos.y += Math::floor((items[i].rect_cache.size.height - icon_size.height) / 2);
- text_ofs.x = icon_size.width + icon_margin;
+ text_ofs.x = icon_size.width + theme_cache.icon_margin;
}
Rect2 draw_rect = Rect2(pos, icon_size);
@@ -1329,7 +1348,7 @@ void ItemList::_notification(int p_what) {
max_len = size2.x;
}
- Color modulate = items[i].selected ? font_selected_color : (items[i].custom_fg != Color() ? items[i].custom_fg : font_color);
+ Color modulate = items[i].selected ? theme_cache.font_selected_color : (items[i].custom_fg != Color() ? items[i].custom_fg : theme_cache.font_color);
if (items[i].disabled) {
modulate.a *= 0.5;
}
@@ -1344,8 +1363,8 @@ void ItemList::_notification(int p_what) {
items.write[i].text_buf->set_alignment(HORIZONTAL_ALIGNMENT_CENTER);
- if (outline_size > 0 && font_outline_color.a > 0) {
- items[i].text_buf->draw_outline(get_canvas_item(), text_ofs, outline_size, font_outline_color);
+ if (theme_cache.font_outline_size > 0 && theme_cache.font_outline_color.a > 0) {
+ items[i].text_buf->draw_outline(get_canvas_item(), text_ofs, theme_cache.font_outline_size, theme_cache.font_outline_color);
}
items[i].text_buf->draw(get_canvas_item(), text_ofs, modulate);
@@ -1375,8 +1394,8 @@ void ItemList::_notification(int p_what) {
items.write[i].text_buf->set_alignment(HORIZONTAL_ALIGNMENT_LEFT);
}
- if (outline_size > 0 && font_outline_color.a > 0) {
- items[i].text_buf->draw_outline(get_canvas_item(), text_ofs, outline_size, font_outline_color);
+ if (theme_cache.font_outline_size > 0 && theme_cache.font_outline_color.a > 0) {
+ items[i].text_buf->draw_outline(get_canvas_item(), text_ofs, theme_cache.font_outline_size, theme_cache.font_outline_color);
}
if (width - text_ofs.x > 0) {
@@ -1388,10 +1407,10 @@ void ItemList::_notification(int p_what) {
if (select_mode == SELECT_MULTI && i == current) {
Rect2 r = rcache;
r.position += base_ofs;
- r.position.y -= vseparation / 2;
- r.size.y += vseparation;
- r.position.x -= hseparation / 2;
- r.size.x += hseparation;
+ r.position.y -= theme_cache.v_separation / 2;
+ r.size.y += theme_cache.v_separation;
+ r.position.x -= theme_cache.h_separation / 2;
+ r.size.x += theme_cache.h_separation;
if (rtl) {
r.position.x = size.width - r.position.x - r.size.x;
@@ -1423,20 +1442,19 @@ void ItemList::_notification(int p_what) {
}
const int y = base_ofs.y + separators[i];
- draw_line(Vector2(bg->get_margin(SIDE_LEFT), y), Vector2(width, y), guide_color);
+ draw_line(Vector2(theme_cache.bg_style->get_margin(SIDE_LEFT), y), Vector2(width, y), theme_cache.guide_color);
}
} break;
}
}
void ItemList::_scroll_changed(double) {
- update();
+ queue_redraw();
}
int ItemList::get_item_at_position(const Point2 &p_pos, bool p_exact) const {
Vector2 pos = p_pos;
- Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
- pos -= bg->get_offset();
+ pos -= theme_cache.bg_style->get_offset();
pos.y += scroll_bar->get_value();
if (is_layout_rtl()) {
@@ -1473,8 +1491,7 @@ bool ItemList::is_pos_at_end_of_items(const Point2 &p_pos) const {
}
Vector2 pos = p_pos;
- Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
- pos -= bg->get_offset();
+ pos -= theme_cache.bg_style->get_offset();
pos.y += scroll_bar->get_value();
if (is_layout_rtl()) {
@@ -1505,7 +1522,7 @@ String ItemList::get_tooltip(const Point2 &p_pos) const {
void ItemList::sort_items_by_text() {
items.sort();
- update();
+ queue_redraw();
shape_changed = true;
if (select_mode == SELECT_SINGLE) {
@@ -1593,7 +1610,7 @@ void ItemList::set_auto_height(bool p_enable) {
auto_height = p_enable;
shape_changed = true;
- update();
+ queue_redraw();
}
bool ItemList::has_auto_height() const {
@@ -1607,7 +1624,7 @@ void ItemList::set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior)
items.write[i].text_buf->set_text_overrun_behavior(p_behavior);
}
shape_changed = true;
- update();
+ queue_redraw();
}
}
diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h
index 21bd22759c..63bc771185 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -109,23 +109,45 @@ private:
int max_columns = 1;
Size2 fixed_icon_size;
-
Size2 max_item_size_cache;
int defer_select_single = -1;
-
bool allow_rmb_select = false;
-
bool allow_reselect = false;
real_t icon_scale = 1.0;
bool do_autoscroll_to_bottom = false;
+ struct ThemeCache {
+ int h_separation = 0;
+ int v_separation = 0;
+
+ Ref<StyleBox> bg_style;
+ Ref<StyleBox> bg_focus_style;
+
+ Ref<Font> font;
+ int font_size = 0;
+ Color font_color;
+ Color font_selected_color;
+ int font_outline_size = 0;
+ Color font_outline_color;
+
+ int line_separation = 0;
+ int icon_margin = 0;
+ Ref<StyleBox> selected_style;
+ Ref<StyleBox> selected_focus_style;
+ Ref<StyleBox> cursor_style;
+ Ref<StyleBox> cursor_focus_style;
+ Color guide_color;
+ } theme_cache;
+
void _scroll_changed(double);
void _shape(int p_idx);
protected:
+ virtual void _update_theme_item_cache() override;
+
void _notification(int p_what);
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index b15578f222..7f7dc96665 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -44,7 +44,7 @@ void Label::set_autowrap_mode(TextServer::AutowrapMode p_mode) {
autowrap_mode = p_mode;
lines_dirty = true;
- update();
+ queue_redraw();
if (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
update_minimum_size();
@@ -63,7 +63,7 @@ void Label::set_uppercase(bool p_uppercase) {
uppercase = p_uppercase;
dirty = true;
- update();
+ queue_redraw();
}
bool Label::is_uppercase() const {
@@ -71,7 +71,7 @@ bool Label::is_uppercase() const {
}
int Label::get_line_height(int p_line) const {
- Ref<Font> font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : get_theme_font(SNAME("font"));
+ Ref<Font> font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : theme_cache.font;
if (p_line >= 0 && p_line < lines_rid.size()) {
return TS->shaped_text_get_size(lines_rid[p_line]).y;
} else if (lines_rid.size() > 0) {
@@ -81,13 +81,13 @@ int Label::get_line_height(int p_line) const {
}
return h;
} else {
- int font_size = settings.is_valid() ? settings->get_font_size() : get_theme_font_size(SNAME("font_size"));
+ int font_size = settings.is_valid() ? settings->get_font_size() : theme_cache.font_size;
return font->get_height(font_size);
}
}
void Label::_shape() {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"), SNAME("Label"));
+ Ref<StyleBox> style = theme_cache.normal_style;
int width = (get_size().width - style->get_minimum_size().width);
if (dirty || font_dirty) {
@@ -99,8 +99,8 @@ void Label::_shape() {
} else {
TS->shaped_text_set_direction(text_rid, (TextServer::Direction)text_direction);
}
- const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : get_theme_font(SNAME("font"));
- int font_size = settings.is_valid() ? settings->get_font_size() : get_theme_font_size(SNAME("font_size"));
+ const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : theme_cache.font;
+ int font_size = settings.is_valid() ? settings->get_font_size() : theme_cache.font_size;
ERR_FAIL_COND(font.is_null());
String text = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text;
if (visible_chars >= 0 && visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) {
@@ -143,8 +143,9 @@ void Label::_shape() {
case TextServer::AUTOWRAP_OFF:
break;
}
- PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags);
+ autowrap_flags = autowrap_flags | TextServer::BREAK_TRIM_EDGE_SPACES;
+ PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags);
for (int i = 0; i < line_breaks.size(); i = i + 2) {
RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
lines_rid.push_back(line);
@@ -231,8 +232,8 @@ void Label::_shape() {
}
void Label::_update_visible() {
- int line_spacing = settings.is_valid() ? settings->get_line_spacing() : get_theme_constant(SNAME("line_spacing"), SNAME("Label"));
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"), SNAME("Label"));
+ int line_spacing = settings.is_valid() ? settings->get_line_spacing() : theme_cache.line_spacing;
+ Ref<StyleBox> style = theme_cache.normal_style;
int lines_visible = lines_rid.size();
if (max_lines_visible >= 0 && lines_visible > max_lines_visible) {
@@ -271,6 +272,22 @@ inline void draw_glyph_outline(const Glyph &p_gl, const RID &p_canvas, const Col
}
}
+void Label::_update_theme_item_cache() {
+ Control::_update_theme_item_cache();
+
+ theme_cache.normal_style = get_theme_stylebox(SNAME("normal"));
+ theme_cache.font = get_theme_font(SNAME("font"));
+
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
+ theme_cache.line_spacing = get_theme_constant(SNAME("line_spacing"));
+ theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_shadow_color = get_theme_color(SNAME("font_shadow_color"));
+ theme_cache.font_shadow_offset = Point2(get_theme_constant(SNAME("shadow_offset_x")), get_theme_constant(SNAME("shadow_offset_y")));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+ theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
+ theme_cache.font_shadow_outline_size = get_theme_constant(SNAME("shadow_outline_size"));
+}
+
void Label::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_TRANSLATION_CHANGED: {
@@ -284,11 +301,11 @@ void Label::_notification(int p_what) {
}
dirty = true;
- update();
+ queue_redraw();
} break;
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
- update();
+ queue_redraw();
} break;
case NOTIFICATION_DRAW: {
@@ -306,15 +323,15 @@ void Label::_notification(int p_what) {
Size2 string_size;
Size2 size = get_size();
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
- Ref<Font> font = (has_settings && settings->get_font().is_valid()) ? settings->get_font() : get_theme_font(SNAME("font"));
- Color font_color = has_settings ? settings->get_font_color() : get_theme_color(SNAME("font_color"));
- Color font_shadow_color = has_settings ? settings->get_shadow_color() : get_theme_color(SNAME("font_shadow_color"));
- Point2 shadow_ofs = has_settings ? settings->get_shadow_offset() : Point2(get_theme_constant(SNAME("shadow_offset_x")), get_theme_constant(SNAME("shadow_offset_y")));
- int line_spacing = has_settings ? settings->get_line_spacing() : get_theme_constant(SNAME("line_spacing"));
- Color font_outline_color = has_settings ? settings->get_outline_color() : get_theme_color(SNAME("font_outline_color"));
- int outline_size = has_settings ? settings->get_outline_size() : get_theme_constant(SNAME("outline_size"));
- int shadow_outline_size = has_settings ? settings->get_shadow_size() : get_theme_constant(SNAME("shadow_outline_size"));
+ Ref<StyleBox> style = theme_cache.normal_style;
+ Ref<Font> font = (has_settings && settings->get_font().is_valid()) ? settings->get_font() : theme_cache.font;
+ Color font_color = has_settings ? settings->get_font_color() : theme_cache.font_color;
+ Color font_shadow_color = has_settings ? settings->get_shadow_color() : theme_cache.font_shadow_color;
+ Point2 shadow_ofs = has_settings ? settings->get_shadow_offset() : theme_cache.font_shadow_offset;
+ int line_spacing = has_settings ? settings->get_line_spacing() : theme_cache.line_spacing;
+ Color font_outline_color = has_settings ? settings->get_outline_color() : theme_cache.font_outline_color;
+ int outline_size = has_settings ? settings->get_outline_size() : theme_cache.font_outline_size;
+ int shadow_outline_size = has_settings ? settings->get_shadow_size() : theme_cache.font_shadow_outline_size;
bool rtl = (TS->shaped_text_get_inferred_direction(text_rid) == TextServer::DIRECTION_RTL);
bool rtl_layout = is_layout_rtl();
@@ -544,7 +561,7 @@ void Label::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED: {
font_dirty = true;
- update();
+ queue_redraw();
} break;
case NOTIFICATION_RESIZED: {
@@ -561,12 +578,12 @@ Size2 Label::get_minimum_size() const {
Size2 min_size = minsize;
- const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : get_theme_font(SNAME("font"));
- int font_size = settings.is_valid() ? settings->get_font_size() : get_theme_font_size(SNAME("font_size"));
+ const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : theme_cache.font;
+ int font_size = settings.is_valid() ? settings->get_font_size() : theme_cache.font_size;
min_size.height = MAX(min_size.height, font->get_height(font_size) + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM));
- Size2 min_style = get_theme_stylebox(SNAME("normal"))->get_minimum_size();
+ Size2 min_style = theme_cache.normal_style->get_minimum_size();
if (autowrap_mode != TextServer::AUTOWRAP_OFF) {
return Size2(1, (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) ? 1 : min_size.height) + min_style;
} else {
@@ -589,8 +606,8 @@ int Label::get_line_count() const {
}
int Label::get_visible_line_count() const {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
- int line_spacing = settings.is_valid() ? settings->get_line_spacing() : get_theme_constant(SNAME("line_spacing"));
+ Ref<StyleBox> style = theme_cache.normal_style;
+ int line_spacing = settings.is_valid() ? settings->get_line_spacing() : theme_cache.line_spacing;
int lines_visible = 0;
float total_h = 0.0;
for (int64_t i = lines_skipped; i < lines_rid.size(); i++) {
@@ -623,7 +640,7 @@ void Label::set_horizontal_alignment(HorizontalAlignment p_alignment) {
}
horizontal_alignment = p_alignment;
- update();
+ queue_redraw();
}
HorizontalAlignment Label::get_horizontal_alignment() const {
@@ -638,7 +655,7 @@ void Label::set_vertical_alignment(VerticalAlignment p_alignment) {
}
vertical_alignment = p_alignment;
- update();
+ queue_redraw();
}
VerticalAlignment Label::get_vertical_alignment() const {
@@ -655,13 +672,13 @@ void Label::set_text(const String &p_string) {
if (visible_ratio < 1) {
visible_chars = get_total_character_count() * visible_ratio;
}
- update();
+ queue_redraw();
update_minimum_size();
}
void Label::_invalidate() {
font_dirty = true;
- update();
+ queue_redraw();
}
void Label::set_label_settings(const Ref<LabelSettings> &p_settings) {
@@ -686,7 +703,7 @@ void Label::set_text_direction(Control::TextDirection p_text_direction) {
if (text_direction != p_text_direction) {
text_direction = p_text_direction;
font_dirty = true;
- update();
+ queue_redraw();
}
}
@@ -694,7 +711,7 @@ void Label::set_structured_text_bidi_override(TextServer::StructuredTextParser p
if (st_parser != p_parser) {
st_parser = p_parser;
dirty = true;
- update();
+ queue_redraw();
}
}
@@ -709,7 +726,7 @@ void Label::set_structured_text_bidi_override_options(Array p_args) {
st_args = p_args;
dirty = true;
- update();
+ queue_redraw();
}
Array Label::get_structured_text_bidi_override_options() const {
@@ -724,7 +741,7 @@ void Label::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
dirty = true;
- update();
+ queue_redraw();
}
}
@@ -738,7 +755,7 @@ void Label::set_clip_text(bool p_clip) {
}
clip = p_clip;
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -753,7 +770,7 @@ void Label::set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior) {
overrun_behavior = p_behavior;
lines_dirty = true;
- update();
+ queue_redraw();
if (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
update_minimum_size();
}
@@ -778,7 +795,7 @@ void Label::set_visible_characters(int p_amount) {
if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) {
dirty = true;
}
- update();
+ queue_redraw();
}
}
@@ -802,7 +819,7 @@ void Label::set_visible_ratio(float p_ratio) {
if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) {
dirty = true;
}
- update();
+ queue_redraw();
}
}
@@ -818,7 +835,7 @@ void Label::set_visible_characters_behavior(TextServer::VisibleCharactersBehavio
if (visible_chars_behavior != p_behavior) {
visible_chars_behavior = p_behavior;
dirty = true;
- update();
+ queue_redraw();
}
}
@@ -831,7 +848,7 @@ void Label::set_lines_skipped(int p_lines) {
lines_skipped = p_lines;
_update_visible();
- update();
+ queue_redraw();
}
int Label::get_lines_skipped() const {
@@ -845,7 +862,7 @@ void Label::set_max_lines_visible(int p_lines) {
max_lines_visible = p_lines;
_update_visible();
- update();
+ queue_redraw();
}
int Label::get_max_lines_visible() const {
@@ -908,9 +925,10 @@ void Label::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "is_clipping_text");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_overrun_behavior", PROPERTY_HINT_ENUM, "Trim Nothing,Trim Characters,Trim Words,Ellipsis,Word Ellipsis"), "set_text_overrun_behavior", "get_text_overrun_behavior");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase");
+
+ ADD_GROUP("Displayed Text", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "lines_skipped", PROPERTY_HINT_RANGE, "0,999,1"), "set_lines_skipped", "get_lines_skipped");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_lines_visible", PROPERTY_HINT_RANGE, "-1,999,1"), "set_max_lines_visible", "get_max_lines_visible");
-
// Note: "visible_characters" and "visible_ratio" should be set after "text" to be correctly applied.
ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1"), "set_visible_characters", "get_visible_characters");
ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters_behavior", PROPERTY_HINT_ENUM, "Characters Before Shaping,Characters After Shaping,Glyphs (Layout Direction),Glyphs (Left-to-Right),Glyphs (Right-to-Left)"), "set_visible_characters_behavior", "get_visible_characters_behavior");
diff --git a/scene/gui/label.h b/scene/gui/label.h
index 65831cab6e..b79c94a5ba 100644
--- a/scene/gui/label.h
+++ b/scene/gui/label.h
@@ -67,13 +67,28 @@ private:
Ref<LabelSettings> settings;
+ struct ThemeCache {
+ Ref<StyleBox> normal_style;
+ Ref<Font> font;
+
+ int font_size = 0;
+ int line_spacing = 0;
+ Color font_color;
+ Color font_shadow_color;
+ Point2 font_shadow_offset;
+ Color font_outline_color;
+ int font_outline_size;
+ int font_shadow_outline_size;
+ } theme_cache;
+
void _update_visible();
void _shape();
void _invalidate();
protected:
- void _notification(int p_what);
+ virtual void _update_theme_item_cache() override;
+ void _notification(int p_what);
static void _bind_methods();
public:
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 34a60b907c..c2ce4bdb83 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -51,7 +51,7 @@ void LineEdit::_swap_current_input_direction() {
input_direction = TEXT_DIRECTION_LTR;
}
set_caret_column(get_caret_column());
- update();
+ queue_redraw();
}
void LineEdit::_move_caret_left(bool p_select, bool p_move_by_word) {
@@ -285,7 +285,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
if (!text.is_empty() && is_editable() && _is_over_clear_button(b->get_position())) {
clear_button_status.press_attempt = true;
clear_button_status.pressing_inside = true;
- update();
+ queue_redraw();
return;
}
@@ -348,7 +348,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
}
}
- update();
+ queue_redraw();
} else {
if (selection.enabled && !pass && b->get_button_index() == MouseButton::LEFT && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
@@ -375,7 +375,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
show_virtual_keyboard();
}
- update();
+ queue_redraw();
}
Ref<InputEventMouseMotion> m = p_event;
@@ -385,7 +385,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
bool last_press_inside = clear_button_status.pressing_inside;
clear_button_status.pressing_inside = clear_button_status.press_attempt && _is_over_clear_button(m->get_position());
if (last_press_inside != clear_button_status.pressing_inside) {
- update();
+ queue_redraw();
}
}
@@ -448,7 +448,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
if (context_menu_enabled) {
if (k->is_action("ui_menu", true)) {
_ensure_menu();
- Point2 pos = Point2(get_caret_pixel_pos().x, (get_size().y + get_theme_font(SNAME("font"))->get_height(get_theme_font_size(SNAME("font_size")))) / 2);
+ Point2 pos = Point2(get_caret_pixel_pos().x, (get_size().y + theme_cache.font->get_height(theme_cache.font_size)) / 2);
menu->set_position(get_screen_position() + pos);
menu->reset_size();
menu->popup();
@@ -613,7 +613,7 @@ void LineEdit::set_horizontal_alignment(HorizontalAlignment p_alignment) {
alignment = p_alignment;
_shape();
- update();
+ queue_redraw();
}
HorizontalAlignment LineEdit::get_horizontal_alignment() const {
@@ -681,7 +681,7 @@ void LineEdit::drop_data(const Point2 &p_point, const Variant &p_data) {
}
text_changed_dirty = true;
}
- update();
+ queue_redraw();
}
}
@@ -696,11 +696,38 @@ bool LineEdit::_is_over_clear_button(const Point2 &p_pos) const {
if (!clear_button_enabled || !has_point(p_pos)) {
return false;
}
- Ref<Texture2D> icon = Control::get_theme_icon(SNAME("clear"));
- int x_ofs = get_theme_stylebox(SNAME("normal"))->get_margin(SIDE_RIGHT);
+ Ref<Texture2D> icon = theme_cache.clear_icon;
+ int x_ofs = theme_cache.normal->get_margin(SIDE_RIGHT);
return p_pos.x > get_size().width - icon->get_width() - x_ofs;
}
+void LineEdit::_update_theme_item_cache() {
+ Control::_update_theme_item_cache();
+
+ theme_cache.normal = get_theme_stylebox(SNAME("normal"));
+ theme_cache.read_only = get_theme_stylebox(SNAME("read_only"));
+ theme_cache.focus = get_theme_stylebox(SNAME("focus"));
+
+ theme_cache.font = get_theme_font(SNAME("font"));
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
+ theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_uneditable_color = get_theme_color(SNAME("font_uneditable_color"));
+ theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
+ theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+ theme_cache.font_placeholder_color = get_theme_color(SNAME("font_placeholder_color"));
+ theme_cache.caret_width = get_theme_constant(SNAME("caret_width"));
+ theme_cache.caret_color = get_theme_color(SNAME("caret_color"));
+ theme_cache.minimum_character_width = get_theme_constant(SNAME("minimum_character_width"));
+ theme_cache.selection_color = get_theme_color(SNAME("selection_color"));
+
+ theme_cache.clear_icon = get_theme_icon(SNAME("clear"));
+ theme_cache.clear_button_color = get_theme_color(SNAME("clear_button_color"));
+ theme_cache.clear_button_color_pressed = get_theme_color(SNAME("clear_button_color_pressed"));
+
+ theme_cache.base_scale = get_theme_default_base_scale();
+}
+
void LineEdit::_notification(int p_what) {
switch (p_what) {
#ifdef TOOLS_ENABLED
@@ -725,25 +752,25 @@ void LineEdit::_notification(int p_what) {
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_THEME_CHANGED: {
_shape();
- update();
+ queue_redraw();
} break;
case NOTIFICATION_TRANSLATION_CHANGED: {
placeholder_translated = atr(placeholder);
_shape();
- update();
+ queue_redraw();
} break;
case NOTIFICATION_WM_WINDOW_FOCUS_IN: {
window_has_focus = true;
draw_caret = true;
- update();
+ queue_redraw();
} break;
case NOTIFICATION_WM_WINDOW_FOCUS_OUT: {
window_has_focus = false;
draw_caret = false;
- update();
+ queue_redraw();
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
@@ -771,19 +798,19 @@ void LineEdit::_notification(int p_what) {
RID ci = get_canvas_item();
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
+ Ref<StyleBox> style = theme_cache.normal;
if (!is_editable()) {
- style = get_theme_stylebox(SNAME("read_only"));
+ style = theme_cache.read_only;
draw_caret = false;
}
- Ref<Font> font = get_theme_font(SNAME("font"));
+ Ref<Font> font = theme_cache.font;
if (!flat) {
style->draw(ci, Rect2(Point2(), size));
}
if (has_focus()) {
- get_theme_stylebox(SNAME("focus"))->draw(ci, Rect2(Point2(), size));
+ theme_cache.focus->draw(ci, Rect2(Point2(), size));
}
int x_ofs = 0;
@@ -821,25 +848,30 @@ void LineEdit::_notification(int p_what) {
int y_area = height - style->get_minimum_size().height;
int y_ofs = style->get_offset().y + (y_area - text_height) / 2;
- Color selection_color = get_theme_color(SNAME("selection_color"));
- Color font_color = get_theme_color(is_editable() ? SNAME("font_color") : SNAME("font_uneditable_color"));
- Color font_selected_color = get_theme_color(SNAME("font_selected_color"));
- Color caret_color = get_theme_color(SNAME("caret_color"));
+ Color selection_color = theme_cache.selection_color;
+ Color font_color;
+ if (is_editable()) {
+ font_color = theme_cache.font_color;
+ } else {
+ font_color = theme_cache.font_uneditable_color;
+ }
+ Color font_selected_color = theme_cache.font_selected_color;
+ Color caret_color = theme_cache.caret_color;
// Draw placeholder color.
if (using_placeholder) {
- font_color = get_theme_color(SNAME("font_placeholder_color"));
+ font_color = theme_cache.font_placeholder_color;
}
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
if (right_icon.is_valid() || display_clear_icon) {
- Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
+ Ref<Texture2D> r_icon = display_clear_icon ? theme_cache.clear_icon : right_icon;
Color color_icon(1, 1, 1, !is_editable() ? .5 * .9 : .9);
if (display_clear_icon) {
if (clear_button_status.press_attempt && clear_button_status.pressing_inside) {
- color_icon = get_theme_color(SNAME("clear_button_color_pressed"));
+ color_icon = theme_cache.clear_button_color_pressed;
} else {
- color_icon = get_theme_color(SNAME("clear_button_color"));
+ color_icon = theme_cache.clear_button_color;
}
}
@@ -879,8 +911,8 @@ void LineEdit::_notification(int p_what) {
// Draw text.
ofs.y += TS->shaped_text_get_ascent(text_rid);
- Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
+ Color font_outline_color = theme_cache.font_outline_color;
+ int outline_size = theme_cache.font_outline_size;
if (outline_size > 0 && font_outline_color.a > 0) {
Vector2 oofs = ofs;
for (int i = 0; i < gl_size; i++) {
@@ -918,7 +950,7 @@ void LineEdit::_notification(int p_what) {
ofs.x = x_ofs + scroll_offset;
if (draw_caret || drag_caret_force_displayed) {
// Prevent carets from disappearing at theme scales below 1.0 (if the caret width is 1).
- const int caret_width = get_theme_constant(SNAME("caret_width")) * MAX(1, get_theme_default_base_scale());
+ const int caret_width = theme_cache.caret_width * MAX(1, theme_cache.base_scale);
if (ime_text.length() == 0) {
// Normal caret.
@@ -926,7 +958,7 @@ void LineEdit::_notification(int p_what) {
if (caret.l_caret == Rect2() && caret.t_caret == Rect2()) {
// No carets, add one at the start.
- int h = get_theme_font(SNAME("font"))->get_height(get_theme_font_size(SNAME("font_size")));
+ int h = theme_cache.font->get_height(theme_cache.font_size);
int y = style->get_offset().y + (y_area - h) / 2;
if (rtl) {
caret.l_dir = TextServer::DIRECTION_RTL;
@@ -1052,7 +1084,7 @@ void LineEdit::_notification(int p_what) {
_shape();
set_caret_column(caret_column); // Update scroll_offset
- update();
+ queue_redraw();
}
} break;
@@ -1193,7 +1225,7 @@ void LineEdit::shift_selection_check_post(bool p_shift) {
}
void LineEdit::set_caret_at_pixel_pos(int p_x) {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
+ Ref<StyleBox> style = theme_cache.normal;
bool rtl = is_layout_rtl();
int x_ofs = 0;
@@ -1226,7 +1258,7 @@ void LineEdit::set_caret_at_pixel_pos(int p_x) {
bool using_placeholder = text.is_empty() && ime_text.is_empty();
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
if (right_icon.is_valid() || display_clear_icon) {
- Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
+ Ref<Texture2D> r_icon = display_clear_icon ? theme_cache.clear_icon : right_icon;
if (alignment == HORIZONTAL_ALIGNMENT_CENTER) {
if (Math::is_zero_approx(scroll_offset)) {
x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - text_width - r_icon->get_width() - style->get_margin(SIDE_RIGHT) * 2) / 2);
@@ -1241,7 +1273,7 @@ void LineEdit::set_caret_at_pixel_pos(int p_x) {
}
Vector2 LineEdit::get_caret_pixel_pos() {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
+ Ref<StyleBox> style = theme_cache.normal;
bool rtl = is_layout_rtl();
int x_ofs = 0;
@@ -1274,7 +1306,7 @@ Vector2 LineEdit::get_caret_pixel_pos() {
bool using_placeholder = text.is_empty() && ime_text.is_empty();
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
if (right_icon.is_valid() || display_clear_icon) {
- Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
+ Ref<Texture2D> r_icon = display_clear_icon ? theme_cache.clear_icon : right_icon;
if (alignment == HORIZONTAL_ALIGNMENT_CENTER) {
if (Math::is_zero_approx(scroll_offset)) {
x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - text_width - r_icon->get_width() - style->get_margin(SIDE_RIGHT) * 2) / 2);
@@ -1357,7 +1389,7 @@ bool LineEdit::is_caret_force_displayed() const {
void LineEdit::set_caret_force_displayed(const bool p_enabled) {
caret_force_displayed = p_enabled;
set_caret_blink_enabled(caret_blink_enabled);
- update();
+ queue_redraw();
}
float LineEdit::get_caret_blink_speed() const {
@@ -1374,7 +1406,7 @@ void LineEdit::_reset_caret_blink_timer() {
draw_caret = true;
if (has_focus()) {
caret_blink_timer = 0.0;
- update();
+ queue_redraw();
}
}
}
@@ -1382,7 +1414,7 @@ void LineEdit::_reset_caret_blink_timer() {
void LineEdit::_toggle_draw_caret() {
draw_caret = !draw_caret;
if (is_visible_in_tree() && ((has_focus() && window_has_focus) || caret_force_displayed)) {
- update();
+ queue_redraw();
}
}
@@ -1425,7 +1457,7 @@ void LineEdit::set_text(String p_text) {
insert_text_at_caret(p_text);
_create_undo_state();
- update();
+ queue_redraw();
caret_column = 0;
scroll_offset = 0.0;
}
@@ -1445,7 +1477,7 @@ void LineEdit::set_text_direction(Control::TextDirection p_text_direction) {
menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_LTR), text_direction == TEXT_DIRECTION_LTR);
menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_RTL), text_direction == TEXT_DIRECTION_RTL);
}
- update();
+ queue_redraw();
}
}
@@ -1457,7 +1489,7 @@ void LineEdit::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
_shape();
- update();
+ queue_redraw();
}
}
@@ -1472,7 +1504,7 @@ void LineEdit::set_draw_control_chars(bool p_draw_control_chars) {
menu->set_item_checked(menu->get_item_index(MENU_DISPLAY_UCC), draw_control_chars);
}
_shape();
- update();
+ queue_redraw();
}
}
@@ -1484,7 +1516,7 @@ void LineEdit::set_structured_text_bidi_override(TextServer::StructuredTextParse
if (st_parser != p_parser) {
st_parser = p_parser;
_shape();
- update();
+ queue_redraw();
}
}
@@ -1495,7 +1527,7 @@ TextServer::StructuredTextParser LineEdit::get_structured_text_bidi_override() c
void LineEdit::set_structured_text_bidi_override_options(Array p_args) {
st_args = p_args;
_shape();
- update();
+ queue_redraw();
}
Array LineEdit::get_structured_text_bidi_override_options() const {
@@ -1534,7 +1566,7 @@ void LineEdit::set_placeholder(String p_text) {
placeholder = p_text;
placeholder_translated = atr(placeholder);
_shape();
- update();
+ queue_redraw();
}
String LineEdit::get_placeholder() const {
@@ -1559,7 +1591,7 @@ void LineEdit::set_caret_column(int p_column) {
return;
}
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
+ Ref<StyleBox> style = theme_cache.normal;
bool rtl = is_layout_rtl();
int x_ofs = 0;
@@ -1593,7 +1625,7 @@ void LineEdit::set_caret_column(int p_column) {
bool using_placeholder = text.is_empty() && ime_text.is_empty();
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
if (right_icon.is_valid() || display_clear_icon) {
- Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
+ Ref<Texture2D> r_icon = display_clear_icon ? theme_cache.clear_icon : right_icon;
if (alignment == HORIZONTAL_ALIGNMENT_CENTER) {
if (Math::is_zero_approx(scroll_offset)) {
x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - text_width - r_icon->get_width() - style->get_margin(SIDE_RIGHT) * 2) / 2);
@@ -1614,7 +1646,7 @@ void LineEdit::set_caret_column(int p_column) {
}
scroll_offset = MIN(0, scroll_offset);
- update();
+ queue_redraw();
}
int LineEdit::get_caret_column() const {
@@ -1660,19 +1692,19 @@ void LineEdit::clear_internal() {
undo_text = "";
text = "";
_shape();
- update();
+ queue_redraw();
}
Size2 LineEdit::get_minimum_size() const {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
- Ref<Font> font = get_theme_font(SNAME("font"));
- int font_size = get_theme_font_size(SNAME("font_size"));
+ Ref<StyleBox> style = theme_cache.normal;
+ Ref<Font> font = theme_cache.font;
+ int font_size = theme_cache.font_size;
Size2 min_size;
// Minimum size of text.
float em_space_size = font->get_char_size('M', font_size).x;
- min_size.width = get_theme_constant(SNAME("minimum_character_width")) * em_space_size;
+ min_size.width = theme_cache.minimum_character_width * em_space_size;
if (expand_to_text_length) {
// Add a space because some fonts are too exact, and because caret needs a bit more when at the end.
@@ -1688,9 +1720,8 @@ Size2 LineEdit::get_minimum_size() const {
icon_max_width = right_icon->get_width();
}
if (clear_button_enabled) {
- Ref<Texture2D> clear_icon = Control::get_theme_icon(SNAME("clear"));
- min_size.height = MAX(min_size.height, clear_icon->get_height());
- icon_max_width = MAX(icon_max_width, clear_icon->get_width());
+ min_size.height = MAX(min_size.height, theme_cache.clear_icon->get_height());
+ icon_max_width = MAX(icon_max_width, theme_cache.clear_icon->get_width());
}
min_size.width += icon_max_width;
@@ -1704,7 +1735,7 @@ void LineEdit::deselect() {
selection.enabled = false;
selection.creating = false;
selection.double_click = false;
- update();
+ queue_redraw();
}
bool LineEdit::has_selection() const {
@@ -1768,7 +1799,7 @@ void LineEdit::select_all() {
selection.begin = 0;
selection.end = text.length();
selection.enabled = true;
- update();
+ queue_redraw();
}
void LineEdit::set_editable(bool p_editable) {
@@ -1779,7 +1810,7 @@ void LineEdit::set_editable(bool p_editable) {
editable = p_editable;
update_minimum_size();
- update();
+ queue_redraw();
}
bool LineEdit::is_editable() const {
@@ -1793,7 +1824,7 @@ void LineEdit::set_secret(bool p_secret) {
pass = p_secret;
_shape();
- update();
+ queue_redraw();
}
bool LineEdit::is_secret() const {
@@ -1811,7 +1842,7 @@ void LineEdit::set_secret_character(const String &p_string) {
secret_character = p_string;
_shape();
- update();
+ queue_redraw();
}
String LineEdit::get_secret_character() const {
@@ -1848,7 +1879,7 @@ void LineEdit::select(int p_from, int p_to) {
selection.end = p_to;
selection.creating = false;
selection.double_click = false;
- update();
+ queue_redraw();
}
bool LineEdit::is_text_field() const {
@@ -2027,7 +2058,7 @@ void LineEdit::set_clear_button_enabled(bool p_enabled) {
clear_button_enabled = p_enabled;
_fit_to_width();
update_minimum_size();
- update();
+ queue_redraw();
}
bool LineEdit::is_clear_button_enabled() const {
@@ -2104,7 +2135,7 @@ void LineEdit::set_right_icon(const Ref<Texture2D> &p_icon) {
right_icon = p_icon;
_fit_to_width();
update_minimum_size();
- update();
+ queue_redraw();
}
Ref<Texture2D> LineEdit::get_right_icon() {
@@ -2114,7 +2145,7 @@ Ref<Texture2D> LineEdit::get_right_icon() {
void LineEdit::set_flat(bool p_enabled) {
if (flat != p_enabled) {
flat = p_enabled;
- update();
+ queue_redraw();
}
}
@@ -2155,8 +2186,8 @@ void LineEdit::_shape() {
}
TS->shaped_text_set_preserve_control(text_rid, draw_control_chars);
- const Ref<Font> &font = get_theme_font(SNAME("font"));
- int font_size = get_theme_font_size(SNAME("font_size"));
+ const Ref<Font> &font = theme_cache.font;
+ int font_size = theme_cache.font_size;
ERR_FAIL_COND(font.is_null());
TS->shaped_text_add_string(text_rid, t, font->get_rids(), font_size, font->get_opentype_features(), language);
for (int i = 0; i < TextServer::SPACING_MAX; i++) {
@@ -2176,12 +2207,12 @@ void LineEdit::_shape() {
void LineEdit::_fit_to_width() {
if (alignment == HORIZONTAL_ALIGNMENT_FILL) {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
+ Ref<StyleBox> style = theme_cache.normal;
int t_width = get_size().width - style->get_margin(SIDE_RIGHT) - style->get_margin(SIDE_LEFT);
bool using_placeholder = text.is_empty() && ime_text.is_empty();
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
if (right_icon.is_valid() || display_clear_icon) {
- Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
+ Ref<Texture2D> r_icon = display_clear_icon ? theme_cache.clear_icon : right_icon;
t_width -= r_icon->get_width();
}
TS->shaped_text_fit_to_width(text_rid, MAX(t_width, full_width));
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index dabdaa3395..38863e805c 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -174,6 +174,31 @@ private:
double caret_blink_timer = 0.0;
bool caret_blinking = false;
+ struct ThemeCache {
+ Ref<StyleBox> normal;
+ Ref<StyleBox> read_only;
+ Ref<StyleBox> focus;
+
+ Ref<Font> font;
+ int font_size = 0;
+ Color font_color;
+ Color font_uneditable_color;
+ Color font_selected_color;
+ int font_outline_size;
+ Color font_outline_color;
+ Color font_placeholder_color;
+ int caret_width = 0;
+ Color caret_color;
+ int minimum_character_width = 0;
+ Color selection_color;
+
+ Ref<Texture2D> clear_icon;
+ Color clear_button_color;
+ Color clear_button_color_pressed;
+
+ int base_scale = 0;
+ } theme_cache;
+
bool _is_over_clear_button(const Point2 &p_pos) const;
void _clear_undo_stack();
@@ -215,6 +240,7 @@ private:
void _ensure_menu();
protected:
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
static void _bind_methods();
virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override;
diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp
index ee3f64e0e5..7219e86f52 100644
--- a/scene/gui/link_button.cpp
+++ b/scene/gui/link_button.cpp
@@ -33,8 +33,8 @@
#include "core/string/translation.h"
void LinkButton::_shape() {
- Ref<Font> font = get_theme_font(SNAME("font"));
- int font_size = get_theme_font_size(SNAME("font_size"));
+ Ref<Font> font = theme_cache.font;
+ int font_size = theme_cache.font_size;
text_buf->clear();
if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
@@ -54,7 +54,7 @@ void LinkButton::set_text(const String &p_text) {
xl_text = atr(text);
_shape();
update_minimum_size();
- update();
+ queue_redraw();
}
String LinkButton::get_text() const {
@@ -65,7 +65,7 @@ void LinkButton::set_structured_text_bidi_override(TextServer::StructuredTextPar
if (st_parser != p_parser) {
st_parser = p_parser;
_shape();
- update();
+ queue_redraw();
}
}
@@ -76,7 +76,7 @@ TextServer::StructuredTextParser LinkButton::get_structured_text_bidi_override()
void LinkButton::set_structured_text_bidi_override_options(Array p_args) {
st_args = p_args;
_shape();
- update();
+ queue_redraw();
}
Array LinkButton::get_structured_text_bidi_override_options() const {
@@ -88,7 +88,7 @@ void LinkButton::set_text_direction(Control::TextDirection p_text_direction) {
if (text_direction != p_text_direction) {
text_direction = p_text_direction;
_shape();
- update();
+ queue_redraw();
}
}
@@ -100,7 +100,7 @@ void LinkButton::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
_shape();
- update();
+ queue_redraw();
}
}
@@ -114,7 +114,7 @@ void LinkButton::set_underline_mode(UnderlineMode p_underline_mode) {
}
underline_mode = p_underline_mode;
- update();
+ queue_redraw();
}
LinkButton::UnderlineMode LinkButton::get_underline_mode() const {
@@ -125,23 +125,43 @@ Size2 LinkButton::get_minimum_size() const {
return text_buf->get_size();
}
+void LinkButton::_update_theme_item_cache() {
+ BaseButton::_update_theme_item_cache();
+
+ theme_cache.focus = get_theme_stylebox(SNAME("focus"));
+
+ theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_focus_color = get_theme_color(SNAME("font_focus_color"));
+ theme_cache.font_pressed_color = get_theme_color(SNAME("font_pressed_color"));
+ theme_cache.font_hover_color = get_theme_color(SNAME("font_hover_color"));
+ theme_cache.font_hover_pressed_color = get_theme_color(SNAME("font_hover_pressed_color"));
+ theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
+
+ theme_cache.font = get_theme_font(SNAME("font"));
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
+ theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+
+ theme_cache.underline_spacing = get_theme_constant(SNAME("underline_spacing"));
+}
+
void LinkButton::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_TRANSLATION_CHANGED: {
xl_text = atr(text);
_shape();
update_minimum_size();
- update();
+ queue_redraw();
} break;
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
- update();
+ queue_redraw();
} break;
case NOTIFICATION_THEME_CHANGED: {
_shape();
update_minimum_size();
- update();
+ queue_redraw();
} break;
case NOTIFICATION_DRAW: {
@@ -153,9 +173,9 @@ void LinkButton::_notification(int p_what) {
switch (get_draw_mode()) {
case DRAW_NORMAL: {
if (has_focus()) {
- color = get_theme_color(SNAME("font_focus_color"));
+ color = theme_cache.font_focus_color;
} else {
- color = get_theme_color(SNAME("font_color"));
+ color = theme_cache.font_color;
}
do_underline = underline_mode == UNDERLINE_MODE_ALWAYS;
@@ -163,35 +183,35 @@ void LinkButton::_notification(int p_what) {
case DRAW_HOVER_PRESSED:
case DRAW_PRESSED: {
if (has_theme_color(SNAME("font_pressed_color"))) {
- color = get_theme_color(SNAME("font_pressed_color"));
+ color = theme_cache.font_pressed_color;
} else {
- color = get_theme_color(SNAME("font_color"));
+ color = theme_cache.font_color;
}
do_underline = underline_mode != UNDERLINE_MODE_NEVER;
} break;
case DRAW_HOVER: {
- color = get_theme_color(SNAME("font_hover_color"));
+ color = theme_cache.font_hover_color;
do_underline = underline_mode != UNDERLINE_MODE_NEVER;
} break;
case DRAW_DISABLED: {
- color = get_theme_color(SNAME("font_disabled_color"));
+ color = theme_cache.font_disabled_color;
do_underline = underline_mode == UNDERLINE_MODE_ALWAYS;
} break;
}
if (has_focus()) {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("focus"));
+ Ref<StyleBox> style = theme_cache.focus;
style->draw(ci, Rect2(Point2(), size));
}
int width = text_buf->get_line_width();
- Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
+ Color font_outline_color = theme_cache.font_outline_color;
+ int outline_size = theme_cache.outline_size;
if (is_layout_rtl()) {
if (outline_size > 0 && font_outline_color.a > 0) {
text_buf->draw_outline(get_canvas_item(), Vector2(size.width - width, 0), outline_size, font_outline_color);
@@ -205,7 +225,7 @@ void LinkButton::_notification(int p_what) {
}
if (do_underline) {
- int underline_spacing = get_theme_constant(SNAME("underline_spacing")) + text_buf->get_line_underline_position();
+ int underline_spacing = theme_cache.underline_spacing + text_buf->get_line_underline_position();
int y = text_buf->get_line_ascent() + underline_spacing;
if (is_layout_rtl()) {
diff --git a/scene/gui/link_button.h b/scene/gui/link_button.h
index 12a6a7618f..accd848163 100644
--- a/scene/gui/link_button.h
+++ b/scene/gui/link_button.h
@@ -55,10 +55,29 @@ private:
TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
Array st_args;
+ struct ThemeCache {
+ Ref<StyleBox> focus;
+
+ Color font_color;
+ Color font_focus_color;
+ Color font_pressed_color;
+ Color font_hover_color;
+ Color font_hover_pressed_color;
+ Color font_disabled_color;
+
+ Ref<Font> font;
+ int font_size = 0;
+ int outline_size = 0;
+ Color font_outline_color;
+
+ int underline_spacing = 0;
+ } theme_cache;
+
void _shape();
protected:
virtual Size2 get_minimum_size() const override;
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/margin_container.cpp b/scene/gui/margin_container.cpp
index fac37a8634..60fe681824 100644
--- a/scene/gui/margin_container.cpp
+++ b/scene/gui/margin_container.cpp
@@ -30,12 +30,16 @@
#include "margin_container.h"
-Size2 MarginContainer::get_minimum_size() const {
- int margin_left = get_theme_constant(SNAME("margin_left"));
- int margin_top = get_theme_constant(SNAME("margin_top"));
- int margin_right = get_theme_constant(SNAME("margin_right"));
- int margin_bottom = get_theme_constant(SNAME("margin_bottom"));
+void MarginContainer::_update_theme_item_cache() {
+ Container::_update_theme_item_cache();
+
+ theme_cache.margin_left = get_theme_constant(SNAME("margin_left"));
+ theme_cache.margin_top = get_theme_constant(SNAME("margin_top"));
+ theme_cache.margin_right = get_theme_constant(SNAME("margin_right"));
+ theme_cache.margin_bottom = get_theme_constant(SNAME("margin_bottom"));
+}
+Size2 MarginContainer::get_minimum_size() const {
Size2 max;
for (int i = 0; i < get_child_count(); i++) {
@@ -59,8 +63,8 @@ Size2 MarginContainer::get_minimum_size() const {
}
}
- max.width += (margin_left + margin_right);
- max.height += (margin_top + margin_bottom);
+ max.width += (theme_cache.margin_left + theme_cache.margin_right);
+ max.height += (theme_cache.margin_top + theme_cache.margin_bottom);
return max;
}
@@ -86,11 +90,6 @@ Vector<int> MarginContainer::get_allowed_size_flags_vertical() const {
void MarginContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_SORT_CHILDREN: {
- int margin_left = get_theme_constant(SNAME("margin_left"));
- int margin_top = get_theme_constant(SNAME("margin_top"));
- int margin_right = get_theme_constant(SNAME("margin_right"));
- int margin_bottom = get_theme_constant(SNAME("margin_bottom"));
-
Size2 s = get_size();
for (int i = 0; i < get_child_count(); i++) {
@@ -102,9 +101,9 @@ void MarginContainer::_notification(int p_what) {
continue;
}
- int w = s.width - margin_left - margin_right;
- int h = s.height - margin_top - margin_bottom;
- fit_child_in_rect(c, Rect2(margin_left, margin_top, w, h));
+ int w = s.width - theme_cache.margin_left - theme_cache.margin_right;
+ int h = s.height - theme_cache.margin_top - theme_cache.margin_bottom;
+ fit_child_in_rect(c, Rect2(theme_cache.margin_left, theme_cache.margin_top, w, h));
}
} break;
diff --git a/scene/gui/margin_container.h b/scene/gui/margin_container.h
index f8a3c5bb11..5c33785170 100644
--- a/scene/gui/margin_container.h
+++ b/scene/gui/margin_container.h
@@ -36,7 +36,16 @@
class MarginContainer : public Container {
GDCLASS(MarginContainer, Container);
+ struct ThemeCache {
+ int margin_left = 0;
+ int margin_top = 0;
+ int margin_right = 0;
+ int margin_bottom = 0;
+ } theme_cache;
+
protected:
+ virtual void _update_theme_item_cache() override;
+
void _notification(int p_what);
public:
diff --git a/scene/gui/menu_bar.cpp b/scene/gui/menu_bar.cpp
index 9eba2feaf7..0613652bdf 100644
--- a/scene/gui/menu_bar.cpp
+++ b/scene/gui/menu_bar.cpp
@@ -60,7 +60,7 @@ void MenuBar::gui_input(const Ref<InputEvent> &p_event) {
if (active_menu >= 0) {
get_menu_popup(active_menu)->hide();
}
- _open_popup(selected_menu);
+ _open_popup(selected_menu, true);
}
return;
} else if (p_event->is_action("ui_right") && p_event->is_pressed()) {
@@ -82,7 +82,7 @@ void MenuBar::gui_input(const Ref<InputEvent> &p_event) {
if (active_menu >= 0) {
get_menu_popup(active_menu)->hide();
}
- _open_popup(selected_menu);
+ _open_popup(selected_menu, true);
}
return;
}
@@ -95,7 +95,7 @@ void MenuBar::gui_input(const Ref<InputEvent> &p_event) {
selected_menu = focused_menu;
}
if (selected_menu != old_sel) {
- update();
+ queue_redraw();
}
}
@@ -110,7 +110,7 @@ void MenuBar::gui_input(const Ref<InputEvent> &p_event) {
}
}
-void MenuBar::_open_popup(int p_index) {
+void MenuBar::_open_popup(int p_index, bool p_focus_item) {
ERR_FAIL_INDEX(p_index, menu_cache.size());
PopupMenu *pm = get_menu_popup(p_index);
@@ -134,16 +134,21 @@ void MenuBar::_open_popup(int p_index) {
pm->set_parent_rect(Rect2(Point2(screen_pos - pm->get_position()), Size2(screen_size.x, screen_pos.y)));
pm->popup();
- update();
+ if (p_focus_item) {
+ for (int i = 0; i < pm->get_item_count(); i++) {
+ if (!pm->is_item_disabled(i)) {
+ pm->set_current_index(i);
+ break;
+ }
+ }
+ }
+
+ queue_redraw();
}
void MenuBar::shortcut_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
- if (is_native_menu()) {
- return;
- }
-
if (!_is_focus_owner_in_shortcut_context()) {
return;
}
@@ -203,7 +208,7 @@ void MenuBar::_popup_visibility_changed(bool p_visible) {
active_menu = -1;
focused_menu = -1;
set_process_internal(false);
- update();
+ queue_redraw();
return;
}
@@ -244,7 +249,7 @@ void MenuBar::_update_submenu(const String &p_menu_name, PopupMenu *p_child) {
DisplayServer::get_singleton()->global_menu_add_submenu_item(p_menu_name, p_child->get_item_text(i), p_menu_name + "/" + itos(i));
_update_submenu(p_menu_name + "/" + itos(i), pm);
} else {
- int index = DisplayServer::get_singleton()->global_menu_add_item(p_menu_name, p_child->get_item_text(i), callable_mp(p_child, &PopupMenu::activate_item), i);
+ int index = DisplayServer::get_singleton()->global_menu_add_item(p_menu_name, p_child->get_item_text(i), callable_mp(p_child, &PopupMenu::activate_item), Callable(), i);
if (p_child->is_item_checkable(i)) {
DisplayServer::get_singleton()->global_menu_set_item_checkable(p_menu_name, index, true);
@@ -328,7 +333,36 @@ void MenuBar::_update_menu() {
}
}
update_minimum_size();
- update();
+ queue_redraw();
+}
+
+void MenuBar::_update_theme_item_cache() {
+ Control::_update_theme_item_cache();
+
+ theme_cache.normal = get_theme_stylebox(SNAME("normal"));
+ theme_cache.normal_mirrored = get_theme_stylebox(SNAME("normal_mirrored"));
+ theme_cache.disabled = get_theme_stylebox(SNAME("disabled"));
+ theme_cache.disabled_mirrored = get_theme_stylebox(SNAME("disabled_mirrored"));
+ theme_cache.pressed = get_theme_stylebox(SNAME("pressed"));
+ theme_cache.pressed_mirrored = get_theme_stylebox(SNAME("pressed_mirrored"));
+ theme_cache.hover = get_theme_stylebox(SNAME("hover"));
+ theme_cache.hover_mirrored = get_theme_stylebox(SNAME("hover_mirrored"));
+ theme_cache.hover_pressed = get_theme_stylebox(SNAME("hover_pressed"));
+ theme_cache.hover_pressed_mirrored = get_theme_stylebox(SNAME("hover_pressed_mirrored"));
+
+ theme_cache.font = get_theme_font(SNAME("font"));
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
+ theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+
+ theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
+ theme_cache.font_pressed_color = get_theme_color(SNAME("font_pressed_color"));
+ theme_cache.font_hover_color = get_theme_color(SNAME("font_hover_color"));
+ theme_cache.font_hover_pressed_color = get_theme_color(SNAME("font_hover_pressed_color"));
+ theme_cache.font_focus_color = get_theme_color(SNAME("font_focus_color"));
+
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
}
void MenuBar::_notification(int p_what) {
@@ -343,7 +377,7 @@ void MenuBar::_notification(int p_what) {
} break;
case NOTIFICATION_MOUSE_EXIT: {
focused_menu = -1;
- update();
+ queue_redraw();
} break;
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
@@ -367,12 +401,24 @@ void MenuBar::_notification(int p_what) {
case NOTIFICATION_INTERNAL_PROCESS: {
MutexLock lock(mutex);
+ if (is_native_menu()) {
+ // Handled by OS.
+ return;
+ }
+
Vector2 pos = DisplayServer::get_singleton()->mouse_get_position() - mouse_pos_adjusted - get_global_position();
+ if (pos == old_mouse_pos) {
+ return;
+ }
+ old_mouse_pos = pos;
+
int index = _get_index_at_point(pos);
if (index >= 0 && index != active_menu) {
selected_menu = index;
focused_menu = selected_menu;
- get_menu_popup(active_menu)->hide();
+ if (active_menu >= 0) {
+ get_menu_popup(active_menu)->hide();
+ }
_open_popup(index);
}
} break;
@@ -380,8 +426,7 @@ void MenuBar::_notification(int p_what) {
}
int MenuBar::_get_index_at_point(const Point2 &p_point) const {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
- int hsep = get_theme_constant(SNAME("h_separation"));
+ Ref<StyleBox> style = theme_cache.normal;
int offset = 0;
for (int i = 0; i < menu_cache.size(); i++) {
if (menu_cache[i].hidden) {
@@ -393,7 +438,7 @@ int MenuBar::_get_index_at_point(const Point2 &p_point) const {
return i;
}
}
- offset += size.x + hsep;
+ offset += size.x + theme_cache.h_separation;
}
return -1;
}
@@ -401,8 +446,7 @@ int MenuBar::_get_index_at_point(const Point2 &p_point) const {
Rect2 MenuBar::_get_menu_item_rect(int p_index) const {
ERR_FAIL_INDEX_V(p_index, menu_cache.size(), Rect2());
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
- int hsep = get_theme_constant(SNAME("h_separation"));
+ Ref<StyleBox> style = theme_cache.normal;
int offset = 0;
for (int i = 0; i < p_index; i++) {
@@ -410,7 +454,7 @@ Rect2 MenuBar::_get_menu_item_rect(int p_index) const {
continue;
}
Size2 size = menu_cache[i].text_buf->get_size() + style->get_minimum_size();
- offset += size.x + hsep;
+ offset += size.x + theme_cache.h_separation;
}
return Rect2(Point2(offset, 0), menu_cache[p_index].text_buf->get_size() + style->get_minimum_size());
@@ -429,76 +473,76 @@ void MenuBar::_draw_menu_item(int p_index) {
}
Color color;
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
+ Ref<StyleBox> style = theme_cache.normal;
Rect2 item_rect = _get_menu_item_rect(p_index);
if (menu_cache[p_index].disabled) {
if (rtl && has_theme_stylebox(SNAME("disabled_mirrored"))) {
- style = get_theme_stylebox(SNAME("disabled_mirrored"));
+ style = theme_cache.disabled_mirrored;
} else {
- style = get_theme_stylebox(SNAME("disabled"));
+ style = theme_cache.disabled;
}
if (!flat) {
style->draw(ci, item_rect);
}
- color = get_theme_color(SNAME("font_disabled_color"));
+ color = theme_cache.font_disabled_color;
} else if (hovered && pressed && has_theme_stylebox("hover_pressed")) {
if (rtl && has_theme_stylebox(SNAME("hover_pressed_mirrored"))) {
- style = get_theme_stylebox(SNAME("hover_pressed_mirrored"));
+ style = theme_cache.hover_pressed_mirrored;
} else {
- style = get_theme_stylebox(SNAME("hover_pressed"));
+ style = theme_cache.hover_pressed;
}
if (!flat) {
style->draw(ci, item_rect);
}
if (has_theme_color(SNAME("font_hover_pressed_color"))) {
- color = get_theme_color(SNAME("font_hover_pressed_color"));
+ color = theme_cache.font_hover_pressed_color;
}
} else if (pressed) {
if (rtl && has_theme_stylebox(SNAME("pressed_mirrored"))) {
- style = get_theme_stylebox(SNAME("pressed_mirrored"));
+ style = theme_cache.pressed_mirrored;
} else {
- style = get_theme_stylebox(SNAME("pressed"));
+ style = theme_cache.pressed;
}
if (!flat) {
style->draw(ci, item_rect);
}
if (has_theme_color(SNAME("font_pressed_color"))) {
- color = get_theme_color(SNAME("font_pressed_color"));
+ color = theme_cache.font_pressed_color;
} else {
- color = get_theme_color(SNAME("font_color"));
+ color = theme_cache.font_color;
}
} else if (hovered) {
if (rtl && has_theme_stylebox(SNAME("hover_mirrored"))) {
- style = get_theme_stylebox(SNAME("hover_mirrored"));
+ style = theme_cache.hover_mirrored;
} else {
- style = get_theme_stylebox(SNAME("hover"));
+ style = theme_cache.hover;
}
if (!flat) {
style->draw(ci, item_rect);
}
- color = get_theme_color(SNAME("font_hover_color"));
+ color = theme_cache.font_hover_color;
} else {
if (rtl && has_theme_stylebox(SNAME("normal_mirrored"))) {
- style = get_theme_stylebox(SNAME("normal_mirrored"));
+ style = theme_cache.normal_mirrored;
} else {
- style = get_theme_stylebox(SNAME("normal"));
+ style = theme_cache.normal;
}
if (!flat) {
style->draw(ci, item_rect);
}
// Focus colors only take precedence over normal state.
if (has_focus()) {
- color = get_theme_color(SNAME("font_focus_color"));
+ color = theme_cache.font_focus_color;
} else {
- color = get_theme_color(SNAME("font_color"));
+ color = theme_cache.font_color;
}
}
Point2 text_ofs = item_rect.position + Point2(style->get_margin(SIDE_LEFT), style->get_margin(SIDE_TOP));
- Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
+ Color font_outline_color = theme_cache.font_outline_color;
+ int outline_size = theme_cache.outline_size;
if (outline_size > 0 && font_outline_color.a > 0) {
menu_cache[p_index].text_buf->draw_outline(ci, text_ofs, outline_size, font_outline_color);
}
@@ -506,16 +550,13 @@ void MenuBar::_draw_menu_item(int p_index) {
}
void MenuBar::shape(Menu &p_menu) {
- Ref<Font> font = get_theme_font(SNAME("font"));
- int font_size = get_theme_font_size(SNAME("font_size"));
-
p_menu.text_buf->clear();
if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
p_menu.text_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
} else {
p_menu.text_buf->set_direction((TextServer::Direction)text_direction);
}
- p_menu.text_buf->add_string(p_menu.name, font, font_size, language);
+ p_menu.text_buf->add_string(p_menu.name, theme_cache.font, theme_cache.font_size, language);
}
void MenuBar::_refresh_menu_names() {
@@ -707,7 +748,7 @@ String MenuBar::get_language() const {
void MenuBar::set_flat(bool p_enabled) {
if (flat != p_enabled) {
flat = p_enabled;
- update();
+ queue_redraw();
}
}
@@ -745,7 +786,7 @@ Size2 MenuBar::get_minimum_size() const {
return Size2();
}
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
+ Ref<StyleBox> style = theme_cache.normal;
Vector2 size;
for (int i = 0; i < menu_cache.size(); i++) {
@@ -757,7 +798,7 @@ Size2 MenuBar::get_minimum_size() const {
size.x += sz.x;
}
if (menu_cache.size() > 1) {
- size.x += get_theme_constant(SNAME("h_separation")) * (menu_cache.size() - 1);
+ size.x += theme_cache.h_separation * (menu_cache.size() - 1);
}
return size;
}
diff --git a/scene/gui/menu_bar.h b/scene/gui/menu_bar.h
index 3c4a25fd06..f7ef19e98b 100644
--- a/scene/gui/menu_bar.h
+++ b/scene/gui/menu_bar.h
@@ -73,8 +73,36 @@ class MenuBar : public Control {
int active_menu = -1;
Vector2i mouse_pos_adjusted;
+ Vector2i old_mouse_pos;
ObjectID shortcut_context;
+ struct ThemeCache {
+ Ref<StyleBox> normal;
+ Ref<StyleBox> normal_mirrored;
+ Ref<StyleBox> disabled;
+ Ref<StyleBox> disabled_mirrored;
+ Ref<StyleBox> pressed;
+ Ref<StyleBox> pressed_mirrored;
+ Ref<StyleBox> hover;
+ Ref<StyleBox> hover_mirrored;
+ Ref<StyleBox> hover_pressed;
+ Ref<StyleBox> hover_pressed_mirrored;
+
+ Ref<Font> font;
+ int font_size = 0;
+ int outline_size = 0;
+ Color font_outline_color;
+
+ Color font_color;
+ Color font_disabled_color;
+ Color font_pressed_color;
+ Color font_hover_color;
+ Color font_hover_pressed_color;
+ Color font_focus_color;
+
+ int h_separation = 0;
+ } theme_cache;
+
int _get_index_at_point(const Point2 &p_point) const;
Rect2 _get_menu_item_rect(int p_index) const;
void _draw_menu_item(int p_index);
@@ -84,7 +112,7 @@ class MenuBar : public Control {
Vector<PopupMenu *> _get_popups() const;
int get_menu_idx_from_control(PopupMenu *p_child) const;
- void _open_popup(int p_index);
+ void _open_popup(int p_index, bool p_focus_item = false);
void _popup_visibility_changed(bool p_visible);
void _update_submenu(const String &p_menu_name, PopupMenu *p_child);
void _clear_menu();
@@ -95,6 +123,7 @@ class MenuBar : public Control {
protected:
virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
virtual void add_child_notify(Node *p_child) override;
virtual void move_child_notify(Node *p_child) override;
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index e6e17cc881..f779f87ae7 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -103,9 +103,14 @@ void MenuButton::pressed() {
popup->set_position(gp);
popup->set_parent_rect(Rect2(Point2(gp - popup->get_position()), size));
- // If not triggered by the mouse, start the popup with its first item selected.
- if (popup->get_item_count() > 0 && !_was_pressed_by_mouse()) {
- popup->set_current_index(0);
+ // If not triggered by the mouse, start the popup with its first enabled item focused.
+ if (!_was_pressed_by_mouse()) {
+ for (int i = 0; i < popup->get_item_count(); i++) {
+ if (!popup->is_item_disabled(i)) {
+ popup->set_current_index(i);
+ break;
+ }
+ }
}
popup->popup();
@@ -161,7 +166,10 @@ void MenuButton::_notification(int p_what) {
if (menu_btn_other && menu_btn_other != this && menu_btn_other->is_switch_on_hover() && !menu_btn_other->is_disabled() &&
(get_parent()->is_ancestor_of(menu_btn_other) || menu_btn_other->get_parent()->is_ancestor_of(popup))) {
popup->hide();
+
menu_btn_other->pressed();
+ // As the popup wasn't triggered by a mouse click, the item focus needs to be removed manually.
+ menu_btn_other->get_popup()->set_current_index(-1);
}
} break;
}
diff --git a/scene/gui/nine_patch_rect.cpp b/scene/gui/nine_patch_rect.cpp
index a7e86dd5de..6048916d7d 100644
--- a/scene/gui/nine_patch_rect.cpp
+++ b/scene/gui/nine_patch_rect.cpp
@@ -94,7 +94,7 @@ void NinePatchRect::set_texture(const Ref<Texture2D> &p_tex) {
return;
}
texture = p_tex;
- update();
+ queue_redraw();
update_minimum_size();
emit_signal(SceneStringNames::get_singleton()->texture_changed);
}
@@ -111,7 +111,7 @@ void NinePatchRect::set_patch_margin(Side p_side, int p_size) {
}
margin[p_side] = p_size;
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -140,7 +140,7 @@ void NinePatchRect::set_draw_center(bool p_enabled) {
}
draw_center = p_enabled;
- update();
+ queue_redraw();
}
bool NinePatchRect::is_draw_center_enabled() const {
@@ -153,7 +153,7 @@ void NinePatchRect::set_h_axis_stretch_mode(AxisStretchMode p_mode) {
}
axis_h = p_mode;
- update();
+ queue_redraw();
}
NinePatchRect::AxisStretchMode NinePatchRect::get_h_axis_stretch_mode() const {
@@ -166,7 +166,7 @@ void NinePatchRect::set_v_axis_stretch_mode(AxisStretchMode p_mode) {
}
axis_v = p_mode;
- update();
+ queue_redraw();
}
NinePatchRect::AxisStretchMode NinePatchRect::get_v_axis_stretch_mode() const {
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index 881acdbf3a..0dd9666858 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -43,11 +43,11 @@ Size2 OptionButton::get_minimum_size() const {
}
if (has_theme_icon(SNAME("arrow"))) {
- const Size2 padding = get_theme_stylebox(SNAME("normal"))->get_minimum_size();
- const Size2 arrow_size = Control::get_theme_icon(SNAME("arrow"))->get_size();
+ const Size2 padding = theme_cache.normal->get_minimum_size();
+ const Size2 arrow_size = theme_cache.arrow_icon->get_size();
Size2 content_size = minsize - padding;
- content_size.width += arrow_size.width + MAX(0, get_theme_constant(SNAME("h_separation")));
+ content_size.width += arrow_size.width + MAX(0, theme_cache.h_separation);
content_size.height = MAX(content_size.height, arrow_size.height);
minsize = content_size + padding;
@@ -56,35 +56,63 @@ Size2 OptionButton::get_minimum_size() const {
return minsize;
}
+void OptionButton::_update_theme_item_cache() {
+ Button::_update_theme_item_cache();
+
+ theme_cache.normal = get_theme_stylebox(SNAME("normal"));
+
+ theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_focus_color = get_theme_color(SNAME("font_focus_color"));
+ theme_cache.font_pressed_color = get_theme_color(SNAME("font_pressed_color"));
+ theme_cache.font_hover_color = get_theme_color(SNAME("font_hover_color"));
+ theme_cache.font_hover_pressed_color = get_theme_color(SNAME("font_hover_pressed_color"));
+ theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
+
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
+
+ theme_cache.arrow_icon = get_theme_icon(SNAME("arrow"));
+ theme_cache.arrow_margin = get_theme_constant(SNAME("arrow_margin"));
+ theme_cache.modulate_arrow = get_theme_constant(SNAME("modulate_arrow"));
+}
+
void OptionButton::_notification(int p_what) {
switch (p_what) {
+ case NOTIFICATION_POSTINITIALIZE: {
+ if (has_theme_icon(SNAME("arrow"))) {
+ if (is_layout_rtl()) {
+ _set_internal_margin(SIDE_LEFT, theme_cache.arrow_icon->get_width());
+ } else {
+ _set_internal_margin(SIDE_RIGHT, theme_cache.arrow_icon->get_width());
+ }
+ }
+ } break;
+
case NOTIFICATION_DRAW: {
if (!has_theme_icon(SNAME("arrow"))) {
return;
}
RID ci = get_canvas_item();
- Ref<Texture2D> arrow = Control::get_theme_icon(SNAME("arrow"));
Color clr = Color(1, 1, 1);
- if (get_theme_constant(SNAME("modulate_arrow"))) {
+ if (theme_cache.modulate_arrow) {
switch (get_draw_mode()) {
case DRAW_PRESSED:
- clr = get_theme_color(SNAME("font_pressed_color"));
+ clr = theme_cache.font_pressed_color;
break;
case DRAW_HOVER:
- clr = get_theme_color(SNAME("font_hover_color"));
+ clr = theme_cache.font_hover_color;
break;
case DRAW_HOVER_PRESSED:
- clr = get_theme_color(SNAME("font_hover_pressed_color"));
+ clr = theme_cache.font_hover_pressed_color;
break;
case DRAW_DISABLED:
- clr = get_theme_color(SNAME("font_disabled_color"));
+ clr = theme_cache.font_disabled_color;
break;
default:
if (has_focus()) {
- clr = get_theme_color(SNAME("font_focus_color"));
+ clr = theme_cache.font_focus_color;
} else {
- clr = get_theme_color(SNAME("font_color"));
+ clr = theme_cache.font_color;
}
}
}
@@ -93,11 +121,11 @@ void OptionButton::_notification(int p_what) {
Point2 ofs;
if (is_layout_rtl()) {
- ofs = Point2(get_theme_constant(SNAME("arrow_margin")), int(Math::abs((size.height - arrow->get_height()) / 2)));
+ ofs = Point2(theme_cache.arrow_margin, int(Math::abs((size.height - theme_cache.arrow_icon->get_height()) / 2)));
} else {
- ofs = Point2(size.width - arrow->get_width() - get_theme_constant(SNAME("arrow_margin")), int(Math::abs((size.height - arrow->get_height()) / 2)));
+ ofs = Point2(size.width - theme_cache.arrow_icon->get_width() - theme_cache.arrow_margin, int(Math::abs((size.height - theme_cache.arrow_icon->get_height()) / 2)));
}
- arrow->draw(ci, ofs, clr);
+ theme_cache.arrow_icon->draw(ci, ofs, clr);
} break;
case NOTIFICATION_TRANSLATION_CHANGED:
@@ -108,11 +136,11 @@ void OptionButton::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED: {
if (has_theme_icon(SNAME("arrow"))) {
if (is_layout_rtl()) {
- _set_internal_margin(SIDE_LEFT, Control::get_theme_icon(SNAME("arrow"))->get_width());
+ _set_internal_margin(SIDE_LEFT, theme_cache.arrow_icon->get_width());
_set_internal_margin(SIDE_RIGHT, 0.f);
} else {
_set_internal_margin(SIDE_LEFT, 0.f);
- _set_internal_margin(SIDE_RIGHT, Control::get_theme_icon(SNAME("arrow"))->get_width());
+ _set_internal_margin(SIDE_RIGHT, theme_cache.arrow_icon->get_width());
}
}
_refresh_size_cache();
@@ -207,12 +235,24 @@ void OptionButton::pressed() {
popup->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y));
popup->set_size(Size2(size.width, 0));
- // If not triggered by the mouse, start the popup with the checked item selected.
- if (popup->get_item_count() > 0) {
+ // If not triggered by the mouse, start the popup with the checked item (or the first enabled one) focused.
+ if (current != NONE_SELECTED && !popup->is_item_disabled(current)) {
if (!_was_pressed_by_mouse()) {
- popup->set_current_index(current > -1 ? current : 0);
+ popup->set_current_index(current);
} else {
- popup->scroll_to_item(current > -1 ? current : 0);
+ popup->scroll_to_item(current);
+ }
+ } else {
+ for (int i = 0; i < popup->get_item_count(); i++) {
+ if (!popup->is_item_disabled(i)) {
+ if (!_was_pressed_by_mouse()) {
+ popup->set_current_index(i);
+ } else {
+ popup->scroll_to_item(i);
+ }
+
+ break;
+ }
}
}
@@ -528,15 +568,6 @@ OptionButton::OptionButton(const String &p_text) :
Button(p_text) {
set_toggle_mode(true);
set_text_alignment(HORIZONTAL_ALIGNMENT_LEFT);
- if (is_layout_rtl()) {
- if (has_theme_icon(SNAME("arrow"))) {
- _set_internal_margin(SIDE_LEFT, Control::get_theme_icon(SNAME("arrow"))->get_width());
- }
- } else {
- if (has_theme_icon(SNAME("arrow"))) {
- _set_internal_margin(SIDE_RIGHT, Control::get_theme_icon(SNAME("arrow"))->get_width());
- }
- }
set_action_mode(ACTION_MODE_BUTTON_PRESS);
popup = memnew(PopupMenu);
diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h
index cd709b8f5f..2c7e0510f5 100644
--- a/scene/gui/option_button.h
+++ b/scene/gui/option_button.h
@@ -43,6 +43,23 @@ class OptionButton : public Button {
Vector2 _cached_size;
bool cache_refresh_pending = false;
+ struct ThemeCache {
+ Ref<StyleBox> normal;
+
+ Color font_color;
+ Color font_focus_color;
+ Color font_pressed_color;
+ Color font_hover_color;
+ Color font_hover_pressed_color;
+ Color font_disabled_color;
+
+ int h_separation = 0;
+
+ Ref<Texture2D> arrow_icon;
+ int arrow_margin = 0;
+ int modulate_arrow = 0;
+ } theme_cache;
+
void _focused(int p_which);
void _selected(int p_which);
void _select(int p_which, bool p_emit = false);
@@ -54,6 +71,7 @@ class OptionButton : public Button {
protected:
Size2 get_minimum_size() const override;
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
diff --git a/scene/gui/panel.cpp b/scene/gui/panel.cpp
index 1ac6cf57ab..09bc295513 100644
--- a/scene/gui/panel.cpp
+++ b/scene/gui/panel.cpp
@@ -30,12 +30,17 @@
#include "panel.h"
+void Panel::_update_theme_item_cache() {
+ Control::_update_theme_item_cache();
+
+ theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
+}
+
void Panel::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
RID ci = get_canvas_item();
- Ref<StyleBox> style = get_theme_stylebox(SNAME("panel"));
- style->draw(ci, Rect2(Point2(), get_size()));
+ theme_cache.panel_style->draw(ci, Rect2(Point2(), get_size()));
} break;
}
}
diff --git a/scene/gui/panel.h b/scene/gui/panel.h
index 5d2e912680..f9bd721681 100644
--- a/scene/gui/panel.h
+++ b/scene/gui/panel.h
@@ -36,7 +36,13 @@
class Panel : public Control {
GDCLASS(Panel, Control);
+ struct ThemeCache {
+ Ref<StyleBox> panel_style;
+ } theme_cache;
+
protected:
+ virtual void _update_theme_item_cache() override;
+
void _notification(int p_what);
public:
diff --git a/scene/gui/panel_container.cpp b/scene/gui/panel_container.cpp
index fe01712a89..eeaded1788 100644
--- a/scene/gui/panel_container.cpp
+++ b/scene/gui/panel_container.cpp
@@ -31,14 +31,6 @@
#include "panel_container.h"
Size2 PanelContainer::get_minimum_size() const {
- Ref<StyleBox> style;
-
- if (has_theme_stylebox(SNAME("panel"))) {
- style = get_theme_stylebox(SNAME("panel"));
- } else {
- style = get_theme_stylebox(SNAME("panel"), SNAME("PanelContainer"));
- }
-
Size2 ms;
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
@@ -54,8 +46,8 @@ Size2 PanelContainer::get_minimum_size() const {
ms.height = MAX(ms.height, minsize.height);
}
- if (style.is_valid()) {
- ms += style->get_minimum_size();
+ if (theme_cache.panel_style.is_valid()) {
+ ms += theme_cache.panel_style->get_minimum_size();
}
return ms;
}
@@ -78,35 +70,25 @@ Vector<int> PanelContainer::get_allowed_size_flags_vertical() const {
return flags;
}
+void PanelContainer::_update_theme_item_cache() {
+ Container::_update_theme_item_cache();
+
+ theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
+}
+
void PanelContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
RID ci = get_canvas_item();
- Ref<StyleBox> style;
-
- if (has_theme_stylebox(SNAME("panel"))) {
- style = get_theme_stylebox(SNAME("panel"));
- } else {
- style = get_theme_stylebox(SNAME("panel"), SNAME("PanelContainer"));
- }
-
- style->draw(ci, Rect2(Point2(), get_size()));
+ theme_cache.panel_style->draw(ci, Rect2(Point2(), get_size()));
} break;
case NOTIFICATION_SORT_CHILDREN: {
- Ref<StyleBox> style;
-
- if (has_theme_stylebox(SNAME("panel"))) {
- style = get_theme_stylebox(SNAME("panel"));
- } else {
- style = get_theme_stylebox(SNAME("panel"), SNAME("PanelContainer"));
- }
-
Size2 size = get_size();
Point2 ofs;
- if (style.is_valid()) {
- size -= style->get_minimum_size();
- ofs += style->get_offset();
+ if (theme_cache.panel_style.is_valid()) {
+ size -= theme_cache.panel_style->get_minimum_size();
+ ofs += theme_cache.panel_style->get_offset();
}
for (int i = 0; i < get_child_count(); i++) {
diff --git a/scene/gui/panel_container.h b/scene/gui/panel_container.h
index 8f07ce38eb..97d0cdc872 100644
--- a/scene/gui/panel_container.h
+++ b/scene/gui/panel_container.h
@@ -36,7 +36,12 @@
class PanelContainer : public Container {
GDCLASS(PanelContainer, Container);
+ struct ThemeCache {
+ Ref<StyleBox> panel_style;
+ } theme_cache;
+
protected:
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
public:
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp
index c4396f636a..ceae3791f3 100644
--- a/scene/gui/popup.cpp
+++ b/scene/gui/popup.cpp
@@ -68,6 +68,12 @@ void Popup::_deinitialize_visible_parents() {
}
}
+void Popup::_update_theme_item_cache() {
+ Window::_update_theme_item_cache();
+
+ theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
+}
+
void Popup::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -186,8 +192,6 @@ Popup::~Popup() {
}
Size2 PopupPanel::_get_contents_minimum_size() const {
- Ref<StyleBox> p = get_theme_stylebox(SNAME("panel"), get_class_name());
-
Size2 ms;
for (int i = 0; i < get_child_count(); i++) {
@@ -205,14 +209,12 @@ Size2 PopupPanel::_get_contents_minimum_size() const {
ms.y = MAX(cms.y, ms.y);
}
- return ms + p->get_minimum_size();
+ return ms + theme_cache.panel_style->get_minimum_size();
}
void PopupPanel::_update_child_rects() {
- Ref<StyleBox> p = get_theme_stylebox(SNAME("panel"), get_class_name());
-
- Vector2 cpos(p->get_offset());
- Vector2 csize(get_size() - p->get_minimum_size());
+ Vector2 cpos(theme_cache.panel_style->get_offset());
+ Vector2 csize(get_size() - theme_cache.panel_style->get_minimum_size());
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
@@ -234,15 +236,17 @@ void PopupPanel::_update_child_rects() {
}
}
+void PopupPanel::_update_theme_item_cache() {
+ Popup::_update_theme_item_cache();
+
+ theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
+}
+
void PopupPanel::_notification(int p_what) {
switch (p_what) {
+ case NOTIFICATION_READY:
case NOTIFICATION_THEME_CHANGED: {
- panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), get_class_name()));
- } break;
-
- case NOTIFICATION_ENTER_TREE:
- case NOTIFICATION_READY: {
- panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), get_class_name()));
+ panel->add_theme_style_override("panel", theme_cache.panel_style);
_update_child_rects();
} break;
diff --git a/scene/gui/popup.h b/scene/gui/popup.h
index 70eb8722d0..0d6ca25c18 100644
--- a/scene/gui/popup.h
+++ b/scene/gui/popup.h
@@ -43,6 +43,10 @@ class Popup : public Window {
LocalVector<Window *> visible_parents;
bool popped_up = false;
+ struct ThemeCache {
+ Ref<StyleBox> panel_style;
+ } theme_cache;
+
void _input_from_window(const Ref<InputEvent> &p_event);
void _initialize_visible_parents();
@@ -52,6 +56,7 @@ protected:
void _close_pressed();
virtual Rect2i _popup_adjust_rect() const override;
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
static void _bind_methods();
@@ -69,8 +74,14 @@ class PopupPanel : public Popup {
Panel *panel = nullptr;
+ struct ThemeCache {
+ Ref<StyleBox> panel_style;
+ } theme_cache;
+
protected:
void _update_child_rects();
+
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
virtual Size2 _get_contents_minimum_size() const override;
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 4e2aec0278..bcc84fc8dc 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -48,15 +48,12 @@ String PopupMenu::_get_accel_text(const Item &p_item) const {
}
Size2 PopupMenu::_get_contents_minimum_size() const {
- int vseparation = get_theme_constant(SNAME("v_separation"));
- int hseparation = get_theme_constant(SNAME("h_separation"));
-
- Size2 minsize = get_theme_stylebox(SNAME("panel"))->get_minimum_size(); // Accounts for margin in the margin container
+ Size2 minsize = theme_cache.panel_style->get_minimum_size(); // Accounts for margin in the margin container
minsize.x += scroll_container->get_v_scroll_bar()->get_size().width * 2; // Adds a buffer so that the scrollbar does not render over the top of content
float max_w = 0.0;
float icon_w = 0.0;
- int check_w = MAX(get_theme_icon(SNAME("checked"))->get_width(), get_theme_icon(SNAME("radio_checked"))->get_width()) + hseparation;
+ int check_w = MAX(theme_cache.checked->get_width(), theme_cache.radio_checked->get_width()) + theme_cache.h_separation;
int accel_max_w = 0;
bool has_check = false;
@@ -67,23 +64,23 @@ Size2 PopupMenu::_get_contents_minimum_size() const {
size.height = _get_item_height(i);
icon_w = MAX(icon_size.width, icon_w);
- size.width += items[i].indent * get_theme_constant(SNAME("indent"));
+ size.width += items[i].indent * theme_cache.indent;
if (items[i].checkable_type && !items[i].separator) {
has_check = true;
}
size.width += items[i].text_buf->get_size().x;
- size.height += vseparation;
+ size.height += theme_cache.v_separation;
if (items[i].accel != Key::NONE || (items[i].shortcut.is_valid() && items[i].shortcut->has_valid_event())) {
- int accel_w = hseparation * 2;
+ int accel_w = theme_cache.h_separation * 2;
accel_w += items[i].accel_text_buf->get_size().x;
accel_max_w = MAX(accel_w, accel_max_w);
}
if (!items[i].submenu.is_empty()) {
- size.width += get_theme_icon(SNAME("submenu"))->get_width();
+ size.width += theme_cache.submenu->get_width();
}
max_w = MAX(max_w, size.width);
@@ -91,7 +88,7 @@ Size2 PopupMenu::_get_contents_minimum_size() const {
minsize.height += size.height;
}
- int item_side_padding = get_theme_constant(SNAME("item_start_padding")) + get_theme_constant(SNAME("item_end_padding"));
+ int item_side_padding = theme_cache.item_start_padding + theme_cache.item_end_padding;
minsize.width += max_w + icon_w + accel_max_w + item_side_padding;
if (has_check) {
@@ -113,33 +110,31 @@ int PopupMenu::_get_item_height(int p_item) const {
int icon_height = items[p_item].get_icon_size().height;
if (items[p_item].checkable_type && !items[p_item].separator) {
- icon_height = MAX(icon_height, MAX(get_theme_icon(SNAME("checked"))->get_height(), get_theme_icon(SNAME("radio_checked"))->get_height()));
+ icon_height = MAX(icon_height, MAX(theme_cache.checked->get_height(), theme_cache.radio_checked->get_height()));
}
int text_height = items[p_item].text_buf->get_size().height;
if (text_height == 0 && !items[p_item].separator) {
- text_height = get_theme_font(SNAME("font"))->get_height(get_theme_font_size(SNAME("font_size")));
+ text_height = theme_cache.font->get_height(theme_cache.font_size);
}
int separator_height = 0;
if (items[p_item].separator) {
- separator_height = MAX(get_theme_stylebox(SNAME("separator"))->get_minimum_size().height, MAX(get_theme_stylebox(SNAME("labeled_separator_left"))->get_minimum_size().height, get_theme_stylebox(SNAME("labeled_separator_right"))->get_minimum_size().height));
+ separator_height = MAX(theme_cache.separator_style->get_minimum_size().height, MAX(theme_cache.labeled_separator_left->get_minimum_size().height, theme_cache.labeled_separator_right->get_minimum_size().height));
}
return MAX(separator_height, MAX(text_height, icon_height));
}
int PopupMenu::_get_items_total_height() const {
- int vsep = get_theme_constant(SNAME("v_separation"));
-
// Get total height of all items by taking max of icon height and font height
int items_total_height = 0;
for (int i = 0; i < items.size(); i++) {
- items_total_height += _get_item_height(i) + vsep;
+ items_total_height += _get_item_height(i) + theme_cache.v_separation;
}
// Subtract a separator which is not needed for the last item.
- return items_total_height - vsep;
+ return items_total_height - theme_cache.v_separation;
}
int PopupMenu::_get_mouse_over(const Point2 &p_over) const {
@@ -147,18 +142,15 @@ int PopupMenu::_get_mouse_over(const Point2 &p_over) const {
return -1;
}
- Ref<StyleBox> style = get_theme_stylebox(SNAME("panel")); // Accounts for margin in the margin container
-
- int vseparation = get_theme_constant(SNAME("v_separation"));
-
- Point2 ofs = style->get_offset() + Point2(0, vseparation / 2);
+ // Accounts for margin in the margin container
+ Point2 ofs = theme_cache.panel_style->get_offset() + Point2(0, theme_cache.v_separation / 2);
if (ofs.y > p_over.y) {
return -1;
}
for (int i = 0; i < items.size(); i++) {
- ofs.y += i > 0 ? vseparation : (float)vseparation / 2;
+ ofs.y += i > 0 ? theme_cache.v_separation : (float)theme_cache.v_separation / 2;
ofs.y += _get_item_height(i);
@@ -179,9 +171,6 @@ void PopupMenu::_activate_submenu(int p_over, bool p_by_keyboard) {
return; // Already visible.
}
- Ref<StyleBox> style = get_theme_stylebox(SNAME("panel"));
- int vsep = get_theme_constant(SNAME("v_separation"));
-
Point2 this_pos = get_position();
Rect2 this_rect(this_pos, get_size());
@@ -216,9 +205,14 @@ void PopupMenu::_activate_submenu(int p_over, bool p_by_keyboard) {
submenu_pum->activated_by_keyboard = p_by_keyboard;
- // If not triggered by the mouse, start the popup with its first item selected.
- if (submenu_pum->get_item_count() > 0 && p_by_keyboard) {
- submenu_pum->set_current_index(0);
+ // If not triggered by the mouse, start the popup with its first enabled item focused.
+ if (p_by_keyboard) {
+ for (int i = 0; i < submenu_pum->get_item_count(); i++) {
+ if (!submenu_pum->is_item_disabled(i)) {
+ submenu_pum->set_current_index(i);
+ break;
+ }
+ }
}
submenu_pum->popup();
@@ -226,7 +220,7 @@ void PopupMenu::_activate_submenu(int p_over, bool p_by_keyboard) {
// Set autohide areas.
Rect2 safe_area = this_rect;
- safe_area.position.y += items[p_over]._ofs_cache + scroll_offset + style->get_offset().height - vsep / 2;
+ safe_area.position.y += items[p_over]._ofs_cache + scroll_offset + theme_cache.panel_style->get_offset().height - theme_cache.v_separation / 2;
safe_area.size.y = items[p_over]._height_cache;
DisplayServer::get_singleton()->window_set_popup_safe_rect(submenu_popup->get_window_id(), safe_area);
@@ -235,11 +229,11 @@ void PopupMenu::_activate_submenu(int p_over, bool p_by_keyboard) {
// Autohide area above the submenu item.
submenu_pum->clear_autohide_areas();
- submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y, this_rect.size.x, items[p_over]._ofs_cache + scroll_offset + style->get_offset().height - vsep / 2));
+ submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y, this_rect.size.x, items[p_over]._ofs_cache + scroll_offset + theme_cache.panel_style->get_offset().height - theme_cache.v_separation / 2));
// If there is an area below the submenu item, add an autohide area there.
if (items[p_over]._ofs_cache + items[p_over]._height_cache + scroll_offset <= control->get_size().height) {
- int from = items[p_over]._ofs_cache + items[p_over]._height_cache + scroll_offset + vsep / 2 + style->get_offset().height;
+ int from = items[p_over]._ofs_cache + items[p_over]._height_cache + scroll_offset + theme_cache.v_separation / 2 + theme_cache.panel_style->get_offset().height;
submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y + from, this_rect.size.x, this_rect.size.y - from));
}
}
@@ -278,102 +272,104 @@ void PopupMenu::_submenu_timeout() {
void PopupMenu::gui_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
- if (p_event->is_action("ui_down") && p_event->is_pressed()) {
- int search_from = mouse_over + 1;
- if (search_from >= items.size()) {
- search_from = 0;
- }
-
- bool match_found = false;
- for (int i = search_from; i < items.size(); i++) {
- if (!items[i].separator && !items[i].disabled) {
- mouse_over = i;
- emit_signal(SNAME("id_focused"), i);
- scroll_to_item(i);
- control->update();
- set_input_as_handled();
- match_found = true;
- break;
+ if (!items.is_empty()) {
+ if (p_event->is_action("ui_down") && p_event->is_pressed()) {
+ int search_from = mouse_over + 1;
+ if (search_from >= items.size()) {
+ search_from = 0;
}
- }
- if (!match_found) {
- // If the last item is not selectable, try re-searching from the start.
- for (int i = 0; i < search_from; i++) {
+ bool match_found = false;
+ for (int i = search_from; i < items.size(); i++) {
if (!items[i].separator && !items[i].disabled) {
mouse_over = i;
emit_signal(SNAME("id_focused"), i);
scroll_to_item(i);
- control->update();
+ control->queue_redraw();
set_input_as_handled();
+ match_found = true;
break;
}
}
- }
- } else if (p_event->is_action("ui_up") && p_event->is_pressed()) {
- int search_from = mouse_over - 1;
- if (search_from < 0) {
- search_from = items.size() - 1;
- }
- bool match_found = false;
- for (int i = search_from; i >= 0; i--) {
- if (!items[i].separator && !items[i].disabled) {
- mouse_over = i;
- emit_signal(SNAME("id_focused"), i);
- scroll_to_item(i);
- control->update();
- set_input_as_handled();
- match_found = true;
- break;
+ if (!match_found) {
+ // If the last item is not selectable, try re-searching from the start.
+ for (int i = 0; i < search_from; i++) {
+ if (!items[i].separator && !items[i].disabled) {
+ mouse_over = i;
+ emit_signal(SNAME("id_focused"), i);
+ scroll_to_item(i);
+ control->queue_redraw();
+ set_input_as_handled();
+ break;
+ }
+ }
+ }
+ } else if (p_event->is_action("ui_up") && p_event->is_pressed()) {
+ int search_from = mouse_over - 1;
+ if (search_from < 0) {
+ search_from = items.size() - 1;
}
- }
- if (!match_found) {
- // If the first item is not selectable, try re-searching from the end.
- for (int i = items.size() - 1; i >= search_from; i--) {
+ bool match_found = false;
+ for (int i = search_from; i >= 0; i--) {
if (!items[i].separator && !items[i].disabled) {
mouse_over = i;
emit_signal(SNAME("id_focused"), i);
scroll_to_item(i);
- control->update();
+ control->queue_redraw();
set_input_as_handled();
+ match_found = true;
break;
}
}
- }
- } else if (p_event->is_action("ui_left") && p_event->is_pressed()) {
- Node *n = get_parent();
- if (n) {
- if (Object::cast_to<PopupMenu>(n)) {
- hide();
- set_input_as_handled();
- } else if (Object::cast_to<MenuBar>(n)) {
- Object::cast_to<MenuBar>(n)->gui_input(p_event);
- set_input_as_handled();
- return;
+
+ if (!match_found) {
+ // If the first item is not selectable, try re-searching from the end.
+ for (int i = items.size() - 1; i >= search_from; i--) {
+ if (!items[i].separator && !items[i].disabled) {
+ mouse_over = i;
+ emit_signal(SNAME("id_focused"), i);
+ scroll_to_item(i);
+ control->queue_redraw();
+ set_input_as_handled();
+ break;
+ }
+ }
}
- }
- } else if (p_event->is_action("ui_right") && p_event->is_pressed()) {
- if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator && !items[mouse_over].submenu.is_empty() && submenu_over != mouse_over) {
- _activate_submenu(mouse_over, true);
- set_input_as_handled();
- } else {
+ } else if (p_event->is_action("ui_left") && p_event->is_pressed()) {
Node *n = get_parent();
- if (n && Object::cast_to<MenuBar>(n)) {
- Object::cast_to<MenuBar>(n)->gui_input(p_event);
- set_input_as_handled();
- return;
+ if (n) {
+ if (Object::cast_to<PopupMenu>(n)) {
+ hide();
+ set_input_as_handled();
+ } else if (Object::cast_to<MenuBar>(n)) {
+ Object::cast_to<MenuBar>(n)->gui_input(p_event);
+ set_input_as_handled();
+ return;
+ }
}
- }
- } else if (p_event->is_action("ui_accept") && p_event->is_pressed()) {
- if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator) {
- if (!items[mouse_over].submenu.is_empty() && submenu_over != mouse_over) {
+ } else if (p_event->is_action("ui_right") && p_event->is_pressed()) {
+ if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator && !items[mouse_over].submenu.is_empty() && submenu_over != mouse_over) {
_activate_submenu(mouse_over, true);
+ set_input_as_handled();
} else {
- activate_item(mouse_over);
+ Node *n = get_parent();
+ if (n && Object::cast_to<MenuBar>(n)) {
+ Object::cast_to<MenuBar>(n)->gui_input(p_event);
+ set_input_as_handled();
+ return;
+ }
+ }
+ } else if (p_event->is_action("ui_accept") && p_event->is_pressed()) {
+ if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator) {
+ if (!items[mouse_over].submenu.is_empty() && submenu_over != mouse_over) {
+ _activate_submenu(mouse_over, true);
+ } else {
+ activate_item(mouse_over);
+ }
+ set_input_as_handled();
}
- set_input_as_handled();
}
}
@@ -456,7 +452,7 @@ void PopupMenu::gui_input(const Ref<InputEvent> &p_event) {
if (id < 0) {
mouse_over = -1;
- control->update();
+ control->queue_redraw();
return;
}
@@ -467,7 +463,7 @@ void PopupMenu::gui_input(const Ref<InputEvent> &p_event) {
if (over != mouse_over) {
mouse_over = over;
- control->update();
+ control->queue_redraw();
}
}
@@ -504,7 +500,7 @@ void PopupMenu::gui_input(const Ref<InputEvent> &p_event) {
mouse_over = i;
emit_signal(SNAME("id_focused"), i);
scroll_to_item(i);
- control->update();
+ control->queue_redraw();
set_input_as_handled();
break;
}
@@ -521,34 +517,17 @@ void PopupMenu::_draw_items() {
margin_size.height = margin_container->get_theme_constant(SNAME("margin_top")) + margin_container->get_theme_constant(SNAME("margin_bottom"));
// Space between the item content and the sides of popup menu.
- int item_start_padding = get_theme_constant(SNAME("item_start_padding"));
- int item_end_padding = get_theme_constant(SNAME("item_end_padding"));
-
bool rtl = control->is_layout_rtl();
- Ref<StyleBox> style = get_theme_stylebox(SNAME("panel"));
- Ref<StyleBox> hover = get_theme_stylebox(SNAME("hover"));
// In Item::checkable_type enum order (less the non-checkable member), with disabled repeated at the end.
- Ref<Texture2D> check[] = { get_theme_icon(SNAME("checked")), get_theme_icon(SNAME("radio_checked")), get_theme_icon(SNAME("checked_disabled")), get_theme_icon(SNAME("radio_checked_disabled")) };
- Ref<Texture2D> uncheck[] = { get_theme_icon(SNAME("unchecked")), get_theme_icon(SNAME("radio_unchecked")), get_theme_icon(SNAME("unchecked_disabled")), get_theme_icon(SNAME("radio_unchecked_disabled")) };
+ Ref<Texture2D> check[] = { theme_cache.checked, theme_cache.radio_checked, theme_cache.checked_disabled, theme_cache.radio_checked_disabled };
+ Ref<Texture2D> uncheck[] = { theme_cache.unchecked, theme_cache.radio_unchecked, theme_cache.unchecked_disabled, theme_cache.radio_unchecked_disabled };
Ref<Texture2D> submenu;
if (rtl) {
- submenu = get_theme_icon(SNAME("submenu_mirrored"));
+ submenu = theme_cache.submenu_mirrored;
} else {
- submenu = get_theme_icon(SNAME("submenu"));
+ submenu = theme_cache.submenu;
}
- Ref<StyleBox> separator = get_theme_stylebox(SNAME("separator"));
- Ref<StyleBox> labeled_separator_left = get_theme_stylebox(SNAME("labeled_separator_left"));
- Ref<StyleBox> labeled_separator_right = get_theme_stylebox(SNAME("labeled_separator_right"));
-
- int vseparation = get_theme_constant(SNAME("v_separation"));
- int hseparation = get_theme_constant(SNAME("h_separation"));
- Color font_color = get_theme_color(SNAME("font_color"));
- Color font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
- Color font_accelerator_color = get_theme_color(SNAME("font_accelerator_color"));
- Color font_hover_color = get_theme_color(SNAME("font_hover_color"));
- Color font_separator_color = get_theme_color(SNAME("font_separator_color"));
-
float scroll_width = scroll_container->get_v_scroll_bar()->is_visible_in_tree() ? scroll_container->get_v_scroll_bar()->get_size().width : 0;
float display_width = control->get_size().width - scroll_width;
@@ -567,7 +546,7 @@ void PopupMenu::_draw_items() {
}
}
if (icon_ofs > 0.0) {
- icon_ofs += hseparation;
+ icon_ofs += theme_cache.h_separation;
}
float check_ofs = 0.0;
@@ -576,7 +555,7 @@ void PopupMenu::_draw_items() {
check_ofs = MAX(check_ofs, check[i]->get_width());
check_ofs = MAX(check_ofs, uncheck[i]->get_width());
}
- check_ofs += hseparation;
+ check_ofs += theme_cache.h_separation;
}
Point2 ofs = Point2();
@@ -584,7 +563,7 @@ void PopupMenu::_draw_items() {
// Loop through all items and draw each.
for (int i = 0; i < items.size(); i++) {
// For the first item only add half a separation. For all other items, add a whole separation to the offset.
- ofs.y += i > 0 ? vseparation : (float)vseparation / 2;
+ ofs.y += i > 0 ? theme_cache.v_separation : (float)theme_cache.v_separation / 2;
_shape_item(i);
@@ -594,47 +573,47 @@ void PopupMenu::_draw_items() {
if (i == mouse_over) {
if (rtl) {
- hover->draw(ci, Rect2(item_ofs + Point2(scroll_width, -vseparation / 2), Size2(display_width, h + vseparation)));
+ theme_cache.hover_style->draw(ci, Rect2(item_ofs + Point2(scroll_width, -theme_cache.v_separation / 2), Size2(display_width, h + theme_cache.v_separation)));
} else {
- hover->draw(ci, Rect2(item_ofs + Point2(0, -vseparation / 2), Size2(display_width, h + vseparation)));
+ theme_cache.hover_style->draw(ci, Rect2(item_ofs + Point2(0, -theme_cache.v_separation / 2), Size2(display_width, h + theme_cache.v_separation)));
}
}
String text = items[i].xl_text;
// Separator
- item_ofs.x += items[i].indent * get_theme_constant(SNAME("indent"));
+ item_ofs.x += items[i].indent * theme_cache.indent;
if (items[i].separator) {
if (!text.is_empty() || !items[i].icon.is_null()) {
- int content_size = items[i].text_buf->get_size().width + hseparation * 2;
+ int content_size = items[i].text_buf->get_size().width + theme_cache.h_separation * 2;
if (!items[i].icon.is_null()) {
- content_size += icon_size.width + hseparation;
+ content_size += icon_size.width + theme_cache.h_separation;
}
int content_center = display_width / 2;
int content_left = content_center - content_size / 2;
int content_right = content_center + content_size / 2;
if (content_left > item_ofs.x) {
- int sep_h = labeled_separator_left->get_center_size().height + labeled_separator_left->get_minimum_size().height;
+ int sep_h = theme_cache.labeled_separator_left->get_center_size().height + theme_cache.labeled_separator_left->get_minimum_size().height;
int sep_ofs = Math::floor((h - sep_h) / 2.0);
- labeled_separator_left->draw(ci, Rect2(item_ofs + Point2(0, sep_ofs), Size2(MAX(0, content_left - item_ofs.x), sep_h)));
+ theme_cache.labeled_separator_left->draw(ci, Rect2(item_ofs + Point2(0, sep_ofs), Size2(MAX(0, content_left - item_ofs.x), sep_h)));
}
if (content_right < display_width) {
- int sep_h = labeled_separator_right->get_center_size().height + labeled_separator_right->get_minimum_size().height;
+ int sep_h = theme_cache.labeled_separator_right->get_center_size().height + theme_cache.labeled_separator_right->get_minimum_size().height;
int sep_ofs = Math::floor((h - sep_h) / 2.0);
- labeled_separator_right->draw(ci, Rect2(Point2(content_right, item_ofs.y + sep_ofs), Size2(MAX(0, display_width - content_right), sep_h)));
+ theme_cache.labeled_separator_right->draw(ci, Rect2(Point2(content_right, item_ofs.y + sep_ofs), Size2(MAX(0, display_width - content_right), sep_h)));
}
} else {
- int sep_h = separator->get_center_size().height + separator->get_minimum_size().height;
+ int sep_h = theme_cache.separator_style->get_center_size().height + theme_cache.separator_style->get_minimum_size().height;
int sep_ofs = Math::floor((h - sep_h) / 2.0);
- separator->draw(ci, Rect2(item_ofs + Point2(0, sep_ofs), Size2(display_width, sep_h)));
+ theme_cache.separator_style->draw(ci, Rect2(item_ofs + Point2(0, sep_ofs), Size2(display_width, sep_h)));
}
}
Color icon_color(1, 1, 1, items[i].disabled && !items[i].separator ? 0.5 : 1);
// For non-separator items, add some padding for the content.
- item_ofs.x += item_start_padding;
+ item_ofs.x += theme_cache.item_start_padding;
// Checkboxes
if (items[i].checkable_type && !items[i].separator) {
@@ -652,7 +631,7 @@ void PopupMenu::_draw_items() {
// Icon
if (!items[i].icon.is_null()) {
if (items[i].separator) {
- separator_ofs -= (icon_size.width + hseparation) / 2;
+ separator_ofs -= (icon_size.width + theme_cache.h_separation) / 2;
if (rtl) {
items[i].icon->draw(ci, Size2(control->get_size().width - item_ofs.x - separator_ofs - icon_size.width, item_ofs.y) + Point2(0, Math::floor((h - icon_size.height) / 2.0)), icon_color);
@@ -671,61 +650,55 @@ void PopupMenu::_draw_items() {
// Submenu arrow on right hand side.
if (!items[i].submenu.is_empty()) {
if (rtl) {
- submenu->draw(ci, Point2(scroll_width + style->get_margin(SIDE_LEFT) + item_end_padding, item_ofs.y + Math::floor(h - submenu->get_height()) / 2), icon_color);
+ submenu->draw(ci, Point2(scroll_width + theme_cache.panel_style->get_margin(SIDE_LEFT) + theme_cache.item_end_padding, item_ofs.y + Math::floor(h - submenu->get_height()) / 2), icon_color);
} else {
- submenu->draw(ci, Point2(display_width - style->get_margin(SIDE_RIGHT) - submenu->get_width() - item_end_padding, item_ofs.y + Math::floor(h - submenu->get_height()) / 2), icon_color);
+ submenu->draw(ci, Point2(display_width - theme_cache.panel_style->get_margin(SIDE_RIGHT) - submenu->get_width() - theme_cache.item_end_padding, item_ofs.y + Math::floor(h - submenu->get_height()) / 2), icon_color);
}
}
- Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
-
// Text
if (items[i].separator) {
- Color font_separator_outline_color = get_theme_color(SNAME("font_separator_outline_color"));
- int separator_outline_size = get_theme_constant(SNAME("separator_outline_size"));
-
if (!text.is_empty()) {
Vector2 text_pos = Point2(separator_ofs, item_ofs.y + Math::floor((h - items[i].text_buf->get_size().y) / 2.0));
if (!rtl && !items[i].icon.is_null()) {
- text_pos.x += icon_size.width + hseparation;
+ text_pos.x += icon_size.width + theme_cache.h_separation;
}
- if (separator_outline_size > 0 && font_separator_outline_color.a > 0) {
- items[i].text_buf->draw_outline(ci, text_pos, separator_outline_size, font_separator_outline_color);
+ if (theme_cache.font_separator_outline_size > 0 && theme_cache.font_separator_outline_color.a > 0) {
+ items[i].text_buf->draw_outline(ci, text_pos, theme_cache.font_separator_outline_size, theme_cache.font_separator_outline_color);
}
- items[i].text_buf->draw(ci, text_pos, font_separator_color);
+ items[i].text_buf->draw(ci, text_pos, theme_cache.font_separator_color);
}
} else {
item_ofs.x += icon_ofs + check_ofs;
if (rtl) {
Vector2 text_pos = Size2(control->get_size().width - items[i].text_buf->get_size().width - item_ofs.x, item_ofs.y) + Point2(0, Math::floor((h - items[i].text_buf->get_size().y) / 2.0));
- if (outline_size > 0 && font_outline_color.a > 0) {
- items[i].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ if (theme_cache.font_outline_size > 0 && theme_cache.font_outline_color.a > 0) {
+ items[i].text_buf->draw_outline(ci, text_pos, theme_cache.font_outline_size, theme_cache.font_outline_color);
}
- items[i].text_buf->draw(ci, text_pos, items[i].disabled ? font_disabled_color : (i == mouse_over ? font_hover_color : font_color));
+ items[i].text_buf->draw(ci, text_pos, items[i].disabled ? theme_cache.font_disabled_color : (i == mouse_over ? theme_cache.font_hover_color : theme_cache.font_color));
} else {
Vector2 text_pos = item_ofs + Point2(0, Math::floor((h - items[i].text_buf->get_size().y) / 2.0));
- if (outline_size > 0 && font_outline_color.a > 0) {
- items[i].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ if (theme_cache.font_outline_size > 0 && theme_cache.font_outline_color.a > 0) {
+ items[i].text_buf->draw_outline(ci, text_pos, theme_cache.font_outline_size, theme_cache.font_outline_color);
}
- items[i].text_buf->draw(ci, text_pos, items[i].disabled ? font_disabled_color : (i == mouse_over ? font_hover_color : font_color));
+ items[i].text_buf->draw(ci, text_pos, items[i].disabled ? theme_cache.font_disabled_color : (i == mouse_over ? theme_cache.font_hover_color : theme_cache.font_color));
}
}
// Accelerator / Shortcut
if (items[i].accel != Key::NONE || (items[i].shortcut.is_valid() && items[i].shortcut->has_valid_event())) {
if (rtl) {
- item_ofs.x = scroll_width + style->get_margin(SIDE_LEFT) + item_end_padding;
+ item_ofs.x = scroll_width + theme_cache.panel_style->get_margin(SIDE_LEFT) + theme_cache.item_end_padding;
} else {
- item_ofs.x = display_width - style->get_margin(SIDE_RIGHT) - items[i].accel_text_buf->get_size().x - item_end_padding;
+ item_ofs.x = display_width - theme_cache.panel_style->get_margin(SIDE_RIGHT) - items[i].accel_text_buf->get_size().x - theme_cache.item_end_padding;
}
Vector2 text_pos = item_ofs + Point2(0, Math::floor((h - items[i].text_buf->get_size().y) / 2.0));
- if (outline_size > 0 && font_outline_color.a > 0) {
- items[i].accel_text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ if (theme_cache.font_outline_size > 0 && theme_cache.font_outline_color.a > 0) {
+ items[i].accel_text_buf->draw_outline(ci, text_pos, theme_cache.font_outline_size, theme_cache.font_outline_color);
}
- items[i].accel_text_buf->draw(ci, text_pos, i == mouse_over ? font_hover_color : font_accelerator_color);
+ items[i].accel_text_buf->draw(ci, text_pos, i == mouse_over ? theme_cache.font_hover_color : theme_cache.font_accelerator_color);
}
// Cache the item vertical offset from the first item and the height.
@@ -737,9 +710,8 @@ void PopupMenu::_draw_items() {
}
void PopupMenu::_draw_background() {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("panel"));
RID ci2 = margin_container->get_canvas_item();
- style->draw(ci2, Rect2(Point2(), margin_container->get_size()));
+ theme_cache.panel_style->draw(ci2, Rect2(Point2(), margin_container->get_size()));
}
void PopupMenu::_minimum_lifetime_timeout() {
@@ -771,8 +743,8 @@ void PopupMenu::_shape_item(int p_item) {
if (items.write[p_item].dirty) {
items.write[p_item].text_buf->clear();
- Ref<Font> font = get_theme_font(items[p_item].separator ? SNAME("font_separator") : SNAME("font"));
- int font_size = get_theme_font_size(items[p_item].separator ? SNAME("font_separator_size") : SNAME("font_size"));
+ Ref<Font> font = items[p_item].separator ? theme_cache.font_separator : theme_cache.font;
+ int font_size = items[p_item].separator ? theme_cache.font_separator_size : theme_cache.font_size;
if (items[p_item].text_direction == Control::TEXT_DIRECTION_INHERITED) {
items.write[p_item].text_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
@@ -814,6 +786,51 @@ void PopupMenu::remove_child_notify(Node *p_child) {
_menu_changed();
}
+void PopupMenu::_update_theme_item_cache() {
+ Popup::_update_theme_item_cache();
+
+ theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
+ theme_cache.hover_style = get_theme_stylebox(SNAME("hover"));
+
+ theme_cache.separator_style = get_theme_stylebox(SNAME("separator"));
+ theme_cache.labeled_separator_left = get_theme_stylebox(SNAME("labeled_separator_left"));
+ theme_cache.labeled_separator_right = get_theme_stylebox(SNAME("labeled_separator_right"));
+
+ theme_cache.v_separation = get_theme_constant(SNAME("v_separation"));
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
+ theme_cache.indent = get_theme_constant(SNAME("indent"));
+ theme_cache.item_start_padding = get_theme_constant(SNAME("item_start_padding"));
+ theme_cache.item_end_padding = get_theme_constant(SNAME("item_end_padding"));
+
+ theme_cache.checked = get_theme_icon(SNAME("checked"));
+ theme_cache.checked_disabled = get_theme_icon(SNAME("checked_disabled"));
+ theme_cache.unchecked = get_theme_icon(SNAME("unchecked"));
+ theme_cache.unchecked_disabled = get_theme_icon(SNAME("unchecked_disabled"));
+ theme_cache.radio_checked = get_theme_icon(SNAME("radio_checked"));
+ theme_cache.radio_checked_disabled = get_theme_icon(SNAME("radio_checked_disabled"));
+ theme_cache.radio_unchecked = get_theme_icon(SNAME("radio_unchecked"));
+ theme_cache.radio_unchecked_disabled = get_theme_icon(SNAME("radio_unchecked_disabled"));
+
+ theme_cache.submenu = get_theme_icon(SNAME("submenu"));
+ theme_cache.submenu_mirrored = get_theme_icon(SNAME("submenu_mirrored"));
+
+ theme_cache.font = get_theme_font(SNAME("font"));
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
+ theme_cache.font_separator = get_theme_font(SNAME("font_separator"));
+ theme_cache.font_separator_size = get_theme_font_size(SNAME("font_separator_size"));
+
+ theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_hover_color = get_theme_color(SNAME("font_hover_color"));
+ theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
+ theme_cache.font_accelerator_color = get_theme_color(SNAME("font_accelerator_color"));
+ theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+
+ theme_cache.font_separator_color = get_theme_color(SNAME("font_separator_color"));
+ theme_cache.font_separator_outline_size = get_theme_constant(SNAME("separator_outline_size"));
+ theme_cache.font_separator_outline_color = get_theme_color(SNAME("font_separator_outline_color"));
+}
+
void PopupMenu::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
@@ -836,7 +853,7 @@ void PopupMenu::_notification(int p_what) {
child_controls_changed();
_menu_changed();
- control->update();
+ control->queue_redraw();
} break;
case NOTIFICATION_WM_MOUSE_ENTER: {
@@ -846,7 +863,7 @@ void PopupMenu::_notification(int p_what) {
case NOTIFICATION_WM_MOUSE_EXIT: {
if (mouse_over >= 0 && (items[mouse_over].submenu.is_empty() || submenu_over != -1)) {
mouse_over = -1;
- control->update();
+ control->queue_redraw();
}
} break;
@@ -874,7 +891,7 @@ void PopupMenu::_notification(int p_what) {
if (!is_visible()) {
if (mouse_over >= 0) {
mouse_over = -1;
- control->update();
+ control->queue_redraw();
}
for (int i = 0; i < items.size(); i++) {
@@ -902,11 +919,10 @@ void PopupMenu::_notification(int p_what) {
}
// Set margin on the margin container
- Ref<StyleBox> panel_style = get_theme_stylebox(SNAME("panel"));
- margin_container->add_theme_constant_override("margin_left", panel_style->get_margin(Side::SIDE_LEFT));
- margin_container->add_theme_constant_override("margin_top", panel_style->get_margin(Side::SIDE_TOP));
- margin_container->add_theme_constant_override("margin_right", panel_style->get_margin(Side::SIDE_RIGHT));
- margin_container->add_theme_constant_override("margin_bottom", panel_style->get_margin(Side::SIDE_BOTTOM));
+ margin_container->add_theme_constant_override("margin_left", theme_cache.panel_style->get_margin(Side::SIDE_LEFT));
+ margin_container->add_theme_constant_override("margin_top", theme_cache.panel_style->get_margin(Side::SIDE_TOP));
+ margin_container->add_theme_constant_override("margin_right", theme_cache.panel_style->get_margin(Side::SIDE_RIGHT));
+ margin_container->add_theme_constant_override("margin_bottom", theme_cache.panel_style->get_margin(Side::SIDE_BOTTOM));
}
} break;
}
@@ -927,7 +943,7 @@ void PopupMenu::add_item(const String &p_label, int p_id, Key p_accel) {
ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel);
items.push_back(item);
_shape_item(items.size() - 1);
- control->update();
+ control->queue_redraw();
child_controls_changed();
notify_property_list_changed();
_menu_changed();
@@ -939,7 +955,7 @@ void PopupMenu::add_icon_item(const Ref<Texture2D> &p_icon, const String &p_labe
item.icon = p_icon;
items.push_back(item);
_shape_item(items.size() - 1);
- control->update();
+ control->queue_redraw();
child_controls_changed();
notify_property_list_changed();
_menu_changed();
@@ -951,7 +967,7 @@ void PopupMenu::add_check_item(const String &p_label, int p_id, Key p_accel) {
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
items.push_back(item);
_shape_item(items.size() - 1);
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -963,7 +979,7 @@ void PopupMenu::add_icon_check_item(const Ref<Texture2D> &p_icon, const String &
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
items.push_back(item);
_shape_item(items.size() - 1);
- control->update();
+ control->queue_redraw();
child_controls_changed();
}
@@ -973,7 +989,7 @@ void PopupMenu::add_radio_check_item(const String &p_label, int p_id, Key p_acce
item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
items.push_back(item);
_shape_item(items.size() - 1);
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -985,7 +1001,7 @@ void PopupMenu::add_icon_radio_check_item(const Ref<Texture2D> &p_icon, const St
item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
items.push_back(item);
_shape_item(items.size() - 1);
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -997,7 +1013,7 @@ void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int
item.state = p_default_state;
items.push_back(item);
_shape_item(items.size() - 1);
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -1016,7 +1032,7 @@ void PopupMenu::add_shortcut(const Ref<Shortcut> &p_shortcut, int p_id, bool p_g
ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
items.push_back(item);
_shape_item(items.size() - 1);
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -1027,7 +1043,7 @@ void PopupMenu::add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<Shortc
item.icon = p_icon;
items.push_back(item);
_shape_item(items.size() - 1);
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -1038,7 +1054,7 @@ void PopupMenu::add_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_id, bo
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
items.push_back(item);
_shape_item(items.size() - 1);
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -1050,7 +1066,7 @@ void PopupMenu::add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
items.push_back(item);
_shape_item(items.size() - 1);
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -1061,7 +1077,7 @@ void PopupMenu::add_radio_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_
item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
items.push_back(item);
_shape_item(items.size() - 1);
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -1073,7 +1089,7 @@ void PopupMenu::add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, cons
item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
items.push_back(item);
_shape_item(items.size() - 1);
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -1086,7 +1102,7 @@ void PopupMenu::add_submenu_item(const String &p_label, const String &p_submenu,
item.submenu = p_submenu;
items.push_back(item);
_shape_item(items.size() - 1);
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -1109,7 +1125,7 @@ void PopupMenu::set_item_text(int p_idx, const String &p_text) {
items.write[p_idx].dirty = true;
_shape_item(p_idx);
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -1123,7 +1139,7 @@ void PopupMenu::set_item_text_direction(int p_item, Control::TextDirection p_tex
if (items[p_item].text_direction != p_text_direction) {
items.write[p_item].text_direction = p_text_direction;
items.write[p_item].dirty = true;
- control->update();
+ control->queue_redraw();
}
}
@@ -1135,7 +1151,7 @@ void PopupMenu::set_item_language(int p_item, const String &p_language) {
if (items[p_item].language != p_language) {
items.write[p_item].language = p_language;
items.write[p_item].dirty = true;
- control->update();
+ control->queue_redraw();
}
}
@@ -1151,7 +1167,7 @@ void PopupMenu::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) {
items.write[p_idx].icon = p_icon;
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -1168,7 +1184,7 @@ void PopupMenu::set_item_checked(int p_idx, bool p_checked) {
items.write[p_idx].checked = p_checked;
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -1185,7 +1201,7 @@ void PopupMenu::set_item_id(int p_idx, int p_id) {
items.write[p_idx].id = p_id;
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -1203,7 +1219,7 @@ void PopupMenu::set_item_accelerator(int p_idx, Key p_accel) {
items.write[p_idx].accel = p_accel;
items.write[p_idx].dirty = true;
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -1219,7 +1235,7 @@ void PopupMenu::set_item_metadata(int p_idx, const Variant &p_meta) {
}
items.write[p_idx].metadata = p_meta;
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -1235,7 +1251,7 @@ void PopupMenu::set_item_disabled(int p_idx, bool p_disabled) {
}
items.write[p_idx].disabled = p_disabled;
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -1251,7 +1267,7 @@ void PopupMenu::set_item_submenu(int p_idx, const String &p_submenu) {
}
items.write[p_idx].submenu = p_submenu;
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -1259,7 +1275,7 @@ void PopupMenu::set_item_submenu(int p_idx, const String &p_submenu) {
void PopupMenu::toggle_item_checked(int p_idx) {
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].checked = !items[p_idx].checked;
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -1370,7 +1386,7 @@ void PopupMenu::set_item_as_separator(int p_idx, bool p_separator) {
}
items.write[p_idx].separator = p_separator;
- control->update();
+ control->queue_redraw();
}
bool PopupMenu::is_item_separator(int p_idx) const {
@@ -1390,7 +1406,7 @@ void PopupMenu::set_item_as_checkable(int p_idx, bool p_checkable) {
}
items.write[p_idx].checkable_type = p_checkable ? Item::CHECKABLE_TYPE_CHECK_BOX : Item::CHECKABLE_TYPE_NONE;
- control->update();
+ control->queue_redraw();
_menu_changed();
}
@@ -1406,7 +1422,7 @@ void PopupMenu::set_item_as_radio_checkable(int p_idx, bool p_radio_checkable) {
}
items.write[p_idx].checkable_type = p_radio_checkable ? Item::CHECKABLE_TYPE_RADIO_BUTTON : Item::CHECKABLE_TYPE_NONE;
- control->update();
+ control->queue_redraw();
_menu_changed();
}
@@ -1421,7 +1437,7 @@ void PopupMenu::set_item_tooltip(int p_idx, const String &p_tooltip) {
}
items.write[p_idx].tooltip = p_tooltip;
- control->update();
+ control->queue_redraw();
_menu_changed();
}
@@ -1446,7 +1462,7 @@ void PopupMenu::set_item_shortcut(int p_idx, const Ref<Shortcut> &p_shortcut, bo
_ref_shortcut(items[p_idx].shortcut);
}
- control->update();
+ control->queue_redraw();
_menu_changed();
}
@@ -1461,7 +1477,7 @@ void PopupMenu::set_item_indent(int p_idx, int p_indent) {
}
items.write[p_idx].indent = p_indent;
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -1477,7 +1493,7 @@ void PopupMenu::set_item_multistate(int p_idx, int p_state) {
}
items.write[p_idx].state = p_state;
- control->update();
+ control->queue_redraw();
_menu_changed();
}
@@ -1492,7 +1508,7 @@ void PopupMenu::set_item_shortcut_disabled(int p_idx, bool p_disabled) {
}
items.write[p_idx].shortcut_is_disabled = p_disabled;
- control->update();
+ control->queue_redraw();
_menu_changed();
}
@@ -1507,7 +1523,7 @@ void PopupMenu::toggle_item_multistate(int p_idx) {
items.write[p_idx].state = 0;
}
- control->update();
+ control->queue_redraw();
_menu_changed();
}
@@ -1532,15 +1548,20 @@ bool PopupMenu::is_item_shortcut_disabled(int p_idx) const {
}
void PopupMenu::set_current_index(int p_idx) {
- ERR_FAIL_INDEX(p_idx, items.size());
+ if (p_idx != -1) {
+ ERR_FAIL_INDEX(p_idx, items.size());
+ }
if (mouse_over == p_idx) {
return;
}
mouse_over = p_idx;
- scroll_to_item(mouse_over);
- control->update();
+ if (mouse_over != -1) {
+ scroll_to_item(mouse_over);
+ }
+
+ control->queue_redraw();
}
int PopupMenu::get_current_index() const {
@@ -1563,7 +1584,7 @@ void PopupMenu::set_item_count(int p_count) {
}
}
- control->update();
+ control->queue_redraw();
child_controls_changed();
notify_property_list_changed();
_menu_changed();
@@ -1706,7 +1727,7 @@ void PopupMenu::remove_item(int p_idx) {
}
items.remove_at(p_idx);
- control->update();
+ control->queue_redraw();
child_controls_changed();
_menu_changed();
}
@@ -1720,7 +1741,7 @@ void PopupMenu::add_separator(const String &p_text, int p_id) {
sep.xl_text = atr(p_text);
}
items.push_back(sep);
- control->update();
+ control->queue_redraw();
_menu_changed();
}
@@ -1732,7 +1753,7 @@ void PopupMenu::clear() {
}
items.clear();
mouse_over = -1;
- control->update();
+ control->queue_redraw();
child_controls_changed();
notify_property_list_changed();
_menu_changed();
@@ -1741,7 +1762,7 @@ void PopupMenu::clear() {
void PopupMenu::_ref_shortcut(Ref<Shortcut> p_sc) {
if (!shortcut_refcount.has(p_sc)) {
shortcut_refcount[p_sc] = 1;
- p_sc->connect("changed", callable_mp((CanvasItem *)this, &CanvasItem::update));
+ p_sc->connect("changed", callable_mp((CanvasItem *)this, &CanvasItem::queue_redraw));
} else {
shortcut_refcount[p_sc] += 1;
}
@@ -1751,7 +1772,7 @@ void PopupMenu::_unref_shortcut(Ref<Shortcut> p_sc) {
ERR_FAIL_COND(!shortcut_refcount.has(p_sc));
shortcut_refcount[p_sc]--;
if (shortcut_refcount[p_sc] == 0) {
- p_sc->disconnect("changed", callable_mp((CanvasItem *)this, &CanvasItem::update));
+ p_sc->disconnect("changed", callable_mp((CanvasItem *)this, &CanvasItem::queue_redraw));
shortcut_refcount.erase(p_sc);
}
}
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index d3ad0762e4..c8c598bd50 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -129,6 +129,49 @@ class PopupMenu : public Popup {
ScrollContainer *scroll_container = nullptr;
Control *control = nullptr;
+ struct ThemeCache {
+ Ref<StyleBox> panel_style;
+ Ref<StyleBox> hover_style;
+
+ Ref<StyleBox> separator_style;
+ Ref<StyleBox> labeled_separator_left;
+ Ref<StyleBox> labeled_separator_right;
+
+ int v_separation = 0;
+ int h_separation = 0;
+ int indent = 0;
+ int item_start_padding = 0;
+ int item_end_padding = 0;
+
+ Ref<Texture2D> checked;
+ Ref<Texture2D> checked_disabled;
+ Ref<Texture2D> unchecked;
+ Ref<Texture2D> unchecked_disabled;
+ Ref<Texture2D> radio_checked;
+ Ref<Texture2D> radio_checked_disabled;
+ Ref<Texture2D> radio_unchecked;
+ Ref<Texture2D> radio_unchecked_disabled;
+
+ Ref<Texture2D> submenu;
+ Ref<Texture2D> submenu_mirrored;
+
+ Ref<Font> font;
+ int font_size = 0;
+ Ref<Font> font_separator;
+ int font_separator_size = 0;
+
+ Color font_color;
+ Color font_hover_color;
+ Color font_disabled_color;
+ Color font_accelerator_color;
+ int font_outline_size = 0;
+ Color font_outline_color;
+
+ Color font_separator_color;
+ int font_separator_outline_size = 0;
+ Color font_separator_outline_color;
+ } theme_cache;
+
void _draw_items();
void _draw_background();
@@ -137,6 +180,8 @@ class PopupMenu : public Popup {
void _menu_changed();
protected:
+ virtual void _update_theme_item_cache() override;
+
virtual void add_child_notify(Node *p_child) override;
virtual void remove_child_notify(Node *p_child) override;
void _notification(int p_what);
diff --git a/scene/gui/progress_bar.cpp b/scene/gui/progress_bar.cpp
index 80859e8eb9..fe609dd834 100644
--- a/scene/gui/progress_bar.cpp
+++ b/scene/gui/progress_bar.cpp
@@ -33,18 +33,13 @@
#include "scene/resources/text_line.h"
Size2 ProgressBar::get_minimum_size() const {
- Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
- Ref<StyleBox> fg = get_theme_stylebox(SNAME("fg"));
- Ref<Font> font = get_theme_font(SNAME("font"));
- int font_size = get_theme_font_size(SNAME("font_size"));
-
- Size2 minimum_size = bg->get_minimum_size();
- minimum_size.height = MAX(minimum_size.height, fg->get_minimum_size().height);
- minimum_size.width = MAX(minimum_size.width, fg->get_minimum_size().width);
+ Size2 minimum_size = theme_cache.bg_style->get_minimum_size();
+ minimum_size.height = MAX(minimum_size.height, theme_cache.fg_style->get_minimum_size().height);
+ minimum_size.width = MAX(minimum_size.width, theme_cache.fg_style->get_minimum_size().width);
if (percent_visible) {
String txt = "100%";
- TextLine tl = TextLine(txt, font, font_size);
- minimum_size.height = MAX(minimum_size.height, bg->get_minimum_size().height + tl.get_size().y);
+ TextLine tl = TextLine(txt, theme_cache.font, theme_cache.font_size);
+ minimum_size.height = MAX(minimum_size.height, theme_cache.bg_style->get_minimum_size().height + tl.get_size().y);
} else { // this is needed, else the progressbar will collapse
minimum_size.width = MAX(minimum_size.width, 1);
minimum_size.height = MAX(minimum_size.height, 1);
@@ -52,23 +47,30 @@ Size2 ProgressBar::get_minimum_size() const {
return minimum_size;
}
+void ProgressBar::_update_theme_item_cache() {
+ Range::_update_theme_item_cache();
+
+ theme_cache.bg_style = get_theme_stylebox(SNAME("bg"));
+ theme_cache.fg_style = get_theme_stylebox(SNAME("fg"));
+
+ theme_cache.font = get_theme_font(SNAME("font"));
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
+ theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+}
+
void ProgressBar::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
- Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
- Ref<StyleBox> fg = get_theme_stylebox(SNAME("fg"));
- Ref<Font> font = get_theme_font(SNAME("font"));
- int font_size = get_theme_font_size(SNAME("font_size"));
- Color font_color = get_theme_color(SNAME("font_color"));
-
- draw_style_box(bg, Rect2(Point2(), get_size()));
+ draw_style_box(theme_cache.bg_style, Rect2(Point2(), get_size()));
float r = get_as_ratio();
switch (mode) {
case FILL_BEGIN_TO_END:
case FILL_END_TO_BEGIN: {
- int mp = fg->get_minimum_size().width;
+ int mp = theme_cache.fg_style->get_minimum_size().width;
int p = round(r * (get_size().width - mp));
// We want FILL_BEGIN_TO_END to map to right to left when UI layout is RTL,
// and left to right otherwise. And likewise for FILL_END_TO_BEGIN.
@@ -76,23 +78,23 @@ void ProgressBar::_notification(int p_what) {
if (p > 0) {
if (right_to_left) {
int p_remaining = round((1.0 - r) * (get_size().width - mp));
- draw_style_box(fg, Rect2(Point2(p_remaining, 0), Size2(p + fg->get_minimum_size().width, get_size().height)));
+ draw_style_box(theme_cache.fg_style, Rect2(Point2(p_remaining, 0), Size2(p + theme_cache.fg_style->get_minimum_size().width, get_size().height)));
} else {
- draw_style_box(fg, Rect2(Point2(0, 0), Size2(p + fg->get_minimum_size().width, get_size().height)));
+ draw_style_box(theme_cache.fg_style, Rect2(Point2(0, 0), Size2(p + theme_cache.fg_style->get_minimum_size().width, get_size().height)));
}
}
} break;
case FILL_TOP_TO_BOTTOM:
case FILL_BOTTOM_TO_TOP: {
- int mp = fg->get_minimum_size().height;
+ int mp = theme_cache.fg_style->get_minimum_size().height;
int p = round(r * (get_size().height - mp));
if (p > 0) {
if (mode == FILL_TOP_TO_BOTTOM) {
- draw_style_box(fg, Rect2(Point2(0, 0), Size2(get_size().width, p + fg->get_minimum_size().height)));
+ draw_style_box(theme_cache.fg_style, Rect2(Point2(0, 0), Size2(get_size().width, p + theme_cache.fg_style->get_minimum_size().height)));
} else {
int p_remaining = round((1.0 - r) * (get_size().height - mp));
- draw_style_box(fg, Rect2(Point2(0, p_remaining), Size2(get_size().width, p + fg->get_minimum_size().height)));
+ draw_style_box(theme_cache.fg_style, Rect2(Point2(0, p_remaining), Size2(get_size().width, p + theme_cache.fg_style->get_minimum_size().height)));
}
}
} break;
@@ -102,14 +104,14 @@ void ProgressBar::_notification(int p_what) {
if (percent_visible) {
String txt = TS->format_number(itos(int(get_as_ratio() * 100))) + TS->percent_sign();
- TextLine tl = TextLine(txt, font, font_size);
+ TextLine tl = TextLine(txt, theme_cache.font, theme_cache.font_size);
Vector2 text_pos = (Point2(get_size().width - tl.get_size().x, get_size().height - tl.get_size().y) / 2).round();
- Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
- if (outline_size > 0 && font_outline_color.a > 0) {
- tl.draw_outline(get_canvas_item(), text_pos, outline_size, font_outline_color);
+
+ if (theme_cache.font_outline_size > 0 && theme_cache.font_outline_color.a > 0) {
+ tl.draw_outline(get_canvas_item(), text_pos, theme_cache.font_outline_size, theme_cache.font_outline_color);
}
- tl.draw(get_canvas_item(), text_pos, font_color);
+
+ tl.draw(get_canvas_item(), text_pos, theme_cache.font_color);
}
} break;
}
@@ -118,7 +120,7 @@ void ProgressBar::_notification(int p_what) {
void ProgressBar::set_fill_mode(int p_fill) {
ERR_FAIL_INDEX(p_fill, FILL_MODE_MAX);
mode = (FillMode)p_fill;
- update();
+ queue_redraw();
}
int ProgressBar::get_fill_mode() {
@@ -131,7 +133,7 @@ void ProgressBar::set_percent_visible(bool p_visible) {
}
percent_visible = p_visible;
update_minimum_size();
- update();
+ queue_redraw();
}
bool ProgressBar::is_percent_visible() const {
diff --git a/scene/gui/progress_bar.h b/scene/gui/progress_bar.h
index 5ba21ad7d5..c79b901928 100644
--- a/scene/gui/progress_bar.h
+++ b/scene/gui/progress_bar.h
@@ -38,7 +38,20 @@ class ProgressBar : public Range {
bool percent_visible = true;
+ struct ThemeCache {
+ Ref<StyleBox> bg_style;
+ Ref<StyleBox> fg_style;
+
+ Ref<Font> font;
+ int font_size = 0;
+ Color font_color;
+ int font_outline_size = 0;
+ Color font_outline_color;
+ } theme_cache;
+
protected:
+ virtual void _update_theme_item_cache() override;
+
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp
index 0fb1f27802..1eb412abaf 100644
--- a/scene/gui/range.cpp
+++ b/scene/gui/range.cpp
@@ -46,7 +46,7 @@ void Range::_value_changed(double p_value) {
void Range::_value_changed_notify() {
_value_changed(shared->val);
emit_signal(SNAME("value_changed"), shared->val);
- update();
+ queue_redraw();
}
void Range::Shared::emit_value_changed() {
@@ -61,7 +61,7 @@ void Range::Shared::emit_value_changed() {
void Range::_changed_notify(const char *p_what) {
emit_signal(SNAME("changed"));
- update();
+ queue_redraw();
}
void Range::_validate_values() {
diff --git a/scene/gui/reference_rect.cpp b/scene/gui/reference_rect.cpp
index 05dfe4b118..fa5ac5b864 100644
--- a/scene/gui/reference_rect.cpp
+++ b/scene/gui/reference_rect.cpp
@@ -51,7 +51,7 @@ void ReferenceRect::set_border_color(const Color &p_color) {
}
border_color = p_color;
- update();
+ queue_redraw();
}
Color ReferenceRect::get_border_color() const {
@@ -65,7 +65,7 @@ void ReferenceRect::set_border_width(float p_width) {
}
border_width = width_max;
- update();
+ queue_redraw();
}
float ReferenceRect::get_border_width() const {
@@ -78,7 +78,7 @@ void ReferenceRect::set_editor_only(const bool &p_enabled) {
}
editor_only = p_enabled;
- update();
+ queue_redraw();
}
bool ReferenceRect::get_editor_only() const {
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 3f1f16cd51..c5fe218a15 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -453,6 +453,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
case TextServer::AUTOWRAP_OFF:
break;
}
+ autowrap_flags = autowrap_flags | TextServer::BREAK_TRIM_EDGE_SPACES;
// Clear cache.
l.text_buf->clear();
@@ -1621,7 +1622,7 @@ void RichTextLabel::_scroll_changed(double) {
scroll_updated = true;
- update();
+ queue_redraw();
}
void RichTextLabel::_update_fx(RichTextLabel::ItemFrame *p_frame, double p_delta_time) {
@@ -1685,20 +1686,20 @@ void RichTextLabel::_notification(int p_what) {
meta_hovering = nullptr;
emit_signal(SNAME("meta_hover_ended"), current_meta);
current_meta = false;
- update();
+ queue_redraw();
}
} break;
case NOTIFICATION_RESIZED: {
_stop_thread();
main->first_resized_line.store(0); //invalidate ALL
- update();
+ queue_redraw();
} break;
case NOTIFICATION_THEME_CHANGED: {
_stop_thread();
main->first_invalid_font_line.store(0); //invalidate ALL
- update();
+ queue_redraw();
} break;
case NOTIFICATION_ENTER_TREE: {
@@ -1708,7 +1709,7 @@ void RichTextLabel::_notification(int p_what) {
}
main->first_invalid_line.store(0); //invalidate ALL
- update();
+ queue_redraw();
} break;
case NOTIFICATION_PREDELETE:
@@ -1720,11 +1721,11 @@ void RichTextLabel::_notification(int p_what) {
case NOTIFICATION_TRANSLATION_CHANGED: {
_stop_thread();
main->first_invalid_line.store(0); //invalidate ALL
- update();
+ queue_redraw();
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
- update();
+ queue_redraw();
} break;
case NOTIFICATION_DRAW: {
@@ -1806,7 +1807,7 @@ void RichTextLabel::_notification(int p_what) {
}
double dt = get_process_delta_time();
_update_fx(main, dt);
- update();
+ queue_redraw();
}
} break;
@@ -1918,7 +1919,7 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text());
}
- update();
+ queue_redraw();
break;
}
}
@@ -2084,7 +2085,7 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
}
selection.active = true;
- update();
+ queue_redraw();
}
Variant meta;
@@ -2541,7 +2542,7 @@ void RichTextLabel::_thread_function(void *self) {
RichTextLabel *rtl = reinterpret_cast<RichTextLabel *>(self);
rtl->_process_line_caches();
rtl->updating.store(false);
- rtl->call_deferred(SNAME("update"));
+ rtl->call_deferred(SNAME("queue_redraw"));
}
void RichTextLabel::_stop_thread() {
@@ -2562,7 +2563,7 @@ void RichTextLabel::set_threaded(bool p_threaded) {
if (threaded != p_threaded) {
_stop_thread();
threaded = p_threaded;
- update();
+ queue_redraw();
}
}
@@ -2661,7 +2662,7 @@ bool RichTextLabel::_validate_line_caches() {
return false;
} else {
_process_line_caches();
- update();
+ queue_redraw();
return true;
}
}
@@ -2799,7 +2800,7 @@ void RichTextLabel::add_text(const String &p_text) {
pos = end + 1;
}
- update();
+ queue_redraw();
}
void RichTextLabel::_add_item(Item *p_item, bool p_enter, bool p_ensure_newline) {
@@ -2837,7 +2838,7 @@ void RichTextLabel::_add_item(Item *p_item, bool p_enter, bool p_ensure_newline)
if (fixed_width != -1) {
update_minimum_size();
}
- update();
+ queue_redraw();
}
void RichTextLabel::_remove_item(Item *p_item, const int p_line, const int p_subitem_line) {
@@ -2918,7 +2919,7 @@ void RichTextLabel::add_newline() {
_add_item(item, false);
current_frame->lines.resize(current_frame->lines.size() + 1);
_invalidate_current_line(current_frame);
- update();
+ queue_redraw();
}
bool RichTextLabel::remove_line(const int p_line) {
@@ -2957,7 +2958,7 @@ bool RichTextLabel::remove_line(const int p_line) {
}
main->first_invalid_line.store(0);
- update();
+ queue_redraw();
return true;
}
@@ -3386,7 +3387,7 @@ void RichTextLabel::set_tab_size(int p_spaces) {
tab_size = p_spaces;
main->first_resized_line.store(0);
- update();
+ queue_redraw();
}
int RichTextLabel::get_tab_size() const {
@@ -3410,7 +3411,7 @@ void RichTextLabel::set_meta_underline(bool p_underline) {
}
underline_meta = p_underline;
- update();
+ queue_redraw();
}
bool RichTextLabel::is_meta_underlined() const {
@@ -3419,7 +3420,7 @@ bool RichTextLabel::is_meta_underlined() const {
void RichTextLabel::set_hint_underline(bool p_underline) {
underline_hint = p_underline;
- update();
+ queue_redraw();
}
bool RichTextLabel::is_hint_underlined() const {
@@ -3445,7 +3446,7 @@ void RichTextLabel::set_scroll_active(bool p_active) {
scroll_active = p_active;
vscroll->set_drag_node_enabled(p_active);
- update();
+ queue_redraw();
}
bool RichTextLabel::is_scroll_active() const {
@@ -4570,7 +4571,7 @@ bool RichTextLabel::search(const String &p_string, bool p_from_selection, bool p
if (!(p_search_previous && char_idx < 0) &&
_search_line(selection.from_frame, selection.from_line, p_string, char_idx, p_search_previous)) {
scroll_to_line(selection.from_frame->line + selection.from_line);
- update();
+ queue_redraw();
return true;
}
char_idx = p_search_previous ? -1 : 0;
@@ -4595,7 +4596,7 @@ bool RichTextLabel::search(const String &p_string, bool p_from_selection, bool p
// Search for next element
if (_search_table(parent_table, parent_element, p_string, p_search_previous)) {
scroll_to_line(selection.from_frame->line + selection.from_line);
- update();
+ queue_redraw();
return true;
}
}
@@ -4619,7 +4620,7 @@ bool RichTextLabel::search(const String &p_string, bool p_from_selection, bool p
if (_search_line(main, current_line, p_string, char_idx, p_search_previous)) {
scroll_to_line(current_line);
- update();
+ queue_redraw();
return true;
}
p_search_previous ? current_line-- : current_line++;
@@ -4729,7 +4730,7 @@ String RichTextLabel::get_selected_text() const {
void RichTextLabel::deselect() {
selection.active = false;
- update();
+ queue_redraw();
}
void RichTextLabel::selection_copy() {
@@ -4784,7 +4785,7 @@ void RichTextLabel::select_all() {
selection.to_char = to_frame->lines[to_line].char_count;
selection.to_item = to_item;
selection.active = true;
- update();
+ queue_redraw();
}
bool RichTextLabel::is_selection_enabled() const {
@@ -4872,7 +4873,7 @@ void RichTextLabel::set_text_direction(Control::TextDirection p_text_direction)
text_direction = p_text_direction;
main->first_invalid_line.store(0); //invalidate ALL
_validate_line_caches();
- update();
+ queue_redraw();
}
}
@@ -4883,7 +4884,7 @@ void RichTextLabel::set_structured_text_bidi_override(TextServer::StructuredText
st_parser = p_parser;
main->first_invalid_line.store(0); //invalidate ALL
_validate_line_caches();
- update();
+ queue_redraw();
}
}
@@ -4898,7 +4899,7 @@ void RichTextLabel::set_structured_text_bidi_override_options(Array p_args) {
st_args = p_args;
main->first_invalid_line.store(0); //invalidate ALL
_validate_line_caches();
- update();
+ queue_redraw();
}
}
@@ -4917,7 +4918,7 @@ void RichTextLabel::set_language(const String &p_language) {
language = p_language;
main->first_invalid_line.store(0); //invalidate ALL
_validate_line_caches();
- update();
+ queue_redraw();
}
}
@@ -4932,7 +4933,7 @@ void RichTextLabel::set_autowrap_mode(TextServer::AutowrapMode p_mode) {
autowrap_mode = p_mode;
main->first_invalid_line = 0; //invalidate ALL
_validate_line_caches();
- update();
+ queue_redraw();
}
}
@@ -4959,7 +4960,7 @@ void RichTextLabel::set_visible_ratio(float p_ratio) {
main->first_invalid_line.store(0); // Invalidate ALL.
_validate_line_caches();
}
- update();
+ queue_redraw();
}
}
@@ -5172,31 +5173,36 @@ void RichTextLabel::_bind_methods() {
// Note: set "bbcode_enabled" first, to avoid unnecessary "text" resets.
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bbcode_enabled"), "set_use_bbcode", "is_using_bbcode");
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "threaded"), "set_threaded", "is_threaded");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "progress_bar_delay", PROPERTY_HINT_NONE, "suffix:ms"), "set_progress_bar_delay", "get_progress_bar_delay");
-
- ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_size", PROPERTY_HINT_RANGE, "0,24,1"), "set_tab_size", "get_tab_size");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text");
+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fit_content_height"), "set_fit_content_height", "is_fit_content_height_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_active"), "set_scroll_active", "is_scroll_active");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_following"), "set_scroll_follow", "is_scroll_following");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selection_enabled"), "set_selection_enabled", "is_selection_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_selected_font_color"), "set_override_selected_font_color", "is_overriding_selected_font_color");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deselect_on_focus_loss_enabled"), "set_deselect_on_focus_loss_enabled", "is_deselect_on_focus_loss_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_size", PROPERTY_HINT_RANGE, "0,24,1"), "set_tab_size", "get_tab_size");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled");
+
+ ADD_GROUP("Markup", "");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "custom_effects", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "RichTextEffect"), (PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE)), "set_effects", "get_effects");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "meta_underlined"), "set_meta_underline", "is_meta_underlined");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hint_underlined"), "set_hint_underline", "is_hint_underlined");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode");
+ ADD_GROUP("Threading", "");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "threaded"), "set_threaded", "is_threaded");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "progress_bar_delay", PROPERTY_HINT_NONE, "suffix:ms"), "set_progress_bar_delay", "get_progress_bar_delay");
+
+ ADD_GROUP("Text Selection", "");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selection_enabled"), "set_selection_enabled", "is_selection_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_selected_font_color"), "set_override_selected_font_color", "is_overriding_selected_font_color");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deselect_on_focus_loss_enabled"), "set_deselect_on_focus_loss_enabled", "is_deselect_on_focus_loss_enabled");
+
+ ADD_GROUP("Displayed Text", "");
// Note: "visible_characters" and "visible_ratio" should be set after "text" to be correctly applied.
ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1"), "set_visible_characters", "get_visible_characters");
ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters_behavior", PROPERTY_HINT_ENUM, "Characters Before Shaping,Characters After Shaping,Glyphs (Layout Direction),Glyphs (Left-to-Right),Glyphs (Right-to-Left)"), "set_visible_characters_behavior", "get_visible_characters_behavior");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visible_ratio", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_visible_ratio", "get_visible_ratio");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled");
-
ADD_GROUP("BiDi", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
@@ -5254,7 +5260,7 @@ void RichTextLabel::set_visible_characters_behavior(TextServer::VisibleCharacter
visible_chars_behavior = p_behavior;
main->first_invalid_line.store(0); //invalidate ALL
_validate_line_caches();
- update();
+ queue_redraw();
}
}
@@ -5275,7 +5281,7 @@ void RichTextLabel::set_visible_characters(int p_visible) {
main->first_invalid_line.store(0); //invalidate ALL
_validate_line_caches();
}
- update();
+ queue_redraw();
}
}
diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp
index 48c57d9b1b..374ce6feea 100644
--- a/scene/gui/scroll_bar.cpp
+++ b/scene/gui/scroll_bar.cpp
@@ -70,8 +70,8 @@ void ScrollBar::gui_input(const Ref<InputEvent> &p_event) {
if (b->is_pressed()) {
double ofs = orientation == VERTICAL ? b->get_position().y : b->get_position().x;
- Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
- Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
+ Ref<Texture2D> decr = theme_cache.decrement_icon;
+ Ref<Texture2D> incr = theme_cache.increment_icon;
double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width();
double incr_size = orientation == VERTICAL ? incr->get_height() : incr->get_width();
@@ -82,14 +82,14 @@ void ScrollBar::gui_input(const Ref<InputEvent> &p_event) {
if (ofs < decr_size) {
decr_active = true;
set_value(get_value() - (custom_step >= 0 ? custom_step : get_step()));
- update();
+ queue_redraw();
return;
}
if (ofs > total - incr_size) {
incr_active = true;
set_value(get_value() + (custom_step >= 0 ? custom_step : get_step()));
- update();
+ queue_redraw();
return;
}
@@ -117,7 +117,7 @@ void ScrollBar::gui_input(const Ref<InputEvent> &p_event) {
drag.active = true;
drag.pos_at_click = grabber_ofs + ofs;
drag.value_at_click = get_as_ratio();
- update();
+ queue_redraw();
} else {
if (scrolling) {
target_scroll = CLAMP(target_scroll + get_page(), get_min(), get_max() - get_page());
@@ -137,7 +137,7 @@ void ScrollBar::gui_input(const Ref<InputEvent> &p_event) {
incr_active = false;
decr_active = false;
drag.active = false;
- update();
+ queue_redraw();
}
}
@@ -146,7 +146,7 @@ void ScrollBar::gui_input(const Ref<InputEvent> &p_event) {
if (drag.active) {
double ofs = orientation == VERTICAL ? m->get_position().y : m->get_position().x;
- Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
+ Ref<Texture2D> decr = theme_cache.decrement_icon;
double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width();
ofs -= decr_size;
@@ -156,8 +156,8 @@ void ScrollBar::gui_input(const Ref<InputEvent> &p_event) {
set_as_ratio(drag.value_at_click + diff);
} else {
double ofs = orientation == VERTICAL ? m->get_position().y : m->get_position().x;
- Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
- Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
+ Ref<Texture2D> decr = theme_cache.decrement_icon;
+ Ref<Texture2D> incr = theme_cache.increment_icon;
double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width();
double incr_size = orientation == VERTICAL ? incr->get_height() : incr->get_width();
@@ -177,7 +177,7 @@ void ScrollBar::gui_input(const Ref<InputEvent> &p_event) {
if (new_hilite != highlight) {
highlight = new_hilite;
- update();
+ queue_redraw();
}
}
}
@@ -217,6 +217,24 @@ void ScrollBar::gui_input(const Ref<InputEvent> &p_event) {
}
}
+void ScrollBar::_update_theme_item_cache() {
+ Range::_update_theme_item_cache();
+
+ theme_cache.scroll_style = get_theme_stylebox(SNAME("scroll"));
+ theme_cache.scroll_focus_style = get_theme_stylebox(SNAME("scroll_focus"));
+ theme_cache.scroll_offset_style = get_theme_stylebox(SNAME("hscroll"));
+ theme_cache.grabber_style = get_theme_stylebox(SNAME("grabber"));
+ theme_cache.grabber_hl_style = get_theme_stylebox(SNAME("grabber_highlight"));
+ theme_cache.grabber_pressed_style = get_theme_stylebox(SNAME("grabber_pressed"));
+
+ theme_cache.increment_icon = get_theme_icon(SNAME("increment"));
+ theme_cache.increment_hl_icon = get_theme_icon(SNAME("increment_highlight"));
+ theme_cache.increment_pressed_icon = get_theme_icon(SNAME("increment_pressed"));
+ theme_cache.decrement_icon = get_theme_icon(SNAME("decrement"));
+ theme_cache.decrement_hl_icon = get_theme_icon(SNAME("decrement_highlight"));
+ theme_cache.decrement_pressed_icon = get_theme_icon(SNAME("decrement_pressed"));
+}
+
void ScrollBar::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
@@ -225,30 +243,30 @@ void ScrollBar::_notification(int p_what) {
Ref<Texture2D> decr, incr;
if (decr_active) {
- decr = get_theme_icon(SNAME("decrement_pressed"));
+ decr = theme_cache.decrement_pressed_icon;
} else if (highlight == HIGHLIGHT_DECR) {
- decr = get_theme_icon(SNAME("decrement_highlight"));
+ decr = theme_cache.decrement_hl_icon;
} else {
- decr = get_theme_icon(SNAME("decrement"));
+ decr = theme_cache.decrement_icon;
}
if (incr_active) {
- incr = get_theme_icon(SNAME("increment_pressed"));
+ incr = theme_cache.increment_pressed_icon;
} else if (highlight == HIGHLIGHT_INCR) {
- incr = get_theme_icon(SNAME("increment_highlight"));
+ incr = theme_cache.increment_hl_icon;
} else {
- incr = get_theme_icon(SNAME("increment"));
+ incr = theme_cache.increment_icon;
}
- Ref<StyleBox> bg = has_focus() ? get_theme_stylebox(SNAME("scroll_focus")) : get_theme_stylebox(SNAME("scroll"));
+ Ref<StyleBox> bg = has_focus() ? theme_cache.scroll_focus_style : theme_cache.scroll_style;
Ref<StyleBox> grabber;
if (drag.active) {
- grabber = get_theme_stylebox(SNAME("grabber_pressed"));
+ grabber = theme_cache.grabber_pressed_style;
} else if (highlight == HIGHLIGHT_RANGE) {
- grabber = get_theme_stylebox(SNAME("grabber_highlight"));
+ grabber = theme_cache.grabber_hl_style;
} else {
- grabber = get_theme_stylebox(SNAME("grabber"));
+ grabber = theme_cache.grabber_style;
}
Point2 ofs;
@@ -408,13 +426,13 @@ void ScrollBar::_notification(int p_what) {
case NOTIFICATION_MOUSE_EXIT: {
highlight = HIGHLIGHT_NONE;
- update();
+ queue_redraw();
} break;
}
}
double ScrollBar::get_grabber_min_size() const {
- Ref<StyleBox> grabber = get_theme_stylebox(SNAME("grabber"));
+ Ref<StyleBox> grabber = theme_cache.grabber_style;
Size2 gminsize = grabber->get_minimum_size() + grabber->get_center_size();
return (orientation == VERTICAL) ? gminsize.height : gminsize.width;
}
@@ -435,17 +453,17 @@ double ScrollBar::get_area_size() const {
switch (orientation) {
case VERTICAL: {
double area = get_size().height;
- area -= get_theme_stylebox(SNAME("scroll"))->get_minimum_size().height;
- area -= get_theme_icon(SNAME("increment"))->get_height();
- area -= get_theme_icon(SNAME("decrement"))->get_height();
+ area -= theme_cache.scroll_style->get_minimum_size().height;
+ area -= theme_cache.increment_icon->get_height();
+ area -= theme_cache.decrement_icon->get_height();
area -= get_grabber_min_size();
return area;
} break;
case HORIZONTAL: {
double area = get_size().width;
- area -= get_theme_stylebox(SNAME("scroll"))->get_minimum_size().width;
- area -= get_theme_icon(SNAME("increment"))->get_width();
- area -= get_theme_icon(SNAME("decrement"))->get_width();
+ area -= theme_cache.scroll_style->get_minimum_size().width;
+ area -= theme_cache.increment_icon->get_width();
+ area -= theme_cache.decrement_icon->get_width();
area -= get_grabber_min_size();
return area;
} break;
@@ -459,13 +477,13 @@ double ScrollBar::get_area_offset() const {
double ofs = 0.0;
if (orientation == VERTICAL) {
- ofs += get_theme_stylebox(SNAME("hscroll"))->get_margin(SIDE_TOP);
- ofs += get_theme_icon(SNAME("decrement"))->get_height();
+ ofs += theme_cache.scroll_offset_style->get_margin(SIDE_TOP);
+ ofs += theme_cache.decrement_icon->get_height();
}
if (orientation == HORIZONTAL) {
- ofs += get_theme_stylebox(SNAME("hscroll"))->get_margin(SIDE_LEFT);
- ofs += get_theme_icon(SNAME("decrement"))->get_width();
+ ofs += theme_cache.scroll_offset_style->get_margin(SIDE_LEFT);
+ ofs += theme_cache.decrement_icon->get_width();
}
return ofs;
@@ -476,9 +494,9 @@ double ScrollBar::get_grabber_offset() const {
}
Size2 ScrollBar::get_minimum_size() const {
- Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
- Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
- Ref<StyleBox> bg = get_theme_stylebox(SNAME("scroll"));
+ Ref<Texture2D> incr = theme_cache.increment_icon;
+ Ref<Texture2D> decr = theme_cache.decrement_icon;
+ Ref<StyleBox> bg = theme_cache.scroll_style;
Size2 minsize;
if (orientation == VERTICAL) {
diff --git a/scene/gui/scroll_bar.h b/scene/gui/scroll_bar.h
index 1823f86a67..13ca62d7ff 100644
--- a/scene/gui/scroll_bar.h
+++ b/scene/gui/scroll_bar.h
@@ -86,14 +86,31 @@ class ScrollBar : public Range {
double target_scroll = 0.0;
bool smooth_scroll_enabled = false;
+ struct ThemeCache {
+ Ref<StyleBox> scroll_style;
+ Ref<StyleBox> scroll_focus_style;
+ Ref<StyleBox> scroll_offset_style;
+ Ref<StyleBox> grabber_style;
+ Ref<StyleBox> grabber_hl_style;
+ Ref<StyleBox> grabber_pressed_style;
+
+ Ref<Texture2D> increment_icon;
+ Ref<Texture2D> increment_hl_icon;
+ Ref<Texture2D> increment_pressed_icon;
+ Ref<Texture2D> decrement_icon;
+ Ref<Texture2D> decrement_hl_icon;
+ Ref<Texture2D> decrement_pressed_icon;
+ } theme_cache;
+
void _drag_node_exit();
void _drag_node_input(const Ref<InputEvent> &p_input);
virtual void gui_input(const Ref<InputEvent> &p_event) override;
protected:
- void _notification(int p_what);
+ virtual void _update_theme_item_cache() override;
+ void _notification(int p_what);
static void _bind_methods();
public:
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index 8fd547813d..f68cebd657 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -35,7 +35,6 @@
#include "scene/main/window.h"
Size2 ScrollContainer::get_minimum_size() const {
- Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg"));
Size2 min_size;
// Calculated in this function, as it needs to traverse all child controls once to calculate;
@@ -77,10 +76,16 @@ Size2 ScrollContainer::get_minimum_size() const {
min_size.x += v_scroll->get_minimum_size().x;
}
- min_size += sb->get_minimum_size();
+ min_size += theme_cache.bg_style->get_minimum_size();
return min_size;
}
+void ScrollContainer::_update_theme_item_cache() {
+ Container::_update_theme_item_cache();
+
+ theme_cache.bg_style = get_theme_stylebox(SNAME("bg"));
+}
+
void ScrollContainer::_cancel_drag() {
set_physics_process_internal(false);
drag_touching_deaccel = false;
@@ -271,9 +276,8 @@ void ScrollContainer::_reposition_children() {
Size2 size = get_size();
Point2 ofs;
- Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg"));
- size -= sb->get_minimum_size();
- ofs += sb->get_offset();
+ size -= theme_cache.bg_style->get_minimum_size();
+ ofs += theme_cache.bg_style->get_offset();
bool rtl = is_layout_rtl();
if (h_scroll->is_visible_in_tree() && h_scroll->get_parent() == this) { //scrolls may have been moved out for reasons
@@ -312,7 +316,7 @@ void ScrollContainer::_reposition_children() {
fit_child_in_rect(c, r);
}
- update();
+ queue_redraw();
}
void ScrollContainer::_notification(int p_what) {
@@ -337,8 +341,7 @@ void ScrollContainer::_notification(int p_what) {
} break;
case NOTIFICATION_DRAW: {
- Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg"));
- draw_style_box(sb, Rect2(Vector2(), get_size()));
+ draw_style_box(theme_cache.bg_style, Rect2(Vector2(), get_size()));
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
@@ -413,8 +416,7 @@ void ScrollContainer::_notification(int p_what) {
void ScrollContainer::update_scrollbars() {
Size2 size = get_size();
- Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg"));
- size -= sb->get_minimum_size();
+ size -= theme_cache.bg_style->get_minimum_size();
Size2 hmin = h_scroll->get_combined_minimum_size();
Size2 vmin = v_scroll->get_combined_minimum_size();
diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h
index bfa74cfd0f..fa1f09ab3f 100644
--- a/scene/gui/scroll_container.h
+++ b/scene/gui/scroll_container.h
@@ -69,9 +69,14 @@ private:
int deadzone = 0;
bool follow_focus = false;
+ struct ThemeCache {
+ Ref<StyleBox> bg_style;
+ } theme_cache;
+
void _cancel_drag();
protected:
+ virtual void _update_theme_item_cache() override;
Size2 get_minimum_size() const override;
void _gui_focus_changed(Control *p_control);
diff --git a/scene/gui/separator.cpp b/scene/gui/separator.cpp
index e3400d9c8f..8177c1e469 100644
--- a/scene/gui/separator.cpp
+++ b/scene/gui/separator.cpp
@@ -33,24 +33,30 @@
Size2 Separator::get_minimum_size() const {
Size2 ms(3, 3);
if (orientation == VERTICAL) {
- ms.x = get_theme_constant(SNAME("separation"));
+ ms.x = theme_cache.separation;
} else { // HORIZONTAL
- ms.y = get_theme_constant(SNAME("separation"));
+ ms.y = theme_cache.separation;
}
return ms;
}
+void Separator::_update_theme_item_cache() {
+ Control::_update_theme_item_cache();
+
+ theme_cache.separation = get_theme_constant(SNAME("separation"));
+ theme_cache.separator_style = get_theme_stylebox(SNAME("separator"));
+}
+
void Separator::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
Size2i size = get_size();
- Ref<StyleBox> style = get_theme_stylebox(SNAME("separator"));
- Size2i ssize = style->get_minimum_size() + style->get_center_size();
+ Size2i ssize = theme_cache.separator_style->get_minimum_size() + theme_cache.separator_style->get_center_size();
if (orientation == VERTICAL) {
- style->draw(get_canvas_item(), Rect2((size.x - ssize.x) / 2, 0, ssize.x, size.y));
+ theme_cache.separator_style->draw(get_canvas_item(), Rect2((size.x - ssize.x) / 2, 0, ssize.x, size.y));
} else {
- style->draw(get_canvas_item(), Rect2(0, (size.y - ssize.y) / 2, size.x, ssize.y));
+ theme_cache.separator_style->draw(get_canvas_item(), Rect2(0, (size.y - ssize.y) / 2, size.x, ssize.y));
}
} break;
}
diff --git a/scene/gui/separator.h b/scene/gui/separator.h
index e6578a4d04..44e18a3f00 100644
--- a/scene/gui/separator.h
+++ b/scene/gui/separator.h
@@ -35,8 +35,16 @@
class Separator : public Control {
GDCLASS(Separator, Control);
+ struct ThemeCache {
+ int separation = 0;
+ Ref<StyleBox> separator_style;
+ } theme_cache;
+
protected:
Orientation orientation = Orientation::HORIZONTAL;
+
+ virtual void _update_theme_item_cache() override;
+
void _notification(int p_what);
public:
diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp
index 2695ad1f14..ff3adfb9ac 100644
--- a/scene/gui/slider.cpp
+++ b/scene/gui/slider.cpp
@@ -33,11 +33,8 @@
#include "core/os/keyboard.h"
Size2 Slider::get_minimum_size() const {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("slider"));
- Size2i ss = style->get_minimum_size() + style->get_center_size();
-
- Ref<Texture2D> grabber = get_theme_icon(SNAME("grabber"));
- Size2i rs = grabber->get_size();
+ Size2i ss = theme_cache.slider_style->get_minimum_size() + theme_cache.slider_style->get_center_size();
+ Size2i rs = theme_cache.grabber_icon->get_size();
if (orientation == HORIZONTAL) {
return Size2i(ss.width, MAX(ss.height, rs.height));
@@ -58,7 +55,13 @@ void Slider::gui_input(const Ref<InputEvent> &p_event) {
if (mb.is_valid()) {
if (mb->get_button_index() == MouseButton::LEFT) {
if (mb->is_pressed()) {
- Ref<Texture2D> grabber = get_theme_icon(mouse_inside || has_focus() ? "grabber_highlight" : "grabber");
+ Ref<Texture2D> grabber;
+ if (mouse_inside || has_focus()) {
+ grabber = theme_cache.grabber_hl_icon;
+ } else {
+ grabber = theme_cache.grabber_icon;
+ }
+
grab.pos = orientation == VERTICAL ? mb->get_position().y : mb->get_position().x;
double grab_width = (double)grabber->get_size().width;
@@ -95,7 +98,7 @@ void Slider::gui_input(const Ref<InputEvent> &p_event) {
if (mm.is_valid()) {
if (grab.active) {
Size2i size = get_size();
- Ref<Texture2D> grabber = get_theme_icon(SNAME("grabber"));
+ Ref<Texture2D> grabber = theme_cache.grabber_icon;
double motion = (orientation == VERTICAL ? mm->get_position().y : mm->get_position().x) - grab.pos;
if (orientation == VERTICAL) {
motion = -motion;
@@ -145,21 +148,34 @@ void Slider::gui_input(const Ref<InputEvent> &p_event) {
}
}
+void Slider::_update_theme_item_cache() {
+ Range::_update_theme_item_cache();
+
+ theme_cache.slider_style = get_theme_stylebox(SNAME("slider"));
+ theme_cache.grabber_area_style = get_theme_stylebox(SNAME("grabber_area"));
+ theme_cache.grabber_area_hl_style = get_theme_stylebox(SNAME("grabber_area_highlight"));
+
+ theme_cache.grabber_icon = get_theme_icon(SNAME("grabber"));
+ theme_cache.grabber_hl_icon = get_theme_icon(SNAME("grabber_highlight"));
+ theme_cache.grabber_disabled_icon = get_theme_icon(SNAME("grabber_disabled"));
+ theme_cache.tick_icon = get_theme_icon(SNAME("tick"));
+}
+
void Slider::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
update_minimum_size();
- update();
+ queue_redraw();
} break;
case NOTIFICATION_MOUSE_ENTER: {
mouse_inside = true;
- update();
+ queue_redraw();
} break;
case NOTIFICATION_MOUSE_EXIT: {
mouse_inside = false;
- update();
+ queue_redraw();
} break;
case NOTIFICATION_VISIBILITY_CHANGED:
@@ -171,13 +187,30 @@ void Slider::_notification(int p_what) {
case NOTIFICATION_DRAW: {
RID ci = get_canvas_item();
Size2i size = get_size();
- Ref<StyleBox> style = get_theme_stylebox(SNAME("slider"));
- bool highlighted = mouse_inside || has_focus();
- Ref<StyleBox> grabber_area = get_theme_stylebox(highlighted ? "grabber_area_highlight" : "grabber_area");
- Ref<Texture2D> grabber = get_theme_icon(editable ? (highlighted ? "grabber_highlight" : "grabber") : "grabber_disabled");
- Ref<Texture2D> tick = get_theme_icon(SNAME("tick"));
double ratio = Math::is_nan(get_as_ratio()) ? 0 : get_as_ratio();
+ Ref<StyleBox> style = theme_cache.slider_style;
+ Ref<Texture2D> tick = theme_cache.tick_icon;
+
+ bool highlighted = mouse_inside || has_focus();
+ Ref<Texture2D> grabber;
+ if (editable) {
+ if (highlighted) {
+ grabber = theme_cache.grabber_hl_icon;
+ } else {
+ grabber = theme_cache.grabber_icon;
+ }
+ } else {
+ grabber = theme_cache.grabber_disabled_icon;
+ }
+
+ Ref<StyleBox> grabber_area;
+ if (highlighted) {
+ grabber_area = theme_cache.grabber_area_hl_style;
+ } else {
+ grabber_area = theme_cache.grabber_area_style;
+ }
+
if (orientation == VERTICAL) {
int widget_width = style->get_minimum_size().width + style->get_center_size().width;
double areasize = size.height - grabber->get_size().height;
@@ -232,7 +265,7 @@ void Slider::set_ticks(int p_count) {
}
ticks = p_count;
- update();
+ queue_redraw();
}
int Slider::get_ticks() const {
@@ -249,7 +282,7 @@ void Slider::set_ticks_on_borders(bool _tob) {
}
ticks_on_borders = _tob;
- update();
+ queue_redraw();
}
void Slider::set_editable(bool p_editable) {
@@ -258,7 +291,7 @@ void Slider::set_editable(bool p_editable) {
}
editable = p_editable;
- update();
+ queue_redraw();
}
bool Slider::is_editable() const {
diff --git a/scene/gui/slider.h b/scene/gui/slider.h
index 5abaee27aa..51adb354fb 100644
--- a/scene/gui/slider.h
+++ b/scene/gui/slider.h
@@ -49,11 +49,24 @@ class Slider : public Range {
bool editable = true;
bool scrollable = true;
+ struct ThemeCache {
+ Ref<StyleBox> slider_style;
+ Ref<StyleBox> grabber_area_style;
+ Ref<StyleBox> grabber_area_hl_style;
+
+ Ref<Texture2D> grabber_icon;
+ Ref<Texture2D> grabber_hl_icon;
+ Ref<Texture2D> grabber_disabled_icon;
+ Ref<Texture2D> tick_icon;
+ } theme_cache;
+
protected:
+ bool ticks_on_borders = false;
+
virtual void gui_input(const Ref<InputEvent> &p_event) override;
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
static void _bind_methods();
- bool ticks_on_borders = false;
public:
virtual Size2 get_minimum_size() const override;
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index 65c4a09c84..fe14049d93 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -210,25 +210,29 @@ inline void SpinBox::_adjust_width_for_icon(const Ref<Texture2D> &icon) {
}
}
+void SpinBox::_update_theme_item_cache() {
+ Range::_update_theme_item_cache();
+
+ theme_cache.updown_icon = get_theme_icon(SNAME("updown"));
+}
+
void SpinBox::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
- Ref<Texture2D> updown = get_theme_icon(SNAME("updown"));
-
- _adjust_width_for_icon(updown);
+ _adjust_width_for_icon(theme_cache.updown_icon);
RID ci = get_canvas_item();
Size2i size = get_size();
if (is_layout_rtl()) {
- updown->draw(ci, Point2i(0, (size.height - updown->get_height()) / 2));
+ theme_cache.updown_icon->draw(ci, Point2i(0, (size.height - theme_cache.updown_icon->get_height()) / 2));
} else {
- updown->draw(ci, Point2i(size.width - updown->get_width(), (size.height - updown->get_height()) / 2));
+ theme_cache.updown_icon->draw(ci, Point2i(size.width - theme_cache.updown_icon->get_width(), (size.height - theme_cache.updown_icon->get_height()) / 2));
}
} break;
case NOTIFICATION_ENTER_TREE: {
- _adjust_width_for_icon(get_theme_icon(SNAME("updown")));
+ _adjust_width_for_icon(theme_cache.updown_icon);
_value_changed(0);
} break;
@@ -238,7 +242,7 @@ void SpinBox::_notification(int p_what) {
case NOTIFICATION_TRANSLATION_CHANGED: {
_value_changed(0);
- update();
+ queue_redraw();
} break;
case NOTIFICATION_THEME_CHANGED: {
@@ -247,7 +251,7 @@ void SpinBox::_notification(int p_what) {
} break;
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
- update();
+ queue_redraw();
} break;
}
}
diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h
index 3fcb85ac99..c2f2ac3f5a 100644
--- a/scene/gui/spin_box.h
+++ b/scene/gui/spin_box.h
@@ -69,9 +69,14 @@ class SpinBox : public Range {
inline void _adjust_width_for_icon(const Ref<Texture2D> &icon);
+ struct ThemeCache {
+ Ref<Texture2D> updown_icon;
+ } theme_cache;
+
protected:
virtual void gui_input(const Ref<InputEvent> &p_event) override;
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp
index 3e60db0846..e7e955a17f 100644
--- a/scene/gui/split_container.cpp
+++ b/scene/gui/split_container.cpp
@@ -76,9 +76,7 @@ void SplitContainer::_resort() {
bool second_expanded = (vertical ? second->get_v_size_flags() : second->get_h_size_flags()) & SIZE_EXPAND;
// Determine the separation between items
- Ref<Texture2D> g = get_theme_icon(SNAME("grabber"));
- int sep = get_theme_constant(SNAME("separation"));
- sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(sep, vertical ? g->get_height() : g->get_width()) : 0;
+ int sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(theme_cache.separation, vertical ? theme_cache.grabber_icon->get_height() : theme_cache.grabber_icon->get_width()) : 0;
// Compute the minimum size
Size2 ms_first = first->get_combined_minimum_size();
@@ -124,16 +122,14 @@ void SplitContainer::_resort() {
}
}
- update();
+ queue_redraw();
}
Size2 SplitContainer::get_minimum_size() const {
/* Calculate MINIMUM SIZE */
Size2i minimum;
- Ref<Texture2D> g = get_theme_icon(SNAME("grabber"));
- int sep = get_theme_constant(SNAME("separation"));
- sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(sep, vertical ? g->get_height() : g->get_width()) : 0;
+ int sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(theme_cache.separation, vertical ? theme_cache.grabber_icon->get_height() : theme_cache.grabber_icon->get_width()) : 0;
for (int i = 0; i < 2; i++) {
if (!_getch(i)) {
@@ -162,6 +158,14 @@ Size2 SplitContainer::get_minimum_size() const {
return minimum;
}
+void SplitContainer::_update_theme_item_cache() {
+ Container::_update_theme_item_cache();
+
+ theme_cache.separation = get_theme_constant(SNAME("separation"));
+ theme_cache.autohide = get_theme_constant(SNAME("autohide"));
+ theme_cache.grabber_icon = get_theme_icon(SNAME("grabber"));
+}
+
void SplitContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_TRANSLATION_CHANGED:
@@ -175,8 +179,8 @@ void SplitContainer::_notification(int p_what) {
case NOTIFICATION_MOUSE_EXIT: {
mouse_inside = false;
- if (get_theme_constant(SNAME("autohide"))) {
- update();
+ if (theme_cache.autohide) {
+ queue_redraw();
}
} break;
@@ -185,7 +189,7 @@ void SplitContainer::_notification(int p_what) {
return;
}
- if (collapsed || (!dragging && !mouse_inside && get_theme_constant(SNAME("autohide")))) {
+ if (collapsed || (!dragging && !mouse_inside && theme_cache.autohide)) {
return;
}
@@ -193,8 +197,8 @@ void SplitContainer::_notification(int p_what) {
return;
}
- int sep = dragger_visibility != DRAGGER_HIDDEN_COLLAPSED ? get_theme_constant(SNAME("separation")) : 0;
- Ref<Texture2D> tex = get_theme_icon(SNAME("grabber"));
+ int sep = dragger_visibility != DRAGGER_HIDDEN_COLLAPSED ? theme_cache.separation : 0;
+ Ref<Texture2D> tex = theme_cache.grabber_icon;
Size2 size = get_size();
if (vertical) {
@@ -222,16 +226,14 @@ void SplitContainer::gui_input(const Ref<InputEvent> &p_event) {
if (mb.is_valid()) {
if (mb->get_button_index() == MouseButton::LEFT) {
if (mb->is_pressed()) {
- int sep = get_theme_constant(SNAME("separation"));
-
if (vertical) {
- if (mb->get_position().y > middle_sep && mb->get_position().y < middle_sep + sep) {
+ if (mb->get_position().y > middle_sep && mb->get_position().y < middle_sep + theme_cache.separation) {
dragging = true;
drag_from = mb->get_position().y;
drag_ofs = split_offset;
}
} else {
- if (mb->get_position().x > middle_sep && mb->get_position().x < middle_sep + sep) {
+ if (mb->get_position().x > middle_sep && mb->get_position().x < middle_sep + theme_cache.separation) {
dragging = true;
drag_from = mb->get_position().x;
drag_ofs = split_offset;
@@ -248,15 +250,15 @@ void SplitContainer::gui_input(const Ref<InputEvent> &p_event) {
if (mm.is_valid()) {
bool mouse_inside_state = false;
if (vertical) {
- mouse_inside_state = mm->get_position().y > middle_sep && mm->get_position().y < middle_sep + get_theme_constant(SNAME("separation"));
+ mouse_inside_state = mm->get_position().y > middle_sep && mm->get_position().y < middle_sep + theme_cache.separation;
} else {
- mouse_inside_state = mm->get_position().x > middle_sep && mm->get_position().x < middle_sep + get_theme_constant(SNAME("separation"));
+ mouse_inside_state = mm->get_position().x > middle_sep && mm->get_position().x < middle_sep + theme_cache.separation;
}
if (mouse_inside != mouse_inside_state) {
mouse_inside = mouse_inside_state;
- if (get_theme_constant(SNAME("autohide"))) {
- update();
+ if (theme_cache.autohide) {
+ queue_redraw();
}
}
@@ -281,14 +283,12 @@ Control::CursorShape SplitContainer::get_cursor_shape(const Point2 &p_pos) const
}
if (!collapsed && _getch(0) && _getch(1) && dragger_visibility == DRAGGER_VISIBLE) {
- int sep = get_theme_constant(SNAME("separation"));
-
if (vertical) {
- if (p_pos.y > middle_sep && p_pos.y < middle_sep + sep) {
+ if (p_pos.y > middle_sep && p_pos.y < middle_sep + theme_cache.separation) {
return CURSOR_VSPLIT;
}
} else {
- if (p_pos.x > middle_sep && p_pos.x < middle_sep + sep) {
+ if (p_pos.x > middle_sep && p_pos.x < middle_sep + theme_cache.separation) {
return CURSOR_HSPLIT;
}
}
@@ -333,7 +333,7 @@ void SplitContainer::set_dragger_visibility(DraggerVisibility p_visibility) {
dragger_visibility = p_visibility;
queue_sort();
- update();
+ queue_redraw();
}
SplitContainer::DraggerVisibility SplitContainer::get_dragger_visibility() const {
diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h
index a69ffe4de9..18f9573973 100644
--- a/scene/gui/split_container.h
+++ b/scene/gui/split_container.h
@@ -55,12 +55,20 @@ private:
DraggerVisibility dragger_visibility = DRAGGER_VISIBLE;
bool mouse_inside = false;
+ struct ThemeCache {
+ int separation = 0;
+ int autohide = 0;
+ Ref<Texture2D> grabber_icon;
+ } theme_cache;
+
Control *_getch(int p_idx) const;
void _resort();
protected:
virtual void gui_input(const Ref<InputEvent> &p_event) override;
+ virtual void _update_theme_item_cache() override;
+
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/subviewport_container.cpp b/scene/gui/subviewport_container.cpp
index 869683e427..88e68ec763 100644
--- a/scene/gui/subviewport_container.cpp
+++ b/scene/gui/subviewport_container.cpp
@@ -60,7 +60,7 @@ void SubViewportContainer::set_stretch(bool p_enable) {
stretch = p_enable;
update_minimum_size();
queue_sort();
- update();
+ queue_redraw();
}
bool SubViewportContainer::is_stretch_enabled() const {
@@ -88,7 +88,7 @@ void SubViewportContainer::set_stretch_shrink(int p_shrink) {
c->set_size(get_size() / shrink);
}
- update();
+ queue_redraw();
}
int SubViewportContainer::get_stretch_shrink() const {
diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp
index e0739f909f..4d18af7743 100644
--- a/scene/gui/tab_bar.cpp
+++ b/scene/gui/tab_bar.cpp
@@ -44,14 +44,7 @@ Size2 TabBar::get_minimum_size() const {
return ms;
}
- Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
- Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
- Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
- Ref<StyleBox> button_highlight = get_theme_stylebox(SNAME("button_highlight"));
- Ref<Texture2D> close = get_theme_icon(SNAME("close"));
- int hseparation = get_theme_constant(SNAME("h_separation"));
-
- int y_margin = MAX(MAX(tab_unselected->get_minimum_size().height, tab_selected->get_minimum_size().height), tab_disabled->get_minimum_size().height);
+ int y_margin = MAX(MAX(theme_cache.tab_unselected_style->get_minimum_size().height, theme_cache.tab_selected_style->get_minimum_size().height), theme_cache.tab_disabled_style->get_minimum_size().height);
for (int i = 0; i < tabs.size(); i++) {
if (tabs[i].hidden) {
@@ -62,22 +55,22 @@ Size2 TabBar::get_minimum_size() const {
Ref<StyleBox> style;
if (tabs[i].disabled) {
- style = tab_disabled;
+ style = theme_cache.tab_disabled_style;
} else if (current == i) {
- style = tab_selected;
+ style = theme_cache.tab_selected_style;
} else {
- style = tab_unselected;
+ style = theme_cache.tab_unselected_style;
}
ms.width += style->get_minimum_size().width;
Ref<Texture2D> tex = tabs[i].icon;
if (tex.is_valid()) {
ms.height = MAX(ms.height, tex->get_size().height + y_margin);
- ms.width += tex->get_size().width + hseparation;
+ ms.width += tex->get_size().width + theme_cache.h_separation;
}
if (!tabs[i].text.is_empty()) {
- ms.width += tabs[i].size_text + hseparation;
+ ms.width += tabs[i].size_text + theme_cache.h_separation;
}
ms.height = MAX(ms.height, tabs[i].text_buf->get_size().y + y_margin);
@@ -87,22 +80,22 @@ Size2 TabBar::get_minimum_size() const {
Ref<Texture2D> rb = tabs[i].right_button;
if (close_visible) {
- ms.width += button_highlight->get_minimum_size().width + rb->get_width();
+ ms.width += theme_cache.button_hl_style->get_minimum_size().width + rb->get_width();
} else {
- ms.width += button_highlight->get_margin(SIDE_LEFT) + rb->get_width() + hseparation;
+ ms.width += theme_cache.button_hl_style->get_margin(SIDE_LEFT) + rb->get_width() + theme_cache.h_separation;
}
ms.height = MAX(ms.height, rb->get_height() + y_margin);
}
if (close_visible) {
- ms.width += button_highlight->get_margin(SIDE_LEFT) + close->get_width() + hseparation;
+ ms.width += theme_cache.button_hl_style->get_margin(SIDE_LEFT) + theme_cache.close_icon->get_width() + theme_cache.h_separation;
- ms.height = MAX(ms.height, close->get_height() + y_margin);
+ ms.height = MAX(ms.height, theme_cache.close_icon->get_height() + y_margin);
}
if (ms.width - ofs > style->get_minimum_size().width) {
- ms.width -= hseparation;
+ ms.width -= theme_cache.h_separation;
}
}
@@ -122,46 +115,43 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
Point2 pos = mm->get_position();
if (buttons_visible) {
- Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
- Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
-
if (is_layout_rtl()) {
- if (pos.x < decr->get_width()) {
+ if (pos.x < theme_cache.decrement_icon->get_width()) {
if (highlight_arrow != 1) {
highlight_arrow = 1;
- update();
+ queue_redraw();
}
- } else if (pos.x < incr->get_width() + decr->get_width()) {
+ } else if (pos.x < theme_cache.increment_icon->get_width() + theme_cache.decrement_icon->get_width()) {
if (highlight_arrow != 0) {
highlight_arrow = 0;
- update();
+ queue_redraw();
}
} else if (highlight_arrow != -1) {
highlight_arrow = -1;
- update();
+ queue_redraw();
}
} else {
- int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width();
- if (pos.x > limit_minus_buttons + decr->get_width()) {
+ int limit_minus_buttons = get_size().width - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width();
+ if (pos.x > limit_minus_buttons + theme_cache.decrement_icon->get_width()) {
if (highlight_arrow != 1) {
highlight_arrow = 1;
- update();
+ queue_redraw();
}
} else if (pos.x > limit_minus_buttons) {
if (highlight_arrow != 0) {
highlight_arrow = 0;
- update();
+ queue_redraw();
}
} else if (highlight_arrow != -1) {
highlight_arrow = -1;
- update();
+ queue_redraw();
}
}
}
if (get_viewport()->gui_is_dragging() && can_drop_data(pos, get_viewport()->gui_get_drag_data())) {
dragging_valid_tab = true;
- update();
+ queue_redraw();
}
_update_hover();
@@ -177,7 +167,7 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
if (offset > 0) {
offset--;
_update_cache();
- update();
+ queue_redraw();
}
}
}
@@ -187,7 +177,7 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
if (missing_right && offset < tabs.size()) {
offset++;
_update_cache();
- update();
+ queue_redraw();
}
}
}
@@ -198,7 +188,7 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
}
rb_pressing = false;
- update();
+ queue_redraw();
}
if (cb_pressing && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) {
@@ -207,46 +197,43 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
}
cb_pressing = false;
- update();
+ queue_redraw();
}
if (mb->is_pressed() && (mb->get_button_index() == MouseButton::LEFT || (select_with_rmb && mb->get_button_index() == MouseButton::RIGHT))) {
Point2 pos = mb->get_position();
if (buttons_visible) {
- Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
- Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
-
if (is_layout_rtl()) {
- if (pos.x < decr->get_width()) {
+ if (pos.x < theme_cache.decrement_icon->get_width()) {
if (missing_right) {
offset++;
_update_cache();
- update();
+ queue_redraw();
}
return;
- } else if (pos.x < incr->get_width() + decr->get_width()) {
+ } else if (pos.x < theme_cache.increment_icon->get_width() + theme_cache.decrement_icon->get_width()) {
if (offset > 0) {
offset--;
_update_cache();
- update();
+ queue_redraw();
}
return;
}
} else {
- int limit = get_size().width - incr->get_width() - decr->get_width();
- if (pos.x > limit + decr->get_width()) {
+ int limit = get_size().width - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width();
+ if (pos.x > limit + theme_cache.decrement_icon->get_width()) {
if (missing_right) {
offset++;
_update_cache();
- update();
+ queue_redraw();
}
return;
} else if (pos.x > limit) {
if (offset > 0) {
offset--;
_update_cache();
- update();
+ queue_redraw();
}
return;
}
@@ -266,13 +253,13 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
if (tabs[i].rb_rect.has_point(pos)) {
rb_pressing = true;
- update();
+ queue_redraw();
return;
}
if (tabs[i].cb_rect.has_point(pos) && (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current))) {
cb_pressing = true;
- update();
+ queue_redraw();
return;
}
@@ -299,9 +286,6 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
}
void TabBar::_shape(int p_tab) {
- Ref<Font> font = get_theme_font(SNAME("font"));
- int font_size = get_theme_font_size(SNAME("font_size"));
-
tabs.write[p_tab].xl_text = atr(tabs[p_tab].text);
tabs.write[p_tab].text_buf->clear();
tabs.write[p_tab].text_buf->set_width(-1);
@@ -311,13 +295,43 @@ void TabBar::_shape(int p_tab) {
tabs.write[p_tab].text_buf->set_direction((TextServer::Direction)tabs[p_tab].text_direction);
}
- tabs.write[p_tab].text_buf->add_string(tabs[p_tab].xl_text, font, font_size, tabs[p_tab].language);
+ tabs.write[p_tab].text_buf->add_string(tabs[p_tab].xl_text, theme_cache.font, theme_cache.font_size, tabs[p_tab].language);
+}
+
+void TabBar::_update_theme_item_cache() {
+ Control::_update_theme_item_cache();
+
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
+
+ theme_cache.tab_unselected_style = get_theme_stylebox(SNAME("tab_unselected"));
+ theme_cache.tab_selected_style = get_theme_stylebox(SNAME("tab_selected"));
+ theme_cache.tab_disabled_style = get_theme_stylebox(SNAME("tab_disabled"));
+
+ theme_cache.increment_icon = get_theme_icon(SNAME("increment"));
+ theme_cache.increment_hl_icon = get_theme_icon(SNAME("increment_highlight"));
+ theme_cache.decrement_icon = get_theme_icon(SNAME("decrement"));
+ theme_cache.decrement_hl_icon = get_theme_icon(SNAME("decrement_highlight"));
+ theme_cache.drop_mark_icon = get_theme_icon(SNAME("drop_mark"));
+ theme_cache.drop_mark_color = get_theme_color(SNAME("drop_mark_color"));
+
+ theme_cache.font = get_theme_font(SNAME("font"));
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
+ theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
+
+ theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
+ theme_cache.font_unselected_color = get_theme_color(SNAME("font_unselected_color"));
+ theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+
+ theme_cache.close_icon = get_theme_icon(SNAME("close"));
+ theme_cache.button_pressed_style = get_theme_stylebox(SNAME("button_pressed"));
+ theme_cache.button_hl_style = get_theme_stylebox(SNAME("button_highlight"));
}
void TabBar::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
- update();
+ queue_redraw();
} break;
case NOTIFICATION_THEME_CHANGED:
@@ -343,7 +357,7 @@ void TabBar::_notification(int p_what) {
case NOTIFICATION_DRAG_END: {
if (dragging_valid_tab) {
dragging_valid_tab = false;
- update();
+ queue_redraw();
}
} break;
@@ -352,18 +366,9 @@ void TabBar::_notification(int p_what) {
return;
}
- Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
- Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
- Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
- Color font_selected_color = get_theme_color(SNAME("font_selected_color"));
- Color font_unselected_color = get_theme_color(SNAME("font_unselected_color"));
- Color font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
- Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
- Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
-
bool rtl = is_layout_rtl();
Vector2 size = get_size();
- int limit_minus_buttons = size.width - incr->get_width() - decr->get_width();
+ int limit_minus_buttons = size.width - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width();
int ofs = tabs[offset].ofs_cache;
@@ -378,14 +383,14 @@ void TabBar::_notification(int p_what) {
Color col;
if (tabs[i].disabled) {
- sb = tab_disabled;
- col = font_disabled_color;
+ sb = theme_cache.tab_disabled_style;
+ col = theme_cache.font_disabled_color;
} else if (i == current) {
- sb = tab_selected;
- col = font_selected_color;
+ sb = theme_cache.tab_selected_style;
+ col = theme_cache.font_selected_color;
} else {
- sb = tab_unselected;
- col = font_unselected_color;
+ sb = theme_cache.tab_unselected_style;
+ col = theme_cache.font_unselected_color;
}
_draw_tab(sb, col, i, rtl ? size.width - ofs - tabs[i].size_cache : ofs);
@@ -396,41 +401,38 @@ void TabBar::_notification(int p_what) {
// Draw selected tab in the front, but only if it's visible.
if (current >= offset && current <= max_drawn_tab && !tabs[current].hidden) {
- Ref<StyleBox> sb = tabs[current].disabled ? tab_disabled : tab_selected;
+ Ref<StyleBox> sb = tabs[current].disabled ? theme_cache.tab_disabled_style : theme_cache.tab_selected_style;
float x = rtl ? size.width - tabs[current].ofs_cache - tabs[current].size_cache : tabs[current].ofs_cache;
- _draw_tab(sb, font_selected_color, current, x);
+ _draw_tab(sb, theme_cache.font_selected_color, current, x);
}
if (buttons_visible) {
- Ref<Texture2D> incr_hl = get_theme_icon(SNAME("increment_highlight"));
- Ref<Texture2D> decr_hl = get_theme_icon(SNAME("decrement_highlight"));
-
- int vofs = (size.height - incr->get_size().height) / 2;
+ int vofs = (size.height - theme_cache.increment_icon->get_size().height) / 2;
if (rtl) {
if (missing_right) {
- draw_texture(highlight_arrow == 1 ? decr_hl : decr, Point2(0, vofs));
+ draw_texture(highlight_arrow == 1 ? theme_cache.decrement_hl_icon : theme_cache.decrement_icon, Point2(0, vofs));
} else {
- draw_texture(decr, Point2(0, vofs), Color(1, 1, 1, 0.5));
+ draw_texture(theme_cache.decrement_icon, Point2(0, vofs), Color(1, 1, 1, 0.5));
}
if (offset > 0) {
- draw_texture(highlight_arrow == 0 ? incr_hl : incr, Point2(incr->get_size().width, vofs));
+ draw_texture(highlight_arrow == 0 ? theme_cache.increment_hl_icon : theme_cache.increment_icon, Point2(theme_cache.increment_icon->get_size().width, vofs));
} else {
- draw_texture(incr, Point2(incr->get_size().width, vofs), Color(1, 1, 1, 0.5));
+ draw_texture(theme_cache.increment_icon, Point2(theme_cache.increment_icon->get_size().width, vofs), Color(1, 1, 1, 0.5));
}
} else {
if (offset > 0) {
- draw_texture(highlight_arrow == 0 ? decr_hl : decr, Point2(limit_minus_buttons, vofs));
+ draw_texture(highlight_arrow == 0 ? theme_cache.decrement_hl_icon : theme_cache.decrement_icon, Point2(limit_minus_buttons, vofs));
} else {
- draw_texture(decr, Point2(limit_minus_buttons, vofs), Color(1, 1, 1, 0.5));
+ draw_texture(theme_cache.decrement_icon, Point2(limit_minus_buttons, vofs), Color(1, 1, 1, 0.5));
}
if (missing_right) {
- draw_texture(highlight_arrow == 1 ? incr_hl : incr, Point2(limit_minus_buttons + decr->get_size().width, vofs));
+ draw_texture(highlight_arrow == 1 ? theme_cache.increment_hl_icon : theme_cache.increment_icon, Point2(limit_minus_buttons + theme_cache.decrement_icon->get_size().width, vofs));
} else {
- draw_texture(incr, Point2(limit_minus_buttons + decr->get_size().width, vofs), Color(1, 1, 1, 0.5));
+ draw_texture(theme_cache.increment_icon, Point2(limit_minus_buttons + theme_cache.decrement_icon->get_size().width, vofs), Color(1, 1, 1, 0.5));
}
}
}
@@ -462,10 +464,7 @@ void TabBar::_notification(int p_what) {
}
}
- Ref<Texture2D> drop_mark = get_theme_icon(SNAME("drop_mark"));
- Color drop_mark_color = get_theme_color(SNAME("drop_mark_color"));
-
- drop_mark->draw(get_canvas_item(), Point2(x - drop_mark->get_width() / 2, (size.height - drop_mark->get_height()) / 2), drop_mark_color);
+ theme_cache.drop_mark_icon->draw(get_canvas_item(), Point2(x - theme_cache.drop_mark_icon->get_width() / 2, (size.height - theme_cache.drop_mark_icon->get_height()) / 2), theme_cache.drop_mark_color);
}
} break;
}
@@ -475,10 +474,6 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in
RID ci = get_canvas_item();
bool rtl = is_layout_rtl();
- Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
- int hseparation = get_theme_constant(SNAME("h_separation"));
-
Rect2 sb_rect = Rect2(p_x, 0, tabs[p_index].size_cache, get_size().height);
p_tab_style->draw(ci, sb_rect);
@@ -491,7 +486,7 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in
if (icon.is_valid()) {
icon->draw(ci, Point2i(rtl ? p_x - icon->get_width() : p_x, p_tab_style->get_margin(SIDE_TOP) + ((sb_rect.size.y - sb_ms.y) - icon->get_height()) / 2));
- p_x = rtl ? p_x - icon->get_width() - hseparation : p_x + icon->get_width() + hseparation;
+ p_x = rtl ? p_x - icon->get_width() - theme_cache.h_separation : p_x + icon->get_width() + theme_cache.h_separation;
}
// Draw the text.
@@ -499,17 +494,17 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in
Point2i text_pos = Point2i(rtl ? p_x - tabs[p_index].size_text : p_x,
p_tab_style->get_margin(SIDE_TOP) + ((sb_rect.size.y - sb_ms.y) - tabs[p_index].text_buf->get_size().y) / 2);
- if (outline_size > 0 && font_outline_color.a > 0) {
- tabs[p_index].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ if (theme_cache.outline_size > 0 && theme_cache.font_outline_color.a > 0) {
+ tabs[p_index].text_buf->draw_outline(ci, text_pos, theme_cache.outline_size, theme_cache.font_outline_color);
}
tabs[p_index].text_buf->draw(ci, text_pos, p_font_color);
- p_x = rtl ? p_x - tabs[p_index].size_text - hseparation : p_x + tabs[p_index].size_text + hseparation;
+ p_x = rtl ? p_x - tabs[p_index].size_text - theme_cache.h_separation : p_x + tabs[p_index].size_text + theme_cache.h_separation;
}
// Draw and calculate rect of the right button.
if (tabs[p_index].right_button.is_valid()) {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("button_highlight"));
+ Ref<StyleBox> style = theme_cache.button_hl_style;
Ref<Texture2D> rb = tabs[p_index].right_button;
Rect2 rb_rect;
@@ -521,7 +516,7 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in
if (rb_hover == p_index) {
if (rb_pressing) {
- get_theme_stylebox(SNAME("button_pressed"))->draw(ci, rb_rect);
+ theme_cache.button_pressed_style->draw(ci, rb_rect);
} else {
style->draw(ci, rb_rect);
}
@@ -534,8 +529,8 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in
// Draw and calculate rect of the close button.
if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && p_index == current)) {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("button_highlight"));
- Ref<Texture2D> cb = get_theme_icon(SNAME("close"));
+ Ref<StyleBox> style = theme_cache.button_hl_style;
+ Ref<Texture2D> cb = theme_cache.close_icon;
Rect2 cb_rect;
cb_rect.size = style->get_minimum_size() + cb->get_size();
@@ -546,7 +541,7 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in
if (!tabs[p_index].disabled && cb_hover == p_index) {
if (cb_pressing) {
- get_theme_stylebox(SNAME("button_pressed"))->draw(ci, cb_rect);
+ theme_cache.button_pressed_style->draw(ci, cb_rect);
} else {
style->draw(ci, cb_rect);
}
@@ -581,7 +576,7 @@ void TabBar::set_tab_count(int p_count) {
}
}
- update();
+ queue_redraw();
update_minimum_size();
notify_property_list_changed();
}
@@ -607,7 +602,7 @@ void TabBar::set_current_tab(int p_current) {
if (scroll_to_selected) {
ensure_tab_visible(current);
}
- update();
+ queue_redraw();
emit_signal(SNAME("tab_changed"), p_current);
}
@@ -647,7 +642,7 @@ void TabBar::set_tab_title(int p_tab, const String &p_title) {
if (scroll_to_selected) {
ensure_tab_visible(current);
}
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -663,7 +658,7 @@ void TabBar::set_tab_text_direction(int p_tab, Control::TextDirection p_text_dir
if (tabs[p_tab].text_direction != p_text_direction) {
tabs.write[p_tab].text_direction = p_text_direction;
_shape(p_tab);
- update();
+ queue_redraw();
}
}
@@ -683,7 +678,7 @@ void TabBar::set_tab_language(int p_tab, const String &p_language) {
if (scroll_to_selected) {
ensure_tab_visible(current);
}
- update();
+ queue_redraw();
update_minimum_size();
}
}
@@ -707,7 +702,7 @@ void TabBar::set_tab_icon(int p_tab, const Ref<Texture2D> &p_icon) {
if (scroll_to_selected) {
ensure_tab_visible(current);
}
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -730,7 +725,7 @@ void TabBar::set_tab_disabled(int p_tab, bool p_disabled) {
if (scroll_to_selected) {
ensure_tab_visible(current);
}
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -753,7 +748,7 @@ void TabBar::set_tab_hidden(int p_tab, bool p_hidden) {
if (scroll_to_selected) {
ensure_tab_visible(current);
}
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -776,7 +771,7 @@ void TabBar::set_tab_button_icon(int p_tab, const Ref<Texture2D> &p_icon) {
if (scroll_to_selected) {
ensure_tab_visible(current);
}
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -817,7 +812,7 @@ void TabBar::_update_hover() {
}
if (hover_buttons != -1) {
- update();
+ queue_redraw();
break;
}
}
@@ -838,7 +833,7 @@ void TabBar::_update_hover() {
cb_hover = hover_buttons;
if (rb_hover != rb_hover_old || cb_hover != cb_hover_old) {
- update();
+ queue_redraw();
}
}
}
@@ -849,14 +844,8 @@ void TabBar::_update_cache() {
return;
}
- Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
- Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
- Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
- Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
- Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
-
int limit = get_size().width;
- int limit_minus_buttons = limit - incr->get_width() - decr->get_width();
+ int limit_minus_buttons = limit - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width();
int w = 0;
@@ -940,7 +929,7 @@ void TabBar::_on_mouse_exited() {
highlight_arrow = -1;
dragging_valid_tab = false;
- update();
+ queue_redraw();
}
void TabBar::add_tab(const String &p_str, const Ref<Texture2D> &p_icon) {
@@ -955,7 +944,7 @@ void TabBar::add_tab(const String &p_str, const Ref<Texture2D> &p_icon) {
if (scroll_to_selected) {
ensure_tab_visible(current);
}
- update();
+ queue_redraw();
update_minimum_size();
if (tabs.size() == 1 && is_inside_tree()) {
@@ -974,7 +963,7 @@ void TabBar::clear_tabs() {
current = 0;
previous = 0;
- update();
+ queue_redraw();
update_minimum_size();
notify_property_list_changed();
}
@@ -1004,7 +993,7 @@ void TabBar::remove_tab(int p_idx) {
}
}
- update();
+ queue_redraw();
update_minimum_size();
notify_property_list_changed();
@@ -1152,7 +1141,7 @@ void TabBar::drop_data(const Point2 &p_point, const Variant &p_data) {
set_current_tab(hover_now);
} else {
_update_cache();
- update();
+ queue_redraw();
}
update_minimum_size();
@@ -1188,7 +1177,7 @@ void TabBar::set_tab_alignment(AlignmentMode p_alignment) {
tab_alignment = p_alignment;
_update_cache();
- update();
+ queue_redraw();
}
TabBar::AlignmentMode TabBar::get_tab_alignment() const {
@@ -1210,7 +1199,7 @@ void TabBar::set_clip_tabs(bool p_clip_tabs) {
if (scroll_to_selected) {
ensure_tab_visible(current);
}
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -1251,59 +1240,54 @@ void TabBar::move_tab(int p_from, int p_to) {
if (scroll_to_selected) {
ensure_tab_visible(current);
}
- update();
+ queue_redraw();
notify_property_list_changed();
}
int TabBar::get_tab_width(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, tabs.size(), 0);
- Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
- Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
- Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
- int hseparation = get_theme_constant(SNAME("h_separation"));
-
Ref<StyleBox> style;
if (tabs[p_idx].disabled) {
- style = tab_disabled;
+ style = theme_cache.tab_disabled_style;
} else if (current == p_idx) {
- style = tab_selected;
+ style = theme_cache.tab_selected_style;
} else {
- style = tab_unselected;
+ style = theme_cache.tab_unselected_style;
}
int x = style->get_minimum_size().width;
Ref<Texture2D> tex = tabs[p_idx].icon;
if (tex.is_valid()) {
- x += tex->get_width() + hseparation;
+ x += tex->get_width() + theme_cache.h_separation;
}
if (!tabs[p_idx].text.is_empty()) {
- x += tabs[p_idx].size_text + hseparation;
+ x += tabs[p_idx].size_text + theme_cache.h_separation;
}
bool close_visible = cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && p_idx == current);
if (tabs[p_idx].right_button.is_valid()) {
- Ref<StyleBox> btn_style = get_theme_stylebox(SNAME("button_highlight"));
+ Ref<StyleBox> btn_style = theme_cache.button_hl_style;
Ref<Texture2D> rb = tabs[p_idx].right_button;
if (close_visible) {
x += btn_style->get_minimum_size().width + rb->get_width();
} else {
- x += btn_style->get_margin(SIDE_LEFT) + rb->get_width() + hseparation;
+ x += btn_style->get_margin(SIDE_LEFT) + rb->get_width() + theme_cache.h_separation;
}
}
if (close_visible) {
- Ref<StyleBox> btn_style = get_theme_stylebox(SNAME("button_highlight"));
- Ref<Texture2D> cb = get_theme_icon(SNAME("close"));
- x += btn_style->get_margin(SIDE_LEFT) + cb->get_width() + hseparation;
+ Ref<StyleBox> btn_style = theme_cache.button_hl_style;
+ Ref<Texture2D> cb = theme_cache.close_icon;
+ x += btn_style->get_margin(SIDE_LEFT) + cb->get_width() + theme_cache.h_separation;
}
if (x > style->get_minimum_size().width) {
- x -= hseparation;
+ x -= theme_cache.h_separation;
}
return x;
@@ -1314,9 +1298,7 @@ void TabBar::_ensure_no_over_offset() {
return;
}
- Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
- Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
- int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width();
+ int limit_minus_buttons = get_size().width - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width();
int prev_offset = offset;
@@ -1337,7 +1319,7 @@ void TabBar::_ensure_no_over_offset() {
if (prev_offset != offset) {
_update_cache();
- update();
+ queue_redraw();
}
}
@@ -1354,14 +1336,12 @@ void TabBar::ensure_tab_visible(int p_idx) {
if (p_idx < offset) {
offset = p_idx;
_update_cache();
- update();
+ queue_redraw();
return;
}
- Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
- Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
- int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width();
+ int limit_minus_buttons = get_size().width - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width();
int total_w = tabs[max_drawn_tab].ofs_cache - tabs[offset].ofs_cache;
for (int i = max_drawn_tab; i <= p_idx; i++) {
@@ -1389,7 +1369,7 @@ void TabBar::ensure_tab_visible(int p_idx) {
if (prev_offset != offset) {
_update_cache();
- update();
+ queue_redraw();
}
}
@@ -1416,7 +1396,7 @@ void TabBar::set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy) {
if (scroll_to_selected) {
ensure_tab_visible(current);
}
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -1438,7 +1418,7 @@ void TabBar::set_max_tab_width(int p_width) {
if (scroll_to_selected) {
ensure_tab_visible(current);
}
- update();
+ queue_redraw();
update_minimum_size();
}
diff --git a/scene/gui/tab_bar.h b/scene/gui/tab_bar.h
index d123385e47..ac4a6a195e 100644
--- a/scene/gui/tab_bar.h
+++ b/scene/gui/tab_bar.h
@@ -104,6 +104,34 @@ private:
bool scroll_to_selected = true;
int tabs_rearrange_group = -1;
+ struct ThemeCache {
+ int h_separation = 0;
+
+ Ref<StyleBox> tab_unselected_style;
+ Ref<StyleBox> tab_selected_style;
+ Ref<StyleBox> tab_disabled_style;
+
+ Ref<Texture2D> increment_icon;
+ Ref<Texture2D> increment_hl_icon;
+ Ref<Texture2D> decrement_icon;
+ Ref<Texture2D> decrement_hl_icon;
+ Ref<Texture2D> drop_mark_icon;
+ Color drop_mark_color;
+
+ Ref<Font> font;
+ int font_size;
+ int outline_size = 0;
+
+ Color font_selected_color;
+ Color font_unselected_color;
+ Color font_disabled_color;
+ Color font_outline_color;
+
+ Ref<Texture2D> close_icon;
+ Ref<StyleBox> button_pressed_style;
+ Ref<StyleBox> button_hl_style;
+ } theme_cache;
+
int get_tab_width(int p_idx) const;
void _ensure_no_over_offset();
@@ -117,6 +145,7 @@ private:
protected:
virtual void gui_input(const Ref<InputEvent> &p_event) override;
+ virtual void _update_theme_item_cache() override;
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 10a6d18330..f45d132a66 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -60,26 +60,24 @@ void TabContainer::gui_input(const Ref<InputEvent> &p_event) {
}
// Handle menu button.
- Ref<Texture2D> menu = get_theme_icon(SNAME("menu"));
-
if (is_layout_rtl()) {
- if (popup && pos.x < menu->get_width()) {
+ if (popup && pos.x < theme_cache.menu_icon->get_width()) {
emit_signal(SNAME("pre_popup_pressed"));
Vector2 popup_pos = get_screen_position();
- popup_pos.y += menu->get_height();
+ popup_pos.y += theme_cache.menu_icon->get_height();
popup->set_position(popup_pos);
popup->popup();
return;
}
} else {
- if (popup && pos.x > size.width - menu->get_width()) {
+ if (popup && pos.x > size.width - theme_cache.menu_icon->get_width()) {
emit_signal(SNAME("pre_popup_pressed"));
Vector2 popup_pos = get_screen_position();
popup_pos.x += size.width - popup->get_size().width;
- popup_pos.y += menu->get_height();
+ popup_pos.y += theme_cache.menu_icon->get_height();
popup->set_position(popup_pos);
popup->popup();
@@ -98,34 +96,33 @@ void TabContainer::gui_input(const Ref<InputEvent> &p_event) {
if (pos.y > _get_top_margin()) {
if (menu_hovered) {
menu_hovered = false;
- update();
+ queue_redraw();
}
return;
}
- Ref<Texture2D> menu = get_theme_icon(SNAME("menu"));
if (popup) {
if (is_layout_rtl()) {
- if (pos.x <= menu->get_width()) {
+ if (pos.x <= theme_cache.menu_icon->get_width()) {
if (!menu_hovered) {
menu_hovered = true;
- update();
+ queue_redraw();
return;
}
} else if (menu_hovered) {
menu_hovered = false;
- update();
+ queue_redraw();
}
} else {
- if (pos.x >= size.width - menu->get_width()) {
+ if (pos.x >= size.width - theme_cache.menu_icon->get_width()) {
if (!menu_hovered) {
menu_hovered = true;
- update();
+ queue_redraw();
return;
}
} else if (menu_hovered) {
menu_hovered = false;
- update();
+ queue_redraw();
}
}
@@ -136,6 +133,41 @@ void TabContainer::gui_input(const Ref<InputEvent> &p_event) {
}
}
+void TabContainer::_update_theme_item_cache() {
+ Container::_update_theme_item_cache();
+
+ theme_cache.side_margin = get_theme_constant(SNAME("side_margin"));
+
+ theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
+ theme_cache.tabbar_style = get_theme_stylebox(SNAME("tabbar_background"));
+
+ theme_cache.menu_icon = get_theme_icon(SNAME("menu"));
+ theme_cache.menu_hl_icon = get_theme_icon(SNAME("menu_highlight"));
+
+ // TabBar overrides.
+ theme_cache.icon_separation = get_theme_constant(SNAME("icon_separation"));
+ theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
+
+ theme_cache.tab_unselected_style = get_theme_stylebox(SNAME("tab_unselected"));
+ theme_cache.tab_selected_style = get_theme_stylebox(SNAME("tab_selected"));
+ theme_cache.tab_disabled_style = get_theme_stylebox(SNAME("tab_disabled"));
+
+ theme_cache.increment_icon = get_theme_icon(SNAME("increment"));
+ theme_cache.increment_hl_icon = get_theme_icon(SNAME("increment_highlight"));
+ theme_cache.decrement_icon = get_theme_icon(SNAME("decrement"));
+ theme_cache.decrement_hl_icon = get_theme_icon(SNAME("decrement_highlight"));
+ theme_cache.drop_mark_icon = get_theme_icon(SNAME("drop_mark"));
+ theme_cache.drop_mark_color = get_theme_color(SNAME("drop_mark_color"));
+
+ theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
+ theme_cache.font_unselected_color = get_theme_color(SNAME("font_unselected_color"));
+ theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+
+ theme_cache.tab_font = get_theme_font(SNAME("font"));
+ theme_cache.tab_font_size = get_theme_font_size(SNAME("font_size"));
+}
+
void TabContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
@@ -155,27 +187,26 @@ void TabContainer::_notification(int p_what) {
Size2 size = get_size();
// Draw only the tab area if the header is hidden.
- Ref<StyleBox> panel = get_theme_stylebox(SNAME("panel"));
if (!tabs_visible) {
- panel->draw(canvas, Rect2(0, 0, size.width, size.height));
+ theme_cache.panel_style->draw(canvas, Rect2(0, 0, size.width, size.height));
return;
}
int header_height = _get_top_margin();
- panel->draw(canvas, Rect2(0, header_height, size.width, size.height - header_height));
+ // Draw background for the tabbar.
+ theme_cache.tabbar_style->draw(canvas, Rect2(0, 0, size.width, header_height));
+ // Draw the background for the tab's content.
+ theme_cache.panel_style->draw(canvas, Rect2(0, header_height, size.width, size.height - header_height));
// Draw the popup menu.
if (get_popup()) {
- Ref<Texture2D> menu = get_theme_icon(SNAME("menu"));
- Ref<Texture2D> menu_hl = get_theme_icon(SNAME("menu_highlight"));
-
- int x = is_layout_rtl() ? 0 : get_size().width - menu->get_width();
+ int x = is_layout_rtl() ? 0 : get_size().width - theme_cache.menu_icon->get_width();
if (menu_hovered) {
- menu_hl->draw(get_canvas_item(), Point2(x, (header_height - menu_hl->get_height()) / 2));
+ theme_cache.menu_hl_icon->draw(get_canvas_item(), Point2(x, (header_height - theme_cache.menu_hl_icon->get_height()) / 2));
} else {
- menu->draw(get_canvas_item(), Point2(x, (header_height - menu->get_height()) / 2));
+ theme_cache.menu_icon->draw(get_canvas_item(), Point2(x, (header_height - theme_cache.menu_icon->get_height()) / 2));
}
}
} break;
@@ -194,23 +225,27 @@ void TabContainer::_on_theme_changed() {
return;
}
- tab_bar->add_theme_style_override(SNAME("tab_unselected"), get_theme_stylebox(SNAME("tab_unselected")));
- tab_bar->add_theme_style_override(SNAME("tab_selected"), get_theme_stylebox(SNAME("tab_selected")));
- tab_bar->add_theme_style_override(SNAME("tab_disabled"), get_theme_stylebox(SNAME("tab_disabled")));
- tab_bar->add_theme_icon_override(SNAME("increment"), get_theme_icon(SNAME("increment")));
- tab_bar->add_theme_icon_override(SNAME("increment_highlight"), get_theme_icon(SNAME("increment_highlight")));
- tab_bar->add_theme_icon_override(SNAME("decrement"), get_theme_icon(SNAME("decrement")));
- tab_bar->add_theme_icon_override(SNAME("decrement_highlight"), get_theme_icon(SNAME("decrement_highlight")));
- tab_bar->add_theme_icon_override(SNAME("drop_mark"), get_theme_icon(SNAME("drop_mark")));
- tab_bar->add_theme_color_override(SNAME("drop_mark_color"), get_theme_color(SNAME("drop_mark_color")));
- tab_bar->add_theme_color_override(SNAME("font_selected_color"), get_theme_color(SNAME("font_selected_color")));
- tab_bar->add_theme_color_override(SNAME("font_unselected_color"), get_theme_color(SNAME("font_unselected_color")));
- tab_bar->add_theme_color_override(SNAME("font_disabled_color"), get_theme_color(SNAME("font_disabled_color")));
- tab_bar->add_theme_color_override(SNAME("font_outline_color"), get_theme_color(SNAME("font_outline_color")));
- tab_bar->add_theme_font_override(SNAME("font"), get_theme_font(SNAME("font")));
- tab_bar->add_theme_font_size_override(SNAME("font_size"), get_theme_font_size(SNAME("font_size")));
- tab_bar->add_theme_constant_override(SNAME("h_separation"), get_theme_constant(SNAME("icon_separation")));
- tab_bar->add_theme_constant_override(SNAME("outline_size"), get_theme_constant(SNAME("outline_size")));
+ tab_bar->add_theme_style_override(SNAME("tab_unselected"), theme_cache.tab_unselected_style);
+ tab_bar->add_theme_style_override(SNAME("tab_selected"), theme_cache.tab_selected_style);
+ tab_bar->add_theme_style_override(SNAME("tab_disabled"), theme_cache.tab_disabled_style);
+
+ tab_bar->add_theme_icon_override(SNAME("increment"), theme_cache.increment_icon);
+ tab_bar->add_theme_icon_override(SNAME("increment_highlight"), theme_cache.increment_hl_icon);
+ tab_bar->add_theme_icon_override(SNAME("decrement"), theme_cache.decrement_icon);
+ tab_bar->add_theme_icon_override(SNAME("decrement_highlight"), theme_cache.decrement_hl_icon);
+ tab_bar->add_theme_icon_override(SNAME("drop_mark"), theme_cache.drop_mark_icon);
+ tab_bar->add_theme_color_override(SNAME("drop_mark_color"), theme_cache.drop_mark_color);
+
+ tab_bar->add_theme_color_override(SNAME("font_selected_color"), theme_cache.font_selected_color);
+ tab_bar->add_theme_color_override(SNAME("font_unselected_color"), theme_cache.font_unselected_color);
+ tab_bar->add_theme_color_override(SNAME("font_disabled_color"), theme_cache.font_disabled_color);
+ tab_bar->add_theme_color_override(SNAME("font_outline_color"), theme_cache.font_outline_color);
+
+ tab_bar->add_theme_font_override(SNAME("font"), theme_cache.tab_font);
+ tab_bar->add_theme_font_size_override(SNAME("font_size"), theme_cache.tab_font_size);
+
+ tab_bar->add_theme_constant_override(SNAME("h_separation"), theme_cache.icon_separation);
+ tab_bar->add_theme_constant_override(SNAME("outline_size"), theme_cache.outline_size);
_update_margins();
if (get_tab_count() > 0) {
@@ -218,13 +253,12 @@ void TabContainer::_on_theme_changed() {
} else {
update_minimum_size();
}
- update();
+ queue_redraw();
theme_changing = false;
}
void TabContainer::_repaint() {
- Ref<StyleBox> sb = get_theme_stylebox(SNAME("panel"));
Vector<Control *> controls = _get_tab_controls();
int current = get_current_tab();
@@ -239,10 +273,10 @@ void TabContainer::_repaint() {
c->set_offset(SIDE_TOP, _get_top_margin());
}
- c->set_offset(SIDE_TOP, c->get_offset(SIDE_TOP) + sb->get_margin(SIDE_TOP));
- c->set_offset(SIDE_LEFT, c->get_offset(SIDE_LEFT) + sb->get_margin(SIDE_LEFT));
- c->set_offset(SIDE_RIGHT, c->get_offset(SIDE_RIGHT) - sb->get_margin(SIDE_RIGHT));
- c->set_offset(SIDE_BOTTOM, c->get_offset(SIDE_BOTTOM) - sb->get_margin(SIDE_BOTTOM));
+ c->set_offset(SIDE_TOP, c->get_offset(SIDE_TOP) + theme_cache.panel_style->get_margin(SIDE_TOP));
+ c->set_offset(SIDE_LEFT, c->get_offset(SIDE_LEFT) + theme_cache.panel_style->get_margin(SIDE_LEFT));
+ c->set_offset(SIDE_RIGHT, c->get_offset(SIDE_RIGHT) - theme_cache.panel_style->get_margin(SIDE_RIGHT));
+ c->set_offset(SIDE_BOTTOM, c->get_offset(SIDE_BOTTOM) - theme_cache.panel_style->get_margin(SIDE_BOTTOM));
} else {
c->hide();
}
@@ -252,8 +286,7 @@ void TabContainer::_repaint() {
}
void TabContainer::_update_margins() {
- int menu_width = get_theme_icon(SNAME("menu"))->get_width();
- int side_margin = get_theme_constant(SNAME("side_margin"));
+ int menu_width = theme_cache.menu_icon->get_width();
// Directly check for validity, to avoid errors when quitting.
bool has_popup = popup_obj_id.is_valid();
@@ -267,7 +300,7 @@ void TabContainer::_update_margins() {
switch (get_tab_alignment()) {
case TabBar::ALIGNMENT_LEFT: {
- tab_bar->set_offset(SIDE_LEFT, side_margin);
+ tab_bar->set_offset(SIDE_LEFT, theme_cache.side_margin);
tab_bar->set_offset(SIDE_RIGHT, has_popup ? -menu_width : 0);
} break;
@@ -289,10 +322,10 @@ void TabContainer::_update_margins() {
int total_tabs_width = last_tab_rect.position.x - first_tab_pos + last_tab_rect.size.width;
// Calculate if all the tabs would still fit if the margin was present.
- if (get_clip_tabs() && (tab_bar->get_offset_buttons_visible() || (get_tab_count() > 1 && (total_tabs_width + side_margin) > get_size().width))) {
+ if (get_clip_tabs() && (tab_bar->get_offset_buttons_visible() || (get_tab_count() > 1 && (total_tabs_width + theme_cache.side_margin) > get_size().width))) {
tab_bar->set_offset(SIDE_RIGHT, has_popup ? -menu_width : 0);
} else {
- tab_bar->set_offset(SIDE_RIGHT, -side_margin);
+ tab_bar->set_offset(SIDE_RIGHT, -theme_cache.side_margin);
}
} break;
@@ -304,7 +337,7 @@ void TabContainer::_update_margins() {
void TabContainer::_on_mouse_exited() {
if (menu_hovered) {
menu_hovered = false;
- update();
+ queue_redraw();
}
}
@@ -502,7 +535,7 @@ void TabContainer::add_child_notify(Node *p_child) {
_update_margins();
if (get_tab_count() == 1) {
- update();
+ queue_redraw();
}
p_child->connect("renamed", callable_mp(this, &TabContainer::_refresh_tab_names));
@@ -558,7 +591,7 @@ void TabContainer::remove_child_notify(Node *p_child) {
_update_margins();
if (get_tab_count() == 0) {
- update();
+ queue_redraw();
}
p_child->remove_meta("_tab_name");
@@ -656,7 +689,7 @@ void TabContainer::set_tabs_visible(bool p_visible) {
}
}
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -794,13 +827,12 @@ Size2 TabContainer::get_minimum_size() const {
if (!get_clip_tabs()) {
if (get_popup()) {
- ms.x += get_theme_icon(SNAME("menu"))->get_width();
+ ms.x += theme_cache.menu_icon->get_width();
}
- int side_margin = get_theme_constant(SNAME("side_margin"));
- if (side_margin > 0 && get_tab_alignment() != TabBar::ALIGNMENT_CENTER &&
+ if (theme_cache.side_margin > 0 && get_tab_alignment() != TabBar::ALIGNMENT_CENTER &&
(get_tab_alignment() != TabBar::ALIGNMENT_RIGHT || !get_popup())) {
- ms.x += side_margin;
+ ms.x += theme_cache.side_margin;
}
}
}
@@ -820,7 +852,7 @@ Size2 TabContainer::get_minimum_size() const {
}
ms.y += max_control_height;
- Size2 panel_ms = get_theme_stylebox(SNAME("panel"))->get_minimum_size();
+ Size2 panel_ms = theme_cache.panel_style->get_minimum_size();
ms.x = MAX(ms.x, panel_ms.x);
ms.y += panel_ms.y;
@@ -838,7 +870,7 @@ void TabContainer::set_popup(Node *p_popup) {
popup_obj_id = popup_id;
if (had_popup != bool(popup)) {
- update();
+ queue_redraw();
_update_margins();
if (!get_clip_tabs()) {
update_minimum_size();
diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h
index 60c8130939..b552aa459b 100644
--- a/scene/gui/tab_container.h
+++ b/scene/gui/tab_container.h
@@ -48,6 +48,39 @@ class TabContainer : public Container {
bool theme_changing = false;
Node *child_removing = nullptr;
+ struct ThemeCache {
+ int side_margin = 0;
+
+ Ref<StyleBox> panel_style;
+ Ref<StyleBox> tabbar_style;
+
+ Ref<Texture2D> menu_icon;
+ Ref<Texture2D> menu_hl_icon;
+
+ // TabBar overrides.
+ int icon_separation = 0;
+ int outline_size = 0;
+
+ Ref<StyleBox> tab_unselected_style;
+ Ref<StyleBox> tab_selected_style;
+ Ref<StyleBox> tab_disabled_style;
+
+ Ref<Texture2D> increment_icon;
+ Ref<Texture2D> increment_hl_icon;
+ Ref<Texture2D> decrement_icon;
+ Ref<Texture2D> decrement_hl_icon;
+ Ref<Texture2D> drop_mark_icon;
+ Color drop_mark_color;
+
+ Color font_selected_color;
+ Color font_unselected_color;
+ Color font_disabled_color;
+ Color font_outline_color;
+
+ Ref<Font> tab_font;
+ int tab_font_size;
+ } theme_cache;
+
int _get_top_margin() const;
Vector<Control *> _get_tab_controls() const;
void _on_theme_changed();
@@ -65,6 +98,8 @@ class TabContainer : public Container {
protected:
virtual void gui_input(const Ref<InputEvent> &p_event) override;
+ virtual void _update_theme_item_cache() override;
+
void _notification(int p_what);
virtual void add_child_notify(Node *p_child) override;
virtual void move_child_notify(Node *p_child) override;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 097eb1fd95..95338c7b8c 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -452,13 +452,13 @@ void TextEdit::_notification(int p_what) {
case NOTIFICATION_WM_WINDOW_FOCUS_IN: {
window_has_focus = true;
draw_caret = true;
- update();
+ queue_redraw();
} break;
case NOTIFICATION_WM_WINDOW_FOCUS_OUT: {
window_has_focus = false;
draw_caret = false;
- update();
+ queue_redraw();
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
@@ -1507,7 +1507,7 @@ void TextEdit::_notification(int p_what) {
}
text.invalidate_cache(caret.line, caret.column, true, t, structured_text_parser(st_parser, st_args, t));
- update();
+ queue_redraw();
}
} break;
@@ -1696,7 +1696,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
}
selection.selecting_line = prev_line;
selection.selecting_column = prev_col;
- update();
+ queue_redraw();
} else {
if (caret.line < selection.selecting_line || (caret.line == selection.selecting_line && caret.column < selection.selecting_column)) {
if (selection.shiftclick_left) {
@@ -1718,7 +1718,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
selection.active = false;
}
- update();
+ queue_redraw();
}
} else if (drag_and_drop_selection_enabled && is_mouse_over_selection()) {
selection.selecting_mode = SelectionMode::SELECTION_MODE_NONE;
@@ -1746,7 +1746,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
last_dblclk = OS::get_singleton()->get_ticks_msec();
last_dblclk_pos = mb->get_position();
}
- update();
+ queue_redraw();
}
if (is_middle_mouse_paste_enabled() && mb->get_button_index() == MouseButton::MIDDLE && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
@@ -1880,7 +1880,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
if (current_hovered_gutter != hovered_gutter) {
hovered_gutter = current_hovered_gutter;
- update();
+ queue_redraw();
}
if (drag_action && can_drop_data(mpos, get_viewport()->gui_get_drag_data())) {
@@ -2146,7 +2146,7 @@ void TextEdit::_swap_current_input_direction() {
input_direction = TEXT_DIRECTION_LTR;
}
set_caret_column(caret.column);
- update();
+ queue_redraw();
}
void TextEdit::_new_line(bool p_split_current_line, bool p_above) {
@@ -2527,7 +2527,7 @@ void TextEdit::_delete(bool p_word, bool p_all_to_right) {
}
_remove_text(caret.line, caret.column, next_line, next_column);
- update();
+ queue_redraw();
}
void TextEdit::_move_caret_document_start(bool p_select) {
@@ -2816,7 +2816,7 @@ void TextEdit::set_editable(const bool p_editable) {
editable = p_editable;
- update();
+ queue_redraw();
}
bool TextEdit::is_editable() const {
@@ -2846,7 +2846,7 @@ void TextEdit::set_text_direction(Control::TextDirection p_text_direction) {
menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_LTR), text_direction == TEXT_DIRECTION_LTR);
menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_RTL), text_direction == TEXT_DIRECTION_RTL);
}
- update();
+ queue_redraw();
}
}
@@ -2866,7 +2866,7 @@ void TextEdit::set_language(const String &p_language) {
text.set_direction_and_language(dir, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale());
text.invalidate_all();
_update_placeholder();
- update();
+ queue_redraw();
}
}
@@ -2880,7 +2880,7 @@ void TextEdit::set_structured_text_bidi_override(TextServer::StructuredTextParse
for (int i = 0; i < text.size(); i++) {
text.set(i, text[i], structured_text_parser(st_parser, st_args, text[i]));
}
- update();
+ queue_redraw();
}
}
@@ -2897,7 +2897,7 @@ void TextEdit::set_structured_text_bidi_override_options(Array p_args) {
for (int i = 0; i < text.size(); i++) {
text.set(i, text[i], structured_text_parser(st_parser, st_args, text[i]));
}
- update();
+ queue_redraw();
}
Array TextEdit::get_structured_text_bidi_override_options() const {
@@ -2912,7 +2912,7 @@ void TextEdit::set_tab_size(const int p_size) {
text.set_tab_size(p_size);
text.invalidate_all_lines();
_update_placeholder();
- update();
+ queue_redraw();
}
int TextEdit::get_tab_size() const {
@@ -2926,7 +2926,7 @@ void TextEdit::set_overtype_mode_enabled(const bool p_enabled) {
}
overtype_mode = p_enabled;
- update();
+ queue_redraw();
}
bool TextEdit::is_overtype_mode_enabled() const {
@@ -3022,7 +3022,7 @@ void TextEdit::set_text(const String &p_text) {
set_caret_line(0);
set_caret_column(0);
- update();
+ queue_redraw();
setting_text = false;
emit_signal(SNAME("text_set"));
}
@@ -3050,7 +3050,7 @@ void TextEdit::set_placeholder(const String &p_text) {
placeholder_text = p_text;
_update_placeholder();
- update();
+ queue_redraw();
}
String TextEdit::get_placeholder() const {
@@ -3149,7 +3149,7 @@ void TextEdit::insert_line_at(int p_at, const String &p_text) {
++selection.to_line;
}
}
- update();
+ queue_redraw();
}
void TextEdit::insert_text_at_caret(const String &p_text) {
@@ -3166,7 +3166,7 @@ void TextEdit::insert_text_at_caret(const String &p_text) {
set_caret_line(new_line, false);
set_caret_column(new_column);
- update();
+ queue_redraw();
if (had_selection) {
end_complex_operation();
@@ -3557,7 +3557,7 @@ void TextEdit::undo() {
set_caret_line(undo_stack_pos->get().from_line, false);
set_caret_column(undo_stack_pos->get().from_column);
}
- update();
+ queue_redraw();
}
void TextEdit::redo() {
@@ -3592,7 +3592,7 @@ void TextEdit::redo() {
set_caret_line(undo_stack_pos->get().to_line, false);
set_caret_column(undo_stack_pos->get().to_column);
undo_stack_pos = undo_stack_pos->next();
- update();
+ queue_redraw();
}
void TextEdit::clear_undo_history() {
@@ -3962,7 +3962,7 @@ void TextEdit::set_caret_type(CaretType p_type) {
}
caret_type = p_type;
- update();
+ queue_redraw();
}
TextEdit::CaretType TextEdit::get_caret_type() const {
@@ -4217,7 +4217,7 @@ void TextEdit::select_all() {
selection.shiftclick_left = true;
set_caret_line(selection.to_line, false);
set_caret_column(selection.to_column, false);
- update();
+ queue_redraw();
}
void TextEdit::select_word_under_caret() {
@@ -4312,7 +4312,7 @@ void TextEdit::select(int p_from_line, int p_from_column, int p_to_line, int p_t
selection.shiftclick_left = true;
}
- update();
+ queue_redraw();
}
bool TextEdit::has_selection() const {
@@ -4359,7 +4359,7 @@ int TextEdit::get_selection_to_column() const {
void TextEdit::deselect() {
selection.active = false;
- update();
+ queue_redraw();
}
void TextEdit::delete_selection() {
@@ -4372,7 +4372,7 @@ void TextEdit::delete_selection() {
_remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column);
set_caret_line(selection.from_line, false, false);
set_caret_column(selection.from_column);
- update();
+ queue_redraw();
}
/* Line wrapping. */
@@ -4464,7 +4464,7 @@ void TextEdit::set_scroll_past_end_of_file_enabled(const bool p_enabled) {
}
scroll_past_end_of_file_enabled = p_enabled;
- update();
+ queue_redraw();
}
bool TextEdit::is_scroll_past_end_of_file_enabled() const {
@@ -4688,7 +4688,7 @@ void TextEdit::adjust_viewport_to_caret() {
}
h_scroll->set_value(caret.x_ofs);
- update();
+ queue_redraw();
}
void TextEdit::center_viewport_to_caret() {
@@ -4741,7 +4741,7 @@ void TextEdit::center_viewport_to_caret() {
}
h_scroll->set_value(caret.x_ofs);
- update();
+ queue_redraw();
}
/* Minimap */
@@ -4752,7 +4752,7 @@ void TextEdit::set_draw_minimap(bool p_enabled) {
draw_minimap = p_enabled;
_update_wrap_at_column();
- update();
+ queue_redraw();
}
bool TextEdit::is_drawing_minimap() const {
@@ -4766,7 +4766,7 @@ void TextEdit::set_minimap_width(int p_minimap_width) {
minimap_width = p_minimap_width;
_update_wrap_at_column();
- update();
+ queue_redraw();
}
int TextEdit::get_minimap_width() const {
@@ -4787,7 +4787,7 @@ void TextEdit::add_gutter(int p_at) {
text.add_gutter(p_at);
emit_signal(SNAME("gutter_added"));
- update();
+ queue_redraw();
}
void TextEdit::remove_gutter(int p_gutter) {
@@ -4797,7 +4797,7 @@ void TextEdit::remove_gutter(int p_gutter) {
text.remove_gutter(p_gutter);
emit_signal(SNAME("gutter_removed"));
- update();
+ queue_redraw();
}
int TextEdit::get_gutter_count() const {
@@ -4822,7 +4822,7 @@ void TextEdit::set_gutter_type(int p_gutter, GutterType p_type) {
}
gutters.write[p_gutter].type = p_type;
- update();
+ queue_redraw();
}
TextEdit::GutterType TextEdit::get_gutter_type(int p_gutter) const {
@@ -4870,7 +4870,7 @@ void TextEdit::set_gutter_clickable(int p_gutter, bool p_clickable) {
}
gutters.write[p_gutter].clickable = p_clickable;
- update();
+ queue_redraw();
}
bool TextEdit::is_gutter_clickable(int p_gutter) const {
@@ -4918,7 +4918,7 @@ void TextEdit::merge_gutters(int p_from_line, int p_to_line) {
text.set_line_gutter_clickable(p_to_line, i, true);
}
}
- update();
+ queue_redraw();
}
void TextEdit::set_gutter_custom_draw(int p_gutter, const Callable &p_draw_callback) {
@@ -4929,7 +4929,7 @@ void TextEdit::set_gutter_custom_draw(int p_gutter, const Callable &p_draw_callb
}
gutters.write[p_gutter].custom_draw_callback = p_draw_callback;
- update();
+ queue_redraw();
}
// Line gutters.
@@ -4954,7 +4954,7 @@ void TextEdit::set_line_gutter_text(int p_line, int p_gutter, const String &p_te
}
text.set_line_gutter_text(p_line, p_gutter, p_text);
- update();
+ queue_redraw();
}
String TextEdit::get_line_gutter_text(int p_line, int p_gutter) const {
@@ -4972,7 +4972,7 @@ void TextEdit::set_line_gutter_icon(int p_line, int p_gutter, const Ref<Texture2
}
text.set_line_gutter_icon(p_line, p_gutter, p_icon);
- update();
+ queue_redraw();
}
Ref<Texture2D> TextEdit::get_line_gutter_icon(int p_line, int p_gutter) const {
@@ -4990,7 +4990,7 @@ void TextEdit::set_line_gutter_item_color(int p_line, int p_gutter, const Color
}
text.set_line_gutter_item_color(p_line, p_gutter, p_color);
- update();
+ queue_redraw();
}
Color TextEdit::get_line_gutter_item_color(int p_line, int p_gutter) const {
@@ -5020,7 +5020,7 @@ void TextEdit::set_line_background_color(int p_line, const Color &p_color) {
}
text.set_line_background_color(p_line, p_color);
- update();
+ queue_redraw();
}
Color TextEdit::get_line_background_color(int p_line) const {
@@ -5038,7 +5038,7 @@ void TextEdit::set_syntax_highlighter(Ref<SyntaxHighlighter> p_syntax_highlighte
if (syntax_highlighter.is_valid()) {
syntax_highlighter->set_text_edit(this);
}
- update();
+ queue_redraw();
}
Ref<SyntaxHighlighter> TextEdit::get_syntax_highlighter() const {
@@ -5052,7 +5052,7 @@ void TextEdit::set_highlight_current_line(bool p_enabled) {
}
highlight_current_line = p_enabled;
- update();
+ queue_redraw();
}
bool TextEdit::is_highlight_current_line_enabled() const {
@@ -5065,7 +5065,7 @@ void TextEdit::set_highlight_all_occurrences(const bool p_enabled) {
}
highlight_all_occurrences = p_enabled;
- update();
+ queue_redraw();
}
bool TextEdit::is_highlight_all_occurrences_enabled() const {
@@ -5081,7 +5081,7 @@ void TextEdit::set_draw_control_chars(bool p_enabled) {
text.set_draw_control_chars(draw_control_chars);
text.invalidate_font();
_update_placeholder();
- update();
+ queue_redraw();
}
}
@@ -5095,7 +5095,7 @@ void TextEdit::set_draw_tabs(bool p_enabled) {
}
draw_tabs = p_enabled;
- update();
+ queue_redraw();
}
bool TextEdit::is_drawing_tabs() const {
@@ -5108,7 +5108,7 @@ void TextEdit::set_draw_spaces(bool p_enabled) {
}
draw_spaces = p_enabled;
- update();
+ queue_redraw();
}
bool TextEdit::is_drawing_spaces() const {
@@ -5560,7 +5560,7 @@ void TextEdit::_set_hiding_enabled(bool p_enabled) {
_unhide_all_lines();
}
hiding_enabled = p_enabled;
- update();
+ queue_redraw();
}
bool TextEdit::_is_hiding_enabled() const {
@@ -5577,7 +5577,7 @@ void TextEdit::_unhide_all_lines() {
text.set_hidden(i, false);
}
_update_scrollbars();
- update();
+ queue_redraw();
}
void TextEdit::_set_line_as_hidden(int p_line, bool p_hidden) {
@@ -5590,7 +5590,7 @@ void TextEdit::_set_line_as_hidden(int p_line, bool p_hidden) {
if (_is_hiding_enabled() || !p_hidden) {
text.set_hidden(p_line, p_hidden);
}
- update();
+ queue_redraw();
}
// Symbol lookup.
@@ -5600,7 +5600,7 @@ void TextEdit::_set_symbol_lookup_word(const String &p_symbol) {
}
lookup_symbol_word = p_symbol;
- update();
+ queue_redraw();
}
/* Text manipulation */
@@ -5985,14 +5985,14 @@ void TextEdit::_reset_caret_blink_timer() {
if (has_focus()) {
caret_blink_timer->stop();
caret_blink_timer->start();
- update();
+ queue_redraw();
}
}
void TextEdit::_toggle_draw_caret() {
draw_caret = !draw_caret;
if (is_visible_in_tree() && has_focus() && window_has_focus) {
- update();
+ queue_redraw();
}
}
@@ -6054,7 +6054,7 @@ void TextEdit::_update_selection_mode_pointer() {
set_caret_line(line, false);
set_caret_column(col);
- update();
+ queue_redraw();
click_select_held->start();
}
@@ -6106,7 +6106,7 @@ void TextEdit::_update_selection_mode_word() {
DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text());
}
- update();
+ queue_redraw();
click_select_held->start();
}
@@ -6137,7 +6137,7 @@ void TextEdit::_update_selection_mode_line() {
DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text());
}
- update();
+ queue_redraw();
click_select_held->start();
}
@@ -6163,7 +6163,7 @@ void TextEdit::_post_shift_selection() {
if (selection.active && selection.selecting_mode == SelectionMode::SELECTION_MODE_SHIFT) {
select(selection.selecting_line, selection.selecting_column, caret.line, caret.column);
- update();
+ queue_redraw();
}
selection.selecting_text = true;
@@ -6325,7 +6325,7 @@ void TextEdit::_scroll_moved(double p_to_val) {
caret.line_ofs = n_line;
caret.wrap_ofs = wi;
}
- update();
+ queue_redraw();
}
double TextEdit::_get_visible_lines_offset() const {
@@ -6447,7 +6447,7 @@ void TextEdit::_update_minimap_hover() {
if (hovering_minimap) {
// Only redraw if the hovering status changed.
hovering_minimap = false;
- update();
+ queue_redraw();
}
// Return early to avoid running the operations below when not needed.
@@ -6460,7 +6460,7 @@ void TextEdit::_update_minimap_hover() {
if (new_hovering_minimap != hovering_minimap) {
// Only redraw if the hovering status changed.
hovering_minimap = new_hovering_minimap;
- update();
+ queue_redraw();
}
}
@@ -6522,7 +6522,7 @@ void TextEdit::_update_gutter_width() {
if (gutters_width > 0) {
gutter_padding = 2;
}
- update();
+ queue_redraw();
}
/* Syntax highlighting. */
diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp
index 916bb2981e..e2fd903e0e 100644
--- a/scene/gui/texture_button.cpp
+++ b/scene/gui/texture_button.cpp
@@ -299,7 +299,7 @@ void TextureButton::set_normal_texture(const Ref<Texture2D> &p_normal) {
}
normal = p_normal;
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -309,7 +309,7 @@ void TextureButton::set_pressed_texture(const Ref<Texture2D> &p_pressed) {
}
pressed = p_pressed;
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -319,7 +319,7 @@ void TextureButton::set_hover_texture(const Ref<Texture2D> &p_hover) {
}
hover = p_hover;
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -329,7 +329,7 @@ void TextureButton::set_disabled_texture(const Ref<Texture2D> &p_disabled) {
}
disabled = p_disabled;
- update();
+ queue_redraw();
}
void TextureButton::set_click_mask(const Ref<BitMap> &p_click_mask) {
@@ -337,7 +337,7 @@ void TextureButton::set_click_mask(const Ref<BitMap> &p_click_mask) {
return;
}
click_mask = p_click_mask;
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -380,7 +380,7 @@ void TextureButton::set_ignore_texture_size(bool p_ignore) {
ignore_texture_size = p_ignore;
update_minimum_size();
- update();
+ queue_redraw();
}
void TextureButton::set_stretch_mode(StretchMode p_stretch_mode) {
@@ -389,7 +389,7 @@ void TextureButton::set_stretch_mode(StretchMode p_stretch_mode) {
}
stretch_mode = p_stretch_mode;
- update();
+ queue_redraw();
}
TextureButton::StretchMode TextureButton::get_stretch_mode() const {
@@ -402,7 +402,7 @@ void TextureButton::set_flip_h(bool p_flip) {
}
hflip = p_flip;
- update();
+ queue_redraw();
}
bool TextureButton::is_flipped_h() const {
@@ -415,7 +415,7 @@ void TextureButton::set_flip_v(bool p_flip) {
}
vflip = p_flip;
- update();
+ queue_redraw();
}
bool TextureButton::is_flipped_v() const {
diff --git a/scene/gui/texture_progress_bar.cpp b/scene/gui/texture_progress_bar.cpp
index 2a9e1a8990..a9982b3ece 100644
--- a/scene/gui/texture_progress_bar.cpp
+++ b/scene/gui/texture_progress_bar.cpp
@@ -38,7 +38,7 @@ void TextureProgressBar::set_under_texture(const Ref<Texture2D> &p_texture) {
}
under = p_texture;
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -52,7 +52,7 @@ void TextureProgressBar::set_over_texture(const Ref<Texture2D> &p_texture) {
}
over = p_texture;
- update();
+ queue_redraw();
if (under.is_null()) {
update_minimum_size();
}
@@ -70,7 +70,7 @@ void TextureProgressBar::set_stretch_margin(Side p_side, int p_size) {
}
stretch_margin[p_side] = p_size;
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -85,7 +85,7 @@ void TextureProgressBar::set_nine_patch_stretch(bool p_stretch) {
}
nine_patch_stretch = p_stretch;
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -113,7 +113,7 @@ void TextureProgressBar::set_progress_texture(const Ref<Texture2D> &p_texture) {
}
progress = p_texture;
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -127,7 +127,7 @@ void TextureProgressBar::set_progress_offset(Point2 p_offset) {
}
progress_offset = p_offset;
- update();
+ queue_redraw();
}
Point2 TextureProgressBar::get_progress_offset() const {
@@ -140,7 +140,7 @@ void TextureProgressBar::set_tint_under(const Color &p_tint) {
}
tint_under = p_tint;
- update();
+ queue_redraw();
}
Color TextureProgressBar::get_tint_under() const {
@@ -153,7 +153,7 @@ void TextureProgressBar::set_tint_progress(const Color &p_tint) {
}
tint_progress = p_tint;
- update();
+ queue_redraw();
}
Color TextureProgressBar::get_tint_progress() const {
@@ -166,7 +166,7 @@ void TextureProgressBar::set_tint_over(const Color &p_tint) {
}
tint_over = p_tint;
- update();
+ queue_redraw();
}
Color TextureProgressBar::get_tint_over() const {
@@ -591,7 +591,7 @@ void TextureProgressBar::set_fill_mode(int p_fill) {
}
mode = (FillMode)p_fill;
- update();
+ queue_redraw();
}
int TextureProgressBar::get_fill_mode() {
@@ -611,7 +611,7 @@ void TextureProgressBar::set_radial_initial_angle(float p_angle) {
}
rad_init_angle = p_angle;
- update();
+ queue_redraw();
}
float TextureProgressBar::get_radial_initial_angle() {
@@ -626,7 +626,7 @@ void TextureProgressBar::set_fill_degrees(float p_angle) {
}
rad_max_degrees = angle_clamped;
- update();
+ queue_redraw();
}
float TextureProgressBar::get_fill_degrees() {
@@ -639,7 +639,7 @@ void TextureProgressBar::set_radial_center_offset(const Point2 &p_off) {
}
rad_center_off = p_off;
- update();
+ queue_redraw();
}
Point2 TextureProgressBar::get_radial_center_offset() {
diff --git a/scene/gui/texture_rect.cpp b/scene/gui/texture_rect.cpp
index 4dd1c74c12..da53da20b0 100644
--- a/scene/gui/texture_rect.cpp
+++ b/scene/gui/texture_rect.cpp
@@ -150,7 +150,7 @@ void TextureRect::_bind_methods() {
void TextureRect::_texture_changed() {
if (texture.is_valid()) {
- update();
+ queue_redraw();
update_minimum_size();
}
}
@@ -170,7 +170,7 @@ void TextureRect::set_texture(const Ref<Texture2D> &p_tex) {
texture->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TextureRect::_texture_changed));
}
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -184,7 +184,7 @@ void TextureRect::set_ignore_texture_size(bool p_ignore) {
}
ignore_texture_size = p_ignore;
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -198,7 +198,7 @@ void TextureRect::set_stretch_mode(StretchMode p_mode) {
}
stretch_mode = p_mode;
- update();
+ queue_redraw();
}
TextureRect::StretchMode TextureRect::get_stretch_mode() const {
@@ -211,7 +211,7 @@ void TextureRect::set_flip_h(bool p_flip) {
}
hflip = p_flip;
- update();
+ queue_redraw();
}
bool TextureRect::is_flipped_h() const {
@@ -224,7 +224,7 @@ void TextureRect::set_flip_v(bool p_flip) {
}
vflip = p_flip;
- update();
+ queue_redraw();
}
bool TextureRect::is_flipped_v() const {
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 2b19ee4d0b..e8164b5728 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -126,13 +126,13 @@ void TreeItem::_change_tree(Tree *p_tree) {
tree->pressing_for_editor = false;
}
- tree->update();
+ tree->queue_redraw();
}
tree = p_tree;
if (tree) {
- tree->update();
+ tree->queue_redraw();
cells.resize(tree->columns.size());
}
}
@@ -551,7 +551,7 @@ void TreeItem::set_collapsed(bool p_collapsed) {
select(tree->selected_col);
}
- tree->update();
+ tree->queue_redraw();
}
}
@@ -569,7 +569,7 @@ void TreeItem::set_visible(bool p_visible) {
}
visible = p_visible;
if (tree) {
- tree->update();
+ tree->queue_redraw();
_changed_notify();
}
}
@@ -610,7 +610,7 @@ TreeItem *TreeItem::create_child(int p_idx) {
TreeItem *ti = memnew(TreeItem(tree));
if (tree) {
ti->cells.resize(tree->columns.size());
- tree->update();
+ tree->queue_redraw();
}
TreeItem *l_prev = nullptr;
@@ -880,7 +880,7 @@ void TreeItem::move_before(TreeItem *p_item) {
p_item->prev = this;
if (tree && old_tree == tree) {
- tree->update();
+ tree->queue_redraw();
}
validate_cache();
@@ -924,7 +924,7 @@ void TreeItem::move_after(TreeItem *p_item) {
}
if (tree && old_tree == tree) {
- tree->update();
+ tree->queue_redraw();
}
validate_cache();
}
@@ -939,7 +939,7 @@ void TreeItem::remove_child(TreeItem *p_item) {
p_item->parent = nullptr;
if (tree) {
- tree->update();
+ tree->queue_redraw();
}
validate_cache();
}
@@ -972,7 +972,7 @@ void TreeItem::set_as_cursor(int p_column) {
}
tree->selected_item = this;
tree->selected_col = p_column;
- tree->update();
+ tree->queue_redraw();
}
void TreeItem::select(int p_column) {
@@ -1013,7 +1013,7 @@ Ref<Texture2D> TreeItem::get_button(int p_column, int p_idx) const {
return cells[p_column].buttons[p_idx].texture;
}
-String TreeItem::get_button_tooltip(int p_column, int p_idx) const {
+String TreeItem::get_button_tooltip_text(int p_column, int p_idx) const {
ERR_FAIL_INDEX_V(p_column, cells.size(), String());
ERR_FAIL_INDEX_V(p_idx, cells[p_column].buttons.size(), String());
return cells[p_column].buttons[p_idx].tooltip;
@@ -1160,12 +1160,12 @@ int TreeItem::get_custom_font_size(int p_column) const {
return cells[p_column].custom_font_size;
}
-void TreeItem::set_tooltip(int p_column, const String &p_tooltip) {
+void TreeItem::set_tooltip_text(int p_column, const String &p_tooltip) {
ERR_FAIL_INDEX(p_column, cells.size());
cells.write[p_column].tooltip = p_tooltip;
}
-String TreeItem::get_tooltip(int p_column) const {
+String TreeItem::get_tooltip_text(int p_column) const {
ERR_FAIL_INDEX_V(p_column, cells.size(), "");
return cells[p_column].tooltip;
}
@@ -1286,14 +1286,14 @@ Size2 TreeItem::get_minimum_size(int p_column) {
// Icon.
if (cell.mode == CELL_MODE_CHECK) {
- size.width += tree->cache.checked->get_width() + tree->cache.hseparation;
+ size.width += tree->theme_cache.checked->get_width() + tree->theme_cache.hseparation;
}
if (cell.icon.is_valid()) {
Size2i icon_size = cell.get_icon_size();
if (cell.icon_max_w > 0 && icon_size.width > cell.icon_max_w) {
icon_size.width = cell.icon_max_w;
}
- size.width += icon_size.width + tree->cache.hseparation;
+ size.width += icon_size.width + tree->theme_cache.hseparation;
size.height = MAX(size.height, icon_size.height);
}
@@ -1301,13 +1301,13 @@ Size2 TreeItem::get_minimum_size(int p_column) {
for (int i = 0; i < cell.buttons.size(); i++) {
Ref<Texture2D> texture = cell.buttons[i].texture;
if (texture.is_valid()) {
- Size2 button_size = texture->get_size() + tree->cache.button_pressed->get_minimum_size();
+ Size2 button_size = texture->get_size() + tree->theme_cache.button_pressed->get_minimum_size();
size.width += button_size.width;
size.height = MAX(size.height, button_size.height);
}
}
if (cell.buttons.size() >= 2) {
- size.width += (cell.buttons.size() - 1) * tree->cache.button_margin;
+ size.width += (cell.buttons.size() - 1) * tree->theme_cache.button_margin;
}
cells.write[p_column].cached_minimum_size = size;
@@ -1441,9 +1441,9 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_custom_as_button", "column", "enable"), &TreeItem::set_custom_as_button);
ClassDB::bind_method(D_METHOD("is_custom_set_as_button", "column"), &TreeItem::is_custom_set_as_button);
- ClassDB::bind_method(D_METHOD("add_button", "column", "button", "id", "disabled", "tooltip"), &TreeItem::add_button, DEFVAL(-1), DEFVAL(false), DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("add_button", "column", "button", "id", "disabled", "tooltip_text"), &TreeItem::add_button, DEFVAL(-1), DEFVAL(false), DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_button_count", "column"), &TreeItem::get_button_count);
- ClassDB::bind_method(D_METHOD("get_button_tooltip", "column", "button_idx"), &TreeItem::get_button_tooltip);
+ ClassDB::bind_method(D_METHOD("get_button_tooltip_text", "column", "button_idx"), &TreeItem::get_button_tooltip_text);
ClassDB::bind_method(D_METHOD("get_button_id", "column", "button_idx"), &TreeItem::get_button_id);
ClassDB::bind_method(D_METHOD("get_button_by_id", "column", "id"), &TreeItem::get_button_by_id);
ClassDB::bind_method(D_METHOD("get_button", "column", "button_idx"), &TreeItem::get_button);
@@ -1452,8 +1452,8 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_button_disabled", "column", "button_idx", "disabled"), &TreeItem::set_button_disabled);
ClassDB::bind_method(D_METHOD("is_button_disabled", "column", "button_idx"), &TreeItem::is_button_disabled);
- ClassDB::bind_method(D_METHOD("set_tooltip", "column", "tooltip"), &TreeItem::set_tooltip);
- ClassDB::bind_method(D_METHOD("get_tooltip", "column"), &TreeItem::get_tooltip);
+ ClassDB::bind_method(D_METHOD("set_tooltip_text", "column", "tooltip"), &TreeItem::set_tooltip_text);
+ ClassDB::bind_method(D_METHOD("get_tooltip_text", "column"), &TreeItem::get_tooltip_text);
ClassDB::bind_method(D_METHOD("set_text_alignment", "column", "text_alignment"), &TreeItem::set_text_alignment);
ClassDB::bind_method(D_METHOD("get_text_alignment", "column"), &TreeItem::get_text_alignment);
@@ -1535,68 +1535,66 @@ TreeItem::~TreeItem() {
/**********************************************/
/**********************************************/
-void Tree::update_cache() {
- cache.font = get_theme_font(SNAME("font"));
- cache.font_size = get_theme_font_size(SNAME("font_size"));
- cache.tb_font = get_theme_font(SNAME("title_button_font"));
- cache.tb_font_size = get_theme_font_size(SNAME("title_button_font_size"));
- cache.bg = get_theme_stylebox(SNAME("bg"));
- cache.selected = get_theme_stylebox(SNAME("selected"));
- cache.selected_focus = get_theme_stylebox(SNAME("selected_focus"));
- cache.cursor = get_theme_stylebox(SNAME("cursor"));
- cache.cursor_unfocus = get_theme_stylebox(SNAME("cursor_unfocused"));
- cache.button_pressed = get_theme_stylebox(SNAME("button_pressed"));
-
- cache.checked = get_theme_icon(SNAME("checked"));
- cache.unchecked = get_theme_icon(SNAME("unchecked"));
- cache.indeterminate = get_theme_icon(SNAME("indeterminate"));
- if (is_layout_rtl()) {
- cache.arrow_collapsed = get_theme_icon(SNAME("arrow_collapsed_mirrored"));
- } else {
- cache.arrow_collapsed = get_theme_icon(SNAME("arrow_collapsed"));
- }
- cache.arrow = get_theme_icon(SNAME("arrow"));
- cache.select_arrow = get_theme_icon(SNAME("select_arrow"));
- cache.updown = get_theme_icon(SNAME("updown"));
-
- cache.custom_button = get_theme_stylebox(SNAME("custom_button"));
- cache.custom_button_hover = get_theme_stylebox(SNAME("custom_button_hover"));
- cache.custom_button_pressed = get_theme_stylebox(SNAME("custom_button_pressed"));
- cache.custom_button_font_highlight = get_theme_color(SNAME("custom_button_font_highlight"));
-
- cache.font_color = get_theme_color(SNAME("font_color"));
- cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
- cache.drop_position_color = get_theme_color(SNAME("drop_position_color"));
- cache.hseparation = get_theme_constant(SNAME("h_separation"));
- cache.vseparation = get_theme_constant(SNAME("v_separation"));
- cache.item_margin = get_theme_constant(SNAME("item_margin"));
- cache.button_margin = get_theme_constant(SNAME("button_margin"));
-
- cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
- cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
-
- cache.draw_guides = get_theme_constant(SNAME("draw_guides"));
- cache.guide_color = get_theme_color(SNAME("guide_color"));
- cache.draw_relationship_lines = get_theme_constant(SNAME("draw_relationship_lines"));
- cache.relationship_line_width = get_theme_constant(SNAME("relationship_line_width"));
- cache.parent_hl_line_width = get_theme_constant(SNAME("parent_hl_line_width"));
- cache.children_hl_line_width = get_theme_constant(SNAME("children_hl_line_width"));
- cache.parent_hl_line_margin = get_theme_constant(SNAME("parent_hl_line_margin"));
- cache.relationship_line_color = get_theme_color(SNAME("relationship_line_color"));
- cache.parent_hl_line_color = get_theme_color(SNAME("parent_hl_line_color"));
- cache.children_hl_line_color = get_theme_color(SNAME("children_hl_line_color"));
-
- cache.scroll_border = get_theme_constant(SNAME("scroll_border"));
- cache.scroll_speed = get_theme_constant(SNAME("scroll_speed"));
-
- cache.title_button = get_theme_stylebox(SNAME("title_button_normal"));
- cache.title_button_pressed = get_theme_stylebox(SNAME("title_button_pressed"));
- cache.title_button_hover = get_theme_stylebox(SNAME("title_button_hover"));
- cache.title_button_color = get_theme_color(SNAME("title_button_color"));
-
- cache.base_scale = get_theme_default_base_scale();
-
- v_scroll->set_custom_step(cache.font->get_height(cache.font_size));
+void Tree::_update_theme_item_cache() {
+ Control::_update_theme_item_cache();
+
+ theme_cache.font = get_theme_font(SNAME("font"));
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
+ theme_cache.tb_font = get_theme_font(SNAME("title_button_font"));
+ theme_cache.tb_font_size = get_theme_font_size(SNAME("title_button_font_size"));
+ theme_cache.bg = get_theme_stylebox(SNAME("bg"));
+ theme_cache.bg_focus = get_theme_stylebox(SNAME("bg_focus"));
+ theme_cache.selected = get_theme_stylebox(SNAME("selected"));
+ theme_cache.selected_focus = get_theme_stylebox(SNAME("selected_focus"));
+ theme_cache.cursor = get_theme_stylebox(SNAME("cursor"));
+ theme_cache.cursor_unfocus = get_theme_stylebox(SNAME("cursor_unfocused"));
+ theme_cache.button_pressed = get_theme_stylebox(SNAME("button_pressed"));
+
+ theme_cache.checked = get_theme_icon(SNAME("checked"));
+ theme_cache.unchecked = get_theme_icon(SNAME("unchecked"));
+ theme_cache.indeterminate = get_theme_icon(SNAME("indeterminate"));
+ theme_cache.arrow = get_theme_icon(SNAME("arrow"));
+ theme_cache.arrow_collapsed = get_theme_icon(SNAME("arrow_collapsed"));
+ theme_cache.arrow_collapsed_mirrored = get_theme_icon(SNAME("arrow_collapsed_mirrored"));
+ theme_cache.select_arrow = get_theme_icon(SNAME("select_arrow"));
+ theme_cache.updown = get_theme_icon(SNAME("updown"));
+
+ theme_cache.custom_button = get_theme_stylebox(SNAME("custom_button"));
+ theme_cache.custom_button_hover = get_theme_stylebox(SNAME("custom_button_hover"));
+ theme_cache.custom_button_pressed = get_theme_stylebox(SNAME("custom_button_pressed"));
+ theme_cache.custom_button_font_highlight = get_theme_color(SNAME("custom_button_font_highlight"));
+
+ theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
+ theme_cache.drop_position_color = get_theme_color(SNAME("drop_position_color"));
+ theme_cache.hseparation = get_theme_constant(SNAME("h_separation"));
+ theme_cache.vseparation = get_theme_constant(SNAME("v_separation"));
+ theme_cache.item_margin = get_theme_constant(SNAME("item_margin"));
+ theme_cache.button_margin = get_theme_constant(SNAME("button_margin"));
+
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+ theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
+
+ theme_cache.draw_guides = get_theme_constant(SNAME("draw_guides"));
+ theme_cache.guide_color = get_theme_color(SNAME("guide_color"));
+ theme_cache.draw_relationship_lines = get_theme_constant(SNAME("draw_relationship_lines"));
+ theme_cache.relationship_line_width = get_theme_constant(SNAME("relationship_line_width"));
+ theme_cache.parent_hl_line_width = get_theme_constant(SNAME("parent_hl_line_width"));
+ theme_cache.children_hl_line_width = get_theme_constant(SNAME("children_hl_line_width"));
+ theme_cache.parent_hl_line_margin = get_theme_constant(SNAME("parent_hl_line_margin"));
+ theme_cache.relationship_line_color = get_theme_color(SNAME("relationship_line_color"));
+ theme_cache.parent_hl_line_color = get_theme_color(SNAME("parent_hl_line_color"));
+ theme_cache.children_hl_line_color = get_theme_color(SNAME("children_hl_line_color"));
+
+ theme_cache.scroll_border = get_theme_constant(SNAME("scroll_border"));
+ theme_cache.scroll_speed = get_theme_constant(SNAME("scroll_speed"));
+
+ theme_cache.title_button = get_theme_stylebox(SNAME("title_button_normal"));
+ theme_cache.title_button_pressed = get_theme_stylebox(SNAME("title_button_pressed"));
+ theme_cache.title_button_hover = get_theme_stylebox(SNAME("title_button_hover"));
+ theme_cache.title_button_color = get_theme_color(SNAME("title_button_color"));
+
+ theme_cache.base_scale = get_theme_default_base_scale();
}
int Tree::compute_item_height(TreeItem *p_item) const {
@@ -1604,7 +1602,7 @@ int Tree::compute_item_height(TreeItem *p_item) const {
return 0;
}
- ERR_FAIL_COND_V(cache.font.is_null(), 0);
+ ERR_FAIL_COND_V(theme_cache.font.is_null(), 0);
int height = 0;
for (int i = 0; i < columns.size(); i++) {
@@ -1622,7 +1620,7 @@ int Tree::compute_item_height(TreeItem *p_item) const {
switch (p_item->cells[i].mode) {
case TreeItem::CELL_MODE_CHECK: {
- int check_icon_h = cache.checked->get_height();
+ int check_icon_h = theme_cache.checked->get_height();
if (height < check_icon_h) {
height = check_icon_h;
}
@@ -1642,7 +1640,7 @@ int Tree::compute_item_height(TreeItem *p_item) const {
}
}
if (p_item->cells[i].mode == TreeItem::CELL_MODE_CUSTOM && p_item->cells[i].custom_button) {
- height += cache.custom_button->get_minimum_size().height;
+ height += theme_cache.custom_button->get_minimum_size().height;
}
} break;
@@ -1655,7 +1653,7 @@ int Tree::compute_item_height(TreeItem *p_item) const {
height = item_min_height;
}
- height += cache.vseparation;
+ height += theme_cache.vseparation;
return height;
}
@@ -1665,7 +1663,7 @@ int Tree::get_item_height(TreeItem *p_item) const {
return 0;
}
int height = compute_item_height(p_item);
- height += cache.vseparation;
+ height += theme_cache.vseparation;
if (!p_item->collapsed) { /* if not collapsed, check the children */
@@ -1682,7 +1680,7 @@ int Tree::get_item_height(TreeItem *p_item) const {
}
void Tree::draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color, const Color &p_icon_color, int p_ol_size, const Color &p_ol_color) {
- ERR_FAIL_COND(cache.font.is_null());
+ ERR_FAIL_COND(theme_cache.font.is_null());
Rect2i rect = p_rect;
Size2 ts = p_cell.text_buf->get_size();
@@ -1694,7 +1692,7 @@ void Tree::draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Co
if (p_cell.icon_max_w > 0 && bmsize.width > p_cell.icon_max_w) {
bmsize.width = p_cell.icon_max_w;
}
- w += bmsize.width + cache.hseparation;
+ w += bmsize.width + theme_cache.hseparation;
if (rect.size.width > 0 && (w + ts.width) > rect.size.width) {
ts.width = rect.size.width - w;
}
@@ -1728,8 +1726,8 @@ void Tree::draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Co
p_cell.text_buf->draw_outline(ci, draw_pos, p_ol_size, p_ol_color);
}
p_cell.text_buf->draw(ci, draw_pos, p_color);
- rect.position.x += ts.width + cache.hseparation;
- rect.size.x -= ts.width + cache.hseparation;
+ rect.position.x += ts.width + theme_cache.hseparation;
+ rect.size.x -= ts.width + theme_cache.hseparation;
}
if (!p_cell.icon.is_null()) {
@@ -1741,8 +1739,8 @@ void Tree::draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Co
}
p_cell.draw_icon(ci, rect.position + Size2i(0, Math::floor((real_t)(rect.size.y - bmsize.y) / 2)), bmsize, p_icon_color);
- rect.position.x += bmsize.x + cache.hseparation;
- rect.size.x -= bmsize.x + cache.hseparation;
+ rect.position.x += bmsize.x + theme_cache.hseparation;
+ rect.size.x -= bmsize.x + theme_cache.hseparation;
}
if (!rtl) {
@@ -1764,7 +1762,7 @@ void Tree::update_column(int p_col) {
columns.write[p_col].text_buf->set_direction((TextServer::Direction)columns[p_col].text_direction);
}
- columns.write[p_col].text_buf->add_string(columns[p_col].title, cache.font, cache.font_size, columns[p_col].language);
+ columns.write[p_col].text_buf->add_string(columns[p_col].title, theme_cache.font, theme_cache.font_size, columns[p_col].language);
}
void Tree::update_item_cell(TreeItem *p_item, int p_col) {
@@ -1813,14 +1811,14 @@ void Tree::update_item_cell(TreeItem *p_item, int p_col) {
if (p_item->cells[p_col].custom_font.is_valid()) {
font = p_item->cells[p_col].custom_font;
} else {
- font = cache.font;
+ font = theme_cache.font;
}
int font_size;
if (p_item->cells[p_col].custom_font_size > 0) {
font_size = p_item->cells[p_col].custom_font_size;
} else {
- font_size = cache.font_size;
+ font_size = theme_cache.font_size;
}
p_item->cells.write[p_col].text_buf->add_string(valtext, font, font_size, p_item->cells[p_col].language);
TS->shaped_text_set_bidi_override(p_item->cells[p_col].text_buf->get_rid(), structured_text_parser(p_item->cells[p_col].st_parser, p_item->cells[p_col].st_args, valtext));
@@ -1840,7 +1838,7 @@ void Tree::update_item_cache(TreeItem *p_item) {
}
int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 &p_draw_size, TreeItem *p_item) {
- if (p_pos.y - cache.offset.y > (p_draw_size.height)) {
+ if (p_pos.y - theme_cache.offset.y > (p_draw_size.height)) {
return -1; //draw no more!
}
@@ -1856,18 +1854,18 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
bool rtl = cache.rtl;
/* Calculate height of the label part */
- label_h += cache.vseparation;
+ label_h += theme_cache.vseparation;
/* Draw label, if height fits */
bool skip = (p_item == root && hide_root);
- if (!skip && (p_pos.y + label_h - cache.offset.y) > 0) {
+ if (!skip && (p_pos.y + label_h - theme_cache.offset.y) > 0) {
// Draw separation.
- ERR_FAIL_COND_V(cache.font.is_null(), -1);
+ ERR_FAIL_COND_V(theme_cache.font.is_null(), -1);
- int ofs = p_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin);
+ int ofs = p_pos.x + ((p_item->disable_folding || hide_folding) ? theme_cache.hseparation : theme_cache.item_margin);
int skip2 = 0;
for (int i = 0; i < columns.size(); i++) {
if (skip2) {
@@ -1885,8 +1883,8 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
continue;
}
} else {
- ofs += cache.hseparation;
- w -= cache.hseparation;
+ ofs += theme_cache.hseparation;
+ w -= theme_cache.hseparation;
}
if (p_item->cells[i].expand_right) {
@@ -1902,10 +1900,10 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
int button_w = 0;
for (int j = p_item->cells[i].buttons.size() - 1; j >= 0; j--) {
Ref<Texture2D> b = p_item->cells[i].buttons[j].texture;
- button_w += b->get_size().width + cache.button_pressed->get_minimum_size().width + cache.button_margin;
+ button_w += b->get_size().width + theme_cache.button_pressed->get_minimum_size().width + theme_cache.button_margin;
}
- int total_ofs = ofs - cache.offset.x;
+ int total_ofs = ofs - theme_cache.offset.x;
if (total_ofs + w > p_draw_size.width) {
w = MAX(button_w, p_draw_size.width - total_ofs);
@@ -1915,9 +1913,9 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
int bw = 0;
for (int j = p_item->cells[i].buttons.size() - 1; j >= 0; j--) {
Ref<Texture2D> b = p_item->cells[i].buttons[j].texture;
- Size2 s = b->get_size() + cache.button_pressed->get_minimum_size();
+ Size2 s = b->get_size() + theme_cache.button_pressed->get_minimum_size();
- Point2i o = Point2i(ofs + w - s.width, p_pos.y) - cache.offset + p_draw_ofs;
+ Point2i o = Point2i(ofs + w - s.width, p_pos.y) - theme_cache.offset + p_draw_ofs;
if (cache.click_type == Cache::CLICK_BUTTON && cache.click_item == p_item && cache.click_column == i && cache.click_index == j && !p_item->cells[i].buttons[j].disabled) {
// Being pressed.
@@ -1925,48 +1923,48 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (rtl) {
od.x = get_size().width - od.x - s.x;
}
- cache.button_pressed->draw(get_canvas_item(), Rect2(od.x, od.y, s.width, MAX(s.height, label_h)));
+ theme_cache.button_pressed->draw(get_canvas_item(), Rect2(od.x, od.y, s.width, MAX(s.height, label_h)));
}
o.y += (label_h - s.height) / 2;
- o += cache.button_pressed->get_offset();
+ o += theme_cache.button_pressed->get_offset();
if (rtl) {
o.x = get_size().width - o.x - b->get_width();
}
b->draw(ci, o, p_item->cells[i].buttons[j].disabled ? Color(1, 1, 1, 0.5) : p_item->cells[i].buttons[j].color);
- w -= s.width + cache.button_margin;
- bw += s.width + cache.button_margin;
+ w -= s.width + theme_cache.button_margin;
+ bw += s.width + theme_cache.button_margin;
}
- Rect2i item_rect = Rect2i(Point2i(ofs, p_pos.y) - cache.offset + p_draw_ofs, Size2i(w, label_h));
+ Rect2i item_rect = Rect2i(Point2i(ofs, p_pos.y) - theme_cache.offset + p_draw_ofs, Size2i(w, label_h));
Rect2i cell_rect = item_rect;
if (i != 0) {
- cell_rect.position.x -= cache.hseparation;
- cell_rect.size.x += cache.hseparation;
+ cell_rect.position.x -= theme_cache.hseparation;
+ cell_rect.size.x += theme_cache.hseparation;
}
- if (cache.draw_guides) {
+ if (theme_cache.draw_guides) {
Rect2 r = cell_rect;
if (rtl) {
r.position.x = get_size().width - r.position.x - r.size.x;
}
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(r.position.x, r.position.y + r.size.height), r.position + r.size, cache.guide_color, 1);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(r.position.x, r.position.y + r.size.height), r.position + r.size, theme_cache.guide_color, 1);
}
if (i == 0) {
if (p_item->cells[0].selected && select_mode == SELECT_ROW) {
- Rect2i row_rect = Rect2i(Point2i(cache.bg->get_margin(SIDE_LEFT), item_rect.position.y), Size2i(get_size().width - cache.bg->get_minimum_size().width, item_rect.size.y));
+ Rect2i row_rect = Rect2i(Point2i(theme_cache.bg->get_margin(SIDE_LEFT), item_rect.position.y), Size2i(get_size().width - theme_cache.bg->get_minimum_size().width, item_rect.size.y));
//Rect2 r = Rect2i(row_rect.pos,row_rect.size);
//r.grow(cache.selected->get_margin(SIDE_LEFT));
if (rtl) {
row_rect.position.x = get_size().width - row_rect.position.x - row_rect.size.x;
}
if (has_focus()) {
- cache.selected_focus->draw(ci, row_rect);
+ theme_cache.selected_focus->draw(ci, row_rect);
} else {
- cache.selected->draw(ci, row_rect);
+ theme_cache.selected->draw(ci, row_rect);
}
}
}
@@ -1982,9 +1980,9 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
}
if (p_item->cells[i].selected) {
if (has_focus()) {
- cache.selected_focus->draw(ci, r);
+ theme_cache.selected_focus->draw(ci, r);
} else {
- cache.selected->draw(ci, r);
+ theme_cache.selected->draw(ci, r);
}
}
}
@@ -1996,8 +1994,8 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
r.position.x = p_draw_ofs.x;
r.size.x = w + ofs;
} else {
- r.position.x -= cache.hseparation;
- r.size.x += cache.hseparation;
+ r.position.x -= theme_cache.hseparation;
+ r.size.x += theme_cache.hseparation;
}
if (rtl) {
r.position.x = get_size().width - r.position.x - r.size.x;
@@ -2020,28 +2018,34 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (drop_mode_over == p_item) {
if (drop_mode_section == 0 || drop_mode_section == -1) {
// Line above.
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, r.size.x, 1), cache.drop_position_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, r.size.x, 1), theme_cache.drop_position_color);
}
if (drop_mode_section == 0) {
// Side lines.
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, 1, r.size.y), cache.drop_position_color);
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x + r.size.x - 1, r.position.y, 1, r.size.y), cache.drop_position_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, 1, r.size.y), theme_cache.drop_position_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x + r.size.x - 1, r.position.y, 1, r.size.y), theme_cache.drop_position_color);
}
if (drop_mode_section == 0 || (drop_mode_section == 1 && (!p_item->get_first_child() || p_item->is_collapsed()))) {
// Line below.
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y + r.size.y, r.size.x, 1), cache.drop_position_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y + r.size.y, r.size.x, 1), theme_cache.drop_position_color);
}
} else if (drop_mode_over == p_item->get_parent()) {
if (drop_mode_section == 1 && !p_item->get_prev() /* && !drop_mode_over->is_collapsed() */) { // The drop_mode_over shouldn't ever be collapsed in here, otherwise we would be drawing a child of a collapsed item.
// Line above.
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, r.size.x, 1), cache.drop_position_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, r.size.x, 1), theme_cache.drop_position_color);
}
}
}
- Color col = p_item->cells[i].custom_color ? p_item->cells[i].color : get_theme_color(p_item->cells[i].selected ? "font_selected_color" : "font_color");
- Color font_outline_color = cache.font_outline_color;
- int outline_size = cache.font_outline_size;
+ Color col;
+ if (p_item->cells[i].custom_color) {
+ col = p_item->cells[i].color;
+ } else {
+ col = p_item->cells[i].selected ? theme_cache.font_selected_color : theme_cache.font_color;
+ }
+
+ Color font_outline_color = theme_cache.font_outline_color;
+ int outline_size = theme_cache.font_outline_size;
Color icon_col = p_item->cells[i].icon_color;
if (p_item->cells[i].dirty) {
@@ -2061,9 +2065,9 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
draw_item_rect(p_item->cells.write[i], item_rect, col, icon_col, outline_size, font_outline_color);
} break;
case TreeItem::CELL_MODE_CHECK: {
- Ref<Texture2D> checked = cache.checked;
- Ref<Texture2D> unchecked = cache.unchecked;
- Ref<Texture2D> indeterminate = cache.indeterminate;
+ Ref<Texture2D> checked = theme_cache.checked;
+ Ref<Texture2D> unchecked = theme_cache.unchecked;
+ Ref<Texture2D> indeterminate = theme_cache.indeterminate;
Point2i check_ofs = item_rect.position;
check_ofs.y += Math::floor((real_t)(item_rect.size.y - checked->get_height()) / 2);
@@ -2075,7 +2079,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
unchecked->draw(ci, check_ofs);
}
- int check_w = checked->get_width() + cache.hseparation;
+ int check_w = checked->get_width() + theme_cache.hseparation;
text_pos.x += check_w;
@@ -2091,7 +2095,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
break;
}
- Ref<Texture2D> downarrow = cache.select_arrow;
+ Ref<Texture2D> downarrow = theme_cache.select_arrow;
int cell_width = item_rect.size.x - downarrow->get_width();
p_item->cells.write[i].text_buf->set_width(cell_width);
@@ -2113,7 +2117,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
downarrow->draw(ci, arrow_pos);
} else {
- Ref<Texture2D> updown = cache.updown;
+ Ref<Texture2D> updown = theme_cache.updown;
int cell_width = item_rect.size.x - updown->get_width();
@@ -2170,7 +2174,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
break;
}
- Ref<Texture2D> downarrow = cache.select_arrow;
+ Ref<Texture2D> downarrow = theme_cache.select_arrow;
Rect2i ir = item_rect;
@@ -2182,16 +2186,16 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (p_item->cells[i].custom_button) {
if (cache.hover_item == p_item && cache.hover_cell == i) {
if (Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT)) {
- draw_style_box(cache.custom_button_pressed, ir);
+ draw_style_box(theme_cache.custom_button_pressed, ir);
} else {
- draw_style_box(cache.custom_button_hover, ir);
- col = cache.custom_button_font_highlight;
+ draw_style_box(theme_cache.custom_button_hover, ir);
+ col = theme_cache.custom_button_font_highlight;
}
} else {
- draw_style_box(cache.custom_button, ir);
+ draw_style_box(theme_cache.custom_button, ir);
}
- ir.size -= cache.custom_button->get_minimum_size();
- ir.position += cache.custom_button->get_offset();
+ ir.size -= theme_cache.custom_button->get_minimum_size();
+ ir.position += theme_cache.custom_button->get_offset();
}
draw_item_rect(p_item->cells.write[i], ir, col, icon_col, outline_size, font_outline_color);
@@ -2212,9 +2216,9 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
cell_rect.position.x = get_size().width - cell_rect.position.x - cell_rect.size.x;
}
if (has_focus()) {
- cache.cursor->draw(ci, cell_rect);
+ theme_cache.cursor->draw(ci, cell_rect);
} else {
- cache.cursor_unfocus->draw(ci, cell_rect);
+ theme_cache.cursor_unfocus->draw(ci, cell_rect);
}
}
}
@@ -2224,13 +2228,17 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
Ref<Texture2D> arrow;
if (p_item->collapsed) {
- arrow = cache.arrow_collapsed;
+ if (is_layout_rtl()) {
+ arrow = theme_cache.arrow_collapsed_mirrored;
+ } else {
+ arrow = theme_cache.arrow_collapsed;
+ }
} else {
- arrow = cache.arrow;
+ arrow = theme_cache.arrow;
}
- Point2 apos = p_pos + Point2i(0, (label_h - arrow->get_height()) / 2) - cache.offset + p_draw_ofs;
- apos.x += cache.item_margin - arrow->get_width();
+ Point2 apos = p_pos + Point2i(0, (label_h - arrow->get_height()) / 2) - theme_cache.offset + p_draw_ofs;
+ apos.x += theme_cache.item_margin - arrow->get_width();
if (rtl) {
apos.x = get_size().width - apos.x - arrow->get_width();
@@ -2243,7 +2251,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
Point2 children_pos = p_pos;
if (!skip) {
- children_pos.x += cache.item_margin;
+ children_pos.x += theme_cache.item_margin;
htotal += label_h;
children_pos.y += htotal;
}
@@ -2251,7 +2259,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (!p_item->collapsed) { /* if not collapsed, check the children */
TreeItem *c = p_item->first_child;
- int base_ofs = children_pos.y - cache.offset.y + p_draw_ofs.y;
+ int base_ofs = children_pos.y - theme_cache.offset.y + p_draw_ofs.y;
int prev_ofs = base_ofs;
int prev_hl_ofs = base_ofs;
@@ -2262,20 +2270,20 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
}
// Draw relationship lines.
- if (cache.draw_relationship_lines > 0 && (!hide_root || c->parent != root) && c->is_visible()) {
- int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin);
- int parent_ofs = p_pos.x + cache.item_margin;
- Point2i root_pos = Point2i(root_ofs, children_pos.y + label_h / 2) - cache.offset + p_draw_ofs;
+ if (theme_cache.draw_relationship_lines > 0 && (!hide_root || c->parent != root) && c->is_visible()) {
+ int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? theme_cache.hseparation : theme_cache.item_margin);
+ int parent_ofs = p_pos.x + theme_cache.item_margin;
+ Point2i root_pos = Point2i(root_ofs, children_pos.y + label_h / 2) - theme_cache.offset + p_draw_ofs;
if (c->get_visible_child_count() > 0) {
- root_pos -= Point2i(cache.arrow->get_width(), 0);
+ root_pos -= Point2i(theme_cache.arrow->get_width(), 0);
}
- float line_width = cache.relationship_line_width * Math::round(cache.base_scale);
- float parent_line_width = cache.parent_hl_line_width * Math::round(cache.base_scale);
- float children_line_width = cache.children_hl_line_width * Math::round(cache.base_scale);
+ float line_width = theme_cache.relationship_line_width * Math::round(theme_cache.base_scale);
+ float parent_line_width = theme_cache.parent_hl_line_width * Math::round(theme_cache.base_scale);
+ float children_line_width = theme_cache.children_hl_line_width * Math::round(theme_cache.base_scale);
- Point2i parent_pos = Point2i(parent_ofs - cache.arrow->get_width() / 2, p_pos.y + label_h / 2 + cache.arrow->get_height() / 2) - cache.offset + p_draw_ofs;
+ Point2i parent_pos = Point2i(parent_ofs - theme_cache.arrow->get_width() / 2, p_pos.y + label_h / 2 + theme_cache.arrow->get_height() / 2) - theme_cache.offset + p_draw_ofs;
int more_prev_ofs = 0;
@@ -2289,43 +2297,43 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (_is_branch_selected(c)) {
// If this item or one of its children is selected, we draw the line using parent highlight style.
if (htotal >= 0) {
- RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(parent_line_width / 2), root_pos.y), cache.parent_hl_line_color, parent_line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(parent_line_width / 2), root_pos.y), theme_cache.parent_hl_line_color, parent_line_width);
}
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), cache.parent_hl_line_color, parent_line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), theme_cache.parent_hl_line_color, parent_line_width);
- more_prev_ofs = cache.parent_hl_line_margin;
+ more_prev_ofs = theme_cache.parent_hl_line_margin;
prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
} else if (p_item->is_selected(0)) {
// If parent item is selected (but this item is not), we draw the line using children highlight style.
// Siblings of the selected branch can be drawn with a slight offset and their vertical line must appear as highlighted.
if (_is_sibling_branch_selected(c)) {
if (htotal >= 0) {
- RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(parent_line_width / 2), root_pos.y), cache.children_hl_line_color, children_line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(parent_line_width / 2), root_pos.y), theme_cache.children_hl_line_color, children_line_width);
}
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), cache.parent_hl_line_color, parent_line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), theme_cache.parent_hl_line_color, parent_line_width);
prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
} else {
if (htotal >= 0) {
- RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(children_line_width / 2), root_pos.y), cache.children_hl_line_color, children_line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(children_line_width / 2), root_pos.y), theme_cache.children_hl_line_color, children_line_width);
}
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(children_line_width / 2)), Point2i(parent_pos.x, prev_ofs + Math::floor(children_line_width / 2)), cache.children_hl_line_color, children_line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(children_line_width / 2)), Point2i(parent_pos.x, prev_ofs + Math::floor(children_line_width / 2)), theme_cache.children_hl_line_color, children_line_width);
}
} else {
// If nothing of the above is true, we draw the line using normal style.
// Siblings of the selected branch can be drawn with a slight offset and their vertical line must appear as highlighted.
if (_is_sibling_branch_selected(c)) {
if (htotal >= 0) {
- RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + cache.parent_hl_line_margin, root_pos.y), cache.relationship_line_color, line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + theme_cache.parent_hl_line_margin, root_pos.y), theme_cache.relationship_line_color, line_width);
}
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), cache.parent_hl_line_color, parent_line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), theme_cache.parent_hl_line_color, parent_line_width);
prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
} else {
if (htotal >= 0) {
- RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(line_width / 2), root_pos.y), cache.relationship_line_color, line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(line_width / 2), root_pos.y), theme_cache.relationship_line_color, line_width);
}
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(line_width / 2)), Point2i(parent_pos.x, prev_ofs + Math::floor(line_width / 2)), cache.relationship_line_color, line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(line_width / 2)), Point2i(parent_pos.x, prev_ofs + Math::floor(line_width / 2)), theme_cache.relationship_line_color, line_width);
}
}
}
@@ -2338,12 +2346,12 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
break; // Last loop done, stop.
}
- if (cache.draw_relationship_lines == 0) {
+ if (theme_cache.draw_relationship_lines == 0) {
return -1; // No need to draw anymore, full stop.
}
htotal = -1;
- children_pos.y = cache.offset.y + p_draw_size.height;
+ children_pos.y = theme_cache.offset.y + p_draw_size.height;
} else {
htotal += child_h;
children_pos.y += child_h;
@@ -2494,7 +2502,7 @@ Rect2 Tree::search_item_rect(TreeItem *p_from, TreeItem *p_item) {
void Tree::_range_click_timeout() {
if (range_item_last && !range_drag_enabled && Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT)) {
- Point2 pos = get_local_mouse_position() - cache.bg->get_offset();
+ Point2 pos = get_local_mouse_position() - theme_cache.bg->get_offset();
if (show_column_titles) {
pos.y -= _get_title_button_height();
@@ -2512,7 +2520,7 @@ void Tree::_range_click_timeout() {
Ref<InputEventMouseButton> mb;
mb.instantiate();
- int x_limit = get_size().width - cache.bg->get_minimum_size().width;
+ int x_limit = get_size().width - theme_cache.bg->get_minimum_size().width;
if (h_scroll->is_visible()) {
x_limit -= h_scroll->get_minimum_size().width;
}
@@ -2521,7 +2529,7 @@ void Tree::_range_click_timeout() {
propagate_mouse_activated = false; // done from outside, so signal handler can't clear the tree in the middle of emit (which is a common case)
blocked++;
- propagate_mouse_event(pos + cache.offset, 0, 0, x_limit + cache.offset.width, false, root, MouseButton::LEFT, mb);
+ propagate_mouse_event(pos + theme_cache.offset, 0, 0, x_limit + theme_cache.offset.width, false, root, MouseButton::LEFT, mb);
blocked--;
if (range_click_timer->is_one_shot()) {
@@ -2550,7 +2558,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
return 0;
}
- int item_h = compute_item_height(p_item) + cache.vseparation;
+ int item_h = compute_item_height(p_item) + theme_cache.vseparation;
bool skip = (p_item == root && hide_root);
@@ -2561,7 +2569,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
return -1;
}
- if (!p_item->disable_folding && !hide_folding && p_item->first_child && (p_pos.x >= x_ofs && p_pos.x < (x_ofs + cache.item_margin))) {
+ if (!p_item->disable_folding && !hide_folding && p_item->first_child && (p_pos.x >= x_ofs && p_pos.x < (x_ofs + theme_cache.item_margin))) {
p_item->set_collapsed(!p_item->is_collapsed());
return -1;
}
@@ -2580,7 +2588,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
if (p_item->cells[i].expand_right) {
int plus = 1;
while (i + plus < columns.size() && !p_item->cells[i + plus].editable && p_item->cells[i + plus].mode == TreeItem::CELL_MODE_STRING && p_item->cells[i + plus].text.is_empty() && p_item->cells[i + plus].icon.is_null()) {
- col_width += cache.hseparation;
+ col_width += theme_cache.hseparation;
col_width += get_column_width(i + plus);
plus++;
}
@@ -2600,16 +2608,16 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
if (col == -1) {
return -1;
} else if (col == 0) {
- int margin = x_ofs + cache.item_margin; //-cache.hseparation;
- //int lm = cache.bg->get_margin(SIDE_LEFT);
+ int margin = x_ofs + theme_cache.item_margin; //-theme_cache.hseparation;
+ //int lm = theme_cache.bg->get_margin(SIDE_LEFT);
col_width -= margin;
limit_w -= margin;
col_ofs += margin;
x -= margin;
} else {
- col_width -= cache.hseparation;
- limit_w -= cache.hseparation;
- x -= cache.hseparation;
+ col_width -= theme_cache.hseparation;
+ limit_w -= theme_cache.hseparation;
+ x -= theme_cache.hseparation;
}
if (!p_item->disable_folding && !hide_folding && !p_item->cells[col].editable && !p_item->cells[col].selectable && p_item->get_first_child()) {
@@ -2626,7 +2634,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
int button_w = 0;
for (int j = p_item->cells[col].buttons.size() - 1; j >= 0; j--) {
Ref<Texture2D> b = p_item->cells[col].buttons[j].texture;
- button_w += b->get_size().width + cache.button_pressed->get_minimum_size().width + cache.button_margin;
+ button_w += b->get_size().width + theme_cache.button_pressed->get_minimum_size().width + theme_cache.button_margin;
}
col_width = MAX(button_w, MIN(limit_w, col_width));
@@ -2634,7 +2642,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
for (int j = c.buttons.size() - 1; j >= 0; j--) {
Ref<Texture2D> b = c.buttons[j].texture;
- int w = b->get_size().width + cache.button_pressed->get_minimum_size().width;
+ int w = b->get_size().width + theme_cache.button_pressed->get_minimum_size().width;
if (x > col_width - w) {
if (c.buttons[j].disabled) {
@@ -2658,11 +2666,11 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
cache.click_item = p_item;
cache.click_column = col;
cache.click_pos = click_pos;
- update();
+ queue_redraw();
return -1;
}
- col_width -= w + cache.button_margin;
+ col_width -= w + theme_cache.button_margin;
}
if (p_button == MouseButton::LEFT || (p_button == MouseButton::RIGHT && allow_rmb_select)) {
@@ -2716,7 +2724,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
emit_signal(SNAME("multi_selected"),p_item,col,true);
}
*/
- update();
+ queue_redraw();
}
}
}
@@ -2742,7 +2750,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
case TreeItem::CELL_MODE_CHECK: {
bring_up_editor = false; //checkboxes are not edited with editor
if (force_edit_checkbox_only_on_checkbox) {
- if (x < cache.checked->get_width()) {
+ if (x < theme_cache.checked->get_width()) {
p_item->set_checked(col, !c.checked);
item_edited(col, p_item, p_button);
}
@@ -2764,7 +2772,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
}
popup_menu->set_size(Size2(col_width, 0));
- popup_menu->set_position(get_screen_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs + item_h) - cache.offset);
+ popup_menu->set_position(get_screen_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs + item_h) - theme_cache.offset);
popup_menu->popup();
popup_edited_item = p_item;
popup_edited_item_col = col;
@@ -2822,9 +2830,9 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
case TreeItem::CELL_MODE_CUSTOM: {
edited_item = p_item;
edited_col = col;
- bool on_arrow = x > col_width - cache.select_arrow->get_width();
+ bool on_arrow = x > col_width - theme_cache.select_arrow->get_width();
- custom_popup_rect = Rect2i(get_global_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs + item_h - cache.offset.y), Size2(get_column_width(col), item_h));
+ custom_popup_rect = Rect2i(get_global_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs + item_h - theme_cache.offset.y), Size2(get_column_width(col), item_h));
if (on_arrow || !p_item->cells[col].custom_button) {
emit_signal(SNAME("custom_popup_edited"), ((bool)(x >= (col_width - item_h / 2))));
@@ -2846,7 +2854,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
popup_pressing_edited_item = p_item;
popup_pressing_edited_item_column = col;
- pressing_item_rect = Rect2(get_global_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs) - cache.offset, Size2(col_width, item_h));
+ pressing_item_rect = Rect2(get_global_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs) - theme_cache.offset, Size2(col_width, item_h));
pressing_for_editor_text = editor_text;
pressing_for_editor = true;
@@ -2855,8 +2863,8 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
Point2i new_pos = p_pos;
if (!skip) {
- x_ofs += cache.item_margin;
- //new_pos.x-=cache.item_margin;
+ x_ofs += theme_cache.item_margin;
+ //new_pos.x-=theme_cache.item_margin;
y_ofs += item_h;
new_pos.y -= item_h;
}
@@ -2935,7 +2943,7 @@ void Tree::_text_editor_submit(String p_text) {
}
item_edited(popup_edited_item_col, popup_edited_item);
- update();
+ queue_redraw();
}
void Tree::value_editor_changed(double p_value) {
@@ -2952,7 +2960,7 @@ void Tree::value_editor_changed(double p_value) {
text_editor->set_text(String::num(c.val, Math::range_step_decimals(c.step)));
item_edited(popup_edited_item_col, popup_edited_item);
- update();
+ queue_redraw();
}
void Tree::popup_select(int p_option) {
@@ -2966,7 +2974,7 @@ void Tree::popup_select(int p_option) {
popup_edited_item->cells.write[popup_edited_item_col].val = p_option;
//popup_edited_item->edited_signal.call( popup_edited_item_col );
- update();
+ queue_redraw();
item_edited(popup_edited_item_col, popup_edited_item);
}
@@ -2993,7 +3001,7 @@ void Tree::_go_left() {
selected_item->select(selected_col - 1);
}
}
- update();
+ queue_redraw();
accept_event();
ensure_cursor_is_visible();
}
@@ -3014,7 +3022,7 @@ void Tree::_go_right() {
selected_item->select(selected_col + 1);
}
}
- update();
+ queue_redraw();
ensure_cursor_is_visible();
accept_event();
}
@@ -3043,7 +3051,7 @@ void Tree::_go_up() {
}
selected_item = prev;
emit_signal(SNAME("cell_selected"));
- update();
+ queue_redraw();
} else {
int col = selected_col < 0 ? 0 : selected_col;
while (prev && !prev->cells[col].selectable) {
@@ -3086,7 +3094,7 @@ void Tree::_go_down() {
selected_item = next;
emit_signal(SNAME("cell_selected"));
- update();
+ queue_redraw();
} else {
int col = selected_col < 0 ? 0 : selected_col;
@@ -3196,7 +3204,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
if (select_mode == SELECT_MULTI) {
selected_item = next;
emit_signal(SNAME("cell_selected"));
- update();
+ queue_redraw();
} else {
while (next && !next->cells[selected_col].selectable) {
next = next->get_next_visible();
@@ -3234,7 +3242,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
if (select_mode == SELECT_MULTI) {
selected_item = prev;
emit_signal(SNAME("cell_selected"));
- update();
+ queue_redraw();
} else {
while (prev && !prev->cells[selected_col].selectable) {
prev = prev->get_prev_visible();
@@ -3300,18 +3308,14 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid()) {
- if (cache.font.is_null()) { // avoid a strange case that may corrupt stuff
- update_cache();
- }
-
- Ref<StyleBox> bg = cache.bg;
+ Ref<StyleBox> bg = theme_cache.bg;
bool rtl = is_layout_rtl();
Point2 pos = mm->get_position();
if (rtl) {
pos.x = get_size().width - pos.x;
}
- pos -= cache.bg->get_offset();
+ pos -= theme_cache.bg->get_offset();
Cache::ClickType old_hover = cache.hover_type;
int old_index = cache.hover_index;
@@ -3321,7 +3325,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
if (show_column_titles) {
pos.y -= _get_title_button_height();
if (pos.y < 0) {
- pos.x += cache.offset.x;
+ pos.x += theme_cache.offset.x;
int len = 0;
for (int i = 0; i < columns.size(); i++) {
len += get_column_width(i);
@@ -3339,7 +3343,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
if (rtl) {
mpos.x = get_size().width - mpos.x;
}
- mpos -= cache.bg->get_offset();
+ mpos -= theme_cache.bg->get_offset();
mpos.y -= _get_title_button_height();
if (mpos.y >= 0) {
if (h_scroll->is_visible_in_tree()) {
@@ -3358,11 +3362,11 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
if (drop_mode_flags) {
if (it != drop_mode_over) {
drop_mode_over = it;
- update();
+ queue_redraw();
}
if (it && section != drop_mode_section) {
drop_mode_section = section;
- update();
+ queue_redraw();
}
}
@@ -3371,14 +3375,14 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
if (it != old_it || col != old_col) {
if (old_it && old_col >= old_it->cells.size()) {
- // Columns may have changed since last update().
- update();
+ // Columns may have changed since last redraw().
+ queue_redraw();
} else {
// Only need to update if mouse enters/exits a button
bool was_over_button = old_it && old_it->cells[old_col].custom_button;
bool is_over_button = it && it->cells[col].custom_button;
if (was_over_button || is_over_button) {
- update();
+ queue_redraw();
}
}
}
@@ -3387,7 +3391,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
// Update if mouse enters/exits columns
if (cache.hover_type != old_hover || cache.hover_index != old_index) {
- update();
+ queue_redraw();
}
if (pressing_for_editor && popup_pressing_edited_item && (popup_pressing_edited_item->get_cell_mode(popup_pressing_edited_item_column) == TreeItem::CELL_MODE_RANGE)) {
@@ -3430,10 +3434,6 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
- if (cache.font.is_null()) { // avoid a strange case that may corrupt stuff
- update_cache();
- }
-
bool rtl = is_layout_rtl();
if (!mb->is_pressed()) {
@@ -3443,12 +3443,12 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
if (rtl) {
pos.x = get_size().width - pos.x;
}
- pos -= cache.bg->get_offset();
+ pos -= theme_cache.bg->get_offset();
if (show_column_titles) {
pos.y -= _get_title_button_height();
if (pos.y < 0) {
- pos.x += cache.offset.x;
+ pos.x += theme_cache.offset.x;
int len = 0;
for (int i = 0; i < columns.size(); i++) {
len += get_column_width(i);
@@ -3526,7 +3526,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
cache.click_id = -1;
cache.click_item = nullptr;
cache.click_column = 0;
- update();
+ queue_redraw();
return;
}
@@ -3537,7 +3537,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
switch (mb->get_button_index()) {
case MouseButton::RIGHT:
case MouseButton::LEFT: {
- Ref<StyleBox> bg = cache.bg;
+ Ref<StyleBox> bg = theme_cache.bg;
Point2 pos = mb->get_position();
if (rtl) {
@@ -3549,14 +3549,14 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
pos.y -= _get_title_button_height();
if (pos.y < 0) {
- pos.x += cache.offset.x;
+ pos.x += theme_cache.offset.x;
int len = 0;
for (int i = 0; i < columns.size(); i++) {
len += get_column_width(i);
if (pos.x < static_cast<real_t>(len)) {
cache.click_type = Cache::CLICK_TITLE;
cache.click_index = i;
- update();
+ queue_redraw();
break;
}
}
@@ -3572,14 +3572,14 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
pressing_for_editor = false;
propagate_mouse_activated = false;
- int x_limit = get_size().width - cache.bg->get_minimum_size().width;
+ int x_limit = get_size().width - theme_cache.bg->get_minimum_size().width;
if (h_scroll->is_visible()) {
x_limit -= h_scroll->get_minimum_size().width;
}
cache.rtl = is_layout_rtl();
blocked++;
- propagate_mouse_event(pos + cache.offset, 0, 0, x_limit + cache.offset.width, mb->is_double_click(), root, mb->get_button_index(), mb);
+ propagate_mouse_event(pos + theme_cache.offset, 0, 0, x_limit + theme_cache.offset.width, mb->is_double_click(), root, mb->get_button_index(), mb);
blocked--;
if (pressing_for_editor) {
@@ -3766,7 +3766,7 @@ bool Tree::is_editing() {
}
Size2 Tree::get_internal_min_size() const {
- Size2i size = cache.bg->get_offset();
+ Size2i size = theme_cache.bg->get_offset();
if (root) {
size.height += get_item_height(root);
}
@@ -3789,23 +3789,23 @@ void Tree::update_scrollbars() {
Size2 hmin = h_scroll->get_combined_minimum_size();
Size2 vmin = v_scroll->get_combined_minimum_size();
- v_scroll->set_begin(Point2(size.width - vmin.width, cache.bg->get_margin(SIDE_TOP)));
- v_scroll->set_end(Point2(size.width, size.height - cache.bg->get_margin(SIDE_TOP) - cache.bg->get_margin(SIDE_BOTTOM)));
+ v_scroll->set_begin(Point2(size.width - vmin.width, theme_cache.bg->get_margin(SIDE_TOP)));
+ v_scroll->set_end(Point2(size.width, size.height - theme_cache.bg->get_margin(SIDE_TOP) - theme_cache.bg->get_margin(SIDE_BOTTOM)));
h_scroll->set_begin(Point2(0, size.height - hmin.height));
h_scroll->set_end(Point2(size.width - vmin.width, size.height));
Size2 internal_min_size = get_internal_min_size();
- bool display_vscroll = internal_min_size.height + cache.bg->get_margin(SIDE_TOP) > size.height;
- bool display_hscroll = internal_min_size.width + cache.bg->get_margin(SIDE_LEFT) > size.width;
+ bool display_vscroll = internal_min_size.height + theme_cache.bg->get_margin(SIDE_TOP) > size.height;
+ bool display_hscroll = internal_min_size.width + theme_cache.bg->get_margin(SIDE_LEFT) > size.width;
for (int i = 0; i < 2; i++) {
// Check twice, as both values are dependent on each other.
if (display_hscroll) {
- display_vscroll = internal_min_size.height + cache.bg->get_margin(SIDE_TOP) + hmin.height > size.height;
+ display_vscroll = internal_min_size.height + theme_cache.bg->get_margin(SIDE_TOP) + hmin.height > size.height;
}
if (display_vscroll) {
- display_hscroll = internal_min_size.width + cache.bg->get_margin(SIDE_LEFT) + vmin.width > size.width;
+ display_hscroll = internal_min_size.width + theme_cache.bg->get_margin(SIDE_LEFT) + vmin.width > size.width;
}
}
@@ -3813,29 +3813,29 @@ void Tree::update_scrollbars() {
v_scroll->show();
v_scroll->set_max(internal_min_size.height);
v_scroll->set_page(size.height - hmin.height - tbh);
- cache.offset.y = v_scroll->get_value();
+ theme_cache.offset.y = v_scroll->get_value();
} else {
v_scroll->hide();
- cache.offset.y = 0;
+ theme_cache.offset.y = 0;
}
if (display_hscroll) {
h_scroll->show();
h_scroll->set_max(internal_min_size.width);
h_scroll->set_page(size.width - vmin.width);
- cache.offset.x = h_scroll->get_value();
+ theme_cache.offset.x = h_scroll->get_value();
} else {
h_scroll->hide();
- cache.offset.x = 0;
+ theme_cache.offset.x = 0;
}
}
int Tree::_get_title_button_height() const {
- ERR_FAIL_COND_V(cache.font.is_null() || cache.title_button.is_null(), 0);
+ ERR_FAIL_COND_V(theme_cache.font.is_null() || theme_cache.title_button.is_null(), 0);
int h = 0;
if (show_column_titles) {
for (int i = 0; i < columns.size(); i++) {
- h = MAX(h, columns[i].text_buf->get_size().y + cache.title_button->get_minimum_size().height);
+ h = MAX(h, columns[i].text_buf->get_size().y + theme_cache.title_button->get_minimum_size().height);
}
}
return h;
@@ -3852,7 +3852,7 @@ void Tree::_notification(int p_what) {
case NOTIFICATION_MOUSE_EXIT: {
if (cache.hover_type != Cache::CLICK_NONE) {
cache.hover_type = Cache::CLICK_NONE;
- update();
+ queue_redraw();
}
} break;
@@ -3860,20 +3860,16 @@ void Tree::_notification(int p_what) {
drag_touching = false;
} break;
- case NOTIFICATION_ENTER_TREE: {
- update_cache();
- } break;
-
case NOTIFICATION_DRAG_END: {
drop_mode_flags = 0;
scrolling = false;
set_physics_process_internal(false);
- update();
+ queue_redraw();
} break;
case NOTIFICATION_DRAG_BEGIN: {
single_select_defer = nullptr;
- if (cache.scroll_speed > 0) {
+ if (theme_cache.scroll_speed > 0) {
scrolling = true;
set_physics_process_internal(true);
}
@@ -3917,22 +3913,22 @@ void Tree::_notification(int p_what) {
}
Point2 mouse_position = get_viewport()->get_mouse_position() - get_global_position();
- if (scrolling && get_rect().grow(cache.scroll_border).has_point(mouse_position)) {
+ if (scrolling && get_rect().grow(theme_cache.scroll_border).has_point(mouse_position)) {
Point2 point;
- if ((ABS(mouse_position.x) < ABS(mouse_position.x - get_size().width)) && (ABS(mouse_position.x) < cache.scroll_border)) {
- point.x = mouse_position.x - cache.scroll_border;
- } else if (ABS(mouse_position.x - get_size().width) < cache.scroll_border) {
- point.x = mouse_position.x - (get_size().width - cache.scroll_border);
+ if ((ABS(mouse_position.x) < ABS(mouse_position.x - get_size().width)) && (ABS(mouse_position.x) < theme_cache.scroll_border)) {
+ point.x = mouse_position.x - theme_cache.scroll_border;
+ } else if (ABS(mouse_position.x - get_size().width) < theme_cache.scroll_border) {
+ point.x = mouse_position.x - (get_size().width - theme_cache.scroll_border);
}
- if ((ABS(mouse_position.y) < ABS(mouse_position.y - get_size().height)) && (ABS(mouse_position.y) < cache.scroll_border)) {
- point.y = mouse_position.y - cache.scroll_border;
- } else if (ABS(mouse_position.y - get_size().height) < cache.scroll_border) {
- point.y = mouse_position.y - (get_size().height - cache.scroll_border);
+ if ((ABS(mouse_position.y) < ABS(mouse_position.y - get_size().height)) && (ABS(mouse_position.y) < theme_cache.scroll_border)) {
+ point.y = mouse_position.y - theme_cache.scroll_border;
+ } else if (ABS(mouse_position.y - get_size().height) < theme_cache.scroll_border) {
+ point.y = mouse_position.y - (get_size().height - theme_cache.scroll_border);
}
- point *= cache.scroll_speed * get_physics_process_delta_time();
+ point *= theme_cache.scroll_speed * get_physics_process_delta_time();
point += get_scroll();
h_scroll->set_value(point.x);
v_scroll->set_value(point.y);
@@ -3940,13 +3936,12 @@ void Tree::_notification(int p_what) {
} break;
case NOTIFICATION_DRAW: {
- update_cache();
+ v_scroll->set_custom_step(theme_cache.font->get_height(theme_cache.font_size));
+
update_scrollbars();
RID ci = get_canvas_item();
- Ref<StyleBox> bg = cache.bg;
- Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
+ Ref<StyleBox> bg = theme_cache.bg;
Point2 draw_ofs;
draw_ofs += bg->get_offset();
@@ -3970,11 +3965,11 @@ void Tree::_notification(int p_what) {
if (show_column_titles) {
//title buttons
- int ofs2 = cache.bg->get_margin(SIDE_LEFT);
+ int ofs2 = theme_cache.bg->get_margin(SIDE_LEFT);
for (int i = 0; i < columns.size(); i++) {
- Ref<StyleBox> sb = (cache.click_type == Cache::CLICK_TITLE && cache.click_index == i) ? cache.title_button_pressed : ((cache.hover_type == Cache::CLICK_TITLE && cache.hover_index == i) ? cache.title_button_hover : cache.title_button);
- Ref<Font> f = cache.tb_font;
- Rect2 tbrect = Rect2(ofs2 - cache.offset.x, bg->get_margin(SIDE_TOP), get_column_width(i), tbh);
+ Ref<StyleBox> sb = (cache.click_type == Cache::CLICK_TITLE && cache.click_index == i) ? theme_cache.title_button_pressed : ((cache.hover_type == Cache::CLICK_TITLE && cache.hover_index == i) ? theme_cache.title_button_hover : theme_cache.title_button);
+ Ref<Font> f = theme_cache.tb_font;
+ Rect2 tbrect = Rect2(ofs2 - theme_cache.offset.x, bg->get_margin(SIDE_TOP), get_column_width(i), tbh);
if (cache.rtl) {
tbrect.position.x = get_size().width - tbrect.size.x - tbrect.position.x;
}
@@ -3985,10 +3980,10 @@ void Tree::_notification(int p_what) {
columns.write[i].text_buf->set_width(clip_w);
Vector2 text_pos = tbrect.position + Point2i(sb->get_offset().x + (tbrect.size.width - columns[i].text_buf->get_size().x) / 2, (tbrect.size.height - columns[i].text_buf->get_size().y) / 2);
- if (outline_size > 0 && font_outline_color.a > 0) {
- columns[i].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ if (theme_cache.font_outline_size > 0 && theme_cache.font_outline_color.a > 0) {
+ columns[i].text_buf->draw_outline(ci, text_pos, theme_cache.font_outline_size, theme_cache.font_outline_color);
}
- columns[i].text_buf->draw(ci, text_pos, cache.title_button_color);
+ columns[i].text_buf->draw(ci, text_pos, theme_cache.title_button_color);
}
}
@@ -3996,8 +3991,7 @@ void Tree::_notification(int p_what) {
// Otherwise, section heading backgrounds can appear to be in front of the focus outline when scrolling.
if (has_focus()) {
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, true);
- const Ref<StyleBox> bg_focus = get_theme_stylebox(SNAME("bg_focus"));
- bg_focus->draw(ci, Rect2(Point2(), get_size()));
+ theme_cache.bg_focus->draw(ci, Rect2(Point2(), get_size()));
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, false);
}
} break;
@@ -4005,7 +3999,6 @@ void Tree::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_TRANSLATION_CHANGED: {
- update_cache();
_update_all();
} break;
@@ -4040,7 +4033,7 @@ Size2 Tree::get_minimum_size() const {
return Size2();
} else {
Vector2 min_size = get_internal_min_size();
- Ref<StyleBox> bg = cache.bg;
+ Ref<StyleBox> bg = theme_cache.bg;
if (bg.is_valid()) {
min_size.x += bg->get_margin(SIDE_LEFT) + bg->get_margin(SIDE_RIGHT);
min_size.y += bg->get_margin(SIDE_TOP) + bg->get_margin(SIDE_BOTTOM);
@@ -4110,7 +4103,7 @@ void Tree::item_changed(int p_column, TreeItem *p_item) {
if (p_item != nullptr && p_column >= 0 && p_column < p_item->cells.size()) {
p_item->cells.write[p_column].dirty = true;
}
- update();
+ queue_redraw();
}
void Tree::item_selected(int p_column, TreeItem *p_item) {
@@ -4129,7 +4122,7 @@ void Tree::item_selected(int p_column, TreeItem *p_item) {
} else {
select_single_item(p_item, root, p_column);
}
- update();
+ queue_redraw();
}
void Tree::item_deselected(int p_column, TreeItem *p_item) {
@@ -4144,7 +4137,7 @@ void Tree::item_deselected(int p_column, TreeItem *p_item) {
if (select_mode == SELECT_MULTI || select_mode == SELECT_SINGLE) {
p_item->cells.write[p_column].selected = false;
}
- update();
+ queue_redraw();
}
void Tree::set_select_mode(SelectMode p_mode) {
@@ -4167,7 +4160,7 @@ void Tree::deselect_all() {
selected_item = nullptr;
selected_col = -1;
- update();
+ queue_redraw();
}
bool Tree::is_anything_selected() {
@@ -4196,7 +4189,7 @@ void Tree::clear() {
popup_edited_item = nullptr;
popup_pressing_edited_item = nullptr;
- update();
+ queue_redraw();
};
void Tree::set_hide_root(bool p_enabled) {
@@ -4205,7 +4198,7 @@ void Tree::set_hide_root(bool p_enabled) {
}
hide_root = p_enabled;
- update();
+ queue_redraw();
}
bool Tree::is_root_hidden() const {
@@ -4223,7 +4216,7 @@ void Tree::set_column_custom_minimum_width(int p_column, int p_min_width) {
return;
}
columns.write[p_column].custom_min_width = p_min_width;
- update();
+ queue_redraw();
}
void Tree::set_column_expand(int p_column, bool p_expand) {
@@ -4234,7 +4227,7 @@ void Tree::set_column_expand(int p_column, bool p_expand) {
}
columns.write[p_column].expand = p_expand;
- update();
+ queue_redraw();
}
void Tree::set_column_expand_ratio(int p_column, int p_ratio) {
@@ -4245,7 +4238,7 @@ void Tree::set_column_expand_ratio(int p_column, int p_ratio) {
}
columns.write[p_column].expand_ratio = p_ratio;
- update();
+ queue_redraw();
}
void Tree::set_column_clip_content(int p_column, bool p_fit) {
@@ -4256,7 +4249,7 @@ void Tree::set_column_clip_content(int p_column, bool p_fit) {
}
columns.write[p_column].clip_content = p_fit;
- update();
+ queue_redraw();
}
bool Tree::is_column_expanding(int p_column) const {
@@ -4336,7 +4329,7 @@ int Tree::get_column_minimum_width(int p_column) const {
// Check if the visible title of the column is wider.
if (show_column_titles) {
- min_width = MAX(cache.font->get_string_size(columns[p_column].title, HORIZONTAL_ALIGNMENT_LEFT, -1, cache.font_size).width + cache.bg->get_margin(SIDE_LEFT) + cache.bg->get_margin(SIDE_RIGHT), min_width);
+ min_width = MAX(theme_cache.font->get_string_size(columns[p_column].title, HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size).width + theme_cache.bg->get_margin(SIDE_LEFT) + theme_cache.bg->get_margin(SIDE_RIGHT), min_width);
}
if (!columns[p_column].clip_content) {
@@ -4360,9 +4353,9 @@ int Tree::get_column_minimum_width(int p_column) const {
// Get the item minimum size.
Size2 item_size = item->get_minimum_size(p_column);
if (p_column == 0) {
- item_size.width += cache.item_margin * depth;
+ item_size.width += theme_cache.item_margin * depth;
} else {
- item_size.width += cache.hseparation;
+ item_size.width += theme_cache.hseparation;
}
// Check if the item is wider.
@@ -4381,7 +4374,7 @@ int Tree::get_column_width(int p_column) const {
if (columns[p_column].expand) {
int expand_area = get_size().width;
- Ref<StyleBox> bg = cache.bg;
+ Ref<StyleBox> bg = theme_cache.bg;
if (bg.is_valid()) {
expand_area -= bg->get_margin(SIDE_LEFT) + bg->get_margin(SIDE_RIGHT);
@@ -4429,7 +4422,7 @@ void Tree::set_columns(int p_columns) {
if (selected_col >= p_columns) {
selected_col = p_columns - 1;
}
- update();
+ queue_redraw();
}
int Tree::get_columns() const {
@@ -4437,7 +4430,7 @@ int Tree::get_columns() const {
}
void Tree::_scroll_moved(float) {
- update();
+ queue_redraw();
}
Rect2 Tree::get_custom_popup_rect() const {
@@ -4458,7 +4451,7 @@ int Tree::get_item_offset(TreeItem *p_item) const {
ofs += compute_item_height(it);
if (it != root || !hide_root) {
- ofs += cache.vseparation;
+ ofs += theme_cache.vseparation;
}
if (it->first_child && !it->collapsed) {
@@ -4489,14 +4482,14 @@ void Tree::ensure_cursor_is_visible() {
return; // Nothing under cursor.
}
- const Size2 area_size = get_size() - cache.bg->get_minimum_size();
+ const Size2 area_size = get_size() - theme_cache.bg->get_minimum_size();
int y_offset = get_item_offset(selected_item);
if (y_offset != -1) {
const int tbh = _get_title_button_height();
y_offset -= tbh;
- const int cell_h = compute_item_height(selected_item) + cache.vseparation;
+ const int cell_h = compute_item_height(selected_item) + theme_cache.vseparation;
const int screen_h = area_size.height - h_scroll->get_combined_minimum_size().height - tbh;
if (cell_h > screen_h) { // Screen size is too small, maybe it was not resized yet.
@@ -4563,7 +4556,7 @@ Rect2 Tree::get_item_rect(TreeItem *p_item, int p_column, int p_button) const {
Vector2 ofst = Vector2(r.position.x + r.size.x, r.position.y);
for (int j = c.buttons.size() - 1; j >= 0; j--) {
Ref<Texture2D> b = c.buttons[j].texture;
- Size2 size = b->get_size() + cache.button_pressed->get_minimum_size();
+ Size2 size = b->get_size() + theme_cache.button_pressed->get_minimum_size();
ofst.x -= size.x;
if (j == p_button) {
@@ -4582,7 +4575,7 @@ void Tree::set_column_titles_visible(bool p_show) {
}
show_column_titles = p_show;
- update();
+ queue_redraw();
}
bool Tree::are_column_titles_visible() const {
@@ -4596,12 +4589,9 @@ void Tree::set_column_title(int p_column, const String &p_title) {
return;
}
- if (cache.font.is_null()) { // avoid a strange case that may corrupt stuff
- update_cache();
- }
columns.write[p_column].title = p_title;
update_column(p_column);
- update();
+ queue_redraw();
}
String Tree::get_column_title(int p_column) const {
@@ -4615,7 +4605,7 @@ void Tree::set_column_title_direction(int p_column, Control::TextDirection p_tex
if (columns[p_column].text_direction != p_text_direction) {
columns.write[p_column].text_direction = p_text_direction;
update_column(p_column);
- update();
+ queue_redraw();
}
}
@@ -4629,7 +4619,7 @@ void Tree::set_column_title_language(int p_column, const String &p_language) {
if (columns[p_column].language != p_language) {
columns.write[p_column].language = p_language;
update_column(p_column);
- update();
+ queue_redraw();
}
}
@@ -4660,7 +4650,7 @@ void Tree::scroll_to_item(TreeItem *p_item, bool p_center_on_item) {
const real_t tree_height = get_size().y;
const Rect2 item_rect = get_item_rect(p_item);
const real_t item_y = item_rect.position.y;
- const real_t item_height = item_rect.size.y + cache.vseparation;
+ const real_t item_height = item_rect.size.y + theme_cache.vseparation;
if (p_center_on_item) {
v_scroll->set_value(item_y - (tree_height - item_height) / 2.0f);
@@ -4784,7 +4774,7 @@ TreeItem *Tree::_find_item_at_pos(TreeItem *p_item, const Point2 &p_pos, int &r_
Point2 pos = p_pos;
if ((root != p_item || !hide_root) && p_item->is_visible()) {
- h = compute_item_height(p_item) + cache.vseparation;
+ h = compute_item_height(p_item) + theme_cache.vseparation;
if (pos.y < h) {
if (drop_mode_flags == DROP_MODE_ON_ITEM) {
section = 0;
@@ -4841,7 +4831,7 @@ int Tree::get_column_at_position(const Point2 &p_pos) const {
if (is_layout_rtl()) {
pos.x = get_size().width - pos.x;
}
- pos -= cache.bg->get_offset();
+ pos -= theme_cache.bg->get_offset();
pos.y -= _get_title_button_height();
if (pos.y < 0) {
return -1;
@@ -4871,7 +4861,7 @@ int Tree::get_drop_section_at_position(const Point2 &p_pos) const {
if (is_layout_rtl()) {
pos.x = get_size().width - pos.x;
}
- pos -= cache.bg->get_offset();
+ pos -= theme_cache.bg->get_offset();
pos.y -= _get_title_button_height();
if (pos.y < 0) {
return -100;
@@ -4901,7 +4891,7 @@ TreeItem *Tree::get_item_at_position(const Point2 &p_pos) const {
if (is_layout_rtl()) {
pos.x = get_size().width - pos.x;
}
- pos -= cache.bg->get_offset();
+ pos -= theme_cache.bg->get_offset();
pos.y -= _get_title_button_height();
if (pos.y < 0) {
return nullptr;
@@ -4928,7 +4918,7 @@ TreeItem *Tree::get_item_at_position(const Point2 &p_pos) const {
int Tree::get_button_id_at_position(const Point2 &p_pos) const {
if (root) {
Point2 pos = p_pos;
- pos -= cache.bg->get_offset();
+ pos -= theme_cache.bg->get_offset();
pos.y -= _get_title_button_height();
if (pos.y < 0) {
return -1;
@@ -4954,7 +4944,7 @@ int Tree::get_button_id_at_position(const Point2 &p_pos) const {
for (int j = c.buttons.size() - 1; j >= 0; j--) {
Ref<Texture2D> b = c.buttons[j].texture;
- Size2 size = b->get_size() + cache.button_pressed->get_minimum_size();
+ Size2 size = b->get_size() + theme_cache.button_pressed->get_minimum_size();
if (pos.x > col_width - size.width) {
return c.buttons[j].id;
}
@@ -4969,7 +4959,7 @@ int Tree::get_button_id_at_position(const Point2 &p_pos) const {
String Tree::get_tooltip(const Point2 &p_pos) const {
if (root) {
Point2 pos = p_pos;
- pos -= cache.bg->get_offset();
+ pos -= theme_cache.bg->get_offset();
pos.y -= _get_title_button_height();
if (pos.y < 0) {
return Control::get_tooltip(p_pos);
@@ -4995,7 +4985,7 @@ String Tree::get_tooltip(const Point2 &p_pos) const {
for (int j = c.buttons.size() - 1; j >= 0; j--) {
Ref<Texture2D> b = c.buttons[j].texture;
- Size2 size = b->get_size() + cache.button_pressed->get_minimum_size();
+ Size2 size = b->get_size() + theme_cache.button_pressed->get_minimum_size();
if (pos.x > col_width - size.width) {
String tooltip = c.buttons[j].tooltip;
if (!tooltip.is_empty()) {
@@ -5005,10 +4995,10 @@ String Tree::get_tooltip(const Point2 &p_pos) const {
col_width -= size.width;
}
String ret;
- if (it->get_tooltip(col) == "") {
+ if (it->get_tooltip_text(col) == "") {
ret = it->get_text(col);
} else {
- ret = it->get_tooltip(col);
+ ret = it->get_tooltip_text(col);
}
return ret;
}
@@ -5027,7 +5017,7 @@ void Tree::set_hide_folding(bool p_hide) {
}
hide_folding = p_hide;
- update();
+ queue_redraw();
}
bool Tree::is_folding_hidden() const {
@@ -5043,7 +5033,7 @@ void Tree::set_drop_mode_flags(int p_flags) {
drop_mode_over = nullptr;
}
- update();
+ queue_redraw();
}
int Tree::get_drop_mode_flags() const {
@@ -5231,8 +5221,6 @@ Tree::Tree() {
set_mouse_filter(MOUSE_FILTER_STOP);
set_clip_contents(true);
-
- update_cache();
}
Tree::~Tree() {
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 7f9c00b1b9..b4ee686bab 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -245,7 +245,7 @@ public:
void add_button(int p_column, const Ref<Texture2D> &p_button, int p_id = -1, bool p_disabled = false, const String &p_tooltip = "");
int get_button_count(int p_column) const;
- String get_button_tooltip(int p_column, int p_idx) const;
+ String get_button_tooltip_text(int p_column, int p_idx) const;
Ref<Texture2D> get_button(int p_column, int p_idx) const;
int get_button_id(int p_column, int p_idx) const;
void erase_button(int p_column, int p_idx);
@@ -308,8 +308,8 @@ public:
void set_custom_as_button(int p_column, bool p_button);
bool is_custom_set_as_button(int p_column) const;
- void set_tooltip(int p_column, const String &p_tooltip);
- String get_tooltip(int p_column) const;
+ void set_tooltip_text(int p_column, const String &p_tooltip);
+ String get_tooltip_text(int p_column) const;
void set_text_alignment(int p_column, HorizontalAlignment p_alignment);
HorizontalAlignment get_text_alignment(int p_column) const;
@@ -482,12 +482,13 @@ private:
void propagate_set_columns(TreeItem *p_item);
- struct Cache {
+ struct ThemeCache {
Ref<Font> font;
Ref<Font> tb_font;
int font_size = 0;
int tb_font_size = 0;
Ref<StyleBox> bg;
+ Ref<StyleBox> bg_focus;
Ref<StyleBox> selected;
Ref<StyleBox> selected_focus;
Ref<StyleBox> cursor;
@@ -505,8 +506,9 @@ private:
Ref<Texture2D> checked;
Ref<Texture2D> unchecked;
Ref<Texture2D> indeterminate;
- Ref<Texture2D> arrow_collapsed;
Ref<Texture2D> arrow;
+ Ref<Texture2D> arrow_collapsed;
+ Ref<Texture2D> arrow_collapsed_mirrored;
Ref<Texture2D> select_arrow;
Ref<Texture2D> updown;
@@ -536,7 +538,9 @@ private:
int scroll_border = 0;
int scroll_speed = 0;
int font_outline_size = 0;
+ } theme_cache;
+ struct Cache {
enum ClickType {
CLICK_NONE,
CLICK_TITLE,
@@ -559,7 +563,6 @@ private:
Point2i text_editor_position;
bool rtl = false;
-
} cache;
int _get_title_button_height() const;
@@ -572,7 +575,6 @@ private:
bool v_scroll_enabled = true;
Size2 get_internal_min_size() const;
- void update_cache();
void update_scrollbars();
Rect2 search_item_rect(TreeItem *p_from, TreeItem *p_item);
@@ -620,6 +622,8 @@ private:
bool _scroll(bool p_horizontal, float p_pages);
protected:
+ virtual void _update_theme_item_cache() override;
+
static void _bind_methods();
public:
diff --git a/scene/gui/video_stream_player.cpp b/scene/gui/video_stream_player.cpp
index 4024d4c80e..1e03ed6e76 100644
--- a/scene/gui/video_stream_player.cpp
+++ b/scene/gui/video_stream_player.cpp
@@ -213,7 +213,7 @@ void VideoStreamPlayer::set_expand(bool p_expand) {
}
expand = p_expand;
- update();
+ queue_redraw();
update_minimum_size();
}
@@ -261,7 +261,7 @@ void VideoStreamPlayer::set_stream(const Ref<VideoStream> &p_stream) {
AudioServer::get_singleton()->unlock();
}
- update();
+ queue_redraw();
if (!expand) {
update_minimum_size();