summaryrefslogtreecommitdiff
path: root/scene/gui
diff options
context:
space:
mode:
authorgolfinq <60325793+golfinq@users.noreply.github.com>2020-01-26 17:11:09 -0500
committergolfinq <golfinqz@gmail.com>2021-06-20 11:29:37 -0400
commit0c1d10d1ca9bbc7126f270b111a0a25cc45bd84d (patch)
treea9d576e3737276ca593b5a74c4fdbf029771c1ec /scene/gui
parentd88be9b70cfecb0ec525216c1bb6267c9d1aa17d (diff)
Rich Text Label now allows for foreground colors and background colors
Diffstat (limited to 'scene/gui')
-rw-r--r--scene/gui/rich_text_label.cpp134
-rw-r--r--scene/gui/rich_text_label.h18
2 files changed, 152 insertions, 0 deletions
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 987d05bf71..7db6665e82 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -934,6 +934,11 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
}
}
+ Vector2 fbg_line_off = off + p_ofs;
+ // Draw background color box
+ Vector2i chr_range = TS->shaped_text_get_range(rid);
+ _draw_fbg_boxes(ci, rid, fbg_line_off, it_from, it_to, chr_range.x, chr_range.y, 0);
+
// Draw main text.
Color selection_fg = get_theme_color("font_selected_color");
Color selection_bg = get_theme_color("selection_color");
@@ -1079,6 +1084,9 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
off.x += glyphs[i].advance;
}
}
+ // Draw foreground color box
+ _draw_fbg_boxes(ci, rid, fbg_line_off, it_from, it_to, chr_range.x, chr_range.y, 1);
+
off.y += TS->shaped_text_get_descent(rid) + l.text_buf->get_spacing_bottom();
}
@@ -2036,6 +2044,36 @@ bool RichTextLabel::_find_meta(Item *p_item, Variant *r_meta, ItemMeta **r_item)
return false;
}
+Color RichTextLabel::_find_bgcolor(Item *p_item) {
+ Item *item = p_item;
+
+ while (item) {
+ if (item->type == ITEM_BGCOLOR) {
+ ItemBGColor *color = static_cast<ItemBGColor *>(item);
+ return color->color;
+ }
+
+ item = item->parent;
+ }
+
+ return Color(0, 0, 0, 0);
+}
+
+Color RichTextLabel::_find_fgcolor(Item *p_item) {
+ Item *item = p_item;
+
+ while (item) {
+ if (item->type == ITEM_FGCOLOR) {
+ ItemFGColor *color = static_cast<ItemFGColor *>(item);
+ return color->color;
+ }
+
+ item = item->parent;
+ }
+
+ return Color(0, 0, 0, 0);
+}
+
bool RichTextLabel::_find_layout_subitem(Item *from, Item *to) {
if (from && from != to) {
if (from->type != ITEM_FONT && from->type != ITEM_COLOR && from->type != ITEM_UNDERLINE && from->type != ITEM_STRIKETHROUGH) {
@@ -2546,6 +2584,22 @@ void RichTextLabel::push_rainbow(float p_saturation, float p_value, float p_freq
_add_item(item, true);
}
+void RichTextLabel::push_bgcolor(const Color &p_color) {
+ ERR_FAIL_COND(current->type == ITEM_TABLE);
+ ItemBGColor *item = memnew(ItemBGColor);
+
+ item->color = p_color;
+ _add_item(item, true);
+}
+
+void RichTextLabel::push_fgcolor(const Color &p_color) {
+ ERR_FAIL_COND(current->type == ITEM_TABLE);
+ ItemFGColor *item = memnew(ItemFGColor);
+
+ item->color = p_color;
+ _add_item(item, true);
+}
+
void RichTextLabel::push_customfx(Ref<RichTextEffect> p_custom_effect, Dictionary p_environment) {
ItemCustomFX *item = memnew(ItemCustomFX);
item->custom_effect = p_custom_effect;
@@ -3352,6 +3406,23 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
pos = brk_end + 1;
tag_stack.push_front("rainbow");
set_process_internal(true);
+
+ } else if (tag.begins_with("bgcolor=")) {
+ String color_str = tag.substr(8, tag.length());
+ Color color = Color::from_string(color_str, base_color);
+
+ push_bgcolor(color);
+ pos = brk_end + 1;
+ tag_stack.push_front("bgcolor");
+
+ } else if (tag.begins_with("fgcolor=")) {
+ String color_str = tag.substr(8, tag.length());
+ Color color = Color::from_string(color_str, base_color);
+
+ push_fgcolor(color);
+ pos = brk_end + 1;
+ tag_stack.push_front("fgcolor");
+
} else {
Vector<String> &expr = split_tag_block;
if (expr.size() < 1) {
@@ -3918,6 +3989,8 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_cell_size_override", "min_size", "max_size"), &RichTextLabel::set_cell_size_override);
ClassDB::bind_method(D_METHOD("set_cell_padding", "padding"), &RichTextLabel::set_cell_padding);
ClassDB::bind_method(D_METHOD("push_cell"), &RichTextLabel::push_cell);
+ ClassDB::bind_method(D_METHOD("push_fgcolor", "fgcolor"), &RichTextLabel::push_fgcolor);
+ ClassDB::bind_method(D_METHOD("push_bgcolor", "bgcolor"), &RichTextLabel::push_bgcolor);
ClassDB::bind_method(D_METHOD("pop"), &RichTextLabel::pop);
ClassDB::bind_method(D_METHOD("clear"), &RichTextLabel::clear);
@@ -4056,6 +4129,8 @@ void RichTextLabel::_bind_methods() {
BIND_ENUM_CONSTANT(ITEM_WAVE);
BIND_ENUM_CONSTANT(ITEM_TORNADO);
BIND_ENUM_CONSTANT(ITEM_RAINBOW);
+ BIND_ENUM_CONSTANT(ITEM_BGCOLOR);
+ BIND_ENUM_CONSTANT(ITEM_FGCOLOR);
BIND_ENUM_CONSTANT(ITEM_META);
BIND_ENUM_CONSTANT(ITEM_DROPCAP);
BIND_ENUM_CONSTANT(ITEM_CUSTOMFX);
@@ -4108,6 +4183,65 @@ Size2 RichTextLabel::get_minimum_size() const {
return size;
}
+void RichTextLabel::_draw_fbg_boxes(RID p_ci, RID p_rid, Vector2 line_off, Item *it_from, Item *it_to, int start, int end, int fbg_flag) {
+ Vector2i fbg_index = Vector2i(end, start);
+ Color last_color = Color(0, 0, 0, 0);
+ bool draw_box = false;
+ // Draw a box based on color tags associated with glyphs
+ for (int i = start; i < end; i++) {
+ Item *it = _get_item_at_pos(it_from, it_to, i);
+ Color color = Color(0, 0, 0, 0);
+
+ if (fbg_flag == 0) {
+ color = _find_bgcolor(it);
+ } else {
+ color = _find_fgcolor(it);
+ }
+
+ bool change_to_color = ((color.a > 0) && ((last_color.a - 0.0) < 0.01));
+ bool change_from_color = (((color.a - 0.0) < 0.01) && (last_color.a > 0.0));
+ bool change_color = (((color.a > 0) == (last_color.a > 0)) && (color != last_color));
+
+ if (change_to_color) {
+ fbg_index.x = MIN(i, fbg_index.x);
+ fbg_index.y = MAX(i, fbg_index.y);
+ }
+
+ if (change_from_color || change_color) {
+ fbg_index.x = MIN(i, fbg_index.x);
+ fbg_index.y = MAX(i, fbg_index.y);
+ draw_box = true;
+ }
+
+ if (draw_box) {
+ Vector<Vector2> sel = TS->shaped_text_get_selection(p_rid, fbg_index.x, fbg_index.y);
+ for (int j = 0; j < sel.size(); j++) {
+ Vector2 rect_off = line_off + Vector2(sel[j].x, -TS->shaped_text_get_ascent(p_rid));
+ Vector2 rect_size = Vector2(sel[j].y - sel[j].x, TS->shaped_text_get_size(p_rid).y);
+ RenderingServer::get_singleton()->canvas_item_add_rect(p_ci, Rect2(rect_off, rect_size), last_color);
+ }
+ fbg_index = Vector2i(end, start);
+ draw_box = false;
+ }
+
+ if (change_color) {
+ fbg_index.x = MIN(i, fbg_index.x);
+ fbg_index.y = MAX(i, fbg_index.y);
+ }
+
+ last_color = color;
+ }
+
+ if (last_color.a > 0) {
+ Vector<Vector2> sel = TS->shaped_text_get_selection(p_rid, fbg_index.x, end);
+ for (int i = 0; i < sel.size(); i++) {
+ Vector2 rect_off = line_off + Vector2(sel[i].x, -TS->shaped_text_get_ascent(p_rid));
+ Vector2 rect_size = Vector2(sel[i].y - sel[i].x, TS->shaped_text_get_size(p_rid).y);
+ RenderingServer::get_singleton()->canvas_item_add_rect(p_ci, Rect2(rect_off, rect_size), last_color);
+ }
+ }
+}
+
Ref<RichTextEffect> RichTextLabel::_get_custom_effect_by_code(String p_bbcode_identifier) {
for (int i = 0; i < custom_effects.size(); i++) {
if (!custom_effects[i].is_valid()) {
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 9cf94b0cd7..9bcb9e93c9 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -75,6 +75,8 @@ public:
ITEM_WAVE,
ITEM_TORNADO,
ITEM_RAINBOW,
+ ITEM_BGCOLOR,
+ ITEM_FGCOLOR,
ITEM_META,
ITEM_DROPCAP,
ITEM_CUSTOMFX
@@ -307,6 +309,16 @@ private:
ItemRainbow() { type = ITEM_RAINBOW; }
};
+ struct ItemBGColor : public Item {
+ Color color;
+ ItemBGColor() { type = ITEM_BGCOLOR; }
+ };
+
+ struct ItemFGColor : public Item {
+ Color color;
+ ItemFGColor() { type = ITEM_FGCOLOR; }
+ };
+
struct ItemCustomFX : public ItemFX {
Ref<CharFXTransform> char_fx_transform;
Ref<RichTextEffect> custom_effect;
@@ -422,6 +434,8 @@ private:
bool _find_underline(Item *p_item);
bool _find_strikethrough(Item *p_item);
bool _find_meta(Item *p_item, Variant *r_meta, ItemMeta **r_item = nullptr);
+ Color _find_bgcolor(Item *p_item);
+ Color _find_fgcolor(Item *p_item);
bool _find_layout_subitem(Item *from, Item *to);
void _fetch_item_fx_stack(Item *p_item, Vector<ItemFX *> &r_stack);
@@ -437,6 +451,8 @@ private:
Ref<RichTextEffect> _get_custom_effect_by_code(String p_bbcode_identifier);
virtual Dictionary parse_expressions_for_values(Vector<String> p_expressions);
+ void _draw_fbg_boxes(RID p_ci, RID p_rid, Vector2 line_off, Item *it_from, Item *it_to, int start, int end, int fbg_flag);
+
bool use_bbcode = false;
String bbcode;
@@ -474,6 +490,8 @@ public:
void push_wave(float p_frequency, float p_amplitude);
void push_tornado(float p_frequency, float p_radius);
void push_rainbow(float p_saturation, float p_value, float p_frequency);
+ void push_bgcolor(const Color &p_color);
+ void push_fgcolor(const Color &p_color);
void push_customfx(Ref<RichTextEffect> p_custom_effect, Dictionary p_environment);
void set_table_column_expand(int p_column, bool p_expand, int p_ratio = 1);
void set_cell_row_background_color(const Color &p_odd_row_bg, const Color &p_even_row_bg);