|
@@ -646,7 +646,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
|
|
|
}
|
|
|
|
|
|
if (p_mode == PROCESS_DRAW && visible) {
|
|
|
- img->image->draw_rect(ci, Rect2(p_ofs + Point2(align_ofs + wofs, y + lh - font->get_descent() - img->size.height), img->size));
|
|
|
+ img->image->draw_rect(ci, Rect2(p_ofs + Point2(align_ofs + wofs, y + lh - font->get_descent() - img->size.height), img->size), false, img->color);
|
|
|
}
|
|
|
p_char_count++;
|
|
|
|
|
@@ -1443,6 +1443,46 @@ void RichTextLabel::_fetch_item_fx_stack(Item *p_item, Vector<ItemFX *> &r_stack
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+Color RichTextLabel::_get_color_from_string(const String &p_color_str, const Color &p_default_color) {
|
|
|
+ if (p_color_str.begins_with("#")) {
|
|
|
+ return Color::html(p_color_str);
|
|
|
+ } else if (p_color_str == "aqua") {
|
|
|
+ return Color(0, 1, 1);
|
|
|
+ } else if (p_color_str == "black") {
|
|
|
+ return Color(0, 0, 0);
|
|
|
+ } else if (p_color_str == "blue") {
|
|
|
+ return Color(0, 0, 1);
|
|
|
+ } else if (p_color_str == "fuchsia") {
|
|
|
+ return Color(1, 0, 1);
|
|
|
+ } else if (p_color_str == "gray" || p_color_str == "grey") {
|
|
|
+ return Color(0.5, 0.5, 0.5);
|
|
|
+ } else if (p_color_str == "green") {
|
|
|
+ return Color(0, 0.5, 0);
|
|
|
+ } else if (p_color_str == "lime") {
|
|
|
+ return Color(0, 1, 0);
|
|
|
+ } else if (p_color_str == "maroon") {
|
|
|
+ return Color(0.5, 0, 0);
|
|
|
+ } else if (p_color_str == "navy") {
|
|
|
+ return Color(0, 0, 0.5);
|
|
|
+ } else if (p_color_str == "olive") {
|
|
|
+ return Color(0.5, 0.5, 0);
|
|
|
+ } else if (p_color_str == "purple") {
|
|
|
+ return Color(0.5, 0, 0.5);
|
|
|
+ } else if (p_color_str == "red") {
|
|
|
+ return Color(1, 0, 0);
|
|
|
+ } else if (p_color_str == "silver") {
|
|
|
+ return Color(0.75, 0.75, 0.75);
|
|
|
+ } else if (p_color_str == "teal") {
|
|
|
+ return Color(0, 0.5, 0.5);
|
|
|
+ } else if (p_color_str == "white") {
|
|
|
+ return Color(1, 1, 1);
|
|
|
+ } else if (p_color_str == "yellow") {
|
|
|
+ return Color(1, 1, 0);
|
|
|
+ } else {
|
|
|
+ return p_default_color;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
bool RichTextLabel::_find_meta(Item *p_item, Variant *r_meta, ItemMeta **r_item) {
|
|
|
Item *item = p_item;
|
|
|
|
|
@@ -1636,7 +1676,7 @@ void RichTextLabel::_remove_item(Item *p_item, const int p_line, const int p_sub
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void RichTextLabel::add_image(const Ref<Texture2D> &p_image, const int p_width, const int p_height) {
|
|
|
+void RichTextLabel::add_image(const Ref<Texture2D> &p_image, const int p_width, const int p_height, const Color &p_color) {
|
|
|
if (current->type == ITEM_TABLE) {
|
|
|
return;
|
|
|
}
|
|
@@ -1645,6 +1685,7 @@ void RichTextLabel::add_image(const Ref<Texture2D> &p_image, const int p_width,
|
|
|
ItemImage *item = memnew(ItemImage);
|
|
|
|
|
|
item->image = p_image;
|
|
|
+ item->color = p_color;
|
|
|
|
|
|
if (p_width > 0) {
|
|
|
// custom width
|
|
@@ -2034,7 +2075,32 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
|
|
|
|
|
|
String tag = p_bbcode.substr(brk_pos + 1, brk_end - brk_pos - 1);
|
|
|
Vector<String> split_tag_block = tag.split(" ", false);
|
|
|
- String bbcode = !split_tag_block.empty() ? split_tag_block[0] : "";
|
|
|
+
|
|
|
+ // Find optional parameters.
|
|
|
+ String bbcode_name;
|
|
|
+ typedef Map<String, String> OptionMap;
|
|
|
+ OptionMap bbcode_options;
|
|
|
+ if (!split_tag_block.empty()) {
|
|
|
+ bbcode_name = split_tag_block[0];
|
|
|
+ for (int i = 1; i < split_tag_block.size(); i++) {
|
|
|
+ const String &expr = split_tag_block[i];
|
|
|
+ int value_pos = expr.find("=");
|
|
|
+ if (value_pos > -1) {
|
|
|
+ bbcode_options[expr.substr(0, value_pos)] = expr.substr(value_pos + 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ bbcode_name = tag;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Find main parameter.
|
|
|
+ String bbcode_value;
|
|
|
+ int main_value_pos = bbcode_name.find("=");
|
|
|
+ if (main_value_pos > -1) {
|
|
|
+ bbcode_value = bbcode_name.substr(main_value_pos + 1);
|
|
|
+ bbcode_name = bbcode_name.substr(0, main_value_pos);
|
|
|
+ }
|
|
|
+
|
|
|
if (tag.begins_with("/") && tag_stack.size()) {
|
|
|
bool tag_ok = tag_stack.size() && tag_stack.front()->get() == tag.substr(1, tag.length());
|
|
|
|
|
@@ -2160,7 +2226,7 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
|
|
|
push_meta(url);
|
|
|
pos = brk_end + 1;
|
|
|
tag_stack.push_front("url");
|
|
|
- } else if (tag == "img") {
|
|
|
+ } else if (bbcode_name == "img") {
|
|
|
int end = p_bbcode.find("[", brk_end);
|
|
|
if (end == -1) {
|
|
|
end = p_bbcode.length();
|
|
@@ -2170,80 +2236,42 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
|
|
|
|
|
|
Ref<Texture2D> texture = ResourceLoader::load(image, "Texture2D");
|
|
|
if (texture.is_valid()) {
|
|
|
- add_image(texture);
|
|
|
- }
|
|
|
-
|
|
|
- pos = end;
|
|
|
- tag_stack.push_front(tag);
|
|
|
- } else if (tag.begins_with("img=")) {
|
|
|
- int width = 0;
|
|
|
- int height = 0;
|
|
|
-
|
|
|
- String params = tag.substr(4, tag.length());
|
|
|
- int sep = params.find("x");
|
|
|
- if (sep == -1) {
|
|
|
- width = params.to_int();
|
|
|
- } else {
|
|
|
- width = params.substr(0, sep).to_int();
|
|
|
- height = params.substr(sep + 1, params.length()).to_int();
|
|
|
- }
|
|
|
+ Color color = Color(1.0, 1.0, 1.0);
|
|
|
+ OptionMap::Element *color_option = bbcode_options.find("color");
|
|
|
+ if (color_option) {
|
|
|
+ color = _get_color_from_string(color_option->value(), color);
|
|
|
+ }
|
|
|
|
|
|
- int end = p_bbcode.find("[", brk_end);
|
|
|
- if (end == -1) {
|
|
|
- end = p_bbcode.length();
|
|
|
- }
|
|
|
+ int width = 0;
|
|
|
+ int height = 0;
|
|
|
+ if (!bbcode_value.empty()) {
|
|
|
+ int sep = bbcode_value.find("x");
|
|
|
+ if (sep == -1) {
|
|
|
+ width = bbcode_value.to_int();
|
|
|
+ } else {
|
|
|
+ width = bbcode_value.substr(0, sep).to_int();
|
|
|
+ height = bbcode_value.substr(sep + 1).to_int();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ OptionMap::Element *width_option = bbcode_options.find("width");
|
|
|
+ if (width_option) {
|
|
|
+ width = width_option->value().to_int();
|
|
|
+ }
|
|
|
|
|
|
- String image = p_bbcode.substr(brk_end + 1, end - brk_end - 1);
|
|
|
+ OptionMap::Element *height_option = bbcode_options.find("height");
|
|
|
+ if (height_option) {
|
|
|
+ height = height_option->value().to_int();
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- Ref<Texture2D> texture = ResourceLoader::load(image, "Texture");
|
|
|
- if (texture.is_valid()) {
|
|
|
- add_image(texture, width, height);
|
|
|
+ add_image(texture, width, height, color);
|
|
|
}
|
|
|
|
|
|
pos = end;
|
|
|
- tag_stack.push_front("img");
|
|
|
+ tag_stack.push_front(bbcode_name);
|
|
|
} else if (tag.begins_with("color=")) {
|
|
|
- String col = tag.substr(6, tag.length());
|
|
|
- Color color;
|
|
|
-
|
|
|
- if (col.begins_with("#")) {
|
|
|
- color = Color::html(col);
|
|
|
- } else if (col == "aqua") {
|
|
|
- color = Color(0, 1, 1);
|
|
|
- } else if (col == "black") {
|
|
|
- color = Color(0, 0, 0);
|
|
|
- } else if (col == "blue") {
|
|
|
- color = Color(0, 0, 1);
|
|
|
- } else if (col == "fuchsia") {
|
|
|
- color = Color(1, 0, 1);
|
|
|
- } else if (col == "gray" || col == "grey") {
|
|
|
- color = Color(0.5, 0.5, 0.5);
|
|
|
- } else if (col == "green") {
|
|
|
- color = Color(0, 0.5, 0);
|
|
|
- } else if (col == "lime") {
|
|
|
- color = Color(0, 1, 0);
|
|
|
- } else if (col == "maroon") {
|
|
|
- color = Color(0.5, 0, 0);
|
|
|
- } else if (col == "navy") {
|
|
|
- color = Color(0, 0, 0.5);
|
|
|
- } else if (col == "olive") {
|
|
|
- color = Color(0.5, 0.5, 0);
|
|
|
- } else if (col == "purple") {
|
|
|
- color = Color(0.5, 0, 0.5);
|
|
|
- } else if (col == "red") {
|
|
|
- color = Color(1, 0, 0);
|
|
|
- } else if (col == "silver") {
|
|
|
- color = Color(0.75, 0.75, 0.75);
|
|
|
- } else if (col == "teal") {
|
|
|
- color = Color(0, 0.5, 0.5);
|
|
|
- } else if (col == "white") {
|
|
|
- color = Color(1, 1, 1);
|
|
|
- } else if (col == "yellow") {
|
|
|
- color = Color(1, 1, 0);
|
|
|
- } else {
|
|
|
- color = base_color;
|
|
|
- }
|
|
|
-
|
|
|
+ String color_str = tag.substr(6, tag.length());
|
|
|
+ Color color = _get_color_from_string(color_str, base_color);
|
|
|
push_color(color);
|
|
|
pos = brk_end + 1;
|
|
|
tag_stack.push_front("color");
|
|
@@ -2261,113 +2289,90 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
|
|
|
pos = brk_end + 1;
|
|
|
tag_stack.push_front("font");
|
|
|
|
|
|
- } else if (bbcode == "fade") {
|
|
|
- int startIndex = 0;
|
|
|
- int length = 10;
|
|
|
+ } else if (bbcode_name == "fade") {
|
|
|
+ int start_index = 0;
|
|
|
+ OptionMap::Element *start_option = bbcode_options.find("start");
|
|
|
+ if (start_option) {
|
|
|
+ start_index = start_option->value().to_int();
|
|
|
+ }
|
|
|
|
|
|
- if (split_tag_block.size() > 1) {
|
|
|
- split_tag_block.remove(0);
|
|
|
- for (int i = 0; i < split_tag_block.size(); i++) {
|
|
|
- String expr = split_tag_block[i];
|
|
|
- if (expr.begins_with("start=")) {
|
|
|
- String start_str = expr.substr(6, expr.length());
|
|
|
- startIndex = start_str.to_int();
|
|
|
- } else if (expr.begins_with("length=")) {
|
|
|
- String end_str = expr.substr(7, expr.length());
|
|
|
- length = end_str.to_int();
|
|
|
- }
|
|
|
- }
|
|
|
+ int length = 10;
|
|
|
+ OptionMap::Element *length_option = bbcode_options.find("length");
|
|
|
+ if (length_option) {
|
|
|
+ length = length_option->value().to_int();
|
|
|
}
|
|
|
|
|
|
- push_fade(startIndex, length);
|
|
|
+ push_fade(start_index, length);
|
|
|
pos = brk_end + 1;
|
|
|
tag_stack.push_front("fade");
|
|
|
- } else if (bbcode == "shake") {
|
|
|
+ } else if (bbcode_name == "shake") {
|
|
|
int strength = 5;
|
|
|
- float rate = 20.0f;
|
|
|
+ OptionMap::Element *strength_option = bbcode_options.find("level");
|
|
|
+ if (strength_option) {
|
|
|
+ strength = strength_option->value().to_int();
|
|
|
+ }
|
|
|
|
|
|
- if (split_tag_block.size() > 1) {
|
|
|
- split_tag_block.remove(0);
|
|
|
- for (int i = 0; i < split_tag_block.size(); i++) {
|
|
|
- String expr = split_tag_block[i];
|
|
|
- if (expr.begins_with("level=")) {
|
|
|
- String str_str = expr.substr(6, expr.length());
|
|
|
- strength = str_str.to_int();
|
|
|
- } else if (expr.begins_with("rate=")) {
|
|
|
- String rate_str = expr.substr(5, expr.length());
|
|
|
- rate = rate_str.to_float();
|
|
|
- }
|
|
|
- }
|
|
|
+ float rate = 20.0f;
|
|
|
+ OptionMap::Element *rate_option = bbcode_options.find("rate");
|
|
|
+ if (rate_option) {
|
|
|
+ rate = rate_option->value().to_float();
|
|
|
}
|
|
|
|
|
|
push_shake(strength, rate);
|
|
|
pos = brk_end + 1;
|
|
|
tag_stack.push_front("shake");
|
|
|
set_process_internal(true);
|
|
|
- } else if (bbcode == "wave") {
|
|
|
+ } else if (bbcode_name == "wave") {
|
|
|
float amplitude = 20.0f;
|
|
|
- float period = 5.0f;
|
|
|
+ OptionMap::Element *amplitude_option = bbcode_options.find("amp");
|
|
|
+ if (amplitude_option) {
|
|
|
+ amplitude = amplitude_option->value().to_float();
|
|
|
+ }
|
|
|
|
|
|
- if (split_tag_block.size() > 1) {
|
|
|
- split_tag_block.remove(0);
|
|
|
- for (int i = 0; i < split_tag_block.size(); i++) {
|
|
|
- String expr = split_tag_block[i];
|
|
|
- if (expr.begins_with("amp=")) {
|
|
|
- String amp_str = expr.substr(4, expr.length());
|
|
|
- amplitude = amp_str.to_float();
|
|
|
- } else if (expr.begins_with("freq=")) {
|
|
|
- String period_str = expr.substr(5, expr.length());
|
|
|
- period = period_str.to_float();
|
|
|
- }
|
|
|
- }
|
|
|
+ float period = 5.0f;
|
|
|
+ OptionMap::Element *period_option = bbcode_options.find("freq");
|
|
|
+ if (period_option) {
|
|
|
+ period = period_option->value().to_float();
|
|
|
}
|
|
|
|
|
|
push_wave(period, amplitude);
|
|
|
pos = brk_end + 1;
|
|
|
tag_stack.push_front("wave");
|
|
|
set_process_internal(true);
|
|
|
- } else if (bbcode == "tornado") {
|
|
|
+ } else if (bbcode_name == "tornado") {
|
|
|
float radius = 10.0f;
|
|
|
- float frequency = 1.0f;
|
|
|
+ OptionMap::Element *radius_option = bbcode_options.find("radius");
|
|
|
+ if (radius_option) {
|
|
|
+ radius = radius_option->value().to_float();
|
|
|
+ }
|
|
|
|
|
|
- if (split_tag_block.size() > 1) {
|
|
|
- split_tag_block.remove(0);
|
|
|
- for (int i = 0; i < split_tag_block.size(); i++) {
|
|
|
- String expr = split_tag_block[i];
|
|
|
- if (expr.begins_with("radius=")) {
|
|
|
- String amp_str = expr.substr(7, expr.length());
|
|
|
- radius = amp_str.to_float();
|
|
|
- } else if (expr.begins_with("freq=")) {
|
|
|
- String period_str = expr.substr(5, expr.length());
|
|
|
- frequency = period_str.to_float();
|
|
|
- }
|
|
|
- }
|
|
|
+ float frequency = 1.0f;
|
|
|
+ OptionMap::Element *frequency_option = bbcode_options.find("freq");
|
|
|
+ if (frequency_option) {
|
|
|
+ frequency = frequency_option->value().to_float();
|
|
|
}
|
|
|
|
|
|
push_tornado(frequency, radius);
|
|
|
pos = brk_end + 1;
|
|
|
tag_stack.push_front("tornado");
|
|
|
set_process_internal(true);
|
|
|
- } else if (bbcode == "rainbow") {
|
|
|
+ } else if (bbcode_name == "rainbow") {
|
|
|
float saturation = 0.8f;
|
|
|
+ OptionMap::Element *saturation_option = bbcode_options.find("sat");
|
|
|
+ if (saturation_option) {
|
|
|
+ saturation = saturation_option->value().to_float();
|
|
|
+ }
|
|
|
+
|
|
|
float value = 0.8f;
|
|
|
- float frequency = 1.0f;
|
|
|
+ OptionMap::Element *value_option = bbcode_options.find("val");
|
|
|
+ if (value_option) {
|
|
|
+ value = value_option->value().to_float();
|
|
|
+ }
|
|
|
|
|
|
- if (split_tag_block.size() > 1) {
|
|
|
- split_tag_block.remove(0);
|
|
|
- for (int i = 0; i < split_tag_block.size(); i++) {
|
|
|
- String expr = split_tag_block[i];
|
|
|
- if (expr.begins_with("sat=")) {
|
|
|
- String sat_str = expr.substr(4, expr.length());
|
|
|
- saturation = sat_str.to_float();
|
|
|
- } else if (expr.begins_with("val=")) {
|
|
|
- String val_str = expr.substr(4, expr.length());
|
|
|
- value = val_str.to_float();
|
|
|
- } else if (expr.begins_with("freq=")) {
|
|
|
- String freq_str = expr.substr(5, expr.length());
|
|
|
- frequency = freq_str.to_float();
|
|
|
- }
|
|
|
- }
|
|
|
+ float frequency = 1.0f;
|
|
|
+ OptionMap::Element *frequency_option = bbcode_options.find("freq");
|
|
|
+ if (frequency_option) {
|
|
|
+ frequency = frequency_option->value().to_float();
|
|
|
}
|
|
|
|
|
|
push_rainbow(saturation, value, frequency);
|
|
@@ -2634,7 +2639,7 @@ void RichTextLabel::_bind_methods() {
|
|
|
ClassDB::bind_method(D_METHOD("get_text"), &RichTextLabel::get_text);
|
|
|
ClassDB::bind_method(D_METHOD("add_text", "text"), &RichTextLabel::add_text);
|
|
|
ClassDB::bind_method(D_METHOD("set_text", "text"), &RichTextLabel::set_text);
|
|
|
- ClassDB::bind_method(D_METHOD("add_image", "image", "width", "height"), &RichTextLabel::add_image, DEFVAL(0), DEFVAL(0));
|
|
|
+ ClassDB::bind_method(D_METHOD("add_image", "image", "width", "height", "color"), &RichTextLabel::add_image, DEFVAL(0), DEFVAL(0), DEFVAL(Color(1.0, 1.0, 1.0)));
|
|
|
ClassDB::bind_method(D_METHOD("newline"), &RichTextLabel::add_newline);
|
|
|
ClassDB::bind_method(D_METHOD("remove_line", "line"), &RichTextLabel::remove_line);
|
|
|
ClassDB::bind_method(D_METHOD("push_font", "font"), &RichTextLabel::push_font);
|