summaryrefslogtreecommitdiff
path: root/scene/gui
diff options
context:
space:
mode:
authorbruvzg <7645683+bruvzg@users.noreply.github.com>2021-09-21 12:27:06 +0300
committerbruvzg <7645683+bruvzg@users.noreply.github.com>2021-09-21 13:51:38 +0300
commitc931906af71ffdc49dd10611bb4ac69febdca559 (patch)
treeaea90b48be5e295df1a004ecbb62edfaab2a259b /scene/gui
parenta412011be7ebe5e0147b61ea37c08e4ab109a57a (diff)
Add flag to connected grapheme. Apply RTL displacement FX only to the whole connected grapheme. Pass more glyph info to the custom RTL FX.
Diffstat (limited to 'scene/gui')
-rw-r--r--scene/gui/rich_text_effect.cpp8
-rw-r--r--scene/gui/rich_text_effect.h14
-rw-r--r--scene/gui/rich_text_label.cpp104
-rw-r--r--scene/gui/rich_text_label.h3
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; }
};