Rich Text Block's handle displaying not just text but inline images and/or widgets, links, combinations of styles, colors, sizes, fonts, localization support, and other features within a single text block. Rich Text Block's do not tick logic as they compute their results during the Paint pass of the widget.
@TODO Add graph visuals for this hierarchy
URichTextBlock
[Parent Class:UTextLayoutWidget
]: UMG implementation of the Rich Text Block.SRichTextBlock
[Parent Class:SWidget
]: Slate Widget implementation of the Rich Text Block.FDefaultRichTextMarkupParser
[Compendium Explanation]: The default implementation class of rich text markup parsing that handles parsing the inputtedFString
to be separated and returned as the parse results(TArray<FTextLineParseResults>
) and aFString
stripped of any markup.FRichTextLayoutMarshaller
[Compendium Explanation]: The marshaller that is used when creating the rich text block layout of this widget.ITextDecorator
[Compendium Explanation]: Decorators that handle parsing the source text to apply custom styling and features to the resulted text of this widget.
When constructed(occurs when the blueprint widget is recompiled in the editor) the rich text widget will cache designer inputted data for drawing in this execution order:
- Caches the markup parser(if applicable otherwise uses
FDefaultRichTextMarkupParser
if nothing is inputted). - Caches the text marshaller(if applicable otherwise uses
FRichTextLayoutMarshaller
if nothing is inputted). - Caches the optionally inputted decorator's within the marshaller.
- Caches the text layout[
FSlateTextBlockLayout
] and caches the marshaller within that text layout.
Within OnPaint
the rich text block goes through a more direct drawing phase that is more composed than split for code paths that occur on the CPU.
This occurs in the paint pass in this execution order in the rich text block widget:
- Starts the draw phase by calculating the geometry of the text block and its position on the screen from the cached text layout.
- Builds up paint data by routing to the cached text layout's
FSlateTextBlockLayout::OnPaint
to then route to FSlateTextLayout::OnPaint which handles the actual drawing. - Recalculate the layout now that the paint data is ready while accounting for wrapping.
- If the paint data is causing the new layout size to require the rich text widget to wrap, then invalidate the widget to fully populate the widget's geometry size change to the hierarchy.
This occurs in this execution order in slate text layout:
- Starts by figuring out if we're suppose to apply the disabled effect or not(causing the text to be at a lower opacity).
- Computes the scale factor of the widget so it scales within the layout.
- Setting up a lambda to check if a line of text is visible within the viewport(recommend studying this function for your own code implementations).
Taking into account horizontal & vertical culling using
FSlateRect::DoRectanglesIntersect
. This is to skip elements that don't need to be drawn as an optimization. - Iterates through each text line and track which layer (found via the text line) is the highest layer or not. This is to have each element layered correctly to account for other widgets.
- There is also checks to account for if the text should be cut off with Ellipsis(
...
). - You can also see a debug box for each line by enabling the console command
Slate.ShowTextDebugging 1
(this is noted in Main Compendium Page - Debug Console Commands). - Text overlay's are also included with this highest layer computation process via
FSlateTextLayout::OnPaintHighlights
.
- There is also checks to account for if the text should be cut off with Ellipsis(
- Outputs the highest layer ID to paint and draw.