summaryrefslogtreecommitdiff
path: root/scene/gui
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui')
-rw-r--r--scene/gui/button.cpp24
-rw-r--r--scene/gui/button.h4
-rw-r--r--scene/gui/color_picker.cpp177
-rw-r--r--scene/gui/color_picker.h6
-rw-r--r--scene/gui/control.cpp10
-rw-r--r--scene/gui/dialogs.cpp4
-rw-r--r--scene/gui/graph_edit.cpp13
-rw-r--r--scene/gui/graph_node.cpp2
-rw-r--r--scene/gui/item_list.cpp8
-rw-r--r--scene/gui/item_list.h6
-rw-r--r--scene/gui/label.cpp79
-rw-r--r--scene/gui/label.h46
-rw-r--r--scene/gui/line_edit.cpp20
-rw-r--r--scene/gui/nine_patch_rect.cpp10
-rw-r--r--scene/gui/popup.cpp11
-rw-r--r--scene/gui/popup.h4
-rw-r--r--scene/gui/popup_menu.cpp34
-rw-r--r--scene/gui/popup_menu.h5
-rw-r--r--scene/gui/reference_rect.cpp2
-rw-r--r--scene/gui/rich_text_label.cpp156
-rw-r--r--scene/gui/rich_text_label.h35
-rw-r--r--scene/gui/scroll_bar.cpp2
-rw-r--r--scene/gui/scroll_container.cpp4
-rw-r--r--scene/gui/split_container.cpp2
-rw-r--r--scene/gui/tab_bar.cpp2
-rw-r--r--scene/gui/text_edit.cpp12
-rw-r--r--scene/gui/texture_progress_bar.cpp12
-rw-r--r--scene/gui/video_stream_player.cpp2
28 files changed, 436 insertions, 256 deletions
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index c54897035a..1371c9cd57 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -35,7 +35,7 @@
Size2 Button::get_minimum_size() const {
Size2 minsize = text_buf->get_size();
- if (clip_text) {
+ if (clip_text || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
minsize.width = 0;
}
@@ -292,9 +292,9 @@ void Button::_notification(int p_what) {
icon_ofs.x = 0.0;
}
int text_clip = size.width - style->get_minimum_size().width - icon_ofs.width;
- text_buf->set_width(clip_text ? text_clip : -1);
+ text_buf->set_width((clip_text || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) ? text_clip : -1);
- int text_width = MAX(1, clip_text ? MIN(text_clip, text_buf->get_size().x) : text_buf->get_size().x);
+ 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"));
@@ -364,6 +364,21 @@ void Button::_shape() {
text_buf->set_direction((TextServer::Direction)text_direction);
}
text_buf->add_string(xl_text, font, font_size, opentype_features, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale());
+ text_buf->set_text_overrun_behavior(overrun_behavior);
+}
+
+void Button::set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior) {
+ if (overrun_behavior != p_behavior) {
+ overrun_behavior = p_behavior;
+ _shape();
+
+ update();
+ update_minimum_size();
+ }
+}
+
+TextServer::OverrunBehavior Button::get_text_overrun_behavior() const {
+ return overrun_behavior;
}
void Button::set_text(const String &p_text) {
@@ -550,6 +565,8 @@ void Button::_get_property_list(List<PropertyInfo> *p_list) const {
void Button::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text", "text"), &Button::set_text);
ClassDB::bind_method(D_METHOD("get_text"), &Button::get_text);
+ ClassDB::bind_method(D_METHOD("set_text_overrun_behavior", "overrun_behavior"), &Button::set_text_overrun_behavior);
+ ClassDB::bind_method(D_METHOD("get_text_overrun_behavior"), &Button::get_text_overrun_behavior);
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &Button::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &Button::get_text_direction);
ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &Button::set_opentype_feature);
@@ -577,6 +594,7 @@ void Button::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "get_clip_text");
ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_text_alignment", "get_text_alignment");
+ 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::INT, "icon_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_icon_alignment", "get_icon_alignment");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand_icon"), "set_expand_icon", "is_expand_icon");
}
diff --git a/scene/gui/button.h b/scene/gui/button.h
index 1abf86c986..a1d71195cb 100644
--- a/scene/gui/button.h
+++ b/scene/gui/button.h
@@ -46,6 +46,7 @@ private:
Dictionary opentype_features;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
+ TextServer::OverrunBehavior overrun_behavior = TextServer::OVERRUN_NO_TRIMMING;
Ref<Texture2D> icon;
bool expand_icon = false;
@@ -71,6 +72,9 @@ public:
void set_text(const String &p_text);
String get_text() const;
+ void set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior);
+ TextServer::OverrunBehavior get_text_overrun_behavior() const;
+
void set_text_direction(TextDirection p_text_direction);
TextDirection get_text_direction() const;
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 6f7ad94139..28d645e8f6 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -31,6 +31,7 @@
#include "color_picker.h"
#include "core/input/input.h"
+#include "core/math/color.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "scene/main/window.h"
@@ -39,6 +40,9 @@
#include "editor/editor_settings.h"
#endif
+#include "thirdparty/misc/ok_color.h"
+#include "thirdparty/misc/ok_color_shader.h"
+
List<Color> ColorPicker::preset_cache;
void ColorPicker::_notification(int p_what) {
@@ -102,6 +106,7 @@ void ColorPicker::_notification(int p_what) {
Ref<Shader> ColorPicker::wheel_shader;
Ref<Shader> ColorPicker::circle_shader;
+Ref<Shader> ColorPicker::circle_ok_color_shader;
void ColorPicker::init_shaders() {
wheel_shader.instantiate();
@@ -152,11 +157,36 @@ void fragment() {
COLOR = vec4(mix(vec3(1.0), clamp(abs(fract(vec3((a - TAU) / TAU) + vec3(1.0, 2.0 / 3.0, 1.0 / 3.0)) * 6.0 - vec3(3.0)) - vec3(1.0), 0.0, 1.0), ((float(sqrt(x * x + y * y)) * 2.0)) / 1.0) * vec3(v), (b + b2 + b3 + b4) / 4.00);
})");
+
+ circle_ok_color_shader.instantiate();
+ circle_ok_color_shader->set_code(OK_COLOR_SHADER + R"(
+// ColorPicker ok color hsv circle shader.
+
+uniform float v = 1.0;
+
+void fragment() {
+ float x = UV.x - 0.5;
+ float y = UV.y - 0.5;
+ x += 0.001;
+ y += 0.001;
+ float b = float(sqrt(x * x + y * y) < 0.5);
+ x -= 0.002;
+ float b2 = float(sqrt(x * x + y * y) < 0.5);
+ y -= 0.002;
+ float b3 = float(sqrt(x * x + y * y) < 0.5);
+ x += 0.002;
+ float b4 = float(sqrt(x * x + y * y) < 0.5);
+ float s = sqrt(x * x + y * y);
+ float h = atan(y, x) / (2.0*M_PI);
+ vec3 col = okhsl_to_srgb(vec3(h, s, v));
+ COLOR = vec4(col, (b + b2 + b3 + b4) / 4.00);
+})");
}
void ColorPicker::finish_shaders() {
wheel_shader.unref();
circle_shader.unref();
+ circle_ok_color_shader.unref();
}
void ColorPicker::set_focus_on_line_edit() {
@@ -166,8 +196,12 @@ void ColorPicker::set_focus_on_line_edit() {
void ColorPicker::_update_controls() {
const char *rgb[3] = { "R", "G", "B" };
const char *hsv[3] = { "H", "S", "V" };
-
- if (hsv_mode_enabled) {
+ const char *hsl[3] = { "H", "S", "L" };
+ if (hsv_mode_enabled && picker_type == SHAPE_OKHSL_CIRCLE) {
+ for (int i = 0; i < 3; i++) {
+ labels[i]->set_text(hsl[i]);
+ }
+ } else if (hsv_mode_enabled && picker_type != SHAPE_OKHSL_CIRCLE) {
for (int i = 0; i < 3; i++) {
labels[i]->set_text(hsv[i]);
}
@@ -176,14 +210,23 @@ void ColorPicker::_update_controls() {
labels[i]->set_text(rgb[i]);
}
}
-
+ if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ btn_hsv->set_text(RTR("OKHSL"));
+ } else {
+ btn_hsv->set_text(RTR("HSV"));
+ }
if (hsv_mode_enabled) {
set_raw_mode(false);
+ set_hsv_mode(true);
btn_raw->set_disabled(true);
} else if (raw_mode_enabled) {
+ set_raw_mode(true);
set_hsv_mode(false);
+ btn_raw->set_disabled(false);
btn_hsv->set_disabled(true);
} else {
+ set_raw_mode(false);
+ set_hsv_mode(false);
btn_raw->set_disabled(false);
btn_hsv->set_disabled(false);
}
@@ -236,8 +279,15 @@ void ColorPicker::_update_controls() {
wheel_edit->show();
w_edit->show();
uv_edit->hide();
-
wheel->set_material(circle_mat);
+ circle_mat->set_shader(circle_shader);
+ break;
+ case SHAPE_OKHSL_CIRCLE:
+ wheel_edit->show();
+ w_edit->show();
+ uv_edit->hide();
+ wheel->set_material(circle_mat);
+ circle_mat->set_shader(circle_ok_color_shader);
break;
default: {
}
@@ -246,11 +296,17 @@ void ColorPicker::_update_controls() {
void ColorPicker::_set_pick_color(const Color &p_color, bool p_update_sliders) {
color = p_color;
- if (color != last_hsv) {
- h = color.get_h();
- s = color.get_s();
- v = color.get_v();
- last_hsv = color;
+ if (color != last_color) {
+ if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ h = color.get_ok_hsl_h();
+ s = color.get_ok_hsl_s();
+ v = color.get_ok_hsl_l();
+ } else {
+ h = color.get_h();
+ s = color.get_s();
+ v = color.get_v();
+ }
+ last_color = color;
}
if (!is_inside_tree()) {
@@ -301,10 +357,13 @@ void ColorPicker::_value_changed(double) {
h = scroll[0]->get_value() / 360.0;
s = scroll[1]->get_value() / 100.0;
v = scroll[2]->get_value() / 100.0;
- color.set_hsv(h, s, v, scroll[3]->get_value() / 255.0);
-
- last_hsv = color;
+ if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ color.set_ok_hsl(h, s, v, Math::round(scroll[3]->get_value() / 255.0));
+ } else {
+ color.set_hsv(h, s, v, Math::round(scroll[3]->get_value() / 255.0));
+ }
+ last_color = color;
} else {
for (int i = 0; i < 4; i++) {
color.components[i] = scroll[i]->get_value() / (raw_mode_enabled ? 1.0 : 255.0);
@@ -342,7 +401,6 @@ void ColorPicker::_update_color(bool p_update_sliders) {
for (int i = 0; i < 4; i++) {
scroll[i]->set_step(1.0);
}
-
scroll[0]->set_max(359);
scroll[0]->set_value(h * 360.0);
scroll[1]->set_max(100);
@@ -350,7 +408,7 @@ void ColorPicker::_update_color(bool p_update_sliders) {
scroll[2]->set_max(100);
scroll[2]->set_value(v * 100.0);
scroll[3]->set_max(255);
- scroll[3]->set_value(color.components[3] * 255.0);
+ scroll[3]->set_value(Math::round(color.components[3] * 255.0));
} else {
for (int i = 0; i < 4; i++) {
if (raw_mode_enabled) {
@@ -362,7 +420,7 @@ void ColorPicker::_update_color(bool p_update_sliders) {
scroll[i]->set_value(color.components[i]);
} else {
scroll[i]->set_step(1);
- const float byte_value = color.components[i] * 255.0;
+ const float byte_value = Math::round(color.components[i] * 255.0);
scroll[i]->set_max(next_power_of_2(MAX(255, byte_value)) - 1);
scroll[i]->set_value(byte_value);
}
@@ -426,7 +484,6 @@ Color ColorPicker::get_pick_color() const {
void ColorPicker::set_picker_shape(PickerShapeType p_picker_type) {
ERR_FAIL_INDEX(p_picker_type, SHAPE_MAX);
picker_type = p_picker_type;
-
_update_controls();
_update_color();
}
@@ -702,7 +759,7 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
Ref<Texture2D> cursor = get_theme_icon(SNAME("picker_cursor"), SNAME("ColorPicker"));
int x;
int y;
- if (picker_type == SHAPE_VHS_CIRCLE) {
+ if (picker_type == SHAPE_VHS_CIRCLE || picker_type == SHAPE_OKHSL_CIRCLE) {
x = center.x + (center.x * Math::cos(h * Math_TAU) * s) - (cursor->get_width() / 2);
y = center.y + (center.y * Math::sin(h * Math_TAU) * s) - (cursor->get_height() / 2);
} else {
@@ -735,6 +792,25 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
Color col;
col.set_hsv(h, 1, 1);
c->draw_line(Point2(0, y), Point2(c->get_size().x, y), col.inverted());
+ } else if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ Vector<Point2> points;
+ Vector<Color> colors;
+ Color col;
+ col.set_ok_hsl(h, s, 1);
+ points.resize(4);
+ colors.resize(4);
+ points.set(0, Vector2());
+ points.set(1, Vector2(c->get_size().x, 0));
+ points.set(2, c->get_size());
+ points.set(3, Vector2(0, c->get_size().y));
+ colors.set(0, col);
+ colors.set(1, col);
+ colors.set(2, Color(0, 0, 0));
+ colors.set(3, Color(0, 0, 0));
+ c->draw_polygon(points, colors);
+ int y = c->get_size().y - c->get_size().y * CLAMP(v, 0, 1);
+ col.set_ok_hsl(h, 1, v);
+ c->draw_line(Point2(0, y), Point2(c->get_size().x, y), col.inverted());
} else if (picker_type == SHAPE_VHS_CIRCLE) {
Vector<Point2> points;
Vector<Color> colors;
@@ -757,7 +833,7 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
}
} else if (p_which == 2) {
c->draw_rect(Rect2(Point2(), c->get_size()), Color(1, 1, 1));
- if (picker_type == SHAPE_VHS_CIRCLE) {
+ if (picker_type == SHAPE_VHS_CIRCLE || picker_type == SHAPE_OKHSL_CIRCLE) {
circle_mat->set_shader_param("v", v);
}
}
@@ -793,10 +869,19 @@ void ColorPicker::_slider_draw(int p_which) {
}
Color s_col;
Color v_col;
- s_col.set_hsv(h, 0, v);
+ if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ s_col.set_ok_hsl(h, 0, v);
+ } else {
+ s_col.set_hsv(h, 0, v);
+ }
left_color = (p_which == 1) ? s_col : Color(0, 0, 0);
- s_col.set_hsv(h, 1, v);
- v_col.set_hsv(h, s, 1);
+ if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ s_col.set_ok_hsl(h, 1, v);
+ v_col.set_ok_hsl(h, s, 1);
+ } else {
+ s_col.set_hsv(h, 1, v);
+ v_col.set_hsv(h, s, 1);
+ }
right_color = (p_which == 1) ? s_col : v_col;
} else {
left_color = Color(
@@ -828,9 +913,8 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) {
if (bev.is_valid()) {
if (bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) {
Vector2 center = c->get_size() / 2.0;
- if (picker_type == SHAPE_VHS_CIRCLE) {
+ if (picker_type == SHAPE_VHS_CIRCLE || picker_type == SHAPE_OKHSL_CIRCLE) {
real_t dist = center.distance_to(bev->get_position());
-
if (dist <= center.x) {
real_t rad = center.angle_to_point(bev->get_position());
h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU;
@@ -867,8 +951,13 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) {
}
}
changing_color = true;
- color.set_hsv(h, s, v, color.a);
- last_hsv = color;
+ if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ color.set_ok_hsl(h, s, v, color.a);
+ } else if (picker_type != SHAPE_OKHSL_CIRCLE) {
+ color.set_hsv(h, s, v, color.a);
+ }
+ last_color = color;
+
set_pick_color(color);
_update_color();
if (!deferred_mode_enabled) {
@@ -892,7 +981,7 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) {
}
Vector2 center = c->get_size() / 2.0;
- if (picker_type == SHAPE_VHS_CIRCLE) {
+ if (picker_type == SHAPE_VHS_CIRCLE || picker_type == SHAPE_OKHSL_CIRCLE) {
real_t dist = center.distance_to(mev->get_position());
real_t rad = center.angle_to_point(mev->get_position());
h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU;
@@ -913,9 +1002,12 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) {
v = 1.0 - (y - corner_y) / real_size.y;
}
}
-
- color.set_hsv(h, s, v, color.a);
- last_hsv = color;
+ if (picker_type != SHAPE_OKHSL_CIRCLE) {
+ color.set_hsv(h, s, v, color.a);
+ } else if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ color.set_ok_hsl(h, s, v, color.a);
+ }
+ last_color = color;
set_pick_color(color);
_update_color();
if (!deferred_mode_enabled) {
@@ -931,7 +1023,7 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) {
if (bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) {
changing_color = true;
float y = CLAMP((float)bev->get_position().y, 0, w_edit->get_size().height);
- if (picker_type == SHAPE_VHS_CIRCLE) {
+ if (picker_type == SHAPE_VHS_CIRCLE || picker_type == SHAPE_OKHSL_CIRCLE) {
v = 1.0 - (y / w_edit->get_size().height);
} else {
h = y / w_edit->get_size().height;
@@ -939,8 +1031,12 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) {
} else {
changing_color = false;
}
- color.set_hsv(h, s, v, color.a);
- last_hsv = color;
+ if (picker_type != SHAPE_OKHSL_CIRCLE) {
+ color.set_hsv(h, s, v, color.a);
+ } else if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ color.set_ok_hsl(h, s, v, color.a);
+ }
+ last_color = color;
set_pick_color(color);
_update_color();
if (!deferred_mode_enabled) {
@@ -957,13 +1053,17 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) {
return;
}
float y = CLAMP((float)mev->get_position().y, 0, w_edit->get_size().height);
- if (picker_type == SHAPE_VHS_CIRCLE) {
+ if (picker_type == SHAPE_VHS_CIRCLE || picker_type == SHAPE_OKHSL_CIRCLE) {
v = 1.0 - (y / w_edit->get_size().height);
} else {
h = y / w_edit->get_size().height;
}
- color.set_hsv(h, s, v, color.a);
- last_hsv = color;
+ if (hsv_mode_enabled && picker_type != SHAPE_OKHSL_CIRCLE) {
+ color.set_hsv(h, s, v, color.a);
+ } else if (hsv_mode_enabled && picker_type == SHAPE_OKHSL_CIRCLE) {
+ color.set_ok_hsl(h, s, v, color.a);
+ }
+ last_color = color;
set_pick_color(color);
_update_color();
if (!deferred_mode_enabled) {
@@ -1008,7 +1108,7 @@ void ColorPicker::_screen_input(const Ref<InputEvent> &p_event) {
Ref<Image> img = r->get_texture()->get_image();
if (img.is_valid() && !img->is_empty()) {
Vector2 ofs = mev->get_global_position() - r->get_visible_rect().get_position();
- Color c = img->get_pixel(ofs.x, r->get_visible_rect().size.height - ofs.y);
+ Color c = img->get_pixel(ofs.x, ofs.y);
set_pick_color(c);
}
@@ -1035,6 +1135,8 @@ void ColorPicker::_screen_pick_pressed() {
screen->connect("gui_input", callable_mp(this, &ColorPicker::_screen_input));
// It immediately toggles off in the first press otherwise.
screen->call_deferred(SNAME("connect"), "hidden", Callable(btn_pick, "set_pressed"), varray(false));
+ } else {
+ screen->show();
}
screen->raise();
#ifndef _MSC_VER
@@ -1128,7 +1230,7 @@ void ColorPicker::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hsv_mode"), "set_hsv_mode", "is_hsv_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "raw_mode"), "set_raw_mode", "is_raw_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deferred_mode"), "set_deferred_mode", "is_deferred_mode");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "picker_shape", PROPERTY_HINT_ENUM, "HSV Rectangle,HSV Rectangle Wheel,VHS Circle"), "set_picker_shape", "get_picker_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "picker_shape", PROPERTY_HINT_ENUM, "HSV Rectangle,HSV Rectangle Wheel,VHS Circle,OKHSL Circle"), "set_picker_shape", "get_picker_shape");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "presets_enabled"), "set_presets_enabled", "are_presets_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "presets_visible"), "set_presets_visible", "are_presets_visible");
@@ -1139,6 +1241,7 @@ void ColorPicker::_bind_methods() {
BIND_ENUM_CONSTANT(SHAPE_HSV_RECTANGLE);
BIND_ENUM_CONSTANT(SHAPE_HSV_WHEEL);
BIND_ENUM_CONSTANT(SHAPE_VHS_CIRCLE);
+ BIND_ENUM_CONSTANT(SHAPE_OKHSL_CIRCLE);
}
ColorPicker::ColorPicker() :
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index 6f3e16009c..953be032ec 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -68,6 +68,7 @@ public:
SHAPE_HSV_RECTANGLE,
SHAPE_HSV_WHEEL,
SHAPE_VHS_CIRCLE,
+ SHAPE_OKHSL_CIRCLE,
SHAPE_MAX
};
@@ -75,6 +76,7 @@ public:
private:
static Ref<Shader> wheel_shader;
static Ref<Shader> circle_shader;
+ static Ref<Shader> circle_ok_color_shader;
static List<Color> preset_cache;
Control *screen = nullptr;
@@ -124,7 +126,7 @@ private:
float h = 0.0;
float s = 0.0;
float v = 0.0;
- Color last_hsv;
+ Color last_color;
void _html_submitted(const String &p_html);
void _value_changed(double);
@@ -161,6 +163,8 @@ public:
void set_edit_alpha(bool p_show);
bool is_editing_alpha() const;
+ int get_preset_size();
+
void _set_pick_color(const Color &p_color, bool p_update_sliders);
void set_pick_color(const Color &p_color);
Color get_pick_color() const;
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index db78b4adb6..036d00345d 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -414,7 +414,7 @@ void Control::_get_property_list(List<PropertyInfo> *p_list) const {
usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
- p_list->push_back(PropertyInfo(Variant::INT, "theme_override_font_sizes/" + E, PROPERTY_HINT_RANGE, "1,256,1,or_greater", usage));
+ p_list->push_back(PropertyInfo(Variant::INT, "theme_override_font_sizes/" + E, PROPERTY_HINT_RANGE, "1,256,1,or_greater,suffix:px", usage));
}
}
{
@@ -478,6 +478,10 @@ void Control::_validate_property(PropertyInfo &property) const {
}
}
+ if (property.name == "scale") {
+ property.hint = PROPERTY_HINT_LINK;
+ }
+
// Validate which positioning properties should be displayed depending on the parent and the layout mode.
Node *parent_node = get_parent_control();
if (!parent_node) {
@@ -3282,7 +3286,7 @@ void Control::_bind_methods() {
ADD_GROUP("Layout", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_contents"), "set_clip_contents", "is_clipping_contents");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "minimum_size"), "set_custom_minimum_size", "get_custom_minimum_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "minimum_size", PROPERTY_HINT_NONE, "suffix:px"), "set_custom_minimum_size", "get_custom_minimum_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_direction", PROPERTY_HINT_ENUM, "Inherited,Locale,Left-to-Right,Right-to-Left"), "set_layout_direction", "get_layout_direction");
ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_mode", PROPERTY_HINT_ENUM, "Position,Anchors,Container,Uncontrolled", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_layout_mode", "_get_layout_mode");
ADD_PROPERTY_DEFAULT("layout_mode", LayoutMode::LAYOUT_MODE_POSITION);
@@ -3317,7 +3321,7 @@ void Control::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_position", PROPERTY_HINT_NONE, "suffix:px", PROPERTY_USAGE_NONE), "_set_global_position", "get_global_position");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians"), "set_rotation", "get_rotation");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale"), "set_scale", "get_scale");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "pivot_offset"), "set_pivot_offset", "get_pivot_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "pivot_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_pivot_offset", "get_pivot_offset");
ADD_SUBGROUP("Container Sizing", "size_flags_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill:1,Expand:2,Shrink Center:4,Shrink End:8"), "set_h_size_flags", "get_h_size_flags");
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index 0bb96a18a5..192d214262 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -154,11 +154,11 @@ bool AcceptDialog::get_close_on_escape() const {
}
void AcceptDialog::set_autowrap(bool p_autowrap) {
- label->set_autowrap_mode(p_autowrap ? Label::AUTOWRAP_WORD : Label::AUTOWRAP_OFF);
+ label->set_autowrap_mode(p_autowrap ? TextServer::AUTOWRAP_WORD : TextServer::AUTOWRAP_OFF);
}
bool AcceptDialog::has_autowrap() {
- return label->get_autowrap_mode() != Label::AUTOWRAP_OFF;
+ return label->get_autowrap_mode() != TextServer::AUTOWRAP_OFF;
}
void AcceptDialog::register_text_enter(Control *p_line_edit) {
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 446d9e800a..c219eafbf7 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -508,8 +508,9 @@ void GraphEdit::_notification(int p_what) {
void GraphEdit::_update_comment_enclosed_nodes_list(GraphNode *p_node, HashMap<StringName, Vector<GraphNode *>> &p_comment_enclosed_nodes) {
Rect2 comment_node_rect = p_node->get_rect();
- Vector<GraphNode *> enclosed_nodes;
+ comment_node_rect.size *= zoom;
+ Vector<GraphNode *> enclosed_nodes;
for (int i = 0; i < get_child_count(); i++) {
GraphNode *gn = Object::cast_to<GraphNode>(get_child(i));
if (!gn || gn->is_selected()) {
@@ -517,6 +518,8 @@ void GraphEdit::_update_comment_enclosed_nodes_list(GraphNode *p_node, HashMap<S
}
Rect2 node_rect = gn->get_rect();
+ node_rect.size *= zoom;
+
bool included = comment_node_rect.encloses(node_rect);
if (included) {
enclosed_nodes.push_back(gn);
@@ -2314,14 +2317,14 @@ void GraphEdit::_bind_methods() {
GDVIRTUAL_BIND(_get_connection_line, "from", "to")
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "right_disconnects"), "set_right_disconnects", "is_right_disconnects_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scroll_offset"), "set_scroll_ofs", "get_scroll_ofs");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "snap_distance"), "set_snap", "get_snap");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scroll_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_scroll_ofs", "get_scroll_ofs");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "snap_distance", PROPERTY_HINT_NONE, "suffix:px"), "set_snap", "get_snap");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_snap"), "set_use_snap", "is_using_snap");
ADD_PROPERTY(PropertyInfo(Variant::INT, "panning_scheme", PROPERTY_HINT_ENUM, "Scroll Zooms,Scroll Pans"), "set_panning_scheme", "get_panning_scheme");
ADD_GROUP("Connection Lines", "connection_lines");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "connection_lines_curvature"), "set_connection_lines_curvature", "get_connection_lines_curvature");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "connection_lines_thickness"), "set_connection_lines_thickness", "get_connection_lines_thickness");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "connection_lines_thickness", PROPERTY_HINT_NONE, "suffix:px"), "set_connection_lines_thickness", "get_connection_lines_thickness");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "connection_lines_antialiased"), "set_connection_lines_antialiased", "is_connection_lines_antialiased");
ADD_GROUP("Zoom", "");
@@ -2333,7 +2336,7 @@ void GraphEdit::_bind_methods() {
ADD_GROUP("Minimap", "minimap");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "minimap_enabled"), "set_minimap_enabled", "is_minimap_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "minimap_size"), "set_minimap_size", "get_minimap_size");
+ 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_SIGNAL(MethodInfo("connection_request", PropertyInfo(Variant::STRING_NAME, "from"), PropertyInfo(Variant::INT, "from_slot"), PropertyInfo(Variant::STRING_NAME, "to"), PropertyInfo(Variant::INT, "to_slot")));
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 5cb28a30e8..87706cd0d7 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -1107,7 +1107,7 @@ void GraphNode::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
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");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position_offset"), "set_position_offset", "get_position_offset");
+ 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, "selected"), "set_selected", "is_selected");
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 8b22f3722a..aeb5338022 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -1550,7 +1550,7 @@ bool ItemList::has_auto_height() const {
return auto_height;
}
-void ItemList::set_text_overrun_behavior(TextParagraph::OverrunBehavior p_behavior) {
+void ItemList::set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior) {
if (text_overrun_behavior != p_behavior) {
text_overrun_behavior = p_behavior;
for (int i = 0; i < items.size(); i++) {
@@ -1561,7 +1561,7 @@ void ItemList::set_text_overrun_behavior(TextParagraph::OverrunBehavior p_behavi
}
}
-TextParagraph::OverrunBehavior ItemList::get_text_overrun_behavior() const {
+TextServer::OverrunBehavior ItemList::get_text_overrun_behavior() const {
return text_overrun_behavior;
}
@@ -1763,11 +1763,11 @@ void ItemList::_bind_methods() {
ADD_GROUP("Columns", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_columns", PROPERTY_HINT_RANGE, "0,10,1,or_greater"), "set_max_columns", "get_max_columns");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "same_column_width"), "set_same_column_width", "is_same_column_width");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_column_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_fixed_column_width", "get_fixed_column_width");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_column_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_fixed_column_width", "get_fixed_column_width");
ADD_GROUP("Icon", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "icon_mode", PROPERTY_HINT_ENUM, "Top,Left"), "set_icon_mode", "get_icon_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "icon_scale"), "set_icon_scale", "get_icon_scale");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "fixed_icon_size"), "set_fixed_icon_size", "get_fixed_icon_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "fixed_icon_size", PROPERTY_HINT_NONE, "suffix:px"), "set_fixed_icon_size", "get_fixed_icon_size");
BIND_ENUM_CONSTANT(ICON_MODE_TOP);
BIND_ENUM_CONSTANT(ICON_MODE_LEFT);
diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h
index ffbe7d055a..a15b090149 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -99,7 +99,7 @@ private:
SelectMode select_mode = SELECT_SINGLE;
IconMode icon_mode = ICON_MODE_LEFT;
VScrollBar *scroll_bar = nullptr;
- TextParagraph::OverrunBehavior text_overrun_behavior = TextParagraph::OVERRUN_TRIM_ELLIPSIS;
+ TextServer::OverrunBehavior text_overrun_behavior = TextServer::OVERRUN_TRIM_ELLIPSIS;
uint64_t search_time_msec = 0;
String search_string;
@@ -188,8 +188,8 @@ public:
void set_item_custom_fg_color(int p_idx, const Color &p_custom_fg_color);
Color get_item_custom_fg_color(int p_idx) const;
- void set_text_overrun_behavior(TextParagraph::OverrunBehavior p_behavior);
- TextParagraph::OverrunBehavior get_text_overrun_behavior() const;
+ void set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior);
+ TextServer::OverrunBehavior get_text_overrun_behavior() const;
void select(int p_idx, bool p_single = true);
void deselect(int p_idx);
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index eda3d40f63..82ab7c2e18 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -36,19 +36,19 @@
#include "servers/text_server.h"
-void Label::set_autowrap_mode(Label::AutowrapMode p_mode) {
+void Label::set_autowrap_mode(TextServer::AutowrapMode p_mode) {
if (autowrap_mode != p_mode) {
autowrap_mode = p_mode;
lines_dirty = true;
}
update();
- if (clip || overrun_behavior != OVERRUN_NO_TRIMMING) {
+ if (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
update_minimum_size();
}
}
-Label::AutowrapMode Label::get_autowrap_mode() const {
+TextServer::AutowrapMode Label::get_autowrap_mode() const {
return autowrap_mode;
}
@@ -96,7 +96,7 @@ void Label::_shape() {
int font_size = get_theme_font_size(SNAME("font_size"));
ERR_FAIL_COND(font.is_null());
String text = (uppercase) ? TS->string_to_upper(xl_text, lang) : xl_text;
- if (visible_chars >= 0 && visible_chars_behavior == VC_CHARS_BEFORE_SHAPING) {
+ if (visible_chars >= 0 && visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) {
text = text.substr(0, visible_chars);
}
if (dirty) {
@@ -121,16 +121,16 @@ void Label::_shape() {
uint16_t autowrap_flags = TextServer::BREAK_MANDATORY;
switch (autowrap_mode) {
- case AUTOWRAP_WORD_SMART:
+ case TextServer::AUTOWRAP_WORD_SMART:
autowrap_flags = TextServer::BREAK_WORD_BOUND_ADAPTIVE | TextServer::BREAK_MANDATORY;
break;
- case AUTOWRAP_WORD:
+ case TextServer::AUTOWRAP_WORD:
autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY;
break;
- case AUTOWRAP_ARBITRARY:
+ case TextServer::AUTOWRAP_ARBITRARY:
autowrap_flags = TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_MANDATORY;
break;
- case AUTOWRAP_OFF:
+ case TextServer::AUTOWRAP_OFF:
break;
}
PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags);
@@ -146,7 +146,7 @@ void Label::_shape() {
return;
}
- if (autowrap_mode == AUTOWRAP_OFF) {
+ if (autowrap_mode == TextServer::AUTOWRAP_OFF) {
minsize.width = 0.0f;
for (int i = 0; i < lines_rid.size(); i++) {
if (minsize.width < TS->shaped_text_get_size(lines_rid[i]).x) {
@@ -156,31 +156,31 @@ void Label::_shape() {
}
if (lines_dirty) {
- uint16_t overrun_flags = TextServer::OVERRUN_NO_TRIMMING;
+ uint16_t overrun_flags = TextServer::OVERRUN_NO_TRIM;
switch (overrun_behavior) {
- case OVERRUN_TRIM_WORD_ELLIPSIS:
+ case TextServer::OVERRUN_TRIM_WORD_ELLIPSIS:
overrun_flags |= TextServer::OVERRUN_TRIM;
overrun_flags |= TextServer::OVERRUN_TRIM_WORD_ONLY;
overrun_flags |= TextServer::OVERRUN_ADD_ELLIPSIS;
break;
- case OVERRUN_TRIM_ELLIPSIS:
+ case TextServer::OVERRUN_TRIM_ELLIPSIS:
overrun_flags |= TextServer::OVERRUN_TRIM;
overrun_flags |= TextServer::OVERRUN_ADD_ELLIPSIS;
break;
- case OVERRUN_TRIM_WORD:
+ case TextServer::OVERRUN_TRIM_WORD:
overrun_flags |= TextServer::OVERRUN_TRIM;
overrun_flags |= TextServer::OVERRUN_TRIM_WORD_ONLY;
break;
- case OVERRUN_TRIM_CHAR:
+ case TextServer::OVERRUN_TRIM_CHAR:
overrun_flags |= TextServer::OVERRUN_TRIM;
break;
- case OVERRUN_NO_TRIMMING:
+ case TextServer::OVERRUN_NO_TRIMMING:
break;
}
// Fill after min_size calculation.
- if (autowrap_mode != AUTOWRAP_OFF) {
+ if (autowrap_mode != TextServer::AUTOWRAP_OFF) {
int visible_lines = get_visible_line_count();
bool lines_hidden = visible_lines > 0 && visible_lines < lines_rid.size();
if (lines_hidden) {
@@ -215,7 +215,7 @@ void Label::_shape() {
_update_visible();
- if (autowrap_mode == AUTOWRAP_OFF || !clip || overrun_behavior == OVERRUN_NO_TRIMMING) {
+ if (autowrap_mode == TextServer::AUTOWRAP_OFF || !clip || overrun_behavior == TextServer::OVERRUN_NO_TRIMMING) {
update_minimum_size();
}
}
@@ -326,9 +326,9 @@ void Label::_notification(int p_what) {
}
int last_line = MIN(lines_rid.size(), lines_visible + lines_skipped);
- bool trim_chars = (visible_chars >= 0) && (visible_chars_behavior == VC_CHARS_AFTER_SHAPING);
- bool trim_glyphs_ltr = (visible_chars >= 0) && ((visible_chars_behavior == VC_GLYPHS_LTR) || ((visible_chars_behavior == VC_GLYPHS_AUTO) && !rtl_layout));
- bool trim_glyphs_rtl = (visible_chars >= 0) && ((visible_chars_behavior == VC_GLYPHS_RTL) || ((visible_chars_behavior == VC_GLYPHS_AUTO) && rtl_layout));
+ bool trim_chars = (visible_chars >= 0) && (visible_chars_behavior == TextServer::VC_CHARS_AFTER_SHAPING);
+ bool trim_glyphs_ltr = (visible_chars >= 0) && ((visible_chars_behavior == TextServer::VC_GLYPHS_LTR) || ((visible_chars_behavior == TextServer::VC_GLYPHS_AUTO) && !rtl_layout));
+ bool trim_glyphs_rtl = (visible_chars >= 0) && ((visible_chars_behavior == TextServer::VC_GLYPHS_RTL) || ((visible_chars_behavior == TextServer::VC_GLYPHS_AUTO) && rtl_layout));
// Get real total height.
int total_glyphs = 0;
@@ -377,7 +377,7 @@ void Label::_notification(int p_what) {
ofs.y += TS->shaped_text_get_ascent(lines_rid[i]) + font->get_spacing(TextServer::SPACING_TOP);
switch (horizontal_alignment) {
case HORIZONTAL_ALIGNMENT_FILL:
- if (rtl && autowrap_mode != AUTOWRAP_OFF) {
+ if (rtl && autowrap_mode != TextServer::AUTOWRAP_OFF) {
ofs.x = int(size.width - style->get_margin(SIDE_RIGHT) - line_size.width);
} else {
ofs.x = style->get_offset().x;
@@ -554,10 +554,10 @@ Size2 Label::get_minimum_size() const {
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) {
- return Size2(1, (clip || overrun_behavior != OVERRUN_NO_TRIMMING) ? 1 : min_size.height) + min_style;
+ if (autowrap_mode != TextServer::AUTOWRAP_OFF) {
+ return Size2(1, (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) ? 1 : min_size.height) + min_style;
} else {
- if (clip || overrun_behavior != OVERRUN_NO_TRIMMING) {
+ if (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
min_size.width = 1;
}
return min_size + min_style;
@@ -719,18 +719,18 @@ bool Label::is_clipping_text() const {
return clip;
}
-void Label::set_text_overrun_behavior(Label::OverrunBehavior p_behavior) {
+void Label::set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior) {
if (overrun_behavior != p_behavior) {
overrun_behavior = p_behavior;
lines_dirty = true;
}
update();
- if (clip || overrun_behavior != OVERRUN_NO_TRIMMING) {
+ if (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
update_minimum_size();
}
}
-Label::OverrunBehavior Label::get_text_overrun_behavior() const {
+TextServer::OverrunBehavior Label::get_text_overrun_behavior() const {
return overrun_behavior;
}
@@ -746,7 +746,7 @@ void Label::set_visible_characters(int p_amount) {
} else {
percent_visible = 1.0;
}
- if (visible_chars_behavior == VC_CHARS_BEFORE_SHAPING) {
+ if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) {
dirty = true;
}
update();
@@ -766,7 +766,7 @@ void Label::set_percent_visible(float p_percent) {
visible_chars = get_total_character_count() * p_percent;
percent_visible = p_percent;
}
- if (visible_chars_behavior == VC_CHARS_BEFORE_SHAPING) {
+ if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) {
dirty = true;
}
update();
@@ -777,11 +777,11 @@ float Label::get_percent_visible() const {
return percent_visible;
}
-Label::VisibleCharactersBehavior Label::get_visible_characters_behavior() const {
+TextServer::VisibleCharactersBehavior Label::get_visible_characters_behavior() const {
return visible_chars_behavior;
}
-void Label::set_visible_characters_behavior(Label::VisibleCharactersBehavior p_behavior) {
+void Label::set_visible_characters_behavior(TextServer::VisibleCharactersBehavior p_behavior) {
if (visible_chars_behavior != p_behavior) {
visible_chars_behavior = p_behavior;
dirty = true;
@@ -909,23 +909,6 @@ void Label::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override_options", "args"), &Label::set_structured_text_bidi_override_options);
ClassDB::bind_method(D_METHOD("get_structured_text_bidi_override_options"), &Label::get_structured_text_bidi_override_options);
- BIND_ENUM_CONSTANT(AUTOWRAP_OFF);
- BIND_ENUM_CONSTANT(AUTOWRAP_ARBITRARY);
- BIND_ENUM_CONSTANT(AUTOWRAP_WORD);
- BIND_ENUM_CONSTANT(AUTOWRAP_WORD_SMART);
-
- BIND_ENUM_CONSTANT(OVERRUN_NO_TRIMMING);
- BIND_ENUM_CONSTANT(OVERRUN_TRIM_CHAR);
- BIND_ENUM_CONSTANT(OVERRUN_TRIM_WORD);
- BIND_ENUM_CONSTANT(OVERRUN_TRIM_ELLIPSIS);
- BIND_ENUM_CONSTANT(OVERRUN_TRIM_WORD_ELLIPSIS);
-
- BIND_ENUM_CONSTANT(VC_CHARS_BEFORE_SHAPING);
- BIND_ENUM_CONSTANT(VC_CHARS_AFTER_SHAPING);
- BIND_ENUM_CONSTANT(VC_GLYPHS_AUTO);
- BIND_ENUM_CONSTANT(VC_GLYPHS_LTR);
- BIND_ENUM_CONSTANT(VC_GLYPHS_RTL);
-
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment");
ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_alignment", PROPERTY_HINT_ENUM, "Top,Center,Bottom,Fill"), "set_vertical_alignment", "get_vertical_alignment");
diff --git a/scene/gui/label.h b/scene/gui/label.h
index f7b725928f..fac3d75a1b 100644
--- a/scene/gui/label.h
+++ b/scene/gui/label.h
@@ -36,38 +36,14 @@
class Label : public Control {
GDCLASS(Label, Control);
-public:
- enum AutowrapMode {
- AUTOWRAP_OFF,
- AUTOWRAP_ARBITRARY,
- AUTOWRAP_WORD,
- AUTOWRAP_WORD_SMART
- };
-
- enum OverrunBehavior {
- OVERRUN_NO_TRIMMING,
- OVERRUN_TRIM_CHAR,
- OVERRUN_TRIM_WORD,
- OVERRUN_TRIM_ELLIPSIS,
- OVERRUN_TRIM_WORD_ELLIPSIS,
- };
-
- enum VisibleCharactersBehavior {
- VC_CHARS_BEFORE_SHAPING,
- VC_CHARS_AFTER_SHAPING,
- VC_GLYPHS_AUTO,
- VC_GLYPHS_LTR,
- VC_GLYPHS_RTL,
- };
-
private:
HorizontalAlignment horizontal_alignment = HORIZONTAL_ALIGNMENT_LEFT;
VerticalAlignment vertical_alignment = VERTICAL_ALIGNMENT_TOP;
String text;
String xl_text;
- AutowrapMode autowrap_mode = AUTOWRAP_OFF;
+ TextServer::AutowrapMode autowrap_mode = TextServer::AUTOWRAP_OFF;
bool clip = false;
- OverrunBehavior overrun_behavior = OVERRUN_NO_TRIMMING;
+ TextServer::OverrunBehavior overrun_behavior = TextServer::OVERRUN_NO_TRIMMING;
Size2 minsize;
bool uppercase = false;
@@ -85,7 +61,7 @@ private:
float percent_visible = 1.0;
- VisibleCharactersBehavior visible_chars_behavior = VC_CHARS_BEFORE_SHAPING;
+ TextServer::VisibleCharactersBehavior visible_chars_behavior = TextServer::VC_CHARS_BEFORE_SHAPING;
int visible_chars = -1;
int lines_skipped = 0;
int max_lines_visible = -1;
@@ -130,14 +106,14 @@ public:
void set_structured_text_bidi_override_options(Array p_args);
Array get_structured_text_bidi_override_options() const;
- void set_autowrap_mode(AutowrapMode p_mode);
- AutowrapMode get_autowrap_mode() const;
+ void set_autowrap_mode(TextServer::AutowrapMode p_mode);
+ TextServer::AutowrapMode get_autowrap_mode() const;
void set_uppercase(bool p_uppercase);
bool is_uppercase() const;
- VisibleCharactersBehavior get_visible_characters_behavior() const;
- void set_visible_characters_behavior(VisibleCharactersBehavior p_behavior);
+ TextServer::VisibleCharactersBehavior get_visible_characters_behavior() const;
+ void set_visible_characters_behavior(TextServer::VisibleCharactersBehavior p_behavior);
void set_visible_characters(int p_amount);
int get_visible_characters() const;
@@ -146,8 +122,8 @@ public:
void set_clip_text(bool p_clip);
bool is_clipping_text() const;
- void set_text_overrun_behavior(OverrunBehavior p_behavior);
- OverrunBehavior get_text_overrun_behavior() const;
+ void set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior);
+ TextServer::OverrunBehavior get_text_overrun_behavior() const;
void set_percent_visible(float p_percent);
float get_percent_visible() const;
@@ -166,8 +142,4 @@ public:
~Label();
};
-VARIANT_ENUM_CAST(Label::AutowrapMode);
-VARIANT_ENUM_CAST(Label::OverrunBehavior);
-VARIANT_ENUM_CAST(Label::VisibleCharactersBehavior);
-
#endif
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index fd9db4ea1b..540250c8e9 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -312,7 +312,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
selection.end = text.length();
selection.double_click = true;
last_dblclk = 0;
- caret_column = selection.begin;
+ set_caret_column(selection.begin);
if (!pass && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
DisplayServer::get_singleton()->clipboard_set_primary(text);
}
@@ -327,7 +327,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
selection.begin = words[i];
selection.end = words[i + 1];
selection.double_click = true;
- caret_column = selection.end;
+ set_caret_column(selection.end);
break;
}
}
@@ -1686,13 +1686,17 @@ Size2 LineEdit::get_minimum_size() const {
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();
- 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;
- min_size.width += r_icon->get_width();
- min_size.height = MAX(min_size.height, r_icon->get_height());
+ int icon_max_width = 0;
+ if (right_icon.is_valid()) {
+ min_size.height = MAX(min_size.height, right_icon->get_height());
+ 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.width += icon_max_width;
return style->get_minimum_size() + min_size;
}
diff --git a/scene/gui/nine_patch_rect.cpp b/scene/gui/nine_patch_rect.cpp
index 4f34ece86f..8fee10b19a 100644
--- a/scene/gui/nine_patch_rect.cpp
+++ b/scene/gui/nine_patch_rect.cpp
@@ -73,13 +73,13 @@ void NinePatchRect::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_center"), "set_draw_center", "is_draw_center_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect");
+ ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect", PROPERTY_HINT_NONE, "suffix:px"), "set_region_rect", "get_region_rect");
ADD_GROUP("Patch Margin", "patch_margin_");
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "patch_margin_left", PROPERTY_HINT_RANGE, "0,16384,1"), "set_patch_margin", "get_patch_margin", SIDE_LEFT);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "patch_margin_top", PROPERTY_HINT_RANGE, "0,16384,1"), "set_patch_margin", "get_patch_margin", SIDE_TOP);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "patch_margin_right", PROPERTY_HINT_RANGE, "0,16384,1"), "set_patch_margin", "get_patch_margin", SIDE_RIGHT);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "patch_margin_bottom", PROPERTY_HINT_RANGE, "0,16384,1"), "set_patch_margin", "get_patch_margin", SIDE_BOTTOM);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "patch_margin_left", PROPERTY_HINT_RANGE, "0,16384,1,suffix:px"), "set_patch_margin", "get_patch_margin", SIDE_LEFT);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "patch_margin_top", PROPERTY_HINT_RANGE, "0,16384,1,suffix:px"), "set_patch_margin", "get_patch_margin", SIDE_TOP);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "patch_margin_right", PROPERTY_HINT_RANGE, "0,16384,1,suffix:px"), "set_patch_margin", "get_patch_margin", SIDE_RIGHT);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "patch_margin_bottom", PROPERTY_HINT_RANGE, "0,16384,1,suffix:px"), "set_patch_margin", "get_patch_margin", SIDE_BOTTOM);
ADD_GROUP("Axis Stretch", "axis_stretch_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "axis_stretch_horizontal", PROPERTY_HINT_ENUM, "Stretch,Tile,Tile Fit"), "set_h_axis_stretch_mode", "get_h_axis_stretch_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "axis_stretch_vertical", PROPERTY_HINT_ENUM, "Stretch,Tile,Tile Fit"), "set_v_axis_stretch_mode", "get_v_axis_stretch_mode");
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp
index 6532fc5934..c4396f636a 100644
--- a/scene/gui/popup.cpp
+++ b/scene/gui/popup.cpp
@@ -108,9 +108,7 @@ void Popup::_close_pressed() {
_deinitialize_visible_parents();
- // Hide after returning to process events, but only if we don't
- // get popped up in the interim.
- call_deferred(SNAME("_popup_conditional_hide"));
+ call_deferred(SNAME("hide"));
}
void Popup::_post_popup() {
@@ -118,15 +116,8 @@ void Popup::_post_popup() {
popped_up = true;
}
-void Popup::_popup_conditional_hide() {
- if (!popped_up) {
- hide();
- }
-}
-
void Popup::_bind_methods() {
ADD_SIGNAL(MethodInfo("popup_hide"));
- ClassDB::bind_method(D_METHOD("_popup_conditional_hide"), &Popup::_popup_conditional_hide);
}
Rect2i Popup::_popup_adjust_rect() const {
diff --git a/scene/gui/popup.h b/scene/gui/popup.h
index 27f46d4a97..b53c8be50f 100644
--- a/scene/gui/popup.h
+++ b/scene/gui/popup.h
@@ -48,8 +48,6 @@ class Popup : public Window {
void _initialize_visible_parents();
void _deinitialize_visible_parents();
- void _parent_focused();
-
protected:
void _close_pressed();
virtual Rect2i _popup_adjust_rect() const override;
@@ -57,7 +55,7 @@ protected:
void _notification(int p_what);
static void _bind_methods();
- void _popup_conditional_hide();
+ virtual void _parent_focused();
virtual void _post_popup() override;
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 8303d6db57..5931c112eb 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -243,6 +243,29 @@ void PopupMenu::_activate_submenu(int p_over, bool p_by_keyboard) {
}
}
+void PopupMenu::_parent_focused() {
+ if (is_embedded()) {
+ Point2 mouse_pos_adjusted;
+ Window *window_parent = Object::cast_to<Window>(get_parent()->get_viewport());
+ while (window_parent) {
+ if (!window_parent->is_embedded()) {
+ mouse_pos_adjusted += window_parent->get_position();
+ break;
+ }
+
+ window_parent = Object::cast_to<Window>(window_parent->get_parent()->get_viewport());
+ }
+
+ Rect2 safe_area = DisplayServer::get_singleton()->window_get_popup_safe_rect(get_window_id());
+ Point2 pos = DisplayServer::get_singleton()->mouse_get_position() - mouse_pos_adjusted;
+ if (safe_area == Rect2i() || !safe_area.has_point(pos)) {
+ Popup::_parent_focused();
+ } else {
+ grab_focus();
+ }
+ }
+}
+
void PopupMenu::_submenu_timeout() {
if (mouse_over == submenu_over) {
_activate_submenu(mouse_over);
@@ -1251,6 +1274,11 @@ Ref<Shortcut> PopupMenu::get_item_shortcut(int p_idx) const {
return items[p_idx].shortcut;
}
+int PopupMenu::get_item_horizontal_offset(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, items.size(), 0);
+ return items[p_idx].h_ofs;
+}
+
int PopupMenu::get_item_state(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, items.size(), -1);
return items[p_idx].state;
@@ -1316,7 +1344,7 @@ void PopupMenu::set_item_shortcut(int p_idx, const Ref<Shortcut> &p_shortcut, bo
control->update();
}
-void PopupMenu::set_item_h_offset(int p_idx, int p_offset) {
+void PopupMenu::set_item_horizontal_offset(int p_idx, int p_offset) {
if (p_idx < 0) {
p_idx += get_item_count();
}
@@ -1839,6 +1867,7 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_item_as_radio_checkable", "index", "enable"), &PopupMenu::set_item_as_radio_checkable);
ClassDB::bind_method(D_METHOD("set_item_tooltip", "index", "tooltip"), &PopupMenu::set_item_tooltip);
ClassDB::bind_method(D_METHOD("set_item_shortcut", "index", "shortcut", "global"), &PopupMenu::set_item_shortcut, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("set_item_horizontal_offset", "index", "offset"), &PopupMenu::set_item_horizontal_offset);
ClassDB::bind_method(D_METHOD("set_item_multistate", "index", "state"), &PopupMenu::set_item_multistate);
ClassDB::bind_method(D_METHOD("set_item_shortcut_disabled", "index", "disabled"), &PopupMenu::set_item_shortcut_disabled);
@@ -1864,6 +1893,7 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_item_shortcut_disabled", "index"), &PopupMenu::is_item_shortcut_disabled);
ClassDB::bind_method(D_METHOD("get_item_tooltip", "index"), &PopupMenu::get_item_tooltip);
ClassDB::bind_method(D_METHOD("get_item_shortcut", "index"), &PopupMenu::get_item_shortcut);
+ ClassDB::bind_method(D_METHOD("get_item_horizontal_offset", "index"), &PopupMenu::get_item_horizontal_offset);
ClassDB::bind_method(D_METHOD("set_current_index", "index"), &PopupMenu::set_current_index);
ClassDB::bind_method(D_METHOD("get_current_index"), &PopupMenu::get_current_index);
@@ -1895,7 +1925,7 @@ void PopupMenu::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_item_selection"), "set_hide_on_item_selection", "is_hide_on_item_selection");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_checkable_item_selection"), "set_hide_on_checkable_item_selection", "is_hide_on_checkable_item_selection");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_state_item_selection"), "set_hide_on_state_item_selection", "is_hide_on_state_item_selection");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "submenu_popup_delay"), "set_submenu_popup_delay", "get_submenu_popup_delay");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "submenu_popup_delay", PROPERTY_HINT_NONE, "suffix:s"), "set_submenu_popup_delay", "get_submenu_popup_delay");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_search"), "set_allow_search", "get_allow_search");
ADD_ARRAY_COUNT("Items", "item_count", "set_item_count", "get_item_count", "item_");
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index 12587b7e73..8218c6122e 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -148,6 +148,8 @@ public:
// this value should be updated to reflect the new size.
static const int ITEM_PROPERTY_SIZE = 10;
+ virtual void _parent_focused() override;
+
void add_item(const String &p_label, int p_id = -1, Key p_accel = Key::NONE);
void add_icon_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id = -1, Key p_accel = Key::NONE);
void add_check_item(const String &p_label, int p_id = -1, Key p_accel = Key::NONE);
@@ -184,7 +186,7 @@ public:
void set_item_as_radio_checkable(int p_idx, bool p_radio_checkable);
void set_item_tooltip(int p_idx, const String &p_tooltip);
void set_item_shortcut(int p_idx, const Ref<Shortcut> &p_shortcut, bool p_global = false);
- void set_item_h_offset(int p_idx, int p_offset);
+ void set_item_horizontal_offset(int p_idx, int p_offset);
void set_item_multistate(int p_idx, int p_state);
void toggle_item_multistate(int p_idx);
void set_item_shortcut_disabled(int p_idx, bool p_disabled);
@@ -210,6 +212,7 @@ public:
bool is_item_shortcut_disabled(int p_idx) const;
String get_item_tooltip(int p_idx) const;
Ref<Shortcut> get_item_shortcut(int p_idx) const;
+ int get_item_horizontal_offset(int p_idx) const;
int get_item_state(int p_idx) const;
void set_current_index(int p_idx);
diff --git a/scene/gui/reference_rect.cpp b/scene/gui/reference_rect.cpp
index ed79da5c22..5190a5a7d2 100644
--- a/scene/gui/reference_rect.cpp
+++ b/scene/gui/reference_rect.cpp
@@ -83,6 +83,6 @@ void ReferenceRect::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_editor_only", "enabled"), &ReferenceRect::set_editor_only);
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "border_color"), "set_border_color", "get_border_color");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "border_width", PROPERTY_HINT_RANGE, "0.0,5.0,0.1,or_greater"), "set_border_width", "get_border_width");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "border_width", PROPERTY_HINT_RANGE, "0.0,5.0,0.1,or_greater,suffix:px"), "set_border_width", "get_border_width");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_only"), "set_editor_only", "get_editor_only");
}
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 94c2a9e64b..0516c8e722 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -414,7 +414,7 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font
}
l.offset.y = p_h;
- return l.offset.y + l.text_buf->get_size().y + l.text_buf->get_line_count() * get_theme_constant(SNAME("line_separation"));
+ return _calculate_line_vertical_offset(l);
}
float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size, int p_width, float p_h, int *r_char_offset) {
@@ -426,16 +426,16 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
uint16_t autowrap_flags = TextServer::BREAK_MANDATORY;
switch (autowrap_mode) {
- case AUTOWRAP_WORD_SMART:
+ case TextServer::AUTOWRAP_WORD_SMART:
autowrap_flags = TextServer::BREAK_WORD_BOUND_ADAPTIVE | TextServer::BREAK_MANDATORY;
break;
- case AUTOWRAP_WORD:
+ case TextServer::AUTOWRAP_WORD:
autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY;
break;
- case AUTOWRAP_ARBITRARY:
+ case TextServer::AUTOWRAP_ARBITRARY:
autowrap_flags = TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_MANDATORY;
break;
- case AUTOWRAP_OFF:
+ case TextServer::AUTOWRAP_OFF:
break;
}
@@ -462,7 +462,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
Item *it_to = (p_line + 1 < (int)p_frame->lines.size()) ? p_frame->lines[p_line + 1].from : nullptr;
int remaining_characters = visible_characters - l.char_offset;
for (Item *it = l.from; it && it != it_to; it = _get_next_item(it)) {
- if (visible_chars_behavior == VC_CHARS_BEFORE_SHAPING && visible_characters >= 0 && remaining_characters <= 0) {
+ if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING && visible_characters >= 0 && remaining_characters <= 0) {
break;
}
switch (it->type) {
@@ -501,7 +501,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
Dictionary font_ftr = _find_font_features(it);
String lang = _find_language(it);
String tx = t->text;
- if (visible_chars_behavior == VC_CHARS_BEFORE_SHAPING && visible_characters >= 0 && remaining_characters >= 0) {
+ if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING && visible_characters >= 0 && remaining_characters >= 0) {
tx = tx.substr(0, remaining_characters);
}
remaining_characters -= tx.length();
@@ -683,7 +683,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
*r_char_offset = l.char_offset + l.char_count;
l.offset.y = p_h;
- return l.offset.y + l.text_buf->get_size().y + l.text_buf->get_line_count() * get_theme_constant(SNAME("line_separation"));
+ return _calculate_line_vertical_offset(l);
}
int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, const Color &p_base_color, int p_outline_size, const Color &p_outline_color, const Color &p_font_shadow_color, int p_shadow_outline_size, const Point2 &p_shadow_ofs, int &r_processed_glyphs) {
@@ -707,9 +707,9 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
bool rtl = (l.text_buf->get_direction() == TextServer::DIRECTION_RTL);
bool lrtl = is_layout_rtl();
- bool trim_chars = (visible_characters >= 0) && (visible_chars_behavior == VC_CHARS_AFTER_SHAPING);
- bool trim_glyphs_ltr = (visible_characters >= 0) && ((visible_chars_behavior == VC_GLYPHS_LTR) || ((visible_chars_behavior == VC_GLYPHS_AUTO) && !lrtl));
- bool trim_glyphs_rtl = (visible_characters >= 0) && ((visible_chars_behavior == VC_GLYPHS_RTL) || ((visible_chars_behavior == VC_GLYPHS_AUTO) && lrtl));
+ bool trim_chars = (visible_characters >= 0) && (visible_chars_behavior == TextServer::VC_CHARS_AFTER_SHAPING);
+ bool trim_glyphs_ltr = (visible_characters >= 0) && ((visible_chars_behavior == TextServer::VC_GLYPHS_LTR) || ((visible_chars_behavior == TextServer::VC_GLYPHS_AUTO) && !lrtl));
+ bool trim_glyphs_rtl = (visible_characters >= 0) && ((visible_chars_behavior == TextServer::VC_GLYPHS_RTL) || ((visible_chars_behavior == TextServer::VC_GLYPHS_AUTO) && lrtl));
int total_glyphs = (trim_glyphs_ltr || trim_glyphs_rtl) ? get_total_glyph_count() : 0;
int visible_glyphs = total_glyphs * percent_visible;
@@ -1243,8 +1243,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
// Draw glyphs.
for (int j = 0; j < glyphs[i].repeat; j++) {
+ bool skip = (trim_chars && l.char_offset + glyphs[i].end > visible_characters) || (trim_glyphs_ltr && (r_processed_glyphs >= visible_glyphs)) || (trim_glyphs_rtl && (r_processed_glyphs < total_glyphs - visible_glyphs));
if (visible) {
- bool skip = (trim_chars && l.char_offset + glyphs[i].end > visible_characters) || (trim_glyphs_ltr && (r_processed_glyphs >= visible_glyphs)) || (trim_glyphs_rtl && (r_processed_glyphs < total_glyphs - visible_glyphs));
if (!skip) {
if (frid != RID()) {
TS->font_draw_glyph(frid, ci, glyphs[i].font_size, p_ofs + fx_offset + off, gl, selected ? selection_fg : font_color);
@@ -1254,6 +1254,27 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
}
r_processed_glyphs++;
}
+ if (skip) {
+ // End underline/overline/strikethrough is previous glyph is skipped.
+ if (ul_started) {
+ ul_started = false;
+ float y_off = TS->shaped_text_get_underline_position(rid);
+ float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
+ draw_line(ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), ul_color, underline_width);
+ }
+ if (dot_ul_started) {
+ dot_ul_started = false;
+ float y_off = TS->shaped_text_get_underline_position(rid);
+ float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
+ draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, underline_width * 2);
+ }
+ if (st_started) {
+ st_started = false;
+ float y_off = -TS->shaped_text_get_ascent(rid) + TS->shaped_text_get_size(rid).y / 2;
+ float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
+ draw_line(st_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), st_color, underline_width);
+ }
+ }
off.x += glyphs[i].advance;
}
}
@@ -1566,7 +1587,7 @@ int RichTextLabel::_find_first_line(int p_from, int p_to, int p_vofs) const {
while (l < r) {
int m = Math::floor(double(l + r) / 2.0);
MutexLock lock(main->lines[m].text_buf->get_mutex());
- int ofs = main->lines[m].offset.y + main->lines[m].text_buf->get_size().y + main->lines[m].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation"));
+ int ofs = _calculate_line_vertical_offset(main->lines[m]);
if (ofs < p_vofs) {
l = m + 1;
} else {
@@ -1576,6 +1597,10 @@ int RichTextLabel::_find_first_line(int p_from, int p_to, int p_vofs) const {
return l;
}
+_FORCE_INLINE_ float RichTextLabel::_calculate_line_vertical_offset(const RichTextLabel::Line &line) const {
+ return line.get_height(get_theme_constant(SNAME("line_separation")));
+}
+
void RichTextLabel::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_MOUSE_EXIT: {
@@ -1609,6 +1634,7 @@ void RichTextLabel::_notification(int p_what) {
update();
} break;
+ case NOTIFICATION_PREDELETE:
case NOTIFICATION_EXIT_TREE: {
_stop_thread();
} break;
@@ -2489,7 +2515,7 @@ bool RichTextLabel::_validate_line_caches() {
// Resize lines without reshaping.
int fi = main->first_resized_line.load();
- float total_height = 0;
+ float total_height = (fi == 0) ? 0 : _calculate_line_vertical_offset(main->lines[fi - 1]);
for (int i = fi; i < (int)main->lines.size(); i++) {
total_height = _resize_line(main, i, base_font, base_font_size, text_rect.get_size().width - scroll_w, total_height);
@@ -2551,6 +2577,10 @@ bool RichTextLabel::_validate_line_caches() {
void RichTextLabel::_process_line_caches() {
// Shape invalid lines.
+ if (!is_inside_tree()) {
+ return;
+ }
+
MutexLock data_lock(data_mutex);
Rect2 text_rect = _get_text_rect();
@@ -2560,10 +2590,9 @@ void RichTextLabel::_process_line_caches() {
int fi = main->first_invalid_line.load();
int total_chars = (fi == 0) ? 0 : (main->lines[fi].char_offset + main->lines[fi].char_count);
- float total_height = 0;
+ float total_height = (fi == 0) ? 0 : _calculate_line_vertical_offset(main->lines[fi - 1]);
for (int i = fi; i < (int)main->lines.size(); i++) {
total_height = _shape_line(main, i, base_font, base_font_size, text_rect.get_size().width - scroll_w, total_height, &total_chars);
-
updating_scroll = true;
bool exceeds = total_height > ctrl_height && scroll_active;
if (exceeds != scroll_visible) {
@@ -2577,11 +2606,11 @@ void RichTextLabel::_process_line_caches() {
scroll_w = 0;
vscroll->hide();
}
-
main->first_invalid_line.store(0);
main->first_resized_line.store(0);
main->first_invalid_font_line.store(0);
+ // since scroll was added or removed we need to resize all lines
total_height = 0;
for (int j = 0; j <= i; j++) {
total_height = _resize_line(main, j, base_font, base_font_size, text_rect.get_size().width - scroll_w, total_height);
@@ -3369,21 +3398,34 @@ void RichTextLabel::append_text(const String &p_bbcode) {
bool in_bold = false;
bool in_italics = false;
+ bool after_list_open_tag = false;
+ bool after_list_close_tag = false;
set_process_internal(false);
- while (pos < p_bbcode.length()) {
+ while (pos <= p_bbcode.length()) {
int brk_pos = p_bbcode.find("[", pos);
if (brk_pos < 0) {
brk_pos = p_bbcode.length();
}
- if (brk_pos > pos) {
- add_text(p_bbcode.substr(pos, brk_pos - pos));
+ String text = brk_pos > pos ? p_bbcode.substr(pos, brk_pos - pos) : "";
+
+ // Trim the first newline character, it may be added later as needed.
+ if (after_list_close_tag || after_list_open_tag) {
+ text = text.trim_prefix("\n");
}
if (brk_pos == p_bbcode.length()) {
+ // For tags that are not properly closed.
+ if (text.is_empty() && after_list_open_tag) {
+ text = "\n";
+ }
+
+ if (!text.is_empty()) {
+ add_text(text);
+ }
break; //nothing else to add
}
@@ -3391,7 +3433,8 @@ void RichTextLabel::append_text(const String &p_bbcode) {
if (brk_end == -1) {
//no close, add the rest
- add_text(p_bbcode.substr(brk_pos, p_bbcode.length() - brk_pos));
+ text += p_bbcode.substr(brk_pos, p_bbcode.length() - brk_pos);
+ add_text(text);
break;
}
@@ -3437,18 +3480,60 @@ void RichTextLabel::append_text(const String &p_bbcode) {
}
if (!tag_ok) {
- add_text("[" + tag);
+ text += "[" + tag;
+ add_text(text);
+ after_list_open_tag = false;
+ after_list_close_tag = false;
pos = brk_end;
continue;
}
+ if (text.is_empty() && after_list_open_tag) {
+ text = "\n"; // Make empty list have at least one item.
+ }
+ after_list_open_tag = false;
+
+ if (tag == "/ol" || tag == "/ul") {
+ if (!text.is_empty()) {
+ // Make sure text ends with a newline character, that is, the last item
+ // will wrap at the end of block.
+ if (!text.ends_with("\n")) {
+ text += "\n";
+ }
+ } else if (!after_list_close_tag) {
+ text = "\n"; // Make the innermost list item wrap at the end of lists.
+ }
+ after_list_close_tag = true;
+ } else {
+ after_list_close_tag = false;
+ }
+
+ if (!text.is_empty()) {
+ add_text(text);
+ }
+
tag_stack.pop_front();
pos = brk_end + 1;
if (tag != "/img" && tag != "/dropcap") {
pop();
}
+ continue;
+ }
+
+ if (tag == "ol" || tag.begins_with("ol ") || tag == "ul" || tag.begins_with("ul ")) {
+ if (text.is_empty() && after_list_open_tag) {
+ text = "\n"; // Make each list have at least one item at the beginning.
+ }
+ after_list_open_tag = true;
+ } else {
+ after_list_open_tag = false;
+ }
+ if (!text.is_empty()) {
+ add_text(text);
+ }
+ after_list_close_tag = false;
- } else if (tag == "b") {
+ if (tag == "b") {
//use bold font
in_bold = true;
if (in_italics) {
@@ -4667,7 +4752,7 @@ String RichTextLabel::get_language() const {
return language;
}
-void RichTextLabel::set_autowrap_mode(RichTextLabel::AutowrapMode p_mode) {
+void RichTextLabel::set_autowrap_mode(TextServer::AutowrapMode p_mode) {
if (autowrap_mode != p_mode) {
_stop_thread();
@@ -4678,7 +4763,7 @@ void RichTextLabel::set_autowrap_mode(RichTextLabel::AutowrapMode p_mode) {
}
}
-RichTextLabel::AutowrapMode RichTextLabel::get_autowrap_mode() const {
+TextServer::AutowrapMode RichTextLabel::get_autowrap_mode() const {
return autowrap_mode;
}
@@ -4693,7 +4778,7 @@ void RichTextLabel::set_percent_visible(float p_percent) {
visible_characters = get_total_character_count() * p_percent;
percent_visible = p_percent;
}
- if (visible_chars_behavior == VC_CHARS_BEFORE_SHAPING) {
+ if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) {
main->first_invalid_line.store(0); //invalidate ALL
_validate_line_caches();
}
@@ -4910,7 +4995,7 @@ void RichTextLabel::_bind_methods() {
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"), "set_progress_bar_delay", "get_progress_bar_delay");
+ 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");
@@ -4947,11 +5032,6 @@ void RichTextLabel::_bind_methods() {
ADD_SIGNAL(MethodInfo("finished"));
- BIND_ENUM_CONSTANT(AUTOWRAP_OFF);
- BIND_ENUM_CONSTANT(AUTOWRAP_ARBITRARY);
- BIND_ENUM_CONSTANT(AUTOWRAP_WORD);
- BIND_ENUM_CONSTANT(AUTOWRAP_WORD_SMART);
-
BIND_ENUM_CONSTANT(LIST_NUMBERS);
BIND_ENUM_CONSTANT(LIST_LETTERS);
BIND_ENUM_CONSTANT(LIST_ROMAN);
@@ -4984,19 +5064,13 @@ void RichTextLabel::_bind_methods() {
BIND_ENUM_CONSTANT(ITEM_HINT);
BIND_ENUM_CONSTANT(ITEM_DROPCAP);
BIND_ENUM_CONSTANT(ITEM_CUSTOMFX);
-
- BIND_ENUM_CONSTANT(VC_CHARS_BEFORE_SHAPING);
- BIND_ENUM_CONSTANT(VC_CHARS_AFTER_SHAPING);
- BIND_ENUM_CONSTANT(VC_GLYPHS_AUTO);
- BIND_ENUM_CONSTANT(VC_GLYPHS_LTR);
- BIND_ENUM_CONSTANT(VC_GLYPHS_RTL);
}
-RichTextLabel::VisibleCharactersBehavior RichTextLabel::get_visible_characters_behavior() const {
+TextServer::VisibleCharactersBehavior RichTextLabel::get_visible_characters_behavior() const {
return visible_chars_behavior;
}
-void RichTextLabel::set_visible_characters_behavior(RichTextLabel::VisibleCharactersBehavior p_behavior) {
+void RichTextLabel::set_visible_characters_behavior(TextServer::VisibleCharactersBehavior p_behavior) {
if (visible_chars_behavior != p_behavior) {
_stop_thread();
@@ -5020,7 +5094,7 @@ void RichTextLabel::set_visible_characters(int p_visible) {
percent_visible = (float)p_visible / (float)total_char_count;
}
}
- if (visible_chars_behavior == VC_CHARS_BEFORE_SHAPING) {
+ if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) {
main->first_invalid_line.store(0); //invalidate ALL
_validate_line_caches();
}
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 7fbd5f1745..c697320976 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -40,13 +40,6 @@ class RichTextLabel : public Control {
GDCLASS(RichTextLabel, Control);
public:
- enum AutowrapMode {
- AUTOWRAP_OFF,
- AUTOWRAP_ARBITRARY,
- AUTOWRAP_WORD,
- AUTOWRAP_WORD_SMART
- };
-
enum ListType {
LIST_NUMBERS,
LIST_LETTERS,
@@ -84,14 +77,6 @@ public:
ITEM_CUSTOMFX
};
- enum VisibleCharactersBehavior {
- VC_CHARS_BEFORE_SHAPING,
- VC_CHARS_AFTER_SHAPING,
- VC_GLYPHS_AUTO,
- VC_GLYPHS_LTR,
- VC_GLYPHS_RTL,
- };
-
enum MenuItems {
MENU_COPY,
MENU_SELECT_ALL,
@@ -117,6 +102,10 @@ private:
int char_count = 0;
Line() { text_buf.instantiate(); }
+
+ _FORCE_INLINE_ float get_height(float line_separation) const {
+ return offset.y + text_buf->get_size().y + text_buf->get_line_count() * line_separation;
+ }
};
struct Item {
@@ -380,7 +369,7 @@ private:
VScrollBar *vscroll = nullptr;
- AutowrapMode autowrap_mode = AUTOWRAP_WORD_SMART;
+ TextServer::AutowrapMode autowrap_mode = TextServer::AUTOWRAP_WORD_SMART;
bool scroll_visible = false;
bool scroll_follow = false;
@@ -456,7 +445,7 @@ private:
int visible_characters = -1;
float percent_visible = 1.0;
- VisibleCharactersBehavior visible_chars_behavior = VC_CHARS_BEFORE_SHAPING;
+ TextServer::VisibleCharactersBehavior visible_chars_behavior = TextServer::VC_CHARS_BEFORE_SHAPING;
bool _is_click_inside_selection() const;
void _find_click(ItemFrame *p_frame, const Point2i &p_click, ItemFrame **r_click_frame = nullptr, int *r_click_line = nullptr, Item **r_click_item = nullptr, int *r_click_char = nullptr, bool *r_outside = nullptr);
@@ -504,6 +493,8 @@ private:
void _scroll_changed(double);
int _find_first_line(int p_from, int p_to, int p_vofs) const;
+ _FORCE_INLINE_ float _calculate_line_vertical_offset(const Line &line) const;
+
virtual void gui_input(const Ref<InputEvent> &p_event) override;
virtual String get_tooltip(const Point2 &p_pos) const override;
Item *_get_next_item(Item *p_item, bool p_free = false) const;
@@ -658,8 +649,8 @@ public:
void set_language(const String &p_language);
String get_language() const;
- void set_autowrap_mode(AutowrapMode p_mode);
- AutowrapMode get_autowrap_mode() const;
+ void set_autowrap_mode(TextServer::AutowrapMode p_mode);
+ TextServer::AutowrapMode get_autowrap_mode() const;
void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser);
TextServer::StructuredTextParser get_structured_text_bidi_override() const;
@@ -677,8 +668,8 @@ public:
void set_percent_visible(float p_percent);
float get_percent_visible() const;
- VisibleCharactersBehavior get_visible_characters_behavior() const;
- void set_visible_characters_behavior(VisibleCharactersBehavior p_behavior);
+ TextServer::VisibleCharactersBehavior get_visible_characters_behavior() const;
+ void set_visible_characters_behavior(TextServer::VisibleCharactersBehavior p_behavior);
void set_effects(Array p_effects);
Array get_effects();
@@ -692,9 +683,7 @@ public:
~RichTextLabel();
};
-VARIANT_ENUM_CAST(RichTextLabel::AutowrapMode);
VARIANT_ENUM_CAST(RichTextLabel::ListType);
VARIANT_ENUM_CAST(RichTextLabel::ItemType);
-VARIANT_ENUM_CAST(RichTextLabel::VisibleCharactersBehavior);
#endif // RICH_TEXT_LABEL_H
diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp
index e1b0e8cca8..f387f91a8b 100644
--- a/scene/gui/scroll_bar.cpp
+++ b/scene/gui/scroll_bar.cpp
@@ -622,7 +622,7 @@ void ScrollBar::_bind_methods() {
ADD_SIGNAL(MethodInfo("scrolling"));
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "custom_step", PROPERTY_HINT_RANGE, "-1,4096"), "set_custom_step", "get_custom_step");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "custom_step", PROPERTY_HINT_RANGE, "-1,4096,suffix:px"), "set_custom_step", "get_custom_step");
}
ScrollBar::ScrollBar(Orientation p_orientation) {
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index 135bad4689..871cc520e9 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -578,8 +578,8 @@ void ScrollContainer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_focus"), "set_follow_focus", "is_following_focus");
ADD_GROUP("Scroll", "scroll_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_horizontal"), "set_h_scroll", "get_h_scroll");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_vertical"), "set_v_scroll", "get_v_scroll");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_horizontal", PROPERTY_HINT_NONE, "suffix:px"), "set_h_scroll", "get_h_scroll");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_vertical", PROPERTY_HINT_NONE, "suffix:px"), "set_v_scroll", "get_v_scroll");
ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_scroll_mode", PROPERTY_HINT_ENUM, "Disabled,Auto,Always Show,Never Show"), "set_horizontal_scroll_mode", "get_horizontal_scroll_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_scroll_mode", PROPERTY_HINT_ENUM, "Disabled,Auto,Always Show,Never Show"), "set_vertical_scroll_mode", "get_vertical_scroll_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_deadzone"), "set_deadzone", "get_deadzone");
diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp
index 6845d46721..d7aa516ee6 100644
--- a/scene/gui/split_container.cpp
+++ b/scene/gui/split_container.cpp
@@ -377,7 +377,7 @@ void SplitContainer::_bind_methods() {
ADD_SIGNAL(MethodInfo("dragged", PropertyInfo(Variant::INT, "offset")));
- ADD_PROPERTY(PropertyInfo(Variant::INT, "split_offset"), "set_split_offset", "get_split_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "split_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_split_offset", "get_split_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collapsed"), "set_collapsed", "is_collapsed");
ADD_PROPERTY(PropertyInfo(Variant::INT, "dragger_visibility", PROPERTY_HINT_ENUM, "Visible,Hidden,Hidden and Collapsed"), "set_dragger_visibility", "get_dragger_visibility");
diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp
index fec8d11bef..b4c90596f9 100644
--- a/scene/gui/tab_bar.cpp
+++ b/scene/gui/tab_bar.cpp
@@ -1606,7 +1606,7 @@ void TabBar::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_tab_alignment", "get_tab_alignment");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_tabs"), "set_clip_tabs", "get_clip_tabs");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_close_display_policy", PROPERTY_HINT_ENUM, "Show Never,Show Active Only,Show Always"), "set_tab_close_display_policy", "get_tab_close_display_policy");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "max_tab_width", PROPERTY_HINT_RANGE, "0,99999,1"), "set_max_tab_width", "get_max_tab_width");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_tab_width", PROPERTY_HINT_RANGE, "0,99999,1,suffix:px"), "set_max_tab_width", "get_max_tab_width");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scrolling_enabled"), "set_scrolling_enabled", "get_scrolling_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_to_rearrange_enabled"), "set_drag_to_rearrange_enabled", "get_drag_to_rearrange_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tabs_rearrange_group"), "set_tabs_rearrange_group", "get_tabs_rearrange_group");
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 0f74c9c357..d9a91590f7 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -3080,7 +3080,7 @@ void TextEdit::set_line(int p_line, const String &p_new_text) {
_remove_text(p_line, 0, p_line, text[p_line].length());
_insert_text(p_line, 0, p_new_text);
if (caret.line == p_line && caret.column > p_new_text.length()) {
- set_caret_column(MIN(caret.column, p_new_text.length()), false);
+ set_caret_column(p_new_text.length(), false);
}
if (has_selection() && p_line == selection.to_line && selection.to_column > text[p_line].length()) {
selection.to_column = text[p_line].length();
@@ -5420,19 +5420,19 @@ void TextEdit::_bind_methods() {
ADD_GROUP("Scroll", "scroll_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_smooth"), "set_smooth_scroll_enable", "is_smooth_scroll_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_v_scroll_speed"), "set_v_scroll_speed", "get_v_scroll_speed");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_v_scroll_speed", PROPERTY_HINT_NONE, "suffix:px/s"), "set_v_scroll_speed", "get_v_scroll_speed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_past_end_of_file"), "set_scroll_past_end_of_file_enabled", "is_scroll_past_end_of_file_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_vertical"), "set_v_scroll", "get_v_scroll");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_horizontal"), "set_h_scroll", "get_h_scroll");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_vertical", PROPERTY_HINT_NONE, "suffix:px"), "set_v_scroll", "get_v_scroll");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_horizontal", PROPERTY_HINT_NONE, "suffix:px"), "set_h_scroll", "get_h_scroll");
ADD_GROUP("Minimap", "minimap_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "minimap_draw"), "set_draw_minimap", "is_drawing_minimap");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "minimap_width"), "set_minimap_width", "get_minimap_width");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "minimap_width", PROPERTY_HINT_NONE, "suffix:px"), "set_minimap_width", "get_minimap_width");
ADD_GROUP("Caret", "caret_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "caret_type", PROPERTY_HINT_ENUM, "Line,Block"), "set_caret_type", "get_caret_type");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), "set_caret_blink_enabled", "is_caret_blink_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.01"), "set_caret_blink_speed", "get_caret_blink_speed");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.01,suffix:s"), "set_caret_blink_speed", "get_caret_blink_speed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_move_on_right_click"), "set_move_caret_on_right_click_enabled", "is_move_caret_on_right_click_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_mid_grapheme"), "set_caret_mid_grapheme_enabled", "is_caret_mid_grapheme_enabled");
diff --git a/scene/gui/texture_progress_bar.cpp b/scene/gui/texture_progress_bar.cpp
index 081d065efe..94e0a6f226 100644
--- a/scene/gui/texture_progress_bar.cpp
+++ b/scene/gui/texture_progress_bar.cpp
@@ -633,16 +633,16 @@ void TextureProgressBar::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "nine_patch_stretch"), "set_nine_patch_stretch", "get_nine_patch_stretch");
ADD_GROUP("Stretch Margin", "stretch_margin_");
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "stretch_margin_left", PROPERTY_HINT_RANGE, "0,16384,1"), "set_stretch_margin", "get_stretch_margin", SIDE_LEFT);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "stretch_margin_top", PROPERTY_HINT_RANGE, "0,16384,1"), "set_stretch_margin", "get_stretch_margin", SIDE_TOP);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "stretch_margin_right", PROPERTY_HINT_RANGE, "0,16384,1"), "set_stretch_margin", "get_stretch_margin", SIDE_RIGHT);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "stretch_margin_bottom", PROPERTY_HINT_RANGE, "0,16384,1"), "set_stretch_margin", "get_stretch_margin", SIDE_BOTTOM);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "stretch_margin_left", PROPERTY_HINT_RANGE, "0,16384,1,suffix:px"), "set_stretch_margin", "get_stretch_margin", SIDE_LEFT);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "stretch_margin_top", PROPERTY_HINT_RANGE, "0,16384,1,suffix:px"), "set_stretch_margin", "get_stretch_margin", SIDE_TOP);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "stretch_margin_right", PROPERTY_HINT_RANGE, "0,16384,1,suffix:px"), "set_stretch_margin", "get_stretch_margin", SIDE_RIGHT);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "stretch_margin_bottom", PROPERTY_HINT_RANGE, "0,16384,1,suffix:px"), "set_stretch_margin", "get_stretch_margin", SIDE_BOTTOM);
ADD_GROUP("Textures", "texture_");
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::VECTOR2, "texture_progress_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_texture_progress_offset", "get_texture_progress_offset");
ADD_GROUP("Tint", "tint_");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "tint_under"), "set_tint_under", "get_tint_under");
@@ -652,7 +652,7 @@ void TextureProgressBar::_bind_methods() {
ADD_GROUP("Radial Fill", "radial_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radial_initial_angle", PROPERTY_HINT_RANGE, "0.0,360.0,0.1,slider,degrees"), "set_radial_initial_angle", "get_radial_initial_angle");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radial_fill_degrees", PROPERTY_HINT_RANGE, "0.0,360.0,0.1,slider,degrees"), "set_fill_degrees", "get_fill_degrees");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "radial_center_offset"), "set_radial_center_offset", "get_radial_center_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "radial_center_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_radial_center_offset", "get_radial_center_offset");
BIND_ENUM_CONSTANT(FILL_LEFT_TO_RIGHT);
BIND_ENUM_CONSTANT(FILL_RIGHT_TO_LEFT);
diff --git a/scene/gui/video_stream_player.cpp b/scene/gui/video_stream_player.cpp
index 20bc9a1028..122e36904b 100644
--- a/scene/gui/video_stream_player.cpp
+++ b/scene/gui/video_stream_player.cpp
@@ -448,7 +448,7 @@ void VideoStreamPlayer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "has_autoplay");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused"), "set_paused", "is_paused");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand"), "set_expand", "has_expand");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "buffering_msec", PROPERTY_HINT_RANGE, "10,1000"), "set_buffering_msec", "get_buffering_msec");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "buffering_msec", PROPERTY_HINT_RANGE, "10,1000,suffix:ms"), "set_buffering_msec", "get_buffering_msec");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "stream_position", PROPERTY_HINT_RANGE, "0,1280000,0.1", PROPERTY_USAGE_NONE), "set_stream_position", "get_stream_position");
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus");