Concept: The Cinematic Preview Pipeline
The showcase feature is three decoupled roles joined by one struct. Your game implements a provider (what does the character look like?), a showcase scene hosts a director (apply that look to a stand), and the manager ferries FCrimsonLoadingCharacterInfo from one to the other at the right moment. The plugin never touches your equipment system, and your equipment system never knows a loading screen exists.
The flow on every show
ShowLoadingScreenfires (a condition became true - often the travel itself).- The manager queries the first local player for a provider:
PlayerController, thenPawn, then each Pawn component - first result with a valid leader mesh wins. - The result is cached (
GetCachedCharacterInfo) before the old world is torn down - by the time the widget exists, the pawn is usually gone. - Every actor in the current world implementing
ICrimsonLoadingCinematicInterfacereceivesOnLoadingScreenStarted(CharacterInfo). - The content-ready delegates broadcast the same struct to non-actor listeners.
- On hide, the same actors receive
OnLoadingScreenEnded(and the visibility delegates fire).
Cached vs live character info
| Getter | Source | Use when |
|---|---|---|
GetCachedCharacterInfo | Snapshot taken when the screen opened | Anywhere during loading - the pawn may already be destroyed |
GetLocalPlayerCharacterInfo | Live provider query right now | Outside loading - menus, character screens, pre-travel checks |
GetCachedCharacterInfo in BeginPlay when GetLoadingScreenDisplayStatus is true - the snapshot is exactly what the event would have delivered.Why a struct and not a pawn reference
During a non-seamless load the old world - pawn, equipment components, everything - is destroyed. A pointer to any of it would dangle. FCrimsonLoadingCharacterInfo copies out only what the showcase needs: mesh assets, material assets, an anim class, transforms. Assets outlive worlds, so the snapshot stays valid for the whole load. This is also why the provider is queried immediately at show time rather than when the widget appears.
Design rules encoded in the data
- Exactly one leader entry (
bIsLeader = true) - it drives the skeleton; the director callsSetLeaderPoseComponenton all others. - A null `Mesh` is meaningful: the slot exists but is empty (bare head), and the director hides that component rather than erroring.
AdditionalActorsare routed by yourActorTypeTagconvention (e.g.CrimsonShowcase.Actor.Mount) to pre-placed showcase actors - the plugin spawns nothing.- Only the first local player is showcased; split-screen players are ignored by design.
IsValid()/GetLeaderComponent()on the struct are C++ helpers; Blueprint checks theMeshComponentsarray directly (all fields are readable and writable).
Where the picture comes from
The director only poses the scene. Getting pixels onto the loading screen is the render-target pipeline: a SceneCapture2D in the showcase world writes to the render target named in Project Settings, bUseLivePreview keeps world rendering alive during the load, and the widget reads GetShowcaseRenderTarget into a dynamic material. See How-To: Live Render Target Preview for the setup and the world-survival constraint (seamless-travel transition map or always-loaded sublevel).