Skip to content

Commit bca435b

Browse files
committed
Add transform support to CharFXTransform
Use absolute transforms for CharFX fix formatting
1 parent b816dd3 commit bca435b

5 files changed

Lines changed: 67 additions & 18 deletions

File tree

doc/classes/CharFXTransform.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@
4949
<member name="relative_index" type="int" setter="set_relative_index" getter="get_relative_index" default="0">
5050
The character offset of the glyph, relative to the current [RichTextEffect] custom block. Setting this property won't affect drawing.
5151
</member>
52+
<member name="transform" type="Transform2D" setter="set_transform" getter="get_transform" default="Transform2D(1, 0, 0, 1, 0, 0)">
53+
The current transform of the current glyph. It can be overridden (for example, by driving the position and rotation from a curve). You can also alter the existing value to apply transforms on top of other effects.
54+
</member>
5255
<member name="visible" type="bool" setter="set_visibility" getter="is_visible" default="true">
5356
If [code]true[/code], the character will be drawn. If [code]false[/code], the character will be hidden. Characters around hidden characters will reflow to take the space of hidden characters. If this is not desired, set their [member color] to [code]Color(1, 1, 1, 0)[/code] instead.
5457
</member>

scene/gui/rich_text_effect.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ RichTextEffect::RichTextEffect() {
6464
}
6565

6666
void CharFXTransform::_bind_methods() {
67+
ClassDB::bind_method(D_METHOD("get_transform"), &CharFXTransform::get_transform);
68+
ClassDB::bind_method(D_METHOD("set_transform", "transform"), &CharFXTransform::set_transform);
69+
6770
ClassDB::bind_method(D_METHOD("get_range"), &CharFXTransform::get_range);
6871
ClassDB::bind_method(D_METHOD("set_range", "range"), &CharFXTransform::set_range);
6972

@@ -100,6 +103,7 @@ void CharFXTransform::_bind_methods() {
100103
ClassDB::bind_method(D_METHOD("get_font"), &CharFXTransform::get_font);
101104
ClassDB::bind_method(D_METHOD("set_font", "font"), &CharFXTransform::set_font);
102105

106+
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform"), "set_transform", "get_transform");
103107
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "range"), "set_range", "get_range");
104108
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "elapsed_time"), "set_elapsed_time", "get_elapsed_time");
105109
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visibility", "is_visible");

