summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/classes/RichTextLabel.xml1
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp2
-rw-r--r--modules/gdscript/gdscript_parser.cpp2
-rw-r--r--scene/gui/color_picker.cpp95
-rw-r--r--scene/gui/color_picker.h10
-rw-r--r--scene/gui/rich_text_label.cpp38
-rw-r--r--scene/gui/rich_text_label.h4
7 files changed, 116 insertions, 36 deletions
diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml
index c44f54749b..4a243a70ce 100644
--- a/doc/classes/RichTextLabel.xml
+++ b/doc/classes/RichTextLabel.xml
@@ -410,6 +410,7 @@
<param index="2" name="language" type="String" default="&quot;&quot;" />
<param index="3" name="st_parser" type="int" enum="TextServer.StructuredTextParser" default="0" />
<param index="4" name="justification_flags" type="int" enum="TextServer.JustificationFlag" default="163" />
+ <param index="5" name="tab_stops" type="PackedFloat32Array" default="PackedFloat32Array()" />
<description>
Adds a [code][p][/code] tag to the tag stack.
</description>
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index 9ff9b521d6..563398e512 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -1866,6 +1866,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
frame_list = memnew(ItemList);
frame_list->set_v_size_flags(SIZE_EXPAND_FILL);
frame_list->set_icon_mode(ItemList::ICON_MODE_TOP);
+ frame_list->set_texture_filter(TEXTURE_FILTER_NEAREST_WITH_MIPMAPS);
frame_list->set_max_columns(0);
frame_list->set_icon_mode(ItemList::ICON_MODE_TOP);
@@ -1990,6 +1991,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
split_sheet_preview = memnew(TextureRect);
split_sheet_preview->set_expand_mode(TextureRect::EXPAND_IGNORE_SIZE);
+ split_sheet_preview->set_texture_filter(TEXTURE_FILTER_NEAREST_WITH_MIPMAPS);
split_sheet_preview->set_mouse_filter(MOUSE_FILTER_PASS);
split_sheet_preview->connect("draw", callable_mp(this, &SpriteFramesEditor::_sheet_preview_draw));
split_sheet_preview->connect("gui_input", callable_mp(this, &SpriteFramesEditor::_sheet_preview_input));
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 3bce258072..fdbd505975 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -4192,7 +4192,7 @@ String GDScriptParser::DataType::to_string() const {
return class_type->fqcn;
case SCRIPT: {
if (is_meta_type) {
- return script_type->get_class_name().operator String();
+ return script_type != nullptr ? script_type->get_class_name().operator String() : "";
}
String name = script_type != nullptr ? script_type->get_name() : "";
if (!name.is_empty()) {
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 5e861ba45d..f79557aded 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -109,6 +109,13 @@ void ColorPicker::_notification(int p_what) {
picker_window->hide();
}
} break;
+
+ case NOTIFICATION_INTERNAL_PROCESS: {
+ if (!is_picking_color) {
+ return;
+ }
+ set_pick_color(DisplayServer::get_singleton()->screen_get_pixel(DisplayServer::get_singleton()->mouse_get_position()));
+ }
}
}
@@ -1421,30 +1428,6 @@ void ColorPicker::_recent_preset_pressed(const bool p_pressed, ColorPresetButton
emit_signal(SNAME("color_changed"), p_preset->get_preset_color());
}
-void ColorPicker::_picker_texture_input(const Ref<InputEvent> &p_event) {
- if (!is_inside_tree()) {
- return;
- }
-
- Ref<InputEventMouseButton> bev = p_event;
- if (bev.is_valid() && bev->get_button_index() == MouseButton::LEFT && !bev->is_pressed()) {
- set_pick_color(picker_color);
- emit_signal(SNAME("color_changed"), color);
- picker_window->hide();
- }
-
- Ref<InputEventMouseMotion> mev = p_event;
- if (mev.is_valid()) {
- Ref<Image> img = picker_texture_rect->get_texture()->get_image();
- if (img.is_valid() && !img->is_empty()) {
- Vector2 ofs = mev->get_position();
- picker_color = img->get_pixel(ofs.x, ofs.y);
- picker_preview_style_box->set_bg_color(picker_color);
- picker_preview_label->set_self_modulate(picker_color.get_luminance() < 0.5 ? Color(1.0f, 1.0f, 1.0f) : Color(0.0f, 0.0f, 0.0f));
- }
- }
-}
-
void ColorPicker::_text_changed(const String &) {
text_changed = true;
}
@@ -1455,6 +1438,34 @@ void ColorPicker::_add_preset_pressed() {
}
void ColorPicker::_pick_button_pressed() {
+ is_picking_color = true;
+ set_process_internal(true);
+
+ if (!picker_window) {
+ picker_window = memnew(Popup);
+ picker_window->set_size(Vector2i(1, 1));
+ picker_window->connect("visibility_changed", callable_mp(this, &ColorPicker::_pick_finished));
+ add_child(picker_window);
+ }
+ picker_window->popup();
+}
+
+void ColorPicker::_pick_finished() {
+ if (picker_window->is_visible()) {
+ return;
+ }
+
+ if (Input::get_singleton()->is_key_pressed(Key::ESCAPE)) {
+ set_pick_color(old_color);
+ } else {
+ emit_signal(SNAME("color_changed"), color);
+ }
+ is_picking_color = false;
+ set_process_internal(false);
+ picker_window->hide();
+}
+
+void ColorPicker::_pick_button_pressed_legacy() {
if (!is_inside_tree()) {
return;
}
@@ -1469,7 +1480,7 @@ void ColorPicker::_pick_button_pressed() {
picker_texture_rect->set_anchors_preset(Control::PRESET_FULL_RECT);
picker_window->add_child(picker_texture_rect);
picker_texture_rect->set_default_cursor_shape(CURSOR_POINTING_HAND);
- picker_texture_rect->connect(SNAME("gui_input"), callable_mp(this, &ColorPicker::_picker_texture_input));
+ picker_texture_rect->connect("gui_input", callable_mp(this, &ColorPicker::_picker_texture_input));
picker_preview = memnew(Panel);
picker_preview->set_anchors_preset(Control::PRESET_CENTER_TOP);
@@ -1529,6 +1540,30 @@ void ColorPicker::_pick_button_pressed() {
picker_window->popup();
}
+void ColorPicker::_picker_texture_input(const Ref<InputEvent> &p_event) {
+ if (!is_inside_tree()) {
+ return;
+ }
+
+ Ref<InputEventMouseButton> bev = p_event;
+ if (bev.is_valid() && bev->get_button_index() == MouseButton::LEFT && !bev->is_pressed()) {
+ set_pick_color(picker_color);
+ emit_signal(SNAME("color_changed"), color);
+ picker_window->hide();
+ }
+
+ Ref<InputEventMouseMotion> mev = p_event;
+ if (mev.is_valid()) {
+ Ref<Image> img = picker_texture_rect->get_texture()->get_image();
+ if (img.is_valid() && !img->is_empty()) {
+ Vector2 ofs = mev->get_position();
+ picker_color = img->get_pixel(ofs.x, ofs.y);
+ picker_preview_style_box->set_bg_color(picker_color);
+ picker_preview_label->set_self_modulate(picker_color.get_luminance() < 0.5 ? Color(1.0f, 1.0f, 1.0f) : Color(0.0f, 0.0f, 0.0f));
+ }
+ }
+}
+
void ColorPicker::_html_focus_exit() {
if (c_text->is_menu_visible()) {
return;
@@ -1692,8 +1727,14 @@ ColorPicker::ColorPicker() {
btn_pick = memnew(Button);
sample_hbc->add_child(btn_pick);
- btn_pick->set_tooltip_text(RTR("Pick a color from the application window."));
- btn_pick->connect(SNAME("pressed"), callable_mp(this, &ColorPicker::_pick_button_pressed));
+ if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_SCREEN_CAPTURE)) {
+ btn_pick->set_tooltip_text(RTR("Pick a color from the screen."));
+ btn_pick->connect(SNAME("pressed"), callable_mp(this, &ColorPicker::_pick_button_pressed));
+ } else {
+ // On unsupported platforms, use a legacy method for color picking.
+ btn_pick->set_tooltip_text(RTR("Pick a color from the application window."));
+ btn_pick->connect(SNAME("pressed"), callable_mp(this, &ColorPicker::_pick_button_pressed_legacy));
+ }
sample = memnew(TextureRect);
sample_hbc->add_child(sample);
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index 018ae10955..711a371688 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -122,11 +122,13 @@ private:
Vector<ColorMode *> modes;
Popup *picker_window = nullptr;
+ // Legacy color picking.
TextureRect *picker_texture_rect = nullptr;
Panel *picker_preview = nullptr;
Label *picker_preview_label = nullptr;
Ref<StyleBoxFlat> picker_preview_style_box;
Color picker_color;
+
Control *uv_edit = nullptr;
Control *w_edit = nullptr;
AspectRatioContainer *wheel_edit = nullptr;
@@ -183,6 +185,7 @@ private:
Color color;
Color old_color;
+ bool is_picking_color = false;
bool display_old_color = false;
bool deferred_mode_enabled = false;
@@ -259,11 +262,14 @@ private:
void _line_edit_input(const Ref<InputEvent> &p_event);
void _preset_input(const Ref<InputEvent> &p_event, const Color &p_color);
void _recent_preset_pressed(const bool pressed, ColorPresetButton *p_preset);
- void _picker_texture_input(const Ref<InputEvent> &p_event);
void _text_changed(const String &p_new_text);
void _add_preset_pressed();
- void _pick_button_pressed();
void _html_focus_exit();
+ void _pick_button_pressed();
+ void _pick_finished();
+ // Legacy color picking.
+ void _pick_button_pressed_legacy();
+ void _picker_texture_input(const Ref<InputEvent> &p_event);
inline int _get_preset_size();
void _add_preset_button(int p_size, const Color &p_color);
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 185db1b972..e12180f2f9 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -277,7 +277,10 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font
l.offset.x = _find_margin(l.from, p_base_font, p_base_font_size);
l.text_buf->set_width(p_width - l.offset.x);
- if (tab_size > 0) { // Align inline tabs.
+ PackedFloat32Array tab_stops = _find_tab_stops(l.from);
+ if (!tab_stops.is_empty()) {
+ l.text_buf->tab_align(tab_stops);
+ } else if (tab_size > 0) { // Align inline tabs.
Vector<float> tabs;
tabs.push_back(tab_size * p_base_font->get_char_size(' ', p_base_font_size).width);
l.text_buf->tab_align(tabs);
@@ -481,7 +484,10 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
l.text_buf->set_alignment(_find_alignment(l.from));
l.text_buf->set_direction(_find_direction(l.from));
- if (tab_size > 0) { // Align inline tabs.
+ PackedFloat32Array tab_stops = _find_tab_stops(l.from);
+ if (!tab_stops.is_empty()) {
+ l.text_buf->tab_align(tab_stops);
+ } else if (tab_size > 0) { // Align inline tabs.
Vector<float> tabs;
tabs.push_back(tab_size * p_base_font->get_char_size(' ', p_base_font_size).width);
l.text_buf->tab_align(tabs);
@@ -2468,6 +2474,21 @@ BitField<TextServer::JustificationFlag> RichTextLabel::_find_jst_flags(Item *p_i
return default_jst_flags;
}
+PackedFloat32Array RichTextLabel::_find_tab_stops(Item *p_item) {
+ Item *item = p_item;
+
+ while (item) {
+ if (item->type == ITEM_PARAGRAPH) {
+ ItemParagraph *p = static_cast<ItemParagraph *>(item);
+ return p->tab_stops;
+ }
+
+ item = item->parent;
+ }
+
+ return PackedFloat32Array();
+}
+
HorizontalAlignment RichTextLabel::_find_alignment(Item *p_item) {
Item *item = p_item;
@@ -3312,7 +3333,7 @@ void RichTextLabel::push_strikethrough() {
_add_item(item, true);
}
-void RichTextLabel::push_paragraph(HorizontalAlignment p_alignment, Control::TextDirection p_direction, const String &p_language, TextServer::StructuredTextParser p_st_parser, BitField<TextServer::JustificationFlag> p_jst_flags) {
+void RichTextLabel::push_paragraph(HorizontalAlignment p_alignment, Control::TextDirection p_direction, const String &p_language, TextServer::StructuredTextParser p_st_parser, BitField<TextServer::JustificationFlag> p_jst_flags, const PackedFloat32Array &p_tab_stops) {
_stop_thread();
MutexLock data_lock(data_mutex);
@@ -3324,6 +3345,7 @@ void RichTextLabel::push_paragraph(HorizontalAlignment p_alignment, Control::Tex
item->language = p_language;
item->st_parser = p_st_parser;
item->jst_flags = p_jst_flags;
+ item->tab_stops = p_tab_stops;
_add_item(item, true, true);
}
@@ -4094,6 +4116,7 @@ void RichTextLabel::append_text(const String &p_bbcode) {
HorizontalAlignment alignment = HORIZONTAL_ALIGNMENT_LEFT;
Control::TextDirection dir = Control::TEXT_DIRECTION_INHERITED;
String lang;
+ PackedFloat32Array tab_stops;
TextServer::StructuredTextParser st_parser_type = TextServer::STRUCTURED_TEXT_DEFAULT;
BitField<TextServer::JustificationFlag> jst_flags = default_jst_flags;
for (int i = 0; i < subtag.size(); i++) {
@@ -4118,6 +4141,11 @@ void RichTextLabel::append_text(const String &p_bbcode) {
jst_flags.set_flag(TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE);
}
}
+ } else if (subtag_a[0] == "tab_stops") {
+ Vector<String> splitters;
+ splitters.push_back(",");
+ splitters.push_back(";");
+ tab_stops = subtag_a[1].split_floats_mk(splitters);
} else if (subtag_a[0] == "align") {
if (subtag_a[1] == "l" || subtag_a[1] == "left") {
alignment = HORIZONTAL_ALIGNMENT_LEFT;
@@ -4157,7 +4185,7 @@ void RichTextLabel::append_text(const String &p_bbcode) {
}
}
}
- push_paragraph(alignment, dir, lang, st_parser_type, jst_flags);
+ push_paragraph(alignment, dir, lang, st_parser_type, jst_flags, tab_stops);
pos = brk_end + 1;
tag_stack.push_front("p");
} else if (tag == "url") {
@@ -5406,7 +5434,7 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("push_color", "color"), &RichTextLabel::push_color);
ClassDB::bind_method(D_METHOD("push_outline_size", "outline_size"), &RichTextLabel::push_outline_size);
ClassDB::bind_method(D_METHOD("push_outline_color", "color"), &RichTextLabel::push_outline_color);
- ClassDB::bind_method(D_METHOD("push_paragraph", "alignment", "base_direction", "language", "st_parser", "justification_flags"), &RichTextLabel::push_paragraph, DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(""), DEFVAL(TextServer::STRUCTURED_TEXT_DEFAULT), DEFVAL(TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE));
+ ClassDB::bind_method(D_METHOD("push_paragraph", "alignment", "base_direction", "language", "st_parser", "justification_flags", "tab_stops"), &RichTextLabel::push_paragraph, DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(""), DEFVAL(TextServer::STRUCTURED_TEXT_DEFAULT), DEFVAL(TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE), DEFVAL(PackedFloat32Array()));
ClassDB::bind_method(D_METHOD("push_indent", "level"), &RichTextLabel::push_indent);
ClassDB::bind_method(D_METHOD("push_list", "level", "type", "capitalize", "bullet"), &RichTextLabel::push_list, DEFVAL(String::utf8("•")));
ClassDB::bind_method(D_METHOD("push_meta", "data"), &RichTextLabel::push_meta);
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 3e3413d47a..f6cc9b2ac4 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -241,6 +241,7 @@ private:
Control::TextDirection direction = Control::TEXT_DIRECTION_AUTO;
TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
BitField<TextServer::JustificationFlag> jst_flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE;
+ PackedFloat32Array tab_stops;
ItemParagraph() { type = ITEM_PARAGRAPH; }
};
@@ -493,6 +494,7 @@ private:
ItemDropcap *_find_dc_item(Item *p_item);
int _find_list(Item *p_item, Vector<int> &r_index, Vector<ItemList *> &r_list);
int _find_margin(Item *p_item, const Ref<Font> &p_base_font, int p_base_font_size);
+ PackedFloat32Array _find_tab_stops(Item *p_item);
HorizontalAlignment _find_alignment(Item *p_item);
BitField<TextServer::JustificationFlag> _find_jst_flags(Item *p_item);
TextServer::Direction _find_direction(Item *p_item);
@@ -596,7 +598,7 @@ public:
void push_outline_color(const Color &p_color);
void push_underline();
void push_strikethrough();
- void push_paragraph(HorizontalAlignment p_alignment, Control::TextDirection p_direction = Control::TEXT_DIRECTION_INHERITED, const String &p_language = "", TextServer::StructuredTextParser p_st_parser = TextServer::STRUCTURED_TEXT_DEFAULT, BitField<TextServer::JustificationFlag> p_jst_flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE);
+ void push_paragraph(HorizontalAlignment p_alignment, Control::TextDirection p_direction = Control::TEXT_DIRECTION_INHERITED, const String &p_language = "", TextServer::StructuredTextParser p_st_parser = TextServer::STRUCTURED_TEXT_DEFAULT, BitField<TextServer::JustificationFlag> p_jst_flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE, const PackedFloat32Array &p_tab_stops = PackedFloat32Array());
void push_indent(int p_level);
void push_list(int p_level, ListType p_list, bool p_capitalize, const String &p_bullet = String::utf8("•"));
void push_meta(const Variant &p_meta);