|
@@ -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);
|
|
|
|