diff options
author | RĂ©mi Verschelde <remi@verschelde.fr> | 2021-09-21 13:33:44 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-21 13:33:44 +0200 |
commit | 8085affdb109123f68059e37beb2236a1f94de1a (patch) | |
tree | 22bd3469568373217e94ebcd8c2368d2f3ce45fa /scene/gui | |
parent | 2717f583a4de73617fe8ae049e4313ac843d6bb0 (diff) | |
parent | c931906af71ffdc49dd10611bb4ac69febdca559 (diff) |
Merge pull request #52890 from bruvzg/rtl_effects_connected
Improve connected grapheme handling in the RTL CharFX.
Diffstat (limited to 'scene/gui')
-rw-r--r-- | scene/gui/rich_text_effect.cpp | 8 | ||||
-rw-r--r-- | scene/gui/rich_text_effect.h | 14 | ||||
-rw-r--r-- | scene/gui/rich_text_label.cpp | 104 | ||||
-rw-r--r-- | scene/gui/rich_text_label.h | 3 |
4 files changed, 103 insertions, 26 deletions
diff --git a/scene/gui/rich_text_effect.cpp b/scene/gui/rich_text_effect.cpp index 236d106af8..076fa132c0 100644 --- a/scene/gui/rich_text_effect.cpp +++ b/scene/gui/rich_text_effect.cpp @@ -90,6 +90,12 @@ void CharFXTransform::_bind_methods() { ClassDB::bind_method(D_METHOD("get_glyph_index"), &CharFXTransform::get_glyph_index); ClassDB::bind_method(D_METHOD("set_glyph_index", "glyph_index"), &CharFXTransform::set_glyph_index); + ClassDB::bind_method(D_METHOD("get_glyph_count"), &CharFXTransform::get_glyph_count); + ClassDB::bind_method(D_METHOD("set_glyph_count", "glyph_count"), &CharFXTransform::set_glyph_count); + + ClassDB::bind_method(D_METHOD("get_glyph_flags"), &CharFXTransform::get_glyph_flags); + ClassDB::bind_method(D_METHOD("set_glyph_flags", "glyph_flags"), &CharFXTransform::set_glyph_flags); + ClassDB::bind_method(D_METHOD("get_font"), &CharFXTransform::get_font); ClassDB::bind_method(D_METHOD("set_font", "font"), &CharFXTransform::set_font); @@ -101,5 +107,7 @@ void CharFXTransform::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color"); ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "env"), "set_environment", "get_environment"); ADD_PROPERTY(PropertyInfo(Variant::INT, "glyph_index"), "set_glyph_index", "get_glyph_index"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "glyph_count"), "set_glyph_count", "get_glyph_count"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "glyph_flags"), "set_glyph_flags", "get_glyph_flags"); ADD_PROPERTY(PropertyInfo(Variant::RID, "font"), "set_font", "get_font"); } diff --git a/scene/gui/rich_text_effect.h b/scene/gui/rich_text_effect.h index f5506542bb..5681f9b193 100644 --- a/scene/gui/rich_text_effect.h +++ b/scene/gui/rich_text_effect.h @@ -50,6 +50,8 @@ public: double elapsed_time = 0.0f; Dictionary environment; uint32_t glyph_index = 0; + uint16_t glyph_flags = 0; + uint8_t glyph_count = 0; RID font; CharFXTransform(); @@ -57,19 +59,31 @@ public: Vector2i get_range() { return range; } void set_range(const Vector2i &p_range) { range = p_range; } + double get_elapsed_time() { return elapsed_time; } void set_elapsed_time(double p_elapsed_time) { elapsed_time = p_elapsed_time; } + bool is_visible() { return visibility; } void set_visibility(bool p_visibility) { visibility = p_visibility; } + bool is_outline() { return outline; } void set_outline(bool p_outline) { outline = p_outline; } + Point2 get_offset() { return offset; } void set_offset(Point2 p_offset) { offset = p_offset; } + Color get_color() { return color; } void set_color(Color p_color) { color = p_color; } uint32_t get_glyph_index() const { return glyph_index; }; void set_glyph_index(uint32_t p_glyph_index) { glyph_index = p_glyph_index; }; + + uint16_t get_glyph_flags() const { return glyph_index; }; + void set_glyph_flags(uint16_t p_glyph_flags) { glyph_flags = p_glyph_flags; }; + + uint8_t get_glyph_count() const { return glyph_count; }; + void set_glyph_count(uint8_t p_glyph_count) { glyph_count = p_glyph_count; }; + RID get_font() const { return font; }; void set_font(RID p_font) { font = p_font; }; 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); diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 806f684b67..94f02a3989 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -267,6 +267,7 @@ private: float rate = 0.0f; uint64_t _current_rng = 0; uint64_t _previous_rng = 0; + Vector2 prev_off; ItemShake() { type = ITEM_SHAKE; } @@ -289,6 +290,7 @@ private: struct ItemWave : public ItemFX { float frequency = 1.0f; float amplitude = 1.0f; + Vector2 prev_off; ItemWave() { type = ITEM_WAVE; } }; @@ -296,6 +298,7 @@ private: struct ItemTornado : public ItemFX { float radius = 1.0f; float frequency = 1.0f; + Vector2 prev_off; ItemTornado() { type = ITEM_TORNADO; } }; |