diff options
Diffstat (limited to 'scene/gui/rich_text_label.cpp')
-rw-r--r-- | scene/gui/rich_text_label.cpp | 104 |
1 files changed, 78 insertions, 26 deletions
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 2314b7a1da..eb88570663 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -852,6 +852,21 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o Point2 fx_offset = Vector2(glyphs[i].x_off, glyphs[i].y_off); RID frid = glyphs[i].font_rid; uint32_t gl = glyphs[i].index; + uint16_t gl_fl = glyphs[i].flags; + uint8_t gl_cn = glyphs[i].count; + bool cprev = false; + if (gl_cn == 0) { // Parts of the same cluster, always connected. + cprev = true; + } + if (gl_fl & TextServer::GRAPHEME_IS_RTL) { // Check if previous grapheme cluster is connected. + if (i > 0 && (glyphs[i - 1].flags & TextServer::GRAPHEME_IS_CONNECTED)) { + cprev = true; + } + } else { + if (glyphs[i].flags & TextServer::GRAPHEME_IS_CONNECTED) { + cprev = true; + } + } //Apply fx. float faded_visibility = 1.0f; @@ -880,6 +895,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o charfx->outline = true; charfx->font = frid; charfx->glyph_index = gl; + charfx->glyph_flags = gl_fl; + charfx->glyph_count = gl_cn; charfx->offset = fx_offset; charfx->color = font_color; @@ -895,25 +912,34 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o } else if (item_fx->type == ITEM_SHAKE) { ItemShake *item_shake = static_cast<ItemShake *>(item_fx); - uint64_t char_current_rand = item_shake->offset_random(glyphs[i].start); - uint64_t char_previous_rand = item_shake->offset_previous_random(glyphs[i].start); - uint64_t max_rand = 2147483647; - double current_offset = Math::range_lerp(char_current_rand % max_rand, 0, max_rand, 0.0f, 2.f * (float)Math_PI); - double previous_offset = Math::range_lerp(char_previous_rand % max_rand, 0, max_rand, 0.0f, 2.f * (float)Math_PI); - double n_time = (double)(item_shake->elapsed_time / (0.5f / item_shake->rate)); - n_time = (n_time > 1.0) ? 1.0 : n_time; - fx_offset += Point2(Math::lerp(Math::sin(previous_offset), Math::sin(current_offset), n_time), Math::lerp(Math::cos(previous_offset), Math::cos(current_offset), n_time)) * (float)item_shake->strength / 10.0f; + if (!cprev) { + uint64_t char_current_rand = item_shake->offset_random(glyphs[i].start); + uint64_t char_previous_rand = item_shake->offset_previous_random(glyphs[i].start); + uint64_t max_rand = 2147483647; + double current_offset = Math::range_lerp(char_current_rand % max_rand, 0, max_rand, 0.0f, 2.f * (float)Math_PI); + double previous_offset = Math::range_lerp(char_previous_rand % max_rand, 0, max_rand, 0.0f, 2.f * (float)Math_PI); + double n_time = (double)(item_shake->elapsed_time / (0.5f / item_shake->rate)); + n_time = (n_time > 1.0) ? 1.0 : n_time; + item_shake->prev_off = Point2(Math::lerp(Math::sin(previous_offset), Math::sin(current_offset), n_time), Math::lerp(Math::cos(previous_offset), Math::cos(current_offset), n_time)) * (float)item_shake->strength / 10.0f; + } + fx_offset += item_shake->prev_off; } 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 + off.x) / 50)) * (item_wave->amplitude / 10.0f); - fx_offset += Point2(0, 1) * value; + if (!cprev) { + double value = Math::sin(item_wave->frequency * item_wave->elapsed_time + ((p_ofs.x + gloff.x) / 50)) * (item_wave->amplitude / 10.0f); + item_wave->prev_off = Point2(0, 1) * value; + } + fx_offset += item_wave->prev_off; } 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 + gloff.x) / 50)) * (item_tornado->radius); - double torn_y = Math::cos(item_tornado->frequency * item_tornado->elapsed_time + ((p_ofs.x + gloff.x) / 50)) * (item_tornado->radius); - fx_offset += Point2(torn_x, torn_y); + if (!cprev) { + double torn_x = Math::sin(item_tornado->frequency * item_tornado->elapsed_time + ((p_ofs.x + gloff.x) / 50)) * (item_tornado->radius); + double torn_y = Math::cos(item_tornado->frequency * item_tornado->elapsed_time + ((p_ofs.x + gloff.x) / 50)) * (item_tornado->radius); + item_tornado->prev_off = Point2(torn_x, torn_y); + } + fx_offset += item_tornado->prev_off; } else if (item_fx->type == ITEM_RAINBOW) { ItemRainbow *item_rainbow = static_cast<ItemRainbow *>(item_fx); @@ -1004,6 +1030,21 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o Point2 fx_offset = Vector2(glyphs[i].x_off, glyphs[i].y_off); RID frid = glyphs[i].font_rid; uint32_t gl = glyphs[i].index; + uint16_t gl_fl = glyphs[i].flags; + uint8_t gl_cn = glyphs[i].count; + bool cprev = false; + if (gl_cn == 0) { // Parts of the same grapheme cluster, always connected. + cprev = true; + } + if (gl_fl & TextServer::GRAPHEME_IS_RTL) { // Check if previous grapheme cluster is connected. + if (i > 0 && (glyphs[i - 1].flags & TextServer::GRAPHEME_IS_CONNECTED)) { + cprev = true; + } + } else { + if (glyphs[i].flags & TextServer::GRAPHEME_IS_CONNECTED) { + cprev = true; + } + } //Apply fx. float faded_visibility = 1.0f; @@ -1032,6 +1073,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o charfx->outline = false; charfx->font = frid; charfx->glyph_index = gl; + charfx->glyph_flags = gl_fl; + charfx->glyph_count = gl_cn; charfx->offset = fx_offset; charfx->color = font_color; @@ -1047,25 +1090,34 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o } else if (item_fx->type == ITEM_SHAKE) { ItemShake *item_shake = static_cast<ItemShake *>(item_fx); - uint64_t char_current_rand = item_shake->offset_random(glyphs[i].start); - uint64_t char_previous_rand = item_shake->offset_previous_random(glyphs[i].start); - uint64_t max_rand = 2147483647; - double current_offset = Math::range_lerp(char_current_rand % max_rand, 0, max_rand, 0.0f, 2.f * (float)Math_PI); - double previous_offset = Math::range_lerp(char_previous_rand % max_rand, 0, max_rand, 0.0f, 2.f * (float)Math_PI); - double n_time = (double)(item_shake->elapsed_time / (0.5f / item_shake->rate)); - n_time = (n_time > 1.0) ? 1.0 : n_time; - fx_offset += Point2(Math::lerp(Math::sin(previous_offset), Math::sin(current_offset), n_time), Math::lerp(Math::cos(previous_offset), Math::cos(current_offset), n_time)) * (float)item_shake->strength / 10.0f; + if (!cprev) { + uint64_t char_current_rand = item_shake->offset_random(glyphs[i].start); + uint64_t char_previous_rand = item_shake->offset_previous_random(glyphs[i].start); + uint64_t max_rand = 2147483647; + double current_offset = Math::range_lerp(char_current_rand % max_rand, 0, max_rand, 0.0f, 2.f * (float)Math_PI); + double previous_offset = Math::range_lerp(char_previous_rand % max_rand, 0, max_rand, 0.0f, 2.f * (float)Math_PI); + double n_time = (double)(item_shake->elapsed_time / (0.5f / item_shake->rate)); + n_time = (n_time > 1.0) ? 1.0 : n_time; + item_shake->prev_off = Point2(Math::lerp(Math::sin(previous_offset), Math::sin(current_offset), n_time), Math::lerp(Math::cos(previous_offset), Math::cos(current_offset), n_time)) * (float)item_shake->strength / 10.0f; + } + fx_offset += item_shake->prev_off; } 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 + off.x) / 50)) * (item_wave->amplitude / 10.0f); - fx_offset += Point2(0, 1) * value; + if (!cprev) { + double value = Math::sin(item_wave->frequency * item_wave->elapsed_time + ((p_ofs.x + off.x) / 50)) * (item_wave->amplitude / 10.0f); + item_wave->prev_off = Point2(0, 1) * value; + } + fx_offset += item_wave->prev_off; } 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 + off.x) / 50)) * (item_tornado->radius); - double torn_y = Math::cos(item_tornado->frequency * item_tornado->elapsed_time + ((p_ofs.x + off.x) / 50)) * (item_tornado->radius); - fx_offset += Point2(torn_x, torn_y); + if (!cprev) { + double torn_x = Math::sin(item_tornado->frequency * item_tornado->elapsed_time + ((p_ofs.x + off.x) / 50)) * (item_tornado->radius); + double torn_y = Math::cos(item_tornado->frequency * item_tornado->elapsed_time + ((p_ofs.x + off.x) / 50)) * (item_tornado->radius); + item_tornado->prev_off = Point2(torn_x, torn_y); + } + fx_offset += item_tornado->prev_off; } else if (item_fx->type == ITEM_RAINBOW) { ItemRainbow *item_rainbow = static_cast<ItemRainbow *>(item_fx); |