Skip to content

Search

Documentation

Text: text2d, text3d and the shaper

The text2d and text3d components: keys, outline and shadow, markup, script calls, measuring, bitmap fonts and what a block costs.

Trên trang này

text2d and text3d draw text in the scene. The widget layer draws text on the screen.

One shaper and one glyph atlas serve both: bidirectional text, Arabic joining, CJK and Thai line breaking and the project's font chain work the same in a panel and in the world.

Text, one row per thing it does

Two components

text2d draws in the 2D pass, sized like a sprite. text3d draws in the 3D pass on a quad facing the camera. They take the same keys.

[[nodes]]
id = "sign"
name = "Sign"

[nodes.transform]
position = [0.0, 1.6, 0.0]

[nodes.text3d]
text = "A score on a sign"
font_size = 64
color = [1.0, 0.85, 0.3, 1.0]
pixels_per_unit = 110
outline_size = 3.0
outline_color = [0.1, 0.05, 0.0, 1.0]
Key What it does
text The string drawn
text_key A key in the project's strings, re-read every frame
font_family Which font chain to shape with: ui, heading, mono or icon
bitmap_font A project-relative .fnt naming a bitmap face
font_size, font_weight, font_style Height in font pixels, 100–900, upright or italic
color, text_align Tint, and where the block sits across the node's origin
max_width, line_height, letter_spacing Wrapping width, baseline spacing, tracking
markup Read the text as markup
outline_size, outline_color An outline around the glyphs
shadow_offset_x, shadow_offset_y, shadow_color A shadow behind them
pixels_per_unit Font pixels to one world unit
  • Doubling font_size and pixels_per_unit together keeps the on-screen size and doubles the sharpness.
  • text3d adds billboard, double_sided, depth_test and alpha_cut.
  • billboard turns the block to the camera every frame. Off, the block stays in the node's own plane.

Markup

With markup = true the text takes the same tags as a widget's label: [b], [i], [color=#7fd4ff], [wave amp= freq=], [center], [right] and an inline [img=…]. A coloured run keeps its own colour over the block's.

Two more tags answer the pointer, which only a widget label can do: [url=target] calls that label's on_link with the target, and [hint=text] shows the text while the pointer rests on the span.

From a script

let node = scene::get_node("Hud/Score");
node.text2d.text = format!("{}", this.score);
render::draw_text_3d(x, y, z, "over a character", #{ font_size: 32.0, text_align: "center" });
render::draw_text_2d(x, y, "in the 2D pass", #{ font_size: 24.0 });
  • text2d.text and text3d.text change what a node draws.
  • draw_text_2d and draw_text_3d draw with no node, for one frame. Neither is recorded: a replay re-runs the script that drew.
  • The editor's Rig tool labels bones with draw_text_3d.

Measuring

let (w, h) = render::text_size("measure me", #{ font_size: 32.0 });
  • Returns the width and height a string shapes to, in font pixels.
  • Measured against the project's fonts and the bundled ones, never the machine's. Every platform answers the same.
  • A width is presentation. A script that writes one into state puts presentation in the digest. The same holds for a kind = "text" mesh, whose vertices are geometry with colliders fitted to them.

Bitmap fonts

[nodes.text2d]
text = "SCORE 1200"
bitmap_font = "fonts/pixel.fnt"
font_size = 32
  • bitmap_font names an AngelCode .fnt. The engine reads its page and every glyph's box, then lays the text out by advance and kerning.
  • Nothing is shaped: a bitmap font has one glyph per character and no contextual forms.
  • The page is copied into the same atlas as the rasterised glyphs. A bitmap glyph and a vector one are one texture and one draw.

Editing in the viewport

Double-click a text2d or text3d in the Scene workspace to open a field over it. Enter keeps the text, Escape drops it.

Cost

  • A block is one mesh per colour it draws in, plus one for the outline and one for the shadow.
  • Glyphs are rasterised at the size the block covers on screen, quantized to buckets 8.7% apart.
  • Walking towards a sign re-shapes it a few times. Two blocks at nearly the same size share their glyphs.
  • A glyph is scaled by up to 8.7% between buckets.

examples/text has all of it.