reckfellENGINE

RichTextLabel: BBCode, user text and effects

A complete C# example: literal text, an allowed link, progressive reveal and a custom RichTextEffect.

On this page

Run the example

Add UiSampleStyle.cs, RichTextDemo.cs and BlueGlowEffect.cs. Attach RichTextDemo to a Control root, build and run with F6. The link changes local status, the slider reveals part of the text, the name retains entered tags literally and the formatted lower line uses a custom effect.

Formatting, a link and a literal name inside a narrow area

RichTextDemo.cs
C#
using Reckfell;

public partial class RichTextDemo : Control
{
    public RichTextLabel Info { get; private set; } = null!;
    public RichTextLabel Log { get; private set; } = null!;
    public Label Status { get; private set; } = null!;
    public int LinkCount { get; private set; }
    public BlueGlowEffect Effect { get; private set; } = null!;
    public override void _Ready()
    {
        UiSampleStyle.Prepare(this);
        var margin = new MarginContainer(); AddChild(margin); margin.SetAnchorsAndOffsetsPreset(LayoutPreset.FullRect, margin: 24);
        var column = new VBoxContainer(); margin.AddChild(column);
        Info = new RichTextLabel
        {
            BbcodeEnabled = true, FitContent = true, ScrollActive = false, Threaded = false,
            Text = "[url=docs]" + UiSampleStyle.Text("Документация", "Documentation") + "[/url]\n[b]Reckfell[/b]  [color=#668fff]C# UI[/color]",
            VisibleCharactersBehavior = TextServer.VisibleCharactersBehavior.CharsAfterShaping
        };
        column.AddChild(Info);
        Effect = new BlueGlowEffect(); Info.InstallEffect(Effect);
        Info.AppendText("\n[blueglow speed=2]" + UiSampleStyle.Text("Свой эффект", "Custom effect") + "[/blueglow]");
        var reveal = new HSlider { MinValue = 0, MaxValue = 1, Step = .01, Value = 1 }; column.AddChild(reveal);
        reveal.ValueChanged += value => SetReveal((float)value);
        Log = new RichTextLabel { BbcodeEnabled = true, SizeFlagsVertical = SizeFlags.ExpandFill, ScrollFollowing = true, Threaded = false }; column.AddChild(Log);
        Status = new Label { Text = UiSampleStyle.Text("Ссылка обрабатывается внутри примера", "The example handles its link locally") }; column.AddChild(Status);
        Info.MetaClicked += HandleMeta;
        AddName("[b]Player[/b]");
    }
    public void AddName(string text)
    {
        Log.PushColor(new Color(.4f, .6f, 1)); Log.AddText(UiSampleStyle.Text("Имя: ", "Name: ")); Log.Pop();
        Log.AddText(text); Log.Newline();
    }
    public void SetReveal(float ratio) { if (float.IsFinite(ratio)) Info.VisibleRatio = Mathf.Clamp(ratio, 0, 1); }
    private void HandleMeta(Variant data)
    {
        if (data.VariantType != Variant.Type.String || data.AsString() != "docs") return;
        LinkCount++; Status.Text = UiSampleStyle.Text("Выбрана документация", "Documentation selected");
    }
}
BlueGlowEffect.cs
C#
using Reckfell;

[Tool]
public partial class BlueGlowEffect : RichTextEffect
{
    [Export] public string bbcode { get; set; } = "blueglow";
    public int Calls { get; private set; }
    public override bool _ProcessCustomFX(CharFXTransform charFX)
    {
        Calls++;
        double speed = 2;
        if (charFX.Env.TryGetValue("speed", out Variant value) &&
            (value.VariantType == Variant.Type.Float || value.VariantType == Variant.Type.Int))
        {
            double requested = value.AsDouble();
            if (double.IsFinite(requested)) speed = System.Math.Clamp(requested, 0, 10);
        }
        Color color = charFX.Color;
        color.A *= (float)(.75 + .25 * System.Math.Cos(charFX.ElapsedTime * speed));
        color.R *= .5f; color.G *= .7f; charFX.Color = color;
        return true;
    }
}

Three ways to append

MethodBehavior
Text with BbcodeEnabledReplaces content and parses markup
AppendTextAppends BBCode markup
AddTextAppends ordinary text without parsing tags
PushColor/PushFont/PushMeta and PopEstablish context for subsequent additions; close each push

Pass player names/messages through AddText. Concatenating unchecked text into BBCode lets it alter formatting and link metadata. If external values must be embedded in markup, escape according to BBCode rules; HTML escaping is not a substitute. GetParsedText returns text without parsed tags from an already built document; it is not a universal arbitrary-BBCode validator/filter.

A link must not automatically execute an arbitrary command or URL. MetaClicked supplies a Variant; the example accepts only the string docs. Define allowed destinations/schemes and the intended action for external navigation.

Compact markup reference

PurposeMain tags / options
Styleb, i, u, s, code; appropriate fonts are needed
Colorcolor/bgcolor/fgcolor; named color or #RRGGBB/#RRGGBBAA
Font and sizefont, font_size; use an existing resource and reasonable size
Paragraphp, center, left, right, fill, indent; check direction/language/spacing on real text
Listsul/ol; numbering type and bullet configure presentation
Link / tooltipurl, hint; your handler defines link behavior
Imageimg; path, dimensions and vertical alignment; do not assume automatic network-address loading
Tabletable with column count, cell; borders, padding, backgrounds and cell bounds
Horizontal rulehr with thickness/color/width options
Literal bracketslb/rb inside trusted BBCode
Built-in animationpulse, wave, tornado, shake, fade, rainbow; frequency/amplitude/color options depend on the effect

Nest/close tags correctly and apply paragraph settings at paragraph level. A color tag does not establish readable contrast; wave does not change layout. See RichTextLabel API for full parameters and matching Push methods.

Reveal, scrolling and cost

VisibleRatio 0…1 controls a character fraction; 1 removes the limit. This is neither BBCode string length nor .NET string.Length. The example uses CharsAfterShaping; truncating before shaping can change wrapping/ligatures. A typewriter needs attention to graphemes, translation and script; glyph counts differ from Unicode-character counts.

FitContent sizes to content; ScrollActive enables internal scrolling. Choose a bounded region or external scrolling and check container dimensions. ScrollFollowing suits a log. Threaded allows background preparation, but completion/measurements need IsFinished/Finished; the example disables it for a small predictable document.

Avoid rebuilding a large Text through += every frame, which can reparse/reshape it. Append in batches, limit log size and profile tables, images, fallback fonts and effects. Each push/pop should leave the intended stack for the next batch.

A custom effect

BlueGlowEffect registers its name through bbcode; lowercase is the engine lookup contract. InstallEffect runs before the tag is added. Env contains parsed arguments; validate type/range. ElapsedTime is effect time, not delta. GlyphIndex is a font glyph index, not a Unicode code point; mapping to source text requires Range/shaping data. Avoid file I/O or expensive per-glyph work. Tool enables editor use; running the game example is checked separately.

Reckfell Engine documentationBack to top ↑
QUICK LINKSGetting startedEntity hierarchyC# & .NET 10Scenes and prefabs
Reckfell guides and full API K
reckfellENGINE
RECKFELL ACCOUNT

Sign in

Sign in to your Reckfell account.

One account for the entire Reckfell platform.