summaryrefslogtreecommitdiff
path: root/scene/gui
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui')
-rw-r--r--scene/gui/box_container.cpp4
-rw-r--r--scene/gui/check_box.cpp18
-rw-r--r--scene/gui/code_edit.cpp28
-rw-r--r--scene/gui/color_picker.cpp20
-rw-r--r--scene/gui/control.cpp29
-rw-r--r--scene/gui/control.h3
-rw-r--r--scene/gui/dialogs.cpp6
-rw-r--r--scene/gui/file_dialog.cpp11
-rw-r--r--scene/gui/gradient_edit.cpp2
-rw-r--r--scene/gui/graph_edit.cpp5
-rw-r--r--scene/gui/item_list.cpp2
-rw-r--r--scene/gui/label.cpp100
-rw-r--r--scene/gui/line_edit.cpp11
-rw-r--r--scene/gui/link_button.cpp16
-rw-r--r--scene/gui/link_button.h1
-rw-r--r--scene/gui/menu_button.cpp2
-rw-r--r--scene/gui/option_button.cpp2
-rw-r--r--scene/gui/option_button.h4
-rw-r--r--scene/gui/popup.cpp2
-rw-r--r--scene/gui/popup_menu.cpp9
-rw-r--r--scene/gui/popup_menu.h4
-rw-r--r--scene/gui/rich_text_effect.h6
-rw-r--r--scene/gui/rich_text_label.cpp34
-rw-r--r--scene/gui/rich_text_label.h6
-rw-r--r--scene/gui/scroll_bar.cpp26
-rw-r--r--scene/gui/scroll_bar.h3
-rw-r--r--scene/gui/scroll_container.cpp7
-rw-r--r--scene/gui/spin_box.cpp4
-rw-r--r--scene/gui/tab_container.cpp20
-rw-r--r--scene/gui/text_edit.cpp223
-rw-r--r--scene/gui/text_edit.h23
-rw-r--r--scene/gui/texture_progress_bar.cpp57
-rw-r--r--scene/gui/texture_progress_bar.h4
-rw-r--r--scene/gui/tree.cpp68
-rw-r--r--scene/gui/tree.h4
-rw-r--r--scene/gui/video_player.cpp5
36 files changed, 561 insertions, 208 deletions
diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp
index a2f1d2b15a..cf2df4e1a2 100644
--- a/scene/gui/box_container.cpp
+++ b/scene/gui/box_container.cpp
@@ -351,11 +351,11 @@ MarginContainer *VBoxContainer::add_margin_child(const String &p_label, Control
Label *l = memnew(Label);
l->set_theme_type_variation("HeaderSmall");
l->set_text(p_label);
- add_child(l);
+ add_child(l, false, INTERNAL_MODE_FRONT);
MarginContainer *mc = memnew(MarginContainer);
mc->add_theme_constant_override("margin_left", 0);
mc->add_child(p_control);
- add_child(mc);
+ add_child(mc, false, INTERNAL_MODE_FRONT);
if (p_expand) {
mc->set_v_size_flags(SIZE_EXPAND_FILL);
}
diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp
index d93107df2d..411fb2e1f0 100644
--- a/scene/gui/check_box.cpp
+++ b/scene/gui/check_box.cpp
@@ -34,11 +34,13 @@
Size2 CheckBox::get_icon_size() const {
Ref<Texture2D> checked = Control::get_theme_icon(SNAME("checked"));
- Ref<Texture2D> checked_disabled = Control::get_theme_icon(SNAME("checked_disabled"));
Ref<Texture2D> unchecked = Control::get_theme_icon(SNAME("unchecked"));
- Ref<Texture2D> unchecked_disabled = Control::get_theme_icon(SNAME("unchecked_disabled"));
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()) {
@@ -53,6 +55,18 @@ Size2 CheckBox::get_icon_size() const {
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 (!checked_disabled.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, checked_disabled->get_width()), MAX(tex_size.height, 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 (!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 (!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()));
+ }
return tex_size;
}
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index 27cac73aef..d05762b6c0 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -1400,7 +1400,8 @@ void CodeEdit::fold_line(int p_line) {
}
/* Find the last line to be hidden. */
- int end_line = get_line_count();
+ const int line_count = get_line_count() - 1;
+ int end_line = line_count;
int in_comment = is_in_comment(p_line);
int in_string = (in_comment == -1) ? is_in_string(p_line) : -1;
@@ -1408,7 +1409,7 @@ void CodeEdit::fold_line(int p_line) {
end_line = get_delimiter_end_position(p_line, get_line(p_line).size() - 1).y;
/* End line is the same therefore we have a block. */
if (end_line == p_line) {
- for (int i = p_line + 1; i < get_line_count(); i++) {
+ for (int i = p_line + 1; i <= line_count; i++) {
if ((in_string != -1 && is_in_string(i) == -1) || (in_comment != -1 && is_in_comment(i) == -1)) {
end_line = i - 1;
break;
@@ -1417,14 +1418,27 @@ void CodeEdit::fold_line(int p_line) {
}
} else {
int start_indent = get_indent_level(p_line);
- for (int i = p_line + 1; i < get_line_count(); i++) {
+ for (int i = p_line + 1; i <= line_count; i++) {
if (get_line(p_line).strip_edges().size() == 0 || is_in_string(i) != -1 || is_in_comment(i) != -1) {
end_line = i;
continue;
}
- if (get_indent_level(i) <= start_indent && get_line(i).strip_edges().size() != 0) {
+ if (i == line_count) {
+ /* Do not fold empty last line of script if any */
+ end_line = i;
+ if (get_line(i).strip_edges().size() == 0) {
+ end_line--;
+ }
+ break;
+ }
+
+ if ((get_indent_level(i) <= start_indent && get_line(i).strip_edges().size() != 0)) {
+ /* Keep an empty line unfolded if any */
end_line = i - 1;
+ if (get_line(i - 1).strip_edges().size() == 0 && i - 2 > p_line) {
+ end_line = i - 2;
+ }
break;
}
}
@@ -1937,7 +1951,7 @@ void CodeEdit::confirm_code_completion(bool p_replace) {
if (pre_brace_pair == -1 && post_brace_pair == -1 && get_caret_column() > 0 && get_caret_column() < get_line(caret_line).length()) {
pre_brace_pair = _get_auto_brace_pair_open_at_pos(caret_line, get_caret_column() + 1);
- if (pre_brace_pair == _get_auto_brace_pair_close_at_pos(caret_line, get_caret_column() - 1)) {
+ if (pre_brace_pair != -1 && pre_brace_pair == _get_auto_brace_pair_close_at_pos(caret_line, get_caret_column() - 1)) {
remove_text(caret_line, get_caret_column() - 2, caret_line, get_caret_column());
if (_get_auto_brace_pair_close_at_pos(caret_line, get_caret_column() - 1) != pre_brace_pair) {
set_caret_column(get_caret_column() - 1);
@@ -2651,7 +2665,7 @@ TypedArray<String> CodeEdit::_get_delimiters(DelimiterType p_type) const {
void CodeEdit::_filter_code_completion_candidates_impl() {
int line_height = get_line_height();
- if (GDVIRTUAL_IS_OVERRIDEN(_filter_code_completion_candidates)) {
+ if (GDVIRTUAL_IS_OVERRIDDEN(_filter_code_completion_candidates)) {
code_completion_options.clear();
code_completion_base = "";
@@ -2744,7 +2758,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() {
/* If we have a space, previous word might be a keyword. eg "func |". */
} else if (cofs > 0 && line[cofs - 1] == ' ') {
int ofs = cofs - 1;
- while (ofs >= 0 && line[ofs] == ' ') {
+ while (ofs > 0 && line[ofs] == ' ') {
ofs--;
}
prev_is_word = _is_char(line[ofs]);
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 661e0dc648..1afb0b8e9d 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -97,6 +97,8 @@ Ref<Shader> ColorPicker::circle_shader;
void ColorPicker::init_shaders() {
wheel_shader.instantiate();
wheel_shader->set_code(R"(
+// ColorPicker wheel shader.
+
shader_type canvas_item;
void fragment() {
@@ -119,6 +121,8 @@ void fragment() {
circle_shader.instantiate();
circle_shader->set_code(R"(
+// ColorPicker circle shader.
+
shader_type canvas_item;
uniform float v = 1.0;
@@ -1135,7 +1139,7 @@ void ColorPicker::_bind_methods() {
ColorPicker::ColorPicker() :
BoxContainer(true) {
HBoxContainer *hb_edit = memnew(HBoxContainer);
- add_child(hb_edit);
+ add_child(hb_edit, false, INTERNAL_MODE_FRONT);
hb_edit->set_v_size_flags(SIZE_EXPAND_FILL);
hb_edit->add_child(uv_edit);
@@ -1147,7 +1151,7 @@ ColorPicker::ColorPicker() :
uv_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(0, uv_edit));
HBoxContainer *hb_smpl = memnew(HBoxContainer);
- add_child(hb_smpl);
+ add_child(hb_smpl, false, INTERNAL_MODE_FRONT);
hb_smpl->add_child(sample);
sample->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -1161,12 +1165,12 @@ ColorPicker::ColorPicker() :
btn_pick->connect("pressed", callable_mp(this, &ColorPicker::_screen_pick_pressed));
VBoxContainer *vbl = memnew(VBoxContainer);
- add_child(vbl);
+ add_child(vbl, false, INTERNAL_MODE_FRONT);
- add_child(memnew(HSeparator));
+ add_child(memnew(HSeparator), false, INTERNAL_MODE_FRONT);
VBoxContainer *vbr = memnew(VBoxContainer);
- add_child(vbr);
+ add_child(vbr, false, INTERNAL_MODE_FRONT);
vbr->set_h_size_flags(SIZE_EXPAND_FILL);
for (int i = 0; i < 4; i++) {
@@ -1269,11 +1273,11 @@ ColorPicker::ColorPicker() :
set_pick_color(Color(1, 1, 1));
- add_child(preset_separator);
+ add_child(preset_separator, false, INTERNAL_MODE_FRONT);
preset_container->set_h_size_flags(SIZE_EXPAND_FILL);
preset_container->set_columns(preset_column_count);
- add_child(preset_container);
+ add_child(preset_container, false, INTERNAL_MODE_FRONT);
btn_add_preset->set_icon_align(Button::ALIGN_CENTER);
btn_add_preset->set_tooltip(RTR("Add current color as a preset."));
@@ -1401,7 +1405,7 @@ void ColorPickerButton::_update_picker() {
picker = memnew(ColorPicker);
picker->set_anchors_and_offsets_preset(PRESET_WIDE);
popup->add_child(picker);
- add_child(popup);
+ add_child(popup, false, INTERNAL_MODE_FRONT);
picker->connect("color_changed", callable_mp(this, &ColorPickerButton::_color_changed));
popup->connect("about_to_popup", callable_mp(this, &ColorPickerButton::_about_to_popup));
popup->connect("popup_hide", callable_mp(this, &ColorPickerButton::_modal_closed));
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 4ac6a58d36..81411d5844 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -30,6 +30,7 @@
#include "control.h"
+#include "container.h"
#include "core/config/project_settings.h"
#include "core/math/geometry_2d.h"
#include "core/object/message_queue.h"
@@ -168,6 +169,20 @@ Size2 Control::_edit_get_minimum_size() const {
}
#endif
+String Control::properties_managed_by_container[] = {
+ "offset_left",
+ "offset_top",
+ "offset_right",
+ "offset_bottom",
+ "anchor_left",
+ "anchor_top",
+ "anchor_right",
+ "anchor_bottom",
+ "rect_position",
+ "rect_scale",
+ "rect_size"
+};
+
void Control::accept_event() {
if (is_inside_tree()) {
get_viewport()->_gui_accept_event();
@@ -442,6 +457,20 @@ void Control::_validate_property(PropertyInfo &property) const {
property.hint_string = hint_string;
}
+ if (!Object::cast_to<Container>(get_parent())) {
+ return;
+ }
+ // Disable the property if it's managed by the parent container.
+ bool property_is_managed_by_container = false;
+ for (unsigned i = 0; i < properties_managed_by_container_count; i++) {
+ property_is_managed_by_container = properties_managed_by_container[i] == property.name;
+ if (property_is_managed_by_container) {
+ break;
+ }
+ }
+ if (property_is_managed_by_container) {
+ property.usage |= PROPERTY_USAGE_READ_ONLY;
+ }
}
Control *Control::get_parent_control() const {
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 0faa617f8d..9cec5d6e8d 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -230,6 +230,9 @@ private:
} data;
+ static constexpr unsigned properties_managed_by_container_count = 11;
+ static String properties_managed_by_container[properties_managed_by_container_count];
+
// used internally
Control *_find_control_at_pos(CanvasItem *p_node, const Point2 &p_pos, const Transform2D &p_xform, Transform2D &r_inv_xform);
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index da858e8e83..5d98aaa698 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -319,7 +319,7 @@ AcceptDialog::AcceptDialog() {
set_clamp_to_embedder(true);
bg = memnew(Panel);
- add_child(bg);
+ add_child(bg, false, INTERNAL_MODE_FRONT);
hbc = memnew(HBoxContainer);
@@ -331,9 +331,9 @@ AcceptDialog::AcceptDialog() {
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);
+ add_child(label, false, INTERNAL_MODE_FRONT);
- add_child(hbc);
+ add_child(hbc, false, INTERNAL_MODE_FRONT);
hbc->add_spacer();
ok = memnew(Button);
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 2512b24623..973b72973d 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -924,7 +924,7 @@ FileDialog::FileDialog() {
show_hidden_files = default_show_hidden_files;
vbox = memnew(VBoxContainer);
- add_child(vbox);
+ add_child(vbox, false, INTERNAL_MODE_FRONT);
vbox->connect("theme_changed", callable_mp(this, &FileDialog::_theme_changed));
mode = FILE_MODE_SAVE_FILE;
@@ -1023,8 +1023,7 @@ FileDialog::FileDialog() {
filter->connect("item_selected", callable_mp(this, &FileDialog::_filter_selected));
confirm_save = memnew(ConfirmationDialog);
- // confirm_save->set_as_top_level(true);
- add_child(confirm_save);
+ add_child(confirm_save, false, INTERNAL_MODE_FRONT);
confirm_save->connect("confirmed", callable_mp(this, &FileDialog::_save_confirm_pressed));
@@ -1036,16 +1035,16 @@ FileDialog::FileDialog() {
makedirname = memnew(LineEdit);
makedirname->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
makevb->add_margin_child(TTRC("Name:"), makedirname);
- add_child(makedialog);
+ add_child(makedialog, false, INTERNAL_MODE_FRONT);
makedialog->register_text_enter(makedirname);
makedialog->connect("confirmed", callable_mp(this, &FileDialog::_make_dir_confirm));
mkdirerr = memnew(AcceptDialog);
mkdirerr->set_text(TTRC("Could not create folder."));
- add_child(mkdirerr);
+ add_child(mkdirerr, false, INTERNAL_MODE_FRONT);
exterr = memnew(AcceptDialog);
exterr->set_text(TTRC("Must use a valid extension."));
- add_child(exterr);
+ add_child(exterr, false, INTERNAL_MODE_FRONT);
update_filters();
update_dir();
diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp
index bbab3008e2..56b8a936e1 100644
--- a/scene/gui/gradient_edit.cpp
+++ b/scene/gui/gradient_edit.cpp
@@ -48,7 +48,7 @@ GradientEdit::GradientEdit() {
picker = memnew(ColorPicker);
popup->add_child(picker);
- add_child(popup);
+ add_child(popup, false, INTERNAL_MODE_FRONT);
}
int GradientEdit::_get_point_from_pos(int x) {
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 0281bc7efb..cabae9feb2 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -366,7 +366,6 @@ void GraphEdit::_graph_node_raised(Node *p_gn) {
}
move_child(connections_layer, first_not_comment);
- top_layer->raise();
emit_signal(SNAME("node_selected"), p_gn);
}
@@ -2246,14 +2245,14 @@ GraphEdit::GraphEdit() {
zoom_max = (1 * Math::pow(zoom_step, 4));
top_layer = memnew(GraphEditFilter(this));
- add_child(top_layer);
+ add_child(top_layer, false, INTERNAL_MODE_BACK);
top_layer->set_mouse_filter(MOUSE_FILTER_PASS);
top_layer->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
top_layer->connect("draw", callable_mp(this, &GraphEdit::_top_layer_draw));
top_layer->connect("gui_input", callable_mp(this, &GraphEdit::_top_layer_input));
connections_layer = memnew(Control);
- add_child(connections_layer);
+ add_child(connections_layer, false, INTERNAL_MODE_FRONT);
connections_layer->connect("draw", callable_mp(this, &GraphEdit::_connections_layer_draw));
connections_layer->set_name("CLAYER");
connections_layer->set_disable_visibility_clip(true); // so it can draw freely and be offset
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 8297de9f30..d10ad90c1f 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -1656,7 +1656,7 @@ void ItemList::_bind_methods() {
ItemList::ItemList() {
scroll_bar = memnew(VScrollBar);
- add_child(scroll_bar);
+ add_child(scroll_bar, false, INTERNAL_MODE_FRONT);
scroll_bar->connect("value_changed", callable_mp(this, &ItemList::_scroll_changed));
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index 50db1fc3ce..5600816b2d 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -66,11 +66,11 @@ bool Label::is_uppercase() const {
int Label::get_line_height(int p_line) const {
Ref<Font> font = get_theme_font(SNAME("font"));
if (p_line >= 0 && p_line < lines_rid.size()) {
- return TS->shaped_text_get_size(lines_rid[p_line]).y + font->get_spacing(Font::SPACING_TOP) + font->get_spacing(Font::SPACING_BOTTOM);
+ return TS->shaped_text_get_size(lines_rid[p_line]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM);
} else if (lines_rid.size() > 0) {
int h = 0;
for (int i = 0; i < lines_rid.size(); i++) {
- h = MAX(h, TS->shaped_text_get_size(lines_rid[i]).y) + font->get_spacing(Font::SPACING_TOP) + font->get_spacing(Font::SPACING_BOTTOM);
+ h = MAX(h, TS->shaped_text_get_size(lines_rid[i]).y) + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM);
}
return h;
} else {
@@ -89,7 +89,10 @@ void Label::_shape() {
} else {
TS->shaped_text_set_direction(text_rid, (TextServer::Direction)text_direction);
}
- TS->shaped_text_add_string(text_rid, (uppercase) ? xl_text.to_upper() : xl_text, get_theme_font(SNAME("font"))->get_rids(), get_theme_font_size(SNAME("font_size")), opentype_features, (language != "") ? language : TranslationServer::get_singleton()->get_tool_locale());
+ const Ref<Font> &font = get_theme_font(SNAME("font"));
+ int font_size = get_theme_font_size(SNAME("font_size"));
+ ERR_FAIL_COND(font.is_null());
+ TS->shaped_text_add_string(text_rid, (uppercase) ? xl_text.to_upper() : xl_text, font->get_rids(), font_size, opentype_features, (language != "") ? language : TranslationServer::get_singleton()->get_tool_locale());
TS->shaped_text_set_bidi_override(text_rid, structured_text_parser(st_parser, st_args, xl_text));
dirty = false;
lines_dirty = true;
@@ -217,14 +220,22 @@ void Label::_update_visible() {
minsize.height = 0;
int last_line = MIN(lines_rid.size(), lines_visible + lines_skipped);
for (int64_t i = lines_skipped; i < last_line; i++) {
- minsize.height += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(Font::SPACING_TOP) + font->get_spacing(Font::SPACING_BOTTOM) + line_spacing;
+ minsize.height += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM) + line_spacing;
if (minsize.height > (get_size().height - style->get_minimum_size().height + line_spacing)) {
break;
}
}
}
-inline void draw_glyph(const TextServer::Glyph &p_gl, const RID &p_canvas, const Color &p_font_color, const Color &p_font_shadow_color, const Color &p_font_outline_color, const int &p_shadow_outline_size, const int &p_outline_size, const Vector2 &p_ofs, const Vector2 &shadow_ofs) {
+inline void draw_glyph(const TextServer::Glyph &p_gl, const RID &p_canvas, const Color &p_font_color, const Vector2 &p_ofs) {
+ if (p_gl.font_rid != RID()) {
+ TS->font_draw_glyph(p_gl.font_rid, p_canvas, p_gl.font_size, p_ofs + Vector2(p_gl.x_off, p_gl.y_off), p_gl.index, p_font_color);
+ } else {
+ TS->draw_hex_code_box(p_canvas, p_gl.font_size, p_ofs + Vector2(p_gl.x_off, p_gl.y_off), p_gl.index, p_font_color);
+ }
+}
+
+inline void draw_glyph_outline(const TextServer::Glyph &p_gl, const RID &p_canvas, const Color &p_font_color, const Color &p_font_shadow_color, const Color &p_font_outline_color, const int &p_shadow_outline_size, const int &p_outline_size, const Vector2 &p_ofs, const Vector2 &shadow_ofs) {
if (p_gl.font_rid != RID()) {
if (p_font_shadow_color.a > 0) {
TS->font_draw_glyph(p_gl.font_rid, p_canvas, p_gl.font_size, p_ofs + Vector2(p_gl.x_off, p_gl.y_off) + shadow_ofs, p_gl.index, p_font_shadow_color);
@@ -237,9 +248,6 @@ inline void draw_glyph(const TextServer::Glyph &p_gl, const RID &p_canvas, const
if (p_font_outline_color.a != 0.0 && p_outline_size > 0) {
TS->font_draw_glyph_outline(p_gl.font_rid, p_canvas, p_gl.font_size, p_outline_size, p_ofs + Vector2(p_gl.x_off, p_gl.y_off), p_gl.index, p_font_outline_color);
}
- TS->font_draw_glyph(p_gl.font_rid, p_canvas, p_gl.font_size, p_ofs + Vector2(p_gl.x_off, p_gl.y_off), p_gl.index, p_font_color);
- } else {
- TS->draw_hex_code_box(p_canvas, p_gl.font_size, p_ofs + Vector2(p_gl.x_off, p_gl.y_off), p_gl.index, p_font_color);
}
}
@@ -286,7 +294,7 @@ void Label::_notification(int p_what) {
// Get number of lines to fit to the height.
for (int64_t i = lines_skipped; i < lines_rid.size(); i++) {
- total_h += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(Font::SPACING_TOP) + font->get_spacing(Font::SPACING_BOTTOM) + line_spacing;
+ total_h += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM) + line_spacing;
if (total_h > (get_size().height - style->get_minimum_size().height + line_spacing)) {
break;
}
@@ -302,7 +310,7 @@ void Label::_notification(int p_what) {
// Get real total height.
total_h = 0;
for (int64_t i = lines_skipped; i < last_line; i++) {
- total_h += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(Font::SPACING_TOP) + font->get_spacing(Font::SPACING_BOTTOM) + line_spacing;
+ total_h += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM) + line_spacing;
}
total_h += style->get_margin(SIDE_TOP) + style->get_margin(SIDE_BOTTOM);
@@ -357,7 +365,7 @@ void Label::_notification(int p_what) {
for (int i = lines_skipped; i < last_line; i++) {
Size2 line_size = TS->shaped_text_get_size(lines_rid[i]);
ofs.x = 0;
- ofs.y += TS->shaped_text_get_ascent(lines_rid[i]) + font->get_spacing(Font::SPACING_TOP);
+ ofs.y += TS->shaped_text_get_ascent(lines_rid[i]) + font->get_spacing(TextServer::SPACING_TOP);
switch (align) {
case ALIGN_FILL:
if (rtl && autowrap_mode != AUTOWRAP_OFF) {
@@ -382,12 +390,70 @@ void Label::_notification(int p_what) {
int gl_size = visual.size();
TextServer::TrimData trim_data = TS->shaped_text_get_trim_data(lines_rid[i]);
+ // Draw outline. Note: Do not merge this into the single loop with the main text, to prevent overlaps.
+ if (font_shadow_color.a > 0 || (font_outline_color.a != 0.0 && outline_size > 0)) {
+ Vector2 offset = ofs;
+ // Draw RTL ellipsis string when necessary.
+ if (rtl && trim_data.ellipsis_pos >= 0) {
+ for (int gl_idx = trim_data.ellipsis_glyph_buf.size() - 1; gl_idx >= 0; gl_idx--) {
+ for (int j = 0; j < trim_data.ellipsis_glyph_buf[gl_idx].repeat; j++) {
+ //Draw glyph outlines and shadow.
+ draw_glyph_outline(trim_data.ellipsis_glyph_buf[gl_idx], ci, font_color, font_shadow_color, font_outline_color, shadow_outline_size, outline_size, offset, shadow_ofs);
+ offset.x += trim_data.ellipsis_glyph_buf[gl_idx].advance;
+ }
+ }
+ }
+
+ // Draw main text.
+ for (int j = 0; j < gl_size; j++) {
+ for (int k = 0; k < glyphs[j].repeat; k++) {
+ if (visible_glyphs != -1) {
+ if ((glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
+ if (glyhps_drawn >= visible_glyphs) {
+ return;
+ }
+ }
+ }
+
+ // Trim when necessary.
+ if (trim_data.trim_pos >= 0) {
+ if (rtl) {
+ if (j < trim_data.trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
+ continue;
+ }
+ } else {
+ if (j >= trim_data.trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
+ break;
+ }
+ }
+ }
+
+ // Draw glyph outlines and shadow.
+ draw_glyph_outline(glyphs[j], ci, font_color, font_shadow_color, font_outline_color, shadow_outline_size, outline_size, offset, shadow_ofs);
+ offset.x += glyphs[j].advance;
+ glyhps_drawn++;
+ }
+ }
+ // Draw LTR ellipsis string when necessary.
+ if (!rtl && trim_data.ellipsis_pos >= 0) {
+ for (int gl_idx = 0; gl_idx < trim_data.ellipsis_glyph_buf.size(); gl_idx++) {
+ for (int j = 0; j < trim_data.ellipsis_glyph_buf[gl_idx].repeat; j++) {
+ //Draw glyph outlines and shadow.
+ draw_glyph_outline(trim_data.ellipsis_glyph_buf[gl_idx], ci, font_color, font_shadow_color, font_outline_color, shadow_outline_size, outline_size, offset, shadow_ofs);
+ offset.x += trim_data.ellipsis_glyph_buf[gl_idx].advance;
+ }
+ }
+ }
+ }
+
+ // Draw main text. Note: Do not merge this into the single loop with the outline, to prevent overlaps.
+
// Draw RTL ellipsis string when necessary.
if (rtl && trim_data.ellipsis_pos >= 0) {
for (int gl_idx = trim_data.ellipsis_glyph_buf.size() - 1; gl_idx >= 0; gl_idx--) {
for (int j = 0; j < trim_data.ellipsis_glyph_buf[gl_idx].repeat; j++) {
//Draw glyph outlines and shadow.
- draw_glyph(trim_data.ellipsis_glyph_buf[gl_idx], ci, font_color, font_shadow_color, font_outline_color, shadow_outline_size, outline_size, ofs, shadow_ofs);
+ draw_glyph(trim_data.ellipsis_glyph_buf[gl_idx], ci, font_color, ofs);
ofs.x += trim_data.ellipsis_glyph_buf[gl_idx].advance;
}
}
@@ -418,7 +484,7 @@ void Label::_notification(int p_what) {
}
// Draw glyph outlines and shadow.
- draw_glyph(glyphs[j], ci, font_color, font_shadow_color, font_outline_color, shadow_outline_size, outline_size, ofs, shadow_ofs);
+ draw_glyph(glyphs[j], ci, font_color, ofs);
ofs.x += glyphs[j].advance;
glyhps_drawn++;
}
@@ -428,12 +494,12 @@ void Label::_notification(int p_what) {
for (int gl_idx = 0; gl_idx < trim_data.ellipsis_glyph_buf.size(); gl_idx++) {
for (int j = 0; j < trim_data.ellipsis_glyph_buf[gl_idx].repeat; j++) {
//Draw glyph outlines and shadow.
- draw_glyph(trim_data.ellipsis_glyph_buf[gl_idx], ci, font_color, font_shadow_color, font_outline_color, shadow_outline_size, outline_size, ofs, shadow_ofs);
+ draw_glyph(trim_data.ellipsis_glyph_buf[gl_idx], ci, font_color, ofs);
ofs.x += trim_data.ellipsis_glyph_buf[gl_idx].advance;
}
}
}
- ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + vsep + line_spacing + font->get_spacing(Font::SPACING_BOTTOM);
+ ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + vsep + line_spacing + font->get_spacing(TextServer::SPACING_BOTTOM);
}
}
@@ -455,7 +521,7 @@ Size2 Label::get_minimum_size() const {
Size2 min_size = minsize;
Ref<Font> font = get_theme_font(SNAME("font"));
- min_size.height = MAX(min_size.height, font->get_height(get_theme_font_size(SNAME("font_size"))) + font->get_spacing(Font::SPACING_TOP) + font->get_spacing(Font::SPACING_BOTTOM));
+ min_size.height = MAX(min_size.height, font->get_height(get_theme_font_size(SNAME("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();
if (autowrap_mode != AUTOWRAP_OFF) {
@@ -486,7 +552,7 @@ int Label::get_visible_line_count() const {
int lines_visible = 0;
float total_h = 0.0;
for (int64_t i = lines_skipped; i < lines_rid.size(); i++) {
- total_h += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(Font::SPACING_TOP) + font->get_spacing(Font::SPACING_BOTTOM) + line_spacing;
+ total_h += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM) + line_spacing;
if (total_h > (get_size().height - style->get_minimum_size().height + line_spacing)) {
break;
}
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 5e9c2d891f..d9acbeb828 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -641,7 +641,7 @@ void LineEdit::_notification(int p_what) {
int x_ofs = 0;
bool using_placeholder = text.is_empty() && ime_text.is_empty();
float text_width = TS->shaped_text_get_size(text_rid).x;
- float text_height = TS->shaped_text_get_size(text_rid).y + font->get_spacing(Font::SPACING_TOP) + font->get_spacing(Font::SPACING_BOTTOM);
+ float text_height = TS->shaped_text_get_size(text_rid).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM);
switch (align) {
case ALIGN_FILL:
@@ -674,7 +674,7 @@ void LineEdit::_notification(int p_what) {
int y_ofs = style->get_offset().y + (y_area - text_height) / 2;
Color selection_color = get_theme_color(SNAME("selection_color"));
- Color font_color = is_editable() ? get_theme_color(SNAME("font_color")) : get_theme_color(SNAME("font_uneditable_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"));
@@ -1531,7 +1531,7 @@ Size2 LineEdit::get_minimum_size() const {
min_size.width = MAX(min_size.width, full_width + em_space_size);
}
- min_size.height = MAX(TS->shaped_text_get_size(text_rid).y + font->get_spacing(Font::SPACING_TOP) + font->get_spacing(Font::SPACING_BOTTOM), font->get_height(font_size));
+ min_size.height = MAX(TS->shaped_text_get_size(text_rid).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM), font->get_height(font_size));
// Take icons into account.
bool using_placeholder = text.is_empty() && ime_text.is_empty();
@@ -1941,6 +1941,7 @@ void LineEdit::_shape() {
const Ref<Font> &font = get_theme_font(SNAME("font"));
int font_size = get_theme_font_size(SNAME("font_size"));
+ ERR_FAIL_COND(font.is_null());
TS->shaped_text_add_string(text_rid, t, font->get_rids(), font_size, opentype_features, (language != "") ? language : TranslationServer::get_singleton()->get_tool_locale());
TS->shaped_text_set_bidi_override(text_rid, structured_text_parser(st_parser, st_args, t));
@@ -2219,7 +2220,7 @@ void LineEdit::_bind_methods() {
void LineEdit::_ensure_menu() {
if (!menu) {
menu = memnew(PopupMenu);
- add_child(menu);
+ add_child(menu, false, INTERNAL_MODE_FRONT);
menu_dir = memnew(PopupMenu);
menu_dir->set_name("DirMenu");
@@ -2304,7 +2305,7 @@ LineEdit::LineEdit() {
set_mouse_filter(MOUSE_FILTER_STOP);
caret_blink_timer = memnew(Timer);
- add_child(caret_blink_timer);
+ add_child(caret_blink_timer, false, INTERNAL_MODE_FRONT);
caret_blink_timer->set_wait_time(0.65);
caret_blink_timer->connect("timeout", callable_mp(this, &LineEdit::_toggle_draw_caret));
set_caret_blink_enabled(false);
diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp
index 419d49bccf..925e6f5b97 100644
--- a/scene/gui/link_button.cpp
+++ b/scene/gui/link_button.cpp
@@ -41,12 +41,16 @@ void LinkButton::_shape() {
} else {
text_buf->set_direction((TextServer::Direction)text_direction);
}
- TS->shaped_text_set_bidi_override(text_buf->get_rid(), structured_text_parser(st_parser, st_args, text));
- text_buf->add_string(text, font, font_size, opentype_features, (language != "") ? language : TranslationServer::get_singleton()->get_tool_locale());
+ TS->shaped_text_set_bidi_override(text_buf->get_rid(), structured_text_parser(st_parser, st_args, xl_text));
+ text_buf->add_string(xl_text, font, font_size, opentype_features, (language != "") ? language : TranslationServer::get_singleton()->get_tool_locale());
}
void LinkButton::set_text(const String &p_text) {
+ if (text == p_text) {
+ return;
+ }
text = p_text;
+ xl_text = atr(text);
_shape();
minimum_size_changed();
update();
@@ -141,7 +145,13 @@ Size2 LinkButton::get_minimum_size() const {
void LinkButton::_notification(int p_what) {
switch (p_what) {
- case NOTIFICATION_TRANSLATION_CHANGED:
+ case NOTIFICATION_TRANSLATION_CHANGED: {
+ xl_text = atr(text);
+ _shape();
+
+ minimum_size_changed();
+ update();
+ } break;
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
update();
} break;
diff --git a/scene/gui/link_button.h b/scene/gui/link_button.h
index 7eaa9f88b6..231543c63c 100644
--- a/scene/gui/link_button.h
+++ b/scene/gui/link_button.h
@@ -47,6 +47,7 @@ public:
private:
String text;
+ String xl_text;
Ref<TextLine> text_buf;
UnderlineMode underline_mode = UNDERLINE_MODE_ALWAYS;
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index e312aaed57..737ba84617 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -172,7 +172,7 @@ MenuButton::MenuButton() {
popup = memnew(PopupMenu);
popup->hide();
- add_child(popup);
+ add_child(popup, false, INTERNAL_MODE_FRONT);
popup->connect("about_to_popup", callable_mp(this, &MenuButton::_popup_visibility_changed), varray(true));
popup->connect("popup_hide", callable_mp(this, &MenuButton::_popup_visibility_changed), varray(false));
}
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index cd55f258b3..d16e96dbec 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -351,7 +351,7 @@ OptionButton::OptionButton() {
popup = memnew(PopupMenu);
popup->hide();
- add_child(popup);
+ add_child(popup, false, INTERNAL_MODE_FRONT);
popup->connect("index_pressed", callable_mp(this, &OptionButton::_selected));
popup->connect("id_focused", callable_mp(this, &OptionButton::_focused));
popup->connect("popup_hide", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(false));
diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h
index d846e395ad..953337ecce 100644
--- a/scene/gui/option_button.h
+++ b/scene/gui/option_button.h
@@ -56,6 +56,10 @@ protected:
static void _bind_methods();
public:
+ // ATTENTION: This is used by the POT generator's scene parser. If the number of properties returned by `_get_items()` ever changes,
+ // this value should be updated to reflect the new size.
+ static const int ITEM_PROPERTY_SIZE = 5;
+
void add_icon_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id = -1);
void add_item(const String &p_label, int p_id = -1);
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp
index f7e7e1cd60..e9414598a2 100644
--- a/scene/gui/popup.cpp
+++ b/scene/gui/popup.cpp
@@ -255,5 +255,5 @@ void PopupPanel::_notification(int p_what) {
PopupPanel::PopupPanel() {
panel = memnew(Panel);
- add_child(panel);
+ add_child(panel, false, INTERNAL_MODE_FRONT);
}
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index f75d6755a8..c0a559e624 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -228,6 +228,7 @@ void PopupMenu::_activate_submenu(int p_over) {
// Set autohide areas
PopupMenu *submenu_pum = Object::cast_to<PopupMenu>(submenu_popup);
if (submenu_pum) {
+ submenu_pum->take_mouse_focus();
// Make the position of the parent popup relative to submenu popup
this_rect.position = this_rect.position - submenu_pum->get_position();
@@ -1689,7 +1690,7 @@ PopupMenu::PopupMenu() {
// Margin Container
margin_container = memnew(MarginContainer);
margin_container->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
- add_child(margin_container);
+ add_child(margin_container, false, INTERNAL_MODE_FRONT);
margin_container->connect("draw", callable_mp(this, &PopupMenu::_draw_background));
// Scroll Container
@@ -1703,7 +1704,7 @@ PopupMenu::PopupMenu() {
control->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
control->set_h_size_flags(Control::SIZE_EXPAND_FILL);
control->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- scroll_container->add_child(control);
+ scroll_container->add_child(control, false, INTERNAL_MODE_FRONT);
control->connect("draw", callable_mp(this, &PopupMenu::_draw_items));
connect("window_input", callable_mp(this, &PopupMenu::gui_input));
@@ -1712,13 +1713,13 @@ PopupMenu::PopupMenu() {
submenu_timer->set_wait_time(0.3);
submenu_timer->set_one_shot(true);
submenu_timer->connect("timeout", callable_mp(this, &PopupMenu::_submenu_timeout));
- add_child(submenu_timer);
+ add_child(submenu_timer, false, INTERNAL_MODE_FRONT);
minimum_lifetime_timer = memnew(Timer);
minimum_lifetime_timer->set_wait_time(0.3);
minimum_lifetime_timer->set_one_shot(true);
minimum_lifetime_timer->connect("timeout", callable_mp(this, &PopupMenu::_minimum_lifetime_timeout));
- add_child(minimum_lifetime_timer);
+ add_child(minimum_lifetime_timer, false, INTERNAL_MODE_FRONT);
}
PopupMenu::~PopupMenu() {
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index 5c427e43bc..428076c6da 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -144,6 +144,10 @@ protected:
static void _bind_methods();
public:
+ // ATTENTION: This is used by the POT generator's scene parser. If the number of properties returned by `_get_items()` ever changes,
+ // this value should be updated to reflect the new size.
+ static const int ITEM_PROPERTY_SIZE = 10;
+
void add_item(const String &p_label, int p_id = -1, uint32_t p_accel = 0);
void add_icon_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id = -1, uint32_t p_accel = 0);
void add_check_item(const String &p_label, int p_id = -1, uint32_t p_accel = 0);
diff --git a/scene/gui/rich_text_effect.h b/scene/gui/rich_text_effect.h
index e674b2f62f..f5506542bb 100644
--- a/scene/gui/rich_text_effect.h
+++ b/scene/gui/rich_text_effect.h
@@ -49,7 +49,7 @@ public:
Color color;
double elapsed_time = 0.0f;
Dictionary environment;
- uint32_t glpyh_index = 0;
+ uint32_t glyph_index = 0;
RID font;
CharFXTransform();
@@ -68,8 +68,8 @@ public:
Color get_color() { return color; }
void set_color(Color p_color) { color = p_color; }
- uint32_t get_glyph_index() const { return glpyh_index; };
- void set_glyph_index(uint32_t p_glpyh_index) { glpyh_index = p_glpyh_index; };
+ uint32_t get_glyph_index() const { return glyph_index; };
+ void set_glyph_index(uint32_t p_glyph_index) { glyph_index = p_glyph_index; };
RID get_font() const { return font; };
void set_font(RID p_font) { font = p_font; };
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 21a87d4e76..aeadfd78ee 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -874,7 +874,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
charfx->visibility = visible;
charfx->outline = true;
charfx->font = frid;
- charfx->glpyh_index = gl;
+ charfx->glyph_index = gl;
charfx->offset = fx_offset;
charfx->color = font_color;
@@ -884,7 +884,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
fx_offset += charfx->offset;
font_color = charfx->color;
frid = charfx->font;
- gl = charfx->glpyh_index;
+ gl = charfx->glyph_index;
visible &= charfx->visibility;
}
} else if (item_fx->type == ITEM_SHAKE) {
@@ -1026,7 +1026,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
charfx->visibility = visible;
charfx->outline = false;
charfx->font = frid;
- charfx->glpyh_index = gl;
+ charfx->glyph_index = gl;
charfx->offset = fx_offset;
charfx->color = font_color;
@@ -1036,7 +1036,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
fx_offset += charfx->offset;
font_color = charfx->color;
frid = charfx->font;
- gl = charfx->glpyh_index;
+ gl = charfx->glyph_index;
visible &= charfx->visibility;
}
} else if (item_fx->type == ITEM_SHAKE) {
@@ -3946,24 +3946,15 @@ float RichTextLabel::get_percent_visible() const {
return percent_visible;
}
-void RichTextLabel::set_effects(const Vector<Variant> &effects) {
- custom_effects.clear();
- for (int i = 0; i < effects.size(); i++) {
- Ref<RichTextEffect> effect = Ref<RichTextEffect>(effects[i]);
- custom_effects.push_back(effect);
- }
-
+void RichTextLabel::set_effects(Array p_effects) {
+ custom_effects = p_effects;
if ((bbcode != "") && use_bbcode) {
parse_bbcode(bbcode);
}
}
-Vector<Variant> RichTextLabel::get_effects() {
- Vector<Variant> r;
- for (int i = 0; i < custom_effects.size(); i++) {
- r.push_back(custom_effects[i]);
- }
- return r;
+Array RichTextLabel::get_effects() {
+ return custom_effects;
}
void RichTextLabel::install_effect(const Variant effect) {
@@ -4279,12 +4270,13 @@ void RichTextLabel::_draw_fbg_boxes(RID p_ci, RID p_rid, Vector2 line_off, Item
Ref<RichTextEffect> RichTextLabel::_get_custom_effect_by_code(String p_bbcode_identifier) {
for (int i = 0; i < custom_effects.size(); i++) {
- if (!custom_effects[i].is_valid()) {
+ Ref<RichTextEffect> effect = custom_effects[i];
+ if (!effect.is_valid()) {
continue;
}
- if (custom_effects[i]->get_bbcode() == p_bbcode_identifier) {
- return custom_effects[i];
+ if (effect->get_bbcode() == p_bbcode_identifier) {
+ return effect;
}
}
@@ -4361,7 +4353,7 @@ RichTextLabel::RichTextLabel() {
current_frame = main;
vscroll = memnew(VScrollBar);
- add_child(vscroll);
+ add_child(vscroll, false, INTERNAL_MODE_FRONT);
vscroll->set_drag_node(String(".."));
vscroll->set_step(1);
vscroll->set_anchor_and_offset(SIDE_TOP, ANCHOR_BEGIN, 0);
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index ae04a7e684..f25a8bf193 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -363,7 +363,7 @@ private:
ItemMeta *meta_hovering = nullptr;
Variant current_meta;
- Vector<Ref<RichTextEffect>> custom_effects;
+ Array custom_effects;
void _invalidate_current_line(ItemFrame *p_frame);
void _validate_line_caches(ItemFrame *p_frame);
@@ -577,8 +577,8 @@ public:
void set_percent_visible(float p_percent);
float get_percent_visible() const;
- void set_effects(const Vector<Variant> &effects);
- Vector<Variant> get_effects();
+ void set_effects(Array p_effects);
+ Array get_effects();
void install_effect(const Variant effect);
diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp
index 08bcb0bdda..4edf373fbf 100644
--- a/scene/gui/scroll_bar.cpp
+++ b/scene/gui/scroll_bar.cpp
@@ -80,12 +80,16 @@ void ScrollBar::gui_input(const Ref<InputEvent> &p_event) {
double total = orientation == VERTICAL ? get_size().height : get_size().width;
if (ofs < decr_size) {
+ decr_active = true;
set_value(get_value() - (custom_step >= 0 ? custom_step : get_step()));
+ update();
return;
}
if (ofs > total - incr_size) {
+ incr_active = true;
set_value(get_value() + (custom_step >= 0 ? custom_step : get_step()));
+ update();
return;
}
@@ -130,6 +134,8 @@ void ScrollBar::gui_input(const Ref<InputEvent> &p_event) {
}
} else {
+ incr_active = false;
+ decr_active = false;
drag.active = false;
update();
}
@@ -215,8 +221,24 @@ void ScrollBar::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
RID ci = get_canvas_item();
- Ref<Texture2D> decr = highlight == HIGHLIGHT_DECR ? get_theme_icon(SNAME("decrement_highlight")) : get_theme_icon(SNAME("decrement"));
- Ref<Texture2D> incr = highlight == HIGHLIGHT_INCR ? get_theme_icon(SNAME("increment_highlight")) : get_theme_icon(SNAME("increment"));
+ Ref<Texture2D> decr, incr;
+
+ if (decr_active) {
+ decr = get_theme_icon(SNAME("decrement_pressed"));
+ } else if (highlight == HIGHLIGHT_DECR) {
+ decr = get_theme_icon(SNAME("decrement_highlight"));
+ } else {
+ decr = get_theme_icon(SNAME("decrement"));
+ }
+
+ if (incr_active) {
+ incr = get_theme_icon(SNAME("increment_pressed"));
+ } else if (highlight == HIGHLIGHT_INCR) {
+ incr = get_theme_icon(SNAME("increment_highlight"));
+ } else {
+ incr = get_theme_icon(SNAME("increment"));
+ }
+
Ref<StyleBox> bg = has_focus() ? get_theme_stylebox(SNAME("scroll_focus")) : get_theme_stylebox(SNAME("scroll"));
Ref<StyleBox> grabber;
diff --git a/scene/gui/scroll_bar.h b/scene/gui/scroll_bar.h
index fbc035397f..574d17ee20 100644
--- a/scene/gui/scroll_bar.h
+++ b/scene/gui/scroll_bar.h
@@ -51,6 +51,9 @@ class ScrollBar : public Range {
HighlightStatus highlight = HIGHLIGHT_NONE;
+ bool incr_active = false;
+ bool decr_active = false;
+
struct Drag {
bool active = false;
float pos_at_click = 0.0;
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index b5daa8b3f1..0c051f61e2 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -228,9 +228,6 @@ void ScrollContainer::_update_scrollbar_position() {
v_scroll->set_anchor_and_offset(SIDE_TOP, ANCHOR_BEGIN, 0);
v_scroll->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, 0);
- h_scroll->raise();
- v_scroll->raise();
-
_updating_scrollbars = false;
}
@@ -618,12 +615,12 @@ void ScrollContainer::_bind_methods() {
ScrollContainer::ScrollContainer() {
h_scroll = memnew(HScrollBar);
h_scroll->set_name("_h_scroll");
- add_child(h_scroll);
+ add_child(h_scroll, false, INTERNAL_MODE_BACK);
h_scroll->connect("value_changed", callable_mp(this, &ScrollContainer::_scroll_moved));
v_scroll = memnew(VScrollBar);
v_scroll->set_name("_v_scroll");
- add_child(v_scroll);
+ add_child(v_scroll, false, INTERNAL_MODE_BACK);
v_scroll->connect("value_changed", callable_mp(this, &ScrollContainer::_scroll_moved));
deadzone = GLOBAL_GET("gui/common/default_scroll_deadzone");
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index 65a3eb3adf..1074d0d8a0 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -278,7 +278,7 @@ void SpinBox::_bind_methods() {
SpinBox::SpinBox() {
line_edit = memnew(LineEdit);
- add_child(line_edit);
+ add_child(line_edit, false, INTERNAL_MODE_FRONT);
line_edit->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
line_edit->set_mouse_filter(MOUSE_FILTER_PASS);
@@ -291,5 +291,5 @@ SpinBox::SpinBox() {
range_click_timer = memnew(Timer);
range_click_timer->connect("timeout", callable_mp(this, &SpinBox::_range_click_timeout));
- add_child(range_click_timer);
+ add_child(range_click_timer, false, INTERNAL_MODE_FRONT);
}
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 5884d2a854..137ce7e96f 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -434,14 +434,14 @@ void TabContainer::_notification(int p_what) {
}
int tab_width = tab_widths[i];
- if (get_tab_disabled(index)) {
+ if (index == current) {
+ x_current = x;
+ } else if (get_tab_disabled(index)) {
if (rtl) {
_draw_tab(tab_disabled, font_disabled_color, index, size.width - (tabs_ofs_cache + x) - tab_width);
} else {
_draw_tab(tab_disabled, font_disabled_color, index, tabs_ofs_cache + x);
}
- } else if (index == current) {
- x_current = x;
} else {
if (rtl) {
_draw_tab(tab_unselected, font_unselected_color, index, size.width - (tabs_ofs_cache + x) - tab_width);
@@ -459,12 +459,13 @@ void TabContainer::_notification(int p_what) {
panel->draw(canvas, Rect2(0, header_height, size.width, size.height - header_height));
}
- // Draw selected tab in front. only draw selected tab when it's in visible range.
+ // Draw selected tab in front. Only draw selected tab when it's in visible range.
if (tabs.size() > 0 && current - first_tab_cache < tab_widths.size() && current >= first_tab_cache) {
+ Ref<StyleBox> current_style_box = get_tab_disabled(current) ? tab_disabled : tab_selected;
if (rtl) {
- _draw_tab(tab_selected, font_selected_color, current, size.width - (tabs_ofs_cache + x_current) - tab_widths[current]);
+ _draw_tab(current_style_box, font_selected_color, current, size.width - (tabs_ofs_cache + x_current) - tab_widths[current]);
} else {
- _draw_tab(tab_selected, font_selected_color, current, tabs_ofs_cache + x_current);
+ _draw_tab(current_style_box, font_selected_color, current, tabs_ofs_cache + x_current);
}
}
@@ -640,8 +641,8 @@ void TabContainer::_on_mouse_exited() {
int TabContainer::_get_tab_width(int p_index) const {
ERR_FAIL_INDEX_V(p_index, get_tab_count(), 0);
- Control *control = Object::cast_to<Control>(_get_tabs()[p_index]);
- if (!control || control->is_set_as_top_level() || get_tab_hidden(p_index)) {
+ Control *control = get_tab_control(p_index);
+ if (!control || get_tab_hidden(p_index)) {
return 0;
}
@@ -905,7 +906,7 @@ void TabContainer::drop_data(const Point2 &p_point, const Variant &p_data) {
if (from_tabc && from_tabc->get_tabs_rearrange_group() == get_tabs_rearrange_group()) {
Control *moving_tabc = from_tabc->get_tab_control(tab_from_id);
from_tabc->remove_child(moving_tabc);
- add_child(moving_tabc);
+ add_child(moving_tabc, false, INTERNAL_MODE_FRONT);
if (hover_now < 0) {
hover_now = get_tab_count() - 1;
}
@@ -1211,6 +1212,7 @@ void TabContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_tab_icon", "tab_idx"), &TabContainer::get_tab_icon);
ClassDB::bind_method(D_METHOD("set_tab_disabled", "tab_idx", "disabled"), &TabContainer::set_tab_disabled);
ClassDB::bind_method(D_METHOD("get_tab_disabled", "tab_idx"), &TabContainer::get_tab_disabled);
+ ClassDB::bind_method(D_METHOD("get_tab_idx_at_point", "point"), &TabContainer::get_tab_idx_at_point);
ClassDB::bind_method(D_METHOD("set_popup", "popup"), &TabContainer::set_popup);
ClassDB::bind_method(D_METHOD("get_popup"), &TabContainer::get_popup);
ClassDB::bind_method(D_METHOD("set_drag_to_rearrange_enabled", "enabled"), &TabContainer::set_drag_to_rearrange_enabled);
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 61dfec6abe..f64c07df76 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -37,6 +37,7 @@
#include "core/object/script_language.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
+#include "core/string/string_builder.h"
#include "core/string/translation.h"
#include "scene/main/window.h"
@@ -78,7 +79,11 @@ void TextEdit::Text::set_font_size(int p_font_size) {
}
void TextEdit::Text::set_tab_size(int p_tab_size) {
+ if (tab_size == p_tab_size) {
+ return;
+ }
tab_size = p_tab_size;
+ tab_size_dirty = true;
}
int TextEdit::Text::get_tab_size() const {
@@ -118,10 +123,8 @@ int TextEdit::Text::get_line_width(int p_line, int p_wrap_index) const {
return text[p_line].data_buf->get_size().x;
}
-int TextEdit::Text::get_line_height(int p_line, int p_wrap_index) const {
- ERR_FAIL_INDEX_V(p_line, text.size(), 0);
-
- return text[p_line].data_buf->get_line_size(p_wrap_index).y;
+int TextEdit::Text::get_line_height() const {
+ return line_height;
}
void TextEdit::Text::set_width(float p_width) {
@@ -153,6 +156,36 @@ _FORCE_INLINE_ const String &TextEdit::Text::operator[](int p_line) const {
return text[p_line].data;
}
+void TextEdit::Text::_calculate_line_height() {
+ int height = 0;
+ for (int i = 0; i < text.size(); i++) {
+ // Found another line with the same height...nothing to update.
+ if (text[i].height == line_height) {
+ height = line_height;
+ break;
+ }
+ height = MAX(height, text[i].height);
+ }
+ line_height = height;
+}
+
+void TextEdit::Text::_calculate_max_line_width() {
+ int width = 0;
+ for (int i = 0; i < text.size(); i++) {
+ if (is_hidden(i)) {
+ continue;
+ }
+
+ // Found another line with the same width...nothing to update.
+ if (text[i].width == max_width) {
+ width = max_width;
+ break;
+ }
+ width = MAX(width, text[i].width);
+ }
+ max_width = width;
+}
+
void TextEdit::Text::invalidate_cache(int p_line, int p_column, const String &p_ime_text, const Vector<Vector2i> &p_bidi_override) {
ERR_FAIL_INDEX(p_line, text.size());
@@ -182,17 +215,54 @@ void TextEdit::Text::invalidate_cache(int p_line, int p_column, const String &p_
tabs.push_back(font->get_char_size(' ', 0, font_size).width * tab_size);
text.write[p_line].data_buf->tab_align(tabs);
}
+
+ // Update height.
+ const int old_height = text.write[p_line].height;
+ const int wrap_amount = get_line_wrap_amount(p_line);
+ int height = font->get_height(font_size);
+ for (int i = 0; i <= wrap_amount; i++) {
+ height = MAX(height, text[p_line].data_buf->get_line_size(i).y);
+ }
+ text.write[p_line].height = height;
+
+ // If this line has shrunk, this may no longer the the tallest line.
+ if (old_height == line_height && height < line_height) {
+ _calculate_line_height();
+ } else {
+ line_height = MAX(height, line_height);
+ }
+
+ // Update width.
+ const int old_width = text.write[p_line].width;
+ int width = get_line_width(p_line);
+ text.write[p_line].width = width;
+
+ // If this line has shrunk, this may no longer the the longest line.
+ if (old_width == max_width && width < max_width) {
+ _calculate_max_line_width();
+ } else if (!is_hidden(p_line)) {
+ max_width = MAX(width, max_width);
+ }
}
void TextEdit::Text::invalidate_all_lines() {
for (int i = 0; i < text.size(); i++) {
text.write[i].data_buf->set_width(width);
- if (tab_size > 0) {
- Vector<float> tabs;
- tabs.push_back(font->get_char_size(' ', 0, font_size).width * tab_size);
- text.write[i].data_buf->tab_align(tabs);
+ if (tab_size_dirty) {
+ if (tab_size > 0) {
+ Vector<float> tabs;
+ tabs.push_back(font->get_char_size(' ', 0, font_size).width * tab_size);
+ text.write[i].data_buf->tab_align(tabs);
+ }
+ // Tabs have changes, force width update.
+ text.write[i].width = get_line_width(i);
}
}
+
+ if (tab_size_dirty) {
+ _calculate_max_line_width();
+ tab_size_dirty = false;
+ }
}
void TextEdit::Text::invalidate_all() {
@@ -211,16 +281,8 @@ void TextEdit::Text::clear() {
insert(0, "", Vector<Vector2i>());
}
-int TextEdit::Text::get_max_width(bool p_exclude_hidden) const {
- // Quite some work, but should be fast enough.
-
- int max = 0;
- for (int i = 0; i < text.size(); i++) {
- if (!p_exclude_hidden || !is_hidden(i)) {
- max = MAX(max, get_line_width(i));
- }
- }
- return max;
+int TextEdit::Text::get_max_width() const {
+ return max_width;
}
void TextEdit::Text::set(int p_line, const String &p_text, const Vector<Vector2i> &p_bidi_override) {
@@ -243,7 +305,20 @@ void TextEdit::Text::insert(int p_at, const String &p_text, const Vector<Vector2
}
void TextEdit::Text::remove(int p_at) {
+ int height = text[p_at].height;
+ int width = text[p_at].width;
+
text.remove(p_at);
+
+ // If this is the tallest line, we need to get the next tallest.
+ if (height == line_height) {
+ _calculate_line_height();
+ }
+
+ // If this is the longest line, we need to get the next longest.
+ if (width == max_width) {
+ _calculate_max_line_width();
+ }
}
void TextEdit::Text::add_gutter(int p_at) {
@@ -293,7 +368,7 @@ void TextEdit::_notification(int p_what) {
case NOTIFICATION_VISIBILITY_CHANGED: {
if (is_visible()) {
call_deferred(SNAME("_update_scrollbars"));
- call_deferred(SNAME("_update_wrap_at"));
+ call_deferred(SNAME("_update_wrap_at_column"));
}
} break;
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
@@ -557,13 +632,25 @@ void TextEdit::_notification(int p_what) {
}
int minimap_draw_amount = minimap_visible_lines + get_line_wrap_count(minimap_line + 1);
- // draw the minimap
- Color viewport_color = (background_color.get_v() < 0.5) ? Color(1, 1, 1, 0.1) : Color(0, 0, 0, 0.1);
+ // Draw the minimap.
+
+ // Add visual feedback when dragging or hovering the the visible area rectangle.
+ float viewport_alpha;
+ if (dragging_minimap) {
+ viewport_alpha = 0.25;
+ } else if (hovering_minimap) {
+ viewport_alpha = 0.175;
+ } else {
+ viewport_alpha = 0.1;
+ }
+
+ const Color viewport_color = (background_color.get_v() < 0.5) ? Color(1, 1, 1, viewport_alpha) : Color(0, 0, 0, viewport_alpha);
if (rtl) {
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - (xmargin_end + 2) - minimap_width, viewport_offset_y, minimap_width, viewport_height), viewport_color);
} else {
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2((xmargin_end + 2), viewport_offset_y, minimap_width, viewport_height), viewport_color);
}
+
for (int i = 0; i < minimap_draw_amount; i++) {
minimap_line++;
@@ -632,8 +719,9 @@ void TextEdit::_notification(int p_what) {
int characters = 0;
int tabs = 0;
for (int j = 0; j < str.length(); j++) {
- if (color_map.has(last_wrap_column + j)) {
- current_color = color_map[last_wrap_column + j].get("color");
+ const Variant *color_data = color_map.getptr(last_wrap_column + j);
+ if (color_data != nullptr) {
+ current_color = (color_data->operator Dictionary()).get("color", font_color);
if (!editable) {
current_color.a = font_readonly_color.a;
}
@@ -888,7 +976,7 @@ void TextEdit::_notification(int p_what) {
// Draw line.
RID rid = ldata->get_line_rid(line_wrap_index);
- float text_height = TS->shaped_text_get_size(rid).y + font->get_spacing(Font::SPACING_TOP) + font->get_spacing(Font::SPACING_BOTTOM);
+ float text_height = TS->shaped_text_get_size(rid).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM);
if (rtl) {
char_margin = size.width - char_margin - TS->shaped_text_get_size(rid).x;
@@ -1011,8 +1099,9 @@ void TextEdit::_notification(int p_what) {
char_ofs = 0;
}
for (int j = 0; j < gl_size; j++) {
- if (color_map.has(glyphs[j].start)) {
- current_color = color_map[glyphs[j].start].get("color");
+ const Variant *color_data = color_map.getptr(glyphs[j].start);
+ if (color_data != nullptr) {
+ current_color = (color_data->operator Dictionary()).get("color", font_color);
if (!editable && current_color.a > font_readonly_color.a) {
current_color.a = font_readonly_color.a;
}
@@ -1549,6 +1638,10 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
+ if (draw_minimap && !dragging_selection) {
+ _update_minimap_hover();
+ }
+
if (v_scroll->get_value() != prev_v_scroll || h_scroll->get_value() != prev_h_scroll) {
accept_event(); // Accept event if scroll changed.
}
@@ -2532,15 +2625,15 @@ void TextEdit::set_text(const String &p_text) {
}
String TextEdit::get_text() const {
- String longthing;
- int len = text.size();
- for (int i = 0; i < len; i++) {
- longthing += text[i];
- if (i != len - 1) {
- longthing += "\n";
+ StringBuilder ret_text;
+ const int text_size = text.size();
+ for (int i = 0; i < text_size; i++) {
+ ret_text += text[i];
+ if (i != text_size - 1) {
+ ret_text += "\n";
}
}
- return longthing;
+ return ret_text.as_string();
}
int TextEdit::get_line_count() const {
@@ -2576,13 +2669,7 @@ int TextEdit::get_line_width(int p_line, int p_wrap_index) const {
}
int TextEdit::get_line_height() const {
- int height = font->get_height(font_size);
- for (int i = 0; i < text.size(); i++) {
- for (int j = 0; j <= text.get_line_wrap_amount(i); j++) {
- height = MAX(height, text.get_line_height(i, j));
- }
- }
- return height + line_spacing;
+ return text.get_line_height() + line_spacing;
}
int TextEdit::get_indent_level(int p_line) const {
@@ -4135,6 +4222,9 @@ TextEdit::GutterType TextEdit::get_gutter_type(int p_gutter) const {
void TextEdit::set_gutter_width(int p_gutter, int p_width) {
ERR_FAIL_INDEX(p_gutter, gutters.size());
+ if (gutters[p_gutter].width == p_width) {
+ return;
+ }
gutters.write[p_gutter].width = p_width;
_update_gutter_width();
}
@@ -4150,6 +4240,9 @@ int TextEdit::get_total_gutter_width() const {
void TextEdit::set_gutter_draw(int p_gutter, bool p_draw) {
ERR_FAIL_INDEX(p_gutter, gutters.size());
+ if (gutters[p_gutter].draw == p_draw) {
+ return;
+ }
gutters.write[p_gutter].draw = p_draw;
_update_gutter_width();
}
@@ -5004,7 +5097,7 @@ void TextEdit::_paste_internal() {
void TextEdit::_generate_context_menu() {
if (!menu) {
menu = memnew(PopupMenu);
- add_child(menu);
+ add_child(menu, false, INTERNAL_MODE_FRONT);
menu_dir = memnew(PopupMenu);
menu_dir->set_name("DirMenu");
@@ -5012,7 +5105,7 @@ void TextEdit::_generate_context_menu() {
menu_dir->add_radio_check_item(RTR("Auto-detect direction"), MENU_DIR_AUTO);
menu_dir->add_radio_check_item(RTR("Left-to-right"), MENU_DIR_LTR);
menu_dir->add_radio_check_item(RTR("Right-to-left"), MENU_DIR_RTL);
- menu->add_child(menu_dir);
+ menu->add_child(menu_dir, false, INTERNAL_MODE_FRONT);
menu_ctl = memnew(PopupMenu);
menu_ctl->set_name("CTLMenu");
@@ -5034,7 +5127,7 @@ void TextEdit::_generate_context_menu() {
menu_ctl->add_item(RTR("Zero width non-joiner (ZWNJ)"), MENU_INSERT_ZWNJ);
menu_ctl->add_item(RTR("Word joiner (WJ)"), MENU_INSERT_WJ);
menu_ctl->add_item(RTR("Soft hyphen (SHY)"), MENU_INSERT_SHY);
- menu->add_child(menu_ctl);
+ menu->add_child(menu_ctl, false, INTERNAL_MODE_FRONT);
menu->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
menu_dir->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
@@ -5442,7 +5535,7 @@ void TextEdit::_update_scrollbars() {
}
int visible_width = size.width - style_normal->get_minimum_size().width;
- int total_width = text.get_max_width(true) + vmin.x + gutters_width + gutter_padding;
+ int total_width = text.get_max_width() + vmin.x + gutters_width + gutter_padding;
if (draw_minimap) {
total_width += minimap_width;
@@ -5644,6 +5737,33 @@ void TextEdit::_scroll_lines_down() {
}
// Minimap
+
+void TextEdit::_update_minimap_hover() {
+ const Point2 mp = get_local_mouse_pos();
+ const int xmargin_end = get_size().width - style_normal->get_margin(SIDE_RIGHT);
+
+ const bool hovering_sidebar = mp.x > xmargin_end - minimap_width && mp.x < xmargin_end;
+ if (!hovering_sidebar) {
+ if (hovering_minimap) {
+ // Only redraw if the hovering status changed.
+ hovering_minimap = false;
+ update();
+ }
+
+ // Return early to avoid running the operations below when not needed.
+ return;
+ }
+
+ const int row = get_minimap_line_at_pos(Point2i(mp.x, mp.y));
+
+ const bool new_hovering_minimap = row >= get_first_visible_line() && row <= get_last_full_visible_line();
+ if (new_hovering_minimap != hovering_minimap) {
+ // Only redraw if the hovering status changed.
+ hovering_minimap = new_hovering_minimap;
+ update();
+ }
+}
+
void TextEdit::_update_minimap_click() {
Point2 mp = get_local_mouse_pos();
@@ -5867,8 +5987,6 @@ void TextEdit::_base_insert_text(int p_line, int p_char, const String &p_text, i
text.set_hidden(p_line, false);
}
- text.invalidate_cache(p_line);
-
r_end_line = p_line + substrings.size() - 1;
r_end_column = text[r_end_line].length() - postinsert_text.length();
@@ -5925,8 +6043,6 @@ void TextEdit::_base_remove_text(int p_from_line, int p_from_column, int p_to_li
}
text.set(p_from_line, pre_text + post_text, structured_text_parser(st_parser, st_args, pre_text + post_text));
- text.invalidate_cache(p_from_line);
-
if (!text_changed_dirty && !setting_text) {
if (is_inside_tree()) {
MessageQueue::get_singleton()->push_call(this, "_text_changed_emit");
@@ -5943,13 +6059,12 @@ TextEdit::TextEdit() {
set_default_cursor_shape(CURSOR_IBEAM);
text.set_tab_size(text.get_tab_size());
- text.clear();
h_scroll = memnew(HScrollBar);
v_scroll = memnew(VScrollBar);
- add_child(h_scroll);
- add_child(v_scroll);
+ add_child(h_scroll, false, INTERNAL_MODE_FRONT);
+ add_child(v_scroll, false, INTERNAL_MODE_FRONT);
h_scroll->connect("value_changed", callable_mp(this, &TextEdit::_scroll_moved));
v_scroll->connect("value_changed", callable_mp(this, &TextEdit::_scroll_moved));
@@ -5958,19 +6073,19 @@ TextEdit::TextEdit() {
/* Caret. */
caret_blink_timer = memnew(Timer);
- add_child(caret_blink_timer);
+ add_child(caret_blink_timer, false, INTERNAL_MODE_FRONT);
caret_blink_timer->set_wait_time(0.65);
caret_blink_timer->connect("timeout", callable_mp(this, &TextEdit::_toggle_draw_caret));
set_caret_blink_enabled(false);
/* Selection. */
click_select_held = memnew(Timer);
- add_child(click_select_held);
+ add_child(click_select_held, false, INTERNAL_MODE_FRONT);
click_select_held->set_wait_time(0.05);
click_select_held->connect("timeout", callable_mp(this, &TextEdit::_click_selection_held));
idle_detect = memnew(Timer);
- add_child(idle_detect);
+ add_child(idle_detect, false, INTERNAL_MODE_FRONT);
idle_detect->set_one_shot(true);
idle_detect->set_wait_time(GLOBAL_GET("gui/timers/text_edit_idle_detect_sec"));
idle_detect->connect("timeout", callable_mp(this, &TextEdit::_push_current_op));
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index ced03e19d0..e996bba983 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -144,6 +144,8 @@ private:
Color background_color = Color(0, 0, 0, 0);
bool hidden = false;
+ int height = 0;
+ int width = 0;
Line() {
data_buf.instantiate();
@@ -152,6 +154,7 @@ private:
private:
bool is_dirty = false;
+ bool tab_size_dirty = false;
mutable Vector<Line> text;
Ref<Font> font;
@@ -162,11 +165,16 @@ private:
TextServer::Direction direction = TextServer::DIRECTION_AUTO;
bool draw_control_chars = false;
+ int line_height = -1;
+ int max_width = -1;
int width = -1;
int tab_size = 4;
int gutter_count = 0;
+ void _calculate_line_height();
+ void _calculate_max_line_width();
+
public:
void set_tab_size(int p_tab_size);
int get_tab_size() const;
@@ -176,9 +184,9 @@ private:
void set_direction_and_language(TextServer::Direction p_direction, const String &p_language);
void set_draw_control_chars(bool p_draw_control_chars);
- int get_line_height(int p_line, int p_wrap_index) const;
+ int get_line_height() const;
int get_line_width(int p_line, int p_wrap_index = -1) const;
- int get_max_width(bool p_exclude_hidden = false) const;
+ int get_max_width() const;
void set_width(float p_width);
int get_line_wrap_amount(int p_line) const;
@@ -187,7 +195,14 @@ private:
const Ref<TextParagraph> get_line_data(int p_line) const;
void set(int p_line, const String &p_text, const Vector<Vector2i> &p_bidi_override);
- void set_hidden(int p_line, bool p_hidden) { text.write[p_line].hidden = p_hidden; }
+ void set_hidden(int p_line, bool p_hidden) {
+ text.write[p_line].hidden = p_hidden;
+ if (!p_hidden && text[p_line].width > max_width) {
+ max_width = text[p_line].width;
+ } else if (p_hidden && text[p_line].width == max_width) {
+ _calculate_max_line_width();
+ }
+ }
bool is_hidden(int p_line) const { return text[p_line].hidden; }
void insert(int p_at, const String &p_text, const Vector<Vector2i> &p_bidi_override);
void remove(int p_at);
@@ -446,12 +461,14 @@ private:
// minimap scroll
bool minimap_clicked = false;
+ bool hovering_minimap = false;
bool dragging_minimap = false;
bool can_drag_minimap = false;
double minimap_scroll_ratio = 0.0;
double minimap_scroll_click_pos = 0.0;
+ void _update_minimap_hover();
void _update_minimap_click();
void _update_minimap_drag();
diff --git a/scene/gui/texture_progress_bar.cpp b/scene/gui/texture_progress_bar.cpp
index 5e5dec3579..286f01ee33 100644
--- a/scene/gui/texture_progress_bar.cpp
+++ b/scene/gui/texture_progress_bar.cpp
@@ -100,6 +100,15 @@ Ref<Texture2D> TextureProgressBar::get_progress_texture() const {
return progress;
}
+void TextureProgressBar::set_progress_offset(Point2 p_offset) {
+ progress_offset = p_offset;
+ update();
+}
+
+Point2 TextureProgressBar::get_progress_offset() const {
+ return progress_offset;
+}
+
void TextureProgressBar::set_tint_under(const Color &p_tint) {
tint_under = p_tint;
update();
@@ -360,6 +369,9 @@ void TextureProgressBar::draw_nine_patch_stretched(const Ref<Texture2D> &p_textu
}
}
+ if (p_texture == progress) {
+ dst_rect.position += progress_offset;
+ }
p_texture->get_rect_region(dst_rect, src_rect, dst_rect, src_rect);
RID ci = get_canvas_item();
@@ -403,20 +415,24 @@ void TextureProgressBar::_notification(int p_what) {
Size2 s = progress->get_size();
switch (mode) {
case FILL_LEFT_TO_RIGHT: {
- Rect2 region = Rect2(Point2(), Size2(s.x * get_as_ratio(), s.y));
- draw_texture_rect_region(progress, region, region, tint_progress);
+ Rect2 region = Rect2(progress_offset, Size2(s.x * get_as_ratio(), s.y));
+ Rect2 source = Rect2(Point2(), Size2(s.x * get_as_ratio(), s.y));
+ draw_texture_rect_region(progress, region, source, tint_progress);
} break;
case FILL_RIGHT_TO_LEFT: {
- Rect2 region = Rect2(Point2(s.x - s.x * get_as_ratio(), 0), Size2(s.x * get_as_ratio(), s.y));
- draw_texture_rect_region(progress, region, region, tint_progress);
+ Rect2 region = Rect2(progress_offset + Point2(s.x - s.x * get_as_ratio(), 0), Size2(s.x * get_as_ratio(), s.y));
+ Rect2 source = Rect2(Point2(s.x - s.x * get_as_ratio(), 0), Size2(s.x * get_as_ratio(), s.y));
+ draw_texture_rect_region(progress, region, source, tint_progress);
} break;
case FILL_TOP_TO_BOTTOM: {
- Rect2 region = Rect2(Point2(), Size2(s.x, s.y * get_as_ratio()));
- draw_texture_rect_region(progress, region, region, tint_progress);
+ Rect2 region = Rect2(progress_offset + Point2(), Size2(s.x, s.y * get_as_ratio()));
+ Rect2 source = Rect2(Point2(), Size2(s.x, s.y * get_as_ratio()));
+ draw_texture_rect_region(progress, region, source, tint_progress);
} break;
case FILL_BOTTOM_TO_TOP: {
- Rect2 region = Rect2(Point2(0, s.y - s.y * get_as_ratio()), Size2(s.x, s.y * get_as_ratio()));
- draw_texture_rect_region(progress, region, region, tint_progress);
+ Rect2 region = Rect2(progress_offset + Point2(0, s.y - s.y * get_as_ratio()), Size2(s.x, s.y * get_as_ratio()));
+ Rect2 source = Rect2(Point2(0, s.y - s.y * get_as_ratio()), Size2(s.x, s.y * get_as_ratio()));
+ draw_texture_rect_region(progress, region, source, tint_progress);
} break;
case FILL_CLOCKWISE:
case FILL_COUNTER_CLOCKWISE:
@@ -427,8 +443,9 @@ void TextureProgressBar::_notification(int p_what) {
float val = get_as_ratio() * rad_max_degrees / 360;
if (val == 1) {
- Rect2 region = Rect2(Point2(), s);
- draw_texture_rect(progress, region, false, tint_progress);
+ Rect2 region = Rect2(progress_offset, s);
+ Rect2 source = Rect2(Point2(), s);
+ draw_texture_rect_region(progress, region, source, tint_progress);
} else if (val != 0) {
Array pts;
float direction = mode == FILL_COUNTER_CLOCKWISE ? -1 : 1;
@@ -454,14 +471,14 @@ void TextureProgressBar::_notification(int p_what) {
Vector<Point2> uvs;
Vector<Point2> points;
uvs.push_back(get_relative_center());
- points.push_back(Point2(s.x * get_relative_center().x, s.y * get_relative_center().y));
+ points.push_back(progress_offset + Point2(s.x * get_relative_center().x, s.y * get_relative_center().y));
for (int i = 0; i < pts.size(); i++) {
Point2 uv = unit_val_to_uv(pts[i]);
if (uvs.find(uv) >= 0) {
continue;
}
uvs.push_back(uv);
- points.push_back(Point2(uv.x * s.x, uv.y * s.y));
+ points.push_back(progress_offset + Point2(uv.x * s.x, uv.y * s.y));
}
Vector<Color> colors;
colors.push_back(tint_progress);
@@ -484,17 +501,19 @@ void TextureProgressBar::_notification(int p_what) {
}
} break;
case FILL_BILINEAR_LEFT_AND_RIGHT: {
- Rect2 region = Rect2(Point2(s.x / 2 - s.x * get_as_ratio() / 2, 0), Size2(s.x * get_as_ratio(), s.y));
- draw_texture_rect_region(progress, region, region, tint_progress);
+ Rect2 region = Rect2(progress_offset + Point2(s.x / 2 - s.x * get_as_ratio() / 2, 0), Size2(s.x * get_as_ratio(), s.y));
+ Rect2 source = Rect2(Point2(s.x / 2 - s.x * get_as_ratio() / 2, 0), Size2(s.x * get_as_ratio(), s.y));
+ draw_texture_rect_region(progress, region, source, tint_progress);
} break;
case FILL_BILINEAR_TOP_AND_BOTTOM: {
- Rect2 region = Rect2(Point2(0, s.y / 2 - s.y * get_as_ratio() / 2), Size2(s.x, s.y * get_as_ratio()));
- draw_texture_rect_region(progress, region, region, tint_progress);
+ Rect2 region = Rect2(progress_offset + Point2(0, s.y / 2 - s.y * get_as_ratio() / 2), Size2(s.x, s.y * get_as_ratio()));
+ Rect2 source = Rect2(Point2(0, s.y / 2 - s.y * get_as_ratio() / 2), Size2(s.x, s.y * get_as_ratio()));
+ draw_texture_rect_region(progress, region, source, tint_progress);
} break;
case FILL_MODE_MAX:
break;
default:
- draw_texture_rect_region(progress, Rect2(Point2(), Size2(s.x * get_as_ratio(), s.y)), Rect2(Point2(), Size2(s.x * get_as_ratio(), s.y)), tint_progress);
+ draw_texture_rect_region(progress, Rect2(progress_offset, Size2(s.x * get_as_ratio(), s.y)), Rect2(Point2(), Size2(s.x * get_as_ratio(), s.y)), tint_progress);
}
}
if (over.is_valid()) {
@@ -585,6 +604,9 @@ void TextureProgressBar::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_tint_over", "tint"), &TextureProgressBar::set_tint_over);
ClassDB::bind_method(D_METHOD("get_tint_over"), &TextureProgressBar::get_tint_over);
+ ClassDB::bind_method(D_METHOD("set_texture_progress_offset", "offset"), &TextureProgressBar::set_progress_offset);
+ ClassDB::bind_method(D_METHOD("get_texture_progress_offset"), &TextureProgressBar::get_progress_offset);
+
ClassDB::bind_method(D_METHOD("set_radial_initial_angle", "mode"), &TextureProgressBar::set_radial_initial_angle);
ClassDB::bind_method(D_METHOD("get_radial_initial_angle"), &TextureProgressBar::get_radial_initial_angle);
@@ -604,6 +626,7 @@ void TextureProgressBar::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_under", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_under_texture", "get_under_texture");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_over", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_over_texture", "get_over_texture");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_progress", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_progress_texture", "get_progress_texture");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "texture_progress_offset"), "set_texture_progress_offset", "get_texture_progress_offset");
ADD_PROPERTY(PropertyInfo(Variant::INT, "fill_mode", PROPERTY_HINT_ENUM, "Left to Right,Right to Left,Top to Bottom,Bottom to Top,Clockwise,Counter Clockwise,Bilinear (Left and Right),Bilinear (Top and Bottom),Clockwise and Counter Clockwise"), "set_fill_mode", "get_fill_mode");
ADD_GROUP("Tint", "tint_");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "tint_under"), "set_tint_under", "get_tint_under");
diff --git a/scene/gui/texture_progress_bar.h b/scene/gui/texture_progress_bar.h
index d147c43a26..c508f41387 100644
--- a/scene/gui/texture_progress_bar.h
+++ b/scene/gui/texture_progress_bar.h
@@ -61,6 +61,9 @@ public:
void set_fill_mode(int p_fill);
int get_fill_mode();
+ void set_progress_offset(Point2 p_offset);
+ Point2 get_progress_offset() const;
+
void set_radial_initial_angle(float p_angle);
float get_radial_initial_angle();
@@ -100,6 +103,7 @@ public:
private:
FillMode mode = FILL_LEFT_TO_RIGHT;
+ Point2 progress_offset;
float rad_init_angle = 0.0;
float rad_max_degrees = 360.0;
Point2 rad_center_off;
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 5f07f5216a..cb990892ed 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -889,11 +889,22 @@ void TreeItem::set_custom_font(int p_column, const Ref<Font> &p_font) {
ERR_FAIL_INDEX(p_column, cells.size());
cells.write[p_column].custom_font = p_font;
}
+
Ref<Font> TreeItem::get_custom_font(int p_column) const {
ERR_FAIL_INDEX_V(p_column, cells.size(), Ref<Font>());
return cells[p_column].custom_font;
}
+void TreeItem::set_custom_font_size(int p_column, int p_font_size) {
+ ERR_FAIL_INDEX(p_column, cells.size());
+ cells.write[p_column].custom_font_size = p_font_size;
+}
+
+int TreeItem::get_custom_font_size(int p_column) const {
+ ERR_FAIL_INDEX_V(p_column, cells.size(), -1);
+ return cells[p_column].custom_font_size;
+}
+
void TreeItem::set_tooltip(int p_column, const String &p_tooltip) {
ERR_FAIL_INDEX(p_column, cells.size());
cells.write[p_column].tooltip = p_tooltip;
@@ -1132,6 +1143,9 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_custom_font", "column", "font"), &TreeItem::set_custom_font);
ClassDB::bind_method(D_METHOD("get_custom_font", "column"), &TreeItem::get_custom_font);
+ ClassDB::bind_method(D_METHOD("set_custom_font_size", "column", "font_size"), &TreeItem::set_custom_font_size);
+ ClassDB::bind_method(D_METHOD("get_custom_font_size", "column"), &TreeItem::get_custom_font_size);
+
ClassDB::bind_method(D_METHOD("set_custom_bg_color", "column", "color", "just_outline"), &TreeItem::set_custom_bg_color, DEFVAL(false));
ClassDB::bind_method(D_METHOD("clear_custom_bg_color", "column"), &TreeItem::clear_custom_bg_color);
ClassDB::bind_method(D_METHOD("get_custom_bg_color", "column"), &TreeItem::get_custom_bg_color);
@@ -1507,7 +1521,14 @@ void Tree::update_item_cell(TreeItem *p_item, int p_col) {
} else {
font = cache.font;
}
- p_item->cells.write[p_col].text_buf->add_string(valtext, font, cache.font_size, p_item->cells[p_col].opentype_features, (p_item->cells[p_col].language != "") ? p_item->cells[p_col].language : TranslationServer::get_singleton()->get_tool_locale());
+
+ 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;
+ }
+ p_item->cells.write[p_col].text_buf->add_string(valtext, font, font_size, p_item->cells[p_col].opentype_features, (p_item->cells[p_col].language != "") ? p_item->cells[p_col].language : TranslationServer::get_singleton()->get_tool_locale());
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));
p_item->cells.write[p_col].dirty = false;
}
@@ -1696,24 +1717,30 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
}
}
- if (drop_mode_flags && drop_mode_over == p_item) {
+ if (drop_mode_flags && drop_mode_over) {
Rect2 r = cell_rect;
- bool has_parent = p_item->get_first_child() != nullptr;
if (rtl) {
r.position.x = get_size().width - r.position.x - r.size.x;
}
-
- if (drop_mode_section == -1 || has_parent || drop_mode_section == 0) {
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, r.size.x, 1), cache.drop_position_color);
- }
-
- if (drop_mode_section == 0) {
- 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);
- }
-
- if ((drop_mode_section == 1 && !has_parent) || drop_mode_section == 0) {
- 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);
+ 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);
+ }
+ 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);
+ }
+ 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);
+ }
+ } 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);
+ }
}
}
@@ -4768,12 +4795,11 @@ Tree::Tree() {
popup_menu = memnew(PopupMenu);
popup_menu->hide();
- add_child(popup_menu);
- // popup_menu->set_as_top_level(true);
+ add_child(popup_menu, false, INTERNAL_MODE_FRONT);
popup_editor = memnew(Popup);
popup_editor->set_wrap_controls(true);
- add_child(popup_editor);
+ add_child(popup_editor, false, INTERNAL_MODE_FRONT);
popup_editor_vb = memnew(VBoxContainer);
popup_editor->add_child(popup_editor_vb);
popup_editor_vb->add_theme_constant_override("separation", 0);
@@ -4791,12 +4817,12 @@ Tree::Tree() {
h_scroll = memnew(HScrollBar);
v_scroll = memnew(VScrollBar);
- add_child(h_scroll);
- add_child(v_scroll);
+ add_child(h_scroll, false, INTERNAL_MODE_FRONT);
+ add_child(v_scroll, false, INTERNAL_MODE_FRONT);
range_click_timer = memnew(Timer);
range_click_timer->connect("timeout", callable_mp(this, &Tree::_range_click_timeout));
- add_child(range_click_timer);
+ add_child(range_click_timer, false, INTERNAL_MODE_FRONT);
h_scroll->connect("value_changed", callable_mp(this, &Tree::_scroll_moved));
v_scroll->connect("value_changed", callable_mp(this, &Tree::_scroll_moved));
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index cce8b527db..8b7ddc3faf 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -114,6 +114,7 @@ private:
Vector<Button> buttons;
Ref<Font> custom_font;
+ int custom_font_size = -1;
Cell() {
text_buf.instantiate();
@@ -299,6 +300,9 @@ public:
void set_custom_font(int p_column, const Ref<Font> &p_font);
Ref<Font> get_custom_font(int p_column) const;
+ void set_custom_font_size(int p_column, int p_font_size);
+ int get_custom_font_size(int p_column) const;
+
void set_custom_bg_color(int p_column, const Color &p_color, bool p_bg_outline = false);
void clear_custom_bg_color(int p_column);
Color get_custom_bg_color(int p_column) const;
diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp
index 229b5384ea..8734037a57 100644
--- a/scene/gui/video_player.cpp
+++ b/scene/gui/video_player.cpp
@@ -129,7 +129,7 @@ void VideoPlayer::_mix_audio() {
void VideoPlayer::_notification(int p_notification) {
switch (p_notification) {
case NOTIFICATION_ENTER_TREE: {
- AudioServer::get_singleton()->add_callback(_mix_audios, this);
+ AudioServer::get_singleton()->add_mix_callback(_mix_audios, this);
if (stream.is_valid() && autoplay && !Engine::get_singleton()->is_editor_hint()) {
play();
@@ -138,8 +138,7 @@ void VideoPlayer::_notification(int p_notification) {
} break;
case NOTIFICATION_EXIT_TREE: {
- AudioServer::get_singleton()->remove_callback(_mix_audios, this);
-
+ AudioServer::get_singleton()->remove_mix_callback(_mix_audios, this);
} break;
case NOTIFICATION_INTERNAL_PROCESS: {