Add a [pulse]
built-in effect to RichTextLabel
In games, blinking text is one of the more frequently used animations. It can be (sparingly) used to bring attention to important messages in a chat log or inventory tooltip, for instance. This effect accepts the following options: - `freq`: How fast text blinks (higher is faster). - `color`: The target color multiplier for blinking. The default mostly fades out text, but not entirely (for better accessibility). - `ease`: The easing function exponent to use. Negative values provide in-out easing, which is why `-2.0` is the default.
This commit is contained in:
parent
0f76ff2115
commit
70e6c3cbb0
2 changed files with 55 additions and 2 deletions
|
@ -1097,6 +1097,11 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
|
||||||
ItemRainbow *item_rainbow = static_cast<ItemRainbow *>(item_fx);
|
ItemRainbow *item_rainbow = static_cast<ItemRainbow *>(item_fx);
|
||||||
|
|
||||||
font_color = font_color.from_hsv(item_rainbow->frequency * (item_rainbow->elapsed_time + ((p_ofs.x + gloff.x) / 50)), item_rainbow->saturation, item_rainbow->value, font_color.a);
|
font_color = font_color.from_hsv(item_rainbow->frequency * (item_rainbow->elapsed_time + ((p_ofs.x + gloff.x) / 50)), item_rainbow->saturation, item_rainbow->value, font_color.a);
|
||||||
|
} else if (item_fx->type == ITEM_PULSE) {
|
||||||
|
ItemPulse *item_pulse = static_cast<ItemPulse *>(item_fx);
|
||||||
|
|
||||||
|
const float sined_time = (Math::ease(Math::pingpong(item_pulse->elapsed_time, 1.0 / item_pulse->frequency) * item_pulse->frequency, item_pulse->ease));
|
||||||
|
font_color = font_color.lerp(font_color * item_pulse->color, sined_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1315,6 +1320,11 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
|
||||||
ItemRainbow *item_rainbow = static_cast<ItemRainbow *>(item_fx);
|
ItemRainbow *item_rainbow = static_cast<ItemRainbow *>(item_fx);
|
||||||
|
|
||||||
font_color = font_color.from_hsv(item_rainbow->frequency * (item_rainbow->elapsed_time + ((p_ofs.x + off.x) / 50)), item_rainbow->saturation, item_rainbow->value, font_color.a);
|
font_color = font_color.from_hsv(item_rainbow->frequency * (item_rainbow->elapsed_time + ((p_ofs.x + off.x) / 50)), item_rainbow->saturation, item_rainbow->value, font_color.a);
|
||||||
|
} else if (item_fx->type == ITEM_PULSE) {
|
||||||
|
ItemPulse *item_pulse = static_cast<ItemPulse *>(item_fx);
|
||||||
|
|
||||||
|
const float sined_time = (Math::ease(Math::pingpong(item_pulse->elapsed_time, 1.0 / item_pulse->frequency) * item_pulse->frequency, item_pulse->ease));
|
||||||
|
font_color = font_color.lerp(font_color * item_pulse->color, sined_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1675,7 +1685,7 @@ void RichTextLabel::_update_fx(RichTextLabel::ItemFrame *p_frame, double p_delta
|
||||||
while (it) {
|
while (it) {
|
||||||
ItemFX *ifx = nullptr;
|
ItemFX *ifx = nullptr;
|
||||||
|
|
||||||
if (it->type == ITEM_CUSTOMFX || it->type == ITEM_SHAKE || it->type == ITEM_WAVE || it->type == ITEM_TORNADO || it->type == ITEM_RAINBOW) {
|
if (it->type == ITEM_CUSTOMFX || it->type == ITEM_SHAKE || it->type == ITEM_WAVE || it->type == ITEM_TORNADO || it->type == ITEM_RAINBOW || it->type == ITEM_PULSE) {
|
||||||
ifx = static_cast<ItemFX *>(it);
|
ifx = static_cast<ItemFX *>(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2616,7 +2626,7 @@ bool RichTextLabel::_find_strikethrough(Item *p_item) {
|
||||||
void RichTextLabel::_fetch_item_fx_stack(Item *p_item, Vector<ItemFX *> &r_stack) {
|
void RichTextLabel::_fetch_item_fx_stack(Item *p_item, Vector<ItemFX *> &r_stack) {
|
||||||
Item *item = p_item;
|
Item *item = p_item;
|
||||||
while (item) {
|
while (item) {
|
||||||
if (item->type == ITEM_CUSTOMFX || item->type == ITEM_SHAKE || item->type == ITEM_WAVE || item->type == ITEM_TORNADO || item->type == ITEM_RAINBOW) {
|
if (item->type == ITEM_CUSTOMFX || item->type == ITEM_SHAKE || item->type == ITEM_WAVE || item->type == ITEM_TORNADO || item->type == ITEM_RAINBOW || item->type == ITEM_PULSE) {
|
||||||
r_stack.push_back(static_cast<ItemFX *>(item));
|
r_stack.push_back(static_cast<ItemFX *>(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3480,6 +3490,17 @@ void RichTextLabel::push_rainbow(float p_saturation, float p_value, float p_freq
|
||||||
_add_item(item, true);
|
_add_item(item, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RichTextLabel::push_pulse(const Color &p_color, float p_frequency, float p_ease) {
|
||||||
|
_stop_thread();
|
||||||
|
MutexLock data_lock(data_mutex);
|
||||||
|
|
||||||
|
ItemPulse *item = memnew(ItemPulse);
|
||||||
|
item->color = p_color;
|
||||||
|
item->frequency = p_frequency;
|
||||||
|
item->ease = p_ease;
|
||||||
|
_add_item(item, true);
|
||||||
|
}
|
||||||
|
|
||||||
void RichTextLabel::push_bgcolor(const Color &p_color) {
|
void RichTextLabel::push_bgcolor(const Color &p_color) {
|
||||||
_stop_thread();
|
_stop_thread();
|
||||||
MutexLock data_lock(data_mutex);
|
MutexLock data_lock(data_mutex);
|
||||||
|
@ -4663,7 +4684,29 @@ void RichTextLabel::append_text(const String &p_bbcode) {
|
||||||
pos = brk_end + 1;
|
pos = brk_end + 1;
|
||||||
tag_stack.push_front("rainbow");
|
tag_stack.push_front("rainbow");
|
||||||
set_process_internal(true);
|
set_process_internal(true);
|
||||||
|
} else if (bbcode_name == "pulse") {
|
||||||
|
Color color = Color(1, 1, 1, 0.25);
|
||||||
|
OptionMap::Iterator color_option = bbcode_options.find("color");
|
||||||
|
if (color_option) {
|
||||||
|
color = Color::from_string(color_option->value, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
float frequency = 1.0;
|
||||||
|
OptionMap::Iterator freq_option = bbcode_options.find("freq");
|
||||||
|
if (freq_option) {
|
||||||
|
frequency = freq_option->value.to_float();
|
||||||
|
}
|
||||||
|
|
||||||
|
float ease = -2.0;
|
||||||
|
OptionMap::Iterator ease_option = bbcode_options.find("ease");
|
||||||
|
if (ease_option) {
|
||||||
|
ease = ease_option->value.to_float();
|
||||||
|
}
|
||||||
|
|
||||||
|
push_pulse(color, frequency, ease);
|
||||||
|
pos = brk_end + 1;
|
||||||
|
tag_stack.push_front("pulse");
|
||||||
|
set_process_internal(true);
|
||||||
} else if (tag.begins_with("bgcolor=")) {
|
} else if (tag.begins_with("bgcolor=")) {
|
||||||
String color_str = tag.substr(8, tag.length()).unquote();
|
String color_str = tag.substr(8, tag.length()).unquote();
|
||||||
Color color = Color::from_string(color_str, theme_cache.default_color);
|
Color color = Color::from_string(color_str, theme_cache.default_color);
|
||||||
|
|
|
@ -70,6 +70,7 @@ public:
|
||||||
ITEM_WAVE,
|
ITEM_WAVE,
|
||||||
ITEM_TORNADO,
|
ITEM_TORNADO,
|
||||||
ITEM_RAINBOW,
|
ITEM_RAINBOW,
|
||||||
|
ITEM_PULSE,
|
||||||
ITEM_BGCOLOR,
|
ITEM_BGCOLOR,
|
||||||
ITEM_FGCOLOR,
|
ITEM_FGCOLOR,
|
||||||
ITEM_META,
|
ITEM_META,
|
||||||
|
@ -343,6 +344,14 @@ private:
|
||||||
ItemRainbow() { type = ITEM_RAINBOW; }
|
ItemRainbow() { type = ITEM_RAINBOW; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ItemPulse : public ItemFX {
|
||||||
|
Color color = Color(1.0, 1.0, 1.0, 0.25);
|
||||||
|
float frequency = 1.0f;
|
||||||
|
float ease = -2.0f;
|
||||||
|
|
||||||
|
ItemPulse() { type = ITEM_PULSE; }
|
||||||
|
};
|
||||||
|
|
||||||
struct ItemBGColor : public Item {
|
struct ItemBGColor : public Item {
|
||||||
Color color;
|
Color color;
|
||||||
ItemBGColor() { type = ITEM_BGCOLOR; }
|
ItemBGColor() { type = ITEM_BGCOLOR; }
|
||||||
|
@ -610,6 +619,7 @@ public:
|
||||||
void push_wave(float p_frequency, float p_amplitude, bool p_connected);
|
void push_wave(float p_frequency, float p_amplitude, bool p_connected);
|
||||||
void push_tornado(float p_frequency, float p_radius, bool p_connected);
|
void push_tornado(float p_frequency, float p_radius, bool p_connected);
|
||||||
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_pulse(const Color &p_color, float p_frequency, float p_ease);
|
||||||
void push_bgcolor(const Color &p_color);
|
void push_bgcolor(const Color &p_color);
|
||||||
void push_fgcolor(const Color &p_color);
|
void push_fgcolor(const Color &p_color);
|
||||||
void push_customfx(Ref<RichTextEffect> p_custom_effect, Dictionary p_environment);
|
void push_customfx(Ref<RichTextEffect> p_custom_effect, Dictionary p_environment);
|
||||||
|
|
Loading…
Reference in a new issue