Merge pull request #32354 from Relintai/rich-text-label-struct-refactor

Implement #32347 - (RichTextLabel's Item's should be structs)
This commit is contained in:
Rémi Verschelde 2019-09-27 08:03:55 +02:00 committed by GitHub
commit 17a81a32d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 93 additions and 144 deletions

View file

@ -120,3 +120,7 @@ CharFXTransform::CharFXTransform() {
color = Color(); color = Color();
character = 0; character = 0;
} }
CharFXTransform::~CharFXTransform() {
environment.clear();
}

View file

@ -64,6 +64,8 @@ public:
Dictionary environment; Dictionary environment;
CharFXTransform(); CharFXTransform();
~CharFXTransform();
uint64_t get_relative_index() { return relative_index; } uint64_t get_relative_index() { return relative_index; }
void set_relative_index(uint64_t p_index) { relative_index = p_index; } void set_relative_index(uint64_t p_index) { relative_index = p_index; }
uint64_t get_absolute_index() { return absolute_index; } uint64_t get_absolute_index() { return absolute_index; }

View file

@ -348,6 +348,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
int it_char_start = p_char_count; int it_char_start = p_char_count;
Vector<ItemFX *> fx_stack = Vector<ItemFX *>(); Vector<ItemFX *> fx_stack = Vector<ItemFX *>();
_fetch_item_fx_stack(text, fx_stack);
bool custom_fx_ok = true; bool custom_fx_ok = true;
if (p_mode == PROCESS_DRAW) { if (p_mode == PROCESS_DRAW) {
@ -359,8 +360,14 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
strikethrough = true; strikethrough = true;
} }
fade = _fetch_by_type<ItemFade>(text, ITEM_FADE); Item *fade_item = it;
_fetch_item_stack<ItemFX>(text, fx_stack); while (fade_item) {
if (fade_item->type == ITEM_FADE) {
fade = static_cast<ItemFade *>(fade_item);
break;
}
fade_item = fade_item->parent;
}
} else if (p_mode == PROCESS_CACHE) { } else if (p_mode == PROCESS_CACHE) {
l.char_count += text->text.length(); l.char_count += text->text.length();
@ -467,18 +474,16 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
faded_visibility > 0.0f); faded_visibility > 0.0f);
for (int j = 0; j < fx_stack.size(); j++) { for (int j = 0; j < fx_stack.size(); j++) {
ItemCustomFX *item_custom = Object::cast_to<ItemCustomFX>(fx_stack[j]); ItemFX *item_fx = fx_stack[j];
ItemShake *item_shake = Object::cast_to<ItemShake>(fx_stack[j]);
ItemWave *item_wave = Object::cast_to<ItemWave>(fx_stack[j]); if (item_fx->type == ITEM_CUSTOMFX && custom_fx_ok) {
ItemTornado *item_tornado = Object::cast_to<ItemTornado>(fx_stack[j]); ItemCustomFX *item_custom = static_cast<ItemCustomFX *>(item_fx);
ItemRainbow *item_rainbow = Object::cast_to<ItemRainbow>(fx_stack[j]);
Ref<CharFXTransform> charfx = item_custom->char_fx_transform;
Ref<RichTextEffect> custom_effect = item_custom->custom_effect;
if (item_custom && custom_fx_ok) {
Ref<CharFXTransform> charfx = Ref<CharFXTransform>(memnew(CharFXTransform));
Ref<RichTextEffect> custom_effect = _get_custom_effect_by_code(item_custom->identifier);
if (!custom_effect.is_null()) { if (!custom_effect.is_null()) {
charfx->elapsed_time = item_custom->elapsed_time; charfx->elapsed_time = item_custom->elapsed_time;
charfx->environment = item_custom->environment;
charfx->relative_index = c_item_offset; charfx->relative_index = c_item_offset;
charfx->absolute_index = p_char_count; charfx->absolute_index = p_char_count;
charfx->visibility = visible; charfx->visibility = visible;
@ -494,7 +499,9 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
visible &= charfx->visibility; visible &= charfx->visibility;
fx_char = charfx->character; fx_char = charfx->character;
} }
} else if (item_shake) { } else if (item_fx->type == ITEM_SHAKE) {
ItemShake *item_shake = static_cast<ItemShake *>(item_fx);
uint64_t char_current_rand = item_shake->offset_random(c_item_offset); uint64_t char_current_rand = item_shake->offset_random(c_item_offset);
uint64_t char_previous_rand = item_shake->offset_previous_random(c_item_offset); uint64_t char_previous_rand = item_shake->offset_previous_random(c_item_offset);
uint64_t max_rand = 2147483647; uint64_t max_rand = 2147483647;
@ -509,14 +516,20 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
Math::cos(current_offset), Math::cos(current_offset),
n_time)) * n_time)) *
(float)item_shake->strength / 10.0f; (float)item_shake->strength / 10.0f;
} else if (item_wave) { } else if (item_fx->type == ITEM_WAVE) {
ItemWave *item_wave = static_cast<ItemWave *>(item_fx);
double value = Math::sin(item_wave->frequency * item_wave->elapsed_time + ((p_ofs.x + pofs) / 50)) * (item_wave->amplitude / 10.0f); double value = Math::sin(item_wave->frequency * item_wave->elapsed_time + ((p_ofs.x + pofs) / 50)) * (item_wave->amplitude / 10.0f);
fx_offset += Point2(0, 1) * value; fx_offset += Point2(0, 1) * value;
} else if (item_tornado) { } else if (item_fx->type == ITEM_TORNADO) {
ItemTornado *item_tornado = static_cast<ItemTornado *>(item_fx);
double torn_x = Math::sin(item_tornado->frequency * item_tornado->elapsed_time + ((p_ofs.x + pofs) / 50)) * (item_tornado->radius); double torn_x = Math::sin(item_tornado->frequency * item_tornado->elapsed_time + ((p_ofs.x + pofs) / 50)) * (item_tornado->radius);
double torn_y = Math::cos(item_tornado->frequency * item_tornado->elapsed_time + ((p_ofs.x + pofs) / 50)) * (item_tornado->radius); double torn_y = Math::cos(item_tornado->frequency * item_tornado->elapsed_time + ((p_ofs.x + pofs) / 50)) * (item_tornado->radius);
fx_offset += Point2(torn_x, torn_y); fx_offset += Point2(torn_x, torn_y);
} else if (item_rainbow) { } else if (item_fx->type == ITEM_RAINBOW) {
ItemRainbow *item_rainbow = static_cast<ItemRainbow *>(item_fx);
fx_color = fx_color.from_hsv(item_rainbow->frequency * (item_rainbow->elapsed_time + ((p_ofs.x + pofs) / 50)), fx_color = fx_color.from_hsv(item_rainbow->frequency * (item_rainbow->elapsed_time + ((p_ofs.x + pofs) / 50)),
item_rainbow->saturation, item_rainbow->saturation,
item_rainbow->value, item_rainbow->value,
@ -884,7 +897,11 @@ void RichTextLabel::_update_scroll() {
void RichTextLabel::_update_fx(RichTextLabel::ItemFrame *p_frame, float p_delta_time) { void RichTextLabel::_update_fx(RichTextLabel::ItemFrame *p_frame, float p_delta_time) {
Item *it = p_frame; Item *it = p_frame;
while (it) { while (it) {
ItemFX *ifx = Object::cast_to<ItemFX>(it); ItemFX *ifx = NULL;
if (it->type == ITEM_CUSTOMFX || it->type == ITEM_SHAKE || it->type == ITEM_WAVE || it->type == ITEM_TORNADO || it->type == ITEM_RAINBOW) {
ifx = static_cast<ItemFX *>(it);
}
if (!ifx) { if (!ifx) {
it = _get_next_item(it, true); it = _get_next_item(it, true);
@ -893,7 +910,12 @@ void RichTextLabel::_update_fx(RichTextLabel::ItemFrame *p_frame, float p_delta_
ifx->elapsed_time += p_delta_time; ifx->elapsed_time += p_delta_time;
ItemShake *shake = Object::cast_to<ItemShake>(it); ItemShake *shake = NULL;
if (it->type == ITEM_SHAKE) {
shake = static_cast<ItemShake *>(it);
}
if (shake) { if (shake) {
bool cycle = (shake->elapsed_time > (1.0f / shake->rate)); bool cycle = (shake->elapsed_time > (1.0f / shake->rate));
if (cycle) { if (cycle) {
@ -983,9 +1005,6 @@ void RichTextLabel::_notification(int p_what) {
case NOTIFICATION_INTERNAL_PROCESS: { case NOTIFICATION_INTERNAL_PROCESS: {
float dt = get_process_delta_time(); float dt = get_process_delta_time();
for (int i = 0; i < custom_effects.size(); i++) {
}
_update_fx(main, dt); _update_fx(main, dt);
update(); update();
} }
@ -1408,6 +1427,17 @@ bool RichTextLabel::_find_by_type(Item *p_item, ItemType p_type) {
return false; return false;
} }
void RichTextLabel::_fetch_item_fx_stack(Item *p_item, Vector<ItemFX *> &r_stack) {
Item *item = p_item;
while (item) {
if (item->type == ITEM_CUSTOMFX || item->type == ITEM_SHAKE || item->type == ITEM_WAVE || item->type == ITEM_TORNADO || item->type == ITEM_RAINBOW) {
r_stack.push_back(static_cast<ItemFX *>(item));
}
item = item->parent;
}
}
bool RichTextLabel::_find_meta(Item *p_item, Variant *r_meta, ItemMeta **r_item) { bool RichTextLabel::_find_meta(Item *p_item, Variant *r_meta, ItemMeta **r_item) {
Item *item = p_item; Item *item = p_item;
@ -1776,10 +1806,10 @@ void RichTextLabel::push_rainbow(float p_saturation, float p_value, float p_freq
_add_item(item, true); _add_item(item, true);
} }
void RichTextLabel::push_customfx(String p_identifier, Dictionary p_environment) { void RichTextLabel::push_customfx(Ref<RichTextEffect> p_custom_effect, Dictionary p_environment) {
ItemCustomFX *item = memnew(ItemCustomFX); ItemCustomFX *item = memnew(ItemCustomFX);
item->identifier = p_identifier; item->custom_effect = p_custom_effect;
item->environment = p_environment; item->char_fx_transform->environment = p_environment;
_add_item(item, true); _add_item(item, true);
} }
@ -2287,7 +2317,7 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
Ref<RichTextEffect> effect = _get_custom_effect_by_code(identifier); Ref<RichTextEffect> effect = _get_custom_effect_by_code(identifier);
if (!effect.is_null()) { if (!effect.is_null()) {
push_customfx(identifier, properties); push_customfx(effect, properties);
pos = brk_end + 1; pos = brk_end + 1;
tag_stack.push_front(identifier); tag_stack.push_front(identifier);
set_process_internal(true); set_process_internal(true);
@ -2700,17 +2730,16 @@ Size2 RichTextLabel::get_minimum_size() const {
} }
Ref<RichTextEffect> RichTextLabel::_get_custom_effect_by_code(String p_bbcode_identifier) { Ref<RichTextEffect> RichTextLabel::_get_custom_effect_by_code(String p_bbcode_identifier) {
Ref<RichTextEffect> r;
for (int i = 0; i < custom_effects.size(); i++) { for (int i = 0; i < custom_effects.size(); i++) {
if (!custom_effects[i].is_valid()) if (!custom_effects[i].is_valid())
continue; continue;
if (custom_effects[i]->get_bbcode() == p_bbcode_identifier) { if (custom_effects[i]->get_bbcode() == p_bbcode_identifier) {
r = custom_effects[i]; return custom_effects[i];
} }
} }
return r; return Ref<RichTextEffect>();
} }
Dictionary RichTextLabel::parse_expressions_for_values(Vector<String> p_expressions) { Dictionary RichTextLabel::parse_expressions_for_values(Vector<String> p_expressions) {

View file

@ -81,7 +81,7 @@ protected:
static void _bind_methods(); static void _bind_methods();
private: private:
class Item; struct Item;
struct Line { struct Line {
@ -103,10 +103,7 @@ private:
} }
}; };
class Item : public Object { struct Item {
GDCLASS(Item, Object);
public:
int index; int index;
Item *parent; Item *parent;
ItemType type; ItemType type;
@ -129,10 +126,7 @@ private:
virtual ~Item() { _clear_children(); } virtual ~Item() { _clear_children(); }
}; };
class ItemFrame : public Item { struct ItemFrame : public Item {
GDCLASS(ItemFrame, Item);
public:
int parent_line; int parent_line;
bool cell; bool cell;
Vector<Line> lines; Vector<Line> lines;
@ -147,95 +141,59 @@ private:
} }
}; };
class ItemText : public Item { struct ItemText : public Item {
GDCLASS(ItemText, Item);
public:
String text; String text;
ItemText() { type = ITEM_TEXT; } ItemText() { type = ITEM_TEXT; }
}; };
class ItemImage : public Item { struct ItemImage : public Item {
GDCLASS(ItemImage, Item);
public:
Ref<Texture> image; Ref<Texture> image;
ItemImage() { type = ITEM_IMAGE; } ItemImage() { type = ITEM_IMAGE; }
}; };
class ItemFont : public Item { struct ItemFont : public Item {
GDCLASS(ItemFont, Item);
public:
Ref<Font> font; Ref<Font> font;
ItemFont() { type = ITEM_FONT; } ItemFont() { type = ITEM_FONT; }
}; };
class ItemColor : public Item { struct ItemColor : public Item {
GDCLASS(ItemColor, Item);
public:
Color color; Color color;
ItemColor() { type = ITEM_COLOR; } ItemColor() { type = ITEM_COLOR; }
}; };
class ItemUnderline : public Item { struct ItemUnderline : public Item {
GDCLASS(ItemUnderline, Item);
public:
ItemUnderline() { type = ITEM_UNDERLINE; } ItemUnderline() { type = ITEM_UNDERLINE; }
}; };
class ItemStrikethrough : public Item { struct ItemStrikethrough : public Item {
GDCLASS(ItemStrikethrough, Item);
public:
ItemStrikethrough() { type = ITEM_STRIKETHROUGH; } ItemStrikethrough() { type = ITEM_STRIKETHROUGH; }
}; };
class ItemMeta : public Item { struct ItemMeta : public Item {
GDCLASS(ItemMeta, Item);
public:
Variant meta; Variant meta;
ItemMeta() { type = ITEM_META; } ItemMeta() { type = ITEM_META; }
}; };
class ItemAlign : public Item { struct ItemAlign : public Item {
GDCLASS(ItemAlign, Item);
public:
Align align; Align align;
ItemAlign() { type = ITEM_ALIGN; } ItemAlign() { type = ITEM_ALIGN; }
}; };
class ItemIndent : public Item { struct ItemIndent : public Item {
GDCLASS(ItemIndent, Item);
public:
int level; int level;
ItemIndent() { type = ITEM_INDENT; } ItemIndent() { type = ITEM_INDENT; }
}; };
class ItemList : public Item { struct ItemList : public Item {
GDCLASS(ItemList, Item);
public:
ListType list_type; ListType list_type;
ItemList() { type = ITEM_LIST; } ItemList() { type = ITEM_LIST; }
}; };
class ItemNewline : public Item { struct ItemNewline : public Item {
GDCLASS(ItemNewline, Item);
public:
ItemNewline() { type = ITEM_NEWLINE; } ItemNewline() { type = ITEM_NEWLINE; }
}; };
class ItemTable : public Item { struct ItemTable : public Item {
GDCLASS(ItemTable, Item);
public:
struct Column { struct Column {
bool expand; bool expand;
int expand_ratio; int expand_ratio;
@ -249,20 +207,14 @@ private:
ItemTable() { type = ITEM_TABLE; } ItemTable() { type = ITEM_TABLE; }
}; };
class ItemFade : public Item { struct ItemFade : public Item {
GDCLASS(ItemFade, Item);
public:
int starting_index; int starting_index;
int length; int length;
ItemFade() { type = ITEM_FADE; } ItemFade() { type = ITEM_FADE; }
}; };
class ItemFX : public Item { struct ItemFX : public Item {
GDCLASS(ItemFX, Item);
public:
float elapsed_time; float elapsed_time;
ItemFX() { ItemFX() {
@ -270,10 +222,7 @@ private:
} }
}; };
class ItemShake : public ItemFX { struct ItemShake : public ItemFX {
GDCLASS(ItemShake, ItemFX);
public:
int strength; int strength;
float rate; float rate;
uint64_t _current_rng; uint64_t _current_rng;
@ -302,10 +251,7 @@ private:
} }
}; };
class ItemWave : public ItemFX { struct ItemWave : public ItemFX {
GDCLASS(ItemWave, ItemFX);
public:
float frequency; float frequency;
float amplitude; float amplitude;
@ -316,10 +262,7 @@ private:
} }
}; };
class ItemTornado : public ItemFX { struct ItemTornado : public ItemFX {
GDCLASS(ItemTornado, ItemFX);
public:
float radius; float radius;
float frequency; float frequency;
@ -330,10 +273,7 @@ private:
} }
}; };
class ItemRainbow : public ItemFX { struct ItemRainbow : public ItemFX {
GDCLASS(ItemRainbow, ItemFX);
public:
float saturation; float saturation;
float value; float value;
float frequency; float frequency;
@ -346,22 +286,21 @@ private:
} }
}; };
class ItemCustomFX : public ItemFX { struct ItemCustomFX : public ItemFX {
GDCLASS(ItemCustomFX, ItemFX); Ref<CharFXTransform> char_fx_transform;
Ref<RichTextEffect> custom_effect;
public:
String identifier;
Dictionary environment;
ItemCustomFX() { ItemCustomFX() {
identifier = "";
environment = Dictionary();
type = ITEM_CUSTOMFX; type = ITEM_CUSTOMFX;
char_fx_transform.instance();
} }
virtual ~ItemCustomFX() { virtual ~ItemCustomFX() {
_clear_children(); _clear_children();
environment.clear();
char_fx_transform.unref();
custom_effect.unref();
} }
}; };
@ -440,32 +379,7 @@ private:
bool _find_meta(Item *p_item, Variant *r_meta, ItemMeta **r_item = NULL); bool _find_meta(Item *p_item, Variant *r_meta, ItemMeta **r_item = NULL);
bool _find_layout_subitem(Item *from, Item *to); bool _find_layout_subitem(Item *from, Item *to);
bool _find_by_type(Item *p_item, ItemType p_type); bool _find_by_type(Item *p_item, ItemType p_type);
template <typename T> void _fetch_item_fx_stack(Item *p_item, Vector<ItemFX *> &r_stack);
T *_fetch_by_type(Item *p_item, ItemType p_type) {
Item *item = p_item;
T *result = NULL;
while (item) {
if (item->type == p_type) {
result = Object::cast_to<T>(item);
if (result)
return result;
}
item = item->parent;
}
return result;
};
template <typename T>
void _fetch_item_stack(Item *p_item, Vector<T *> &r_stack) {
Item *item = p_item;
while (item) {
T *found = Object::cast_to<T>(item);
if (found) {
r_stack.push_back(found);
}
item = item->parent;
}
}
void _update_scroll(); void _update_scroll();
void _update_fx(ItemFrame *p_frame, float p_delta_time); void _update_fx(ItemFrame *p_frame, float p_delta_time);
@ -509,7 +423,7 @@ public:
void push_wave(float p_frequency, float p_amplitude); void push_wave(float p_frequency, float p_amplitude);
void push_tornado(float p_frequency, float p_radius); void push_tornado(float p_frequency, float p_radius);
void push_rainbow(float p_saturation, float p_value, float p_frequency); void push_rainbow(float p_saturation, float p_value, float p_frequency);
void push_customfx(String p_identifier, Dictionary p_environment); 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_table_column_expand(int p_column, bool p_expand, int p_ratio = 1);
int get_current_table_column() const; int get_current_table_column() const;
void push_cell(); void push_cell();