Entity display: name, colour, portrait
The entity palette resolves a speaker once — and colour is user data, so a game asks whether there is one rather than assuming.
All documentation — Playing a story
Start here
Concepts
Authoring for a build
Playing a story
The generated assets and code
The plugin and sync
On this page
An entity reference on a step arrives already looked up. The session’s entity palette is the one place that turns it into the three things a game actually draws: a name, a colour, and a portrait.
#include "TaleShardEntityDisplay.h"#include "TaleShardSession.h"#include "TaleShardStepTypes.h"
namespace TaleShardDocSamples{ // The speaker's name and colour, as one line of text. FString DescribeSpeaker(UTaleShardSession* Session, const FTaleShardResolvedActor& Actor) { // The one place that decides what a speaker looks like, so a game never reads the raw // entity fields for this. const FTaleShardEntityDisplay Display = Session->GetEntityPalette()->Of(Actor);
// Colour is user data: an author may leave it unset, and bHasColor is how you find out. // Color Or takes your own fallback rather than inventing one. const FLinearColor Tint = UTaleShardEntityPalette::ColorOr(Display, FLinearColor::White);
return Display.Name + TEXT(" ") + Tint.ToFColor(true).ToHex(); }}In Blueprint: Get Entity Palette on the session, then Of with an actor from Get Cast. Use it rather than reading the entity’s raw fields. Every entity carries a small set of intrinsics — name, code, colour, voice, description, portrait — under reserved keys, and those are what make a shipped preset possible: a binding to a custom field code binds one that may exist in no project, while a binding to an intrinsic works everywhere.
$voice is the code of the voice this character is cast to, and it is absent when they are uncast.
It is what answers which voice speaks this line with no naming convention: the speaker is already
resolved per step, so the voice for a line is the speaker’s — which is why a voice clip on a step
carries that code rather than making you look it up. $description and $portrait are absent the
same way, when nothing was written and when no picture is set.
Four ways in
| Read | Takes | Use it for |
|---|---|---|
| Of | an actor from Get Cast | the speaker, and everyone else on stage. No lookup |
| Of Entity | an entity from a field read | an entity reached through Get Entity |
| By Code | a TaleShard.Entity.<Code> tag | a portrait gallery, a codex — anything not driven by a step |
| By Id | an id string | what a payload reference and a mention carry |
What a display carries
| Pin | Meaning |
|---|---|
| Name | the name to draw: overlaid, language-resolved, current. The code is never substituted for it |
| Code | the author’s code — unchanged when the entity’s name changes, and what a tag carries. Renaming the code itself makes a new code |
| Has Color | false means the author chose no colour. Not that they chose black, and not that the string was unreadable, which Color Outcome tells apart |
| Color, Color Hex | the colour to draw, after the policy. White when there is none — the identity tint, not a value to treat as authored |
| Color Outcome | what the contrast policy did, so a host can surface it |
| Has Portrait, Portrait | the entity’s portrait as the payload’s own media reference |
| Is Action | the entity is an input action — see below. Code is then the action’s code |
An entity that is an input action
A project can declare its input actions as records — Crouch, Interact — whose definition says a
mention of them draws as a keycap. Is Action tells you an entity is one, and its Code is the
name your game maps to its own input action; the record’s Name is the action in the player’s
language. Every read of the palette sets it — Of, Of Entity, By Code, By Id and Resolve Mention —
because the palette reads it off the entity’s definition in the payload. FTaleShardEntityDisplay::Of
called on its own cannot see the payload unless you pass it as the third argument, and answers false
without it.
A mention of such a record is drawn by your own code: the palette marks it as an action and leaves the binding to you, so a rebind reaches every prompt. How to answer it, and how a glyph is treated, are on drawing a line of text.
Colour is user data
Inventing a colour is worse than it sounds. A game that substitutes its own accent for an unset entity colour will show two characters in the same colour and imply a relationship the author did not author.
Contrast
By default the palette hands you the author’s colour untouched and unmeasured. Tell it what it is drawing on with Set Readable On — a background hex and a minimum contrast — and every display it produces afterwards carries a colour adjusted to be readable there, with Color Outcome saying what was done. Set Contrast Off returns to the default.
The outcome is reported rather than hidden because a silently corrected colour is a colour the author did not pick, with nothing on screen saying so. Surface it in a debug view; leave it out of the game.
Portraits
The portrait arrives as a media reference, not as a loaded asset. Resolve it through the media library and load it with the Load Media action; loading is yours, and that is deliberate — when and whether to load is a game’s decision, and a plugin that loaded eagerly would make it for you at the worst possible moment.
Next
Implementing commands — how a story makes your game do something.