scene/gui/rich_text_effect.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class CharFXTransform : public RefCounted {
4242
static void _bind_methods();
4343

4444
public:
45+
Transform2D transform;
4546
Vector2i range;
4647
bool visibility = true;
4748
bool outline = false;
@@ -58,6 +59,9 @@ class CharFXTransform : public RefCounted {
5859
CharFXTransform();
5960
~CharFXTransform();
6061

62+
void set_transform(const Transform2D &p_transform) { transform = p_transform; }
63+
const Transform2D &get_transform() { return transform; }
64+
6165
Vector2i get_range() { return range; }
6266
void set_range(const Vector2i &p_range) { range = p_range; }
6367

scene/gui/rich_text_label.cpp

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "core/os/os.h"
3737
#include "core/string/translation.h"
3838
#include "scene/gui/label.h"
39+
#include "scene/gui/rich_text_effect.h"
3940
#include "scene/resources/atlas_texture.h"
4041
#include "scene/scene_string_names.h"
4142
#include "servers/display_server.h"
@@ -45,6 +46,18 @@
4546
#include "modules/regex/regex.h"
4647
#endif
4748

49+
RichTextLabel::ItemCustomFX::ItemCustomFX() {
50+
type = ITEM_CUSTOMFX;
51+
char_fx_transform.instantiate();
52+
}
53+
54+
RichTextLabel::ItemCustomFX::~ItemCustomFX() {
55+
_clear_children();
56+
57+
char_fx_transform.unref();
58+
custom_effect.unref();
59+
}
60+
4861
RichTextLabel::Item *RichTextLabel::_get_next_item(Item *p_item, bool p_free) const {
4962
if (p_free) {
5063
if (p_item->subitems.size()) {
@@ -1030,6 +1043,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
10301043
}
10311044

10321045
bool txt_visible = (font_outline_color.a != 0) || (font_shadow_color.a != 0);
1046+
Transform2D char_xform;
1047+
char_xform.set_origin(gloff + p_ofs);
10331048

10341049
for (int j = 0; j < fx_stack.size(); j++) {
10351050
ItemFX *item_fx = fx_stack[j];
@@ -1053,10 +1068,12 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
10531068
charfx->glyph_count = gl_cn;
10541069
charfx->offset = fx_offset;
10551070
charfx->color = font_color;
1071+
charfx->transform = char_xform;
10561072

10571073
bool effect_status = custom_effect->_process_effect_impl(charfx);
10581074
custom_fx_ok = effect_status;
10591075

1076+
char_xform = charfx->transform;
10601077
fx_offset += charfx->offset;
10611078
font_color = charfx->color;
10621079
frid = charfx->font;
@@ -1110,6 +1127,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
11101127
fx_offset = fx_offset.round();
11111128
}
11121129

1130+
Vector2i char_off = char_xform.get_origin();
1131+
11131132
// Draw glyph outlines.
11141133
const Color modulated_outline_color = font_outline_color * Color(1, 1, 1, font_color.a);
11151134
const Color modulated_shadow_color = font_shadow_color * Color(1, 1, 1, font_color.a);
@@ -1118,20 +1137,32 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
11181137
bool skip = (trim_chars && l.char_offset + glyphs[i].end > visible_characters) || (trim_glyphs_ltr && (processed_glyphs_ol >= visible_glyphs)) || (trim_glyphs_rtl && (processed_glyphs_ol < total_glyphs - visible_glyphs));
11191138
if (!skip && frid != RID()) {
11201139
if (modulated_shadow_color.a > 0) {
1121-
TS->font_draw_glyph(frid, ci, glyphs[i].font_size, p_ofs + fx_offset + gloff + p_shadow_ofs, gl, modulated_shadow_color);
1122-
}
1123-
if (modulated_shadow_color.a > 0 && p_shadow_outline_size > 0) {
1124-
TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, p_shadow_outline_size, p_ofs + fx_offset + gloff + p_shadow_ofs, gl, modulated_shadow_color);
1140+
Transform2D char_reverse_xform;
1141+
char_reverse_xform.set_origin(-char_off - p_shadow_ofs);
1142+
Transform2D char_final_xform = char_xform * char_reverse_xform;
1143+
char_final_xform.columns[2] += p_shadow_ofs;
1144+
draw_set_transform_matrix(char_final_xform);
1145+
1146+
TS->font_draw_glyph(frid, ci, glyphs[i].font_size, fx_offset + char_off + p_shadow_ofs, gl, modulated_shadow_color);
1147+
if (p_shadow_outline_size > 0) {
1148+
TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, p_shadow_outline_size, fx_offset + char_off + p_shadow_ofs, gl, modulated_shadow_color);
1149+
}
11251150
}
11261151
if (modulated_outline_color.a != 0.0 && size > 0) {
1127-
TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, size, p_ofs + fx_offset + gloff, gl, modulated_outline_color);
1152+
Transform2D char_reverse_xform;
1153+
char_reverse_xform.set_origin(-char_off);
1154+
Transform2D char_final_xform = char_xform * char_reverse_xform;
1155+
draw_set_transform_matrix(char_final_xform);
1156+
1157+
TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, size, fx_offset + char_off, gl, modulated_outline_color);
11281158
}
11291159
}
11301160
processed_glyphs_ol++;
11311161
}
11321162
gloff.x += glyphs[i].advance;
11331163
}
11341164
}
1165+
draw_set_transform_matrix(Transform2D());
11351166

11361167
Vector2 fbg_line_off = off + p_ofs;
11371168
// Draw background color box
@@ -1258,6 +1289,9 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
12581289

12591290
bool txt_visible = (font_color.a != 0);
12601291

1292+
Transform2D char_xform;
1293+
char_xform.set_origin(p_ofs + off);
1294+
12611295
for (int j = 0; j < fx_stack.size(); j++) {
12621296
ItemFX *item_fx = fx_stack[j];
12631297
bool cn = cprev_cluster || (cprev_conn && item_fx->connected);
@@ -1280,10 +1314,12 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
12801314
charfx->glyph_count = gl_cn;
12811315
charfx->offset = fx_offset;
12821316
charfx->color = font_color;
1317+
charfx->transform = char_xform;
12831318

12841319
bool effect_status = custom_effect->_process_effect_impl(charfx);
12851320
custom_fx_ok = effect_status;
12861321

1322+
char_xform = charfx->transform;
12871323
fx_offset += charfx->offset;
12881324
font_color = charfx->color;
12891325
frid = charfx->font;
@@ -1337,6 +1373,12 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
13371373
fx_offset = fx_offset.round();
13381374
}
13391375

1376+
Vector2i char_off = char_xform.get_origin();
1377+
Transform2D char_reverse_xform;
1378+
char_reverse_xform.set_origin(-char_off);
1379+
char_xform = char_xform * char_reverse_xform;
1380+
draw_set_transform_matrix(char_xform);
1381+
13401382
if (selected && use_selected_font_color) {
13411383
font_color = theme_cache.font_selected_color;
13421384
}
@@ -1347,9 +1389,9 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
13471389
if (txt_visible) {
13481390
if (!skip) {
13491391
if (frid != RID()) {
1350-
TS->font_draw_glyph(frid, ci, glyphs[i].font_size, p_ofs + fx_offset + off, gl, font_color);
1392+
TS->font_draw_glyph(frid, ci, glyphs[i].font_size, fx_offset + char_off, gl, font_color);
13511393
} else if (((glyphs[i].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) && ((glyphs[i].flags & TextServer::GRAPHEME_IS_EMBEDDED_OBJECT) != TextServer::GRAPHEME_IS_EMBEDDED_OBJECT)) {
1352-
TS->draw_hex_code_box(ci, glyphs[i].font_size, p_ofs + fx_offset + off, gl, font_color);
1394+
TS->draw_hex_code_box(ci, glyphs[i].font_size, fx_offset + char_off, gl, font_color);
13531395
}
13541396
}
13551397
r_processed_glyphs++;
@@ -1377,6 +1419,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
13771419
}
13781420
off.x += glyphs[i].advance;
13791421
}
1422+
1423+
draw_set_transform_matrix(Transform2D());
13801424
}
13811425
if (ul_started) {
13821426
ul_started = false;

scene/gui/rich_text_label.h

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@
3333

3434
#include "core/object/worker_thread_pool.h"
3535
#include "scene/gui/popup_menu.h"
36-
#include "scene/gui/rich_text_effect.h"
3736
#include "scene/gui/scroll_bar.h"
3837
#include "scene/resources/text_paragraph.h"
3938

39+
class CharFXTransform;
40+
class RichTextEffect;
41+
4042
class RichTextLabel : public Control {
4143
GDCLASS(RichTextLabel, Control);
4244

@@ -367,17 +369,9 @@ class RichTextLabel : public Control {
367369
Ref<CharFXTransform> char_fx_transform;
368370
Ref<RichTextEffect> custom_effect;
369371

370-
ItemCustomFX() {
371-
type = ITEM_CUSTOMFX;
372-
char_fx_transform.instantiate();
373-
}
374-
375-
virtual ~ItemCustomFX() {
376-
_clear_children();
372+
ItemCustomFX();
377373

378-
char_fx_transform.unref();
379-
custom_effect.unref();
380-
}
374+
virtual ~ItemCustomFX();
381375
};
382376

383377
struct ItemContext : public Item {

0 commit comments

Comments
 (0)