Rich Text Label now allows for foreground colors and background colors
This commit is contained in:
parent
d88be9b70c
commit
0c1d10d1ca
|
@ -170,6 +170,15 @@
|
|||
Terminates the current tag. Use after [code]push_*[/code] methods to close BBCodes manually. Does not need to follow [code]add_*[/code] methods.
|
||||
</description>
|
||||
</method>
|
||||
<method name="push_bgcolor">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="bgcolor" type="Color">
|
||||
</argument>
|
||||
<description>
|
||||
Adds a [code][bgcolor][/code] tag to the tag stack.
|
||||
</description>
|
||||
</method>
|
||||
<method name="push_bold">
|
||||
<return type="void">
|
||||
</return>
|
||||
|
@ -221,6 +230,15 @@
|
|||
Adds a [code][dropcap][/code] tag to the tag stack. Drop cap (dropped capital) is a decorative element at the beginning of a paragraph that is larger than the rest of the text.
|
||||
</description>
|
||||
</method>
|
||||
<method name="push_fgcolor">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="fgcolor" type="Color">
|
||||
</argument>
|
||||
<description>
|
||||
Adds a [code][fgcolor][/code] tag to the tag stack.
|
||||
</description>
|
||||
</method>
|
||||
<method name="push_font">
|
||||
<return type="void">
|
||||
</return>
|
||||
|
@ -592,11 +610,15 @@
|
|||
</constant>
|
||||
<constant name="ITEM_RAINBOW" value="20" enum="ItemType">
|
||||
</constant>
|
||||
<constant name="ITEM_META" value="21" enum="ItemType">
|
||||
<constant name="ITEM_BGCOLOR" value="21" enum="ItemType">
|
||||
</constant>
|
||||
<constant name="ITEM_DROPCAP" value="22" enum="ItemType">
|
||||
<constant name="ITEM_FGCOLOR" value="22" enum="ItemType">
|
||||
</constant>
|
||||
<constant name="ITEM_CUSTOMFX" value="23" enum="ItemType">
|
||||
<constant name="ITEM_META" value="23" enum="ItemType">
|
||||
</constant>
|
||||
<constant name="ITEM_DROPCAP" value="24" enum="ItemType">
|
||||
</constant>
|
||||
<constant name="ITEM_CUSTOMFX" value="25" enum="ItemType">
|
||||
</constant>
|
||||
</constants>
|
||||
<theme_items>
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue