[RTL] Add option to apply built-in effects to the individual connected glyphs.

This commit is contained in:
bruvzg 2022-09-18 22:20:48 +03:00
parent e5594c26b1
commit 46af7cbfdd
No known key found for this signature in database
GPG key ID: 7960FCF39844EC38
2 changed files with 51 additions and 23 deletions

View file

@ -965,17 +965,18 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
uint32_t gl = glyphs[i].index;
uint16_t gl_fl = glyphs[i].flags;
uint8_t gl_cn = glyphs[i].count;
bool cprev = false;
bool cprev_cluster = false;
bool cprev_conn = false;
if (gl_cn == 0) { // Parts of the same cluster, always connected.
cprev = true;
cprev_cluster = 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;
cprev_conn = true;
}
} else {
if (glyphs[i].flags & TextServer::GRAPHEME_IS_CONNECTED) {
cprev = true;
cprev_conn = true;
}
}
@ -994,6 +995,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
for (int j = 0; j < fx_stack.size(); j++) {
ItemFX *item_fx = fx_stack[j];
bool cn = cprev_cluster || (cprev_conn && item_fx->connected);
if (item_fx->type == ITEM_CUSTOMFX && custom_fx_ok) {
ItemCustomFX *item_custom = static_cast<ItemCustomFX *>(item_fx);
@ -1024,7 +1027,7 @@ 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);
if (!cprev) {
if (!cn) {
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;
@ -1038,7 +1041,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
} else if (item_fx->type == ITEM_WAVE) {
ItemWave *item_wave = static_cast<ItemWave *>(item_fx);
if (!cprev) {
if (!cn) {
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;
}
@ -1046,7 +1049,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
} else if (item_fx->type == ITEM_TORNADO) {
ItemTornado *item_tornado = static_cast<ItemTornado *>(item_fx);
if (!cprev) {
if (!cn) {
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);
@ -1181,17 +1184,18 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
uint32_t gl = glyphs[i].index;
uint16_t gl_fl = glyphs[i].flags;
uint8_t gl_cn = glyphs[i].count;
bool cprev = false;
bool cprev_cluster = false;
bool cprev_conn = false;
if (gl_cn == 0) { // Parts of the same grapheme cluster, always connected.
cprev = true;
cprev_cluster = 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;
cprev_conn = true;
}
} else {
if (glyphs[i].flags & TextServer::GRAPHEME_IS_CONNECTED) {
cprev = true;
cprev_conn = true;
}
}
@ -1209,6 +1213,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
for (int j = 0; j < fx_stack.size(); j++) {
ItemFX *item_fx = fx_stack[j];
bool cn = cprev_cluster || (cprev_conn && item_fx->connected);
if (item_fx->type == ITEM_CUSTOMFX && custom_fx_ok) {
ItemCustomFX *item_custom = static_cast<ItemCustomFX *>(item_fx);
@ -1239,7 +1245,7 @@ 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);
if (!cprev) {
if (!cn) {
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;
@ -1253,7 +1259,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
} else if (item_fx->type == ITEM_WAVE) {
ItemWave *item_wave = static_cast<ItemWave *>(item_fx);
if (!cprev) {
if (!cn) {
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;
}
@ -1261,7 +1267,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
} else if (item_fx->type == ITEM_TORNADO) {
ItemTornado *item_tornado = static_cast<ItemTornado *>(item_fx);
if (!cprev) {
if (!cn) {
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);
@ -3236,33 +3242,36 @@ void RichTextLabel::push_fade(int p_start_index, int p_length) {
_add_item(item, true);
}
void RichTextLabel::push_shake(int p_strength = 10, float p_rate = 24.0f) {
void RichTextLabel::push_shake(int p_strength = 10, float p_rate = 24.0f, bool p_connected = true) {
_stop_thread();
MutexLock data_lock(data_mutex);
ItemShake *item = memnew(ItemShake);
item->strength = p_strength;
item->rate = p_rate;
item->connected = p_connected;
_add_item(item, true);
}
void RichTextLabel::push_wave(float p_frequency = 1.0f, float p_amplitude = 10.0f) {
void RichTextLabel::push_wave(float p_frequency = 1.0f, float p_amplitude = 10.0f, bool p_connected = true) {
_stop_thread();
MutexLock data_lock(data_mutex);
ItemWave *item = memnew(ItemWave);
item->frequency = p_frequency;
item->amplitude = p_amplitude;
item->connected = p_connected;
_add_item(item, true);
}
void RichTextLabel::push_tornado(float p_frequency = 1.0f, float p_radius = 10.0f) {
void RichTextLabel::push_tornado(float p_frequency = 1.0f, float p_radius = 10.0f, bool p_connected = true) {
_stop_thread();
MutexLock data_lock(data_mutex);
ItemTornado *item = memnew(ItemTornado);
item->frequency = p_frequency;
item->radius = p_radius;
item->connected = p_connected;
_add_item(item, true);
}
@ -4265,7 +4274,13 @@ void RichTextLabel::append_text(const String &p_bbcode) {
rate = rate_option->value.to_float();
}
push_shake(strength, rate);
bool connected = true;
OptionMap::Iterator connected_option = bbcode_options.find("connected");
if (connected_option) {
connected = connected_option->value.to_int();
}
push_shake(strength, rate, connected);
pos = brk_end + 1;
tag_stack.push_front("shake");
set_process_internal(true);
@ -4282,7 +4297,13 @@ void RichTextLabel::append_text(const String &p_bbcode) {
period = period_option->value.to_float();
}
push_wave(period, amplitude);
bool connected = true;
OptionMap::Iterator connected_option = bbcode_options.find("connected");
if (connected_option) {
connected = connected_option->value.to_int();
}
push_wave(period, amplitude, connected);
pos = brk_end + 1;
tag_stack.push_front("wave");
set_process_internal(true);
@ -4299,7 +4320,13 @@ void RichTextLabel::append_text(const String &p_bbcode) {
frequency = frequency_option->value.to_float();
}
push_tornado(frequency, radius);
bool connected = true;
OptionMap::Iterator connected_option = bbcode_options.find("connected");
if (connected_option) {
connected = connected_option->value.to_int();
}
push_tornado(frequency, radius, connected);
pos = brk_end + 1;
tag_stack.push_front("tornado");
set_process_internal(true);

View file

@ -282,6 +282,7 @@ private:
struct ItemFX : public Item {
double elapsed_time = 0.f;
bool connected = true;
};
struct ItemShake : public ItemFX {
@ -590,9 +591,9 @@ public:
void push_hint(const String &p_string);
void push_table(int p_columns, InlineAlignment p_alignment = INLINE_ALIGNMENT_TOP);
void push_fade(int p_start_index, int p_length);
void push_shake(int p_strength, float p_rate);
void push_wave(float p_frequency, float p_amplitude);
void push_tornado(float p_frequency, float p_radius);
void push_shake(int p_strength, float p_rate, 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_rainbow(float p_saturation, float p_value, float p_frequency);
void push_bgcolor(const Color &p_color);
void push_fgcolor(const Color &p_color);