Contents

The idle layer: bodies that act

Product audit 3 (docs/audits/product-audit-2026-10d.md, finding 6) found that faces act and bodies don't. Over Otto's four-second excited line in the cold open, the mouth flaps and the head turns a few degrees, but nothing below the neck moves for 96 frames. A held pose with a talking head is legitimate limited animation; a pose held for four seconds with nothing alive in it reads as a still.

The idle layer keeps every character in frame alive between and through its gestures: it breathes, shifts its weight every few seconds, glances about, leans into its lines and settles after each gesture. It stays subtle: a breath and a settle, never a jitter.

Where it lives

In the engine, as a function of the frame. RwActorSampler reads what it needs from the Timeline the compiler already writes (the speaking spans, the gestures, the walks, the expression keys and the breathing cycle) into the RwActorState, and RwPoseSolver poses it (RwIdle holds its signals). Nothing is remembered between frames, so the same Timeline draws the same frames in a render and in Studio, on the desktop and on the web (the web edition runs the same GDScript). No Timeline field was added. The compiler changed one value: a speaking span's intensity now carries the line's volume (a loud line +0.15, a shout +0.3, a soft one -0.15, a whisper -0.3), since that intensity is what drives the talking body.

A pose drawn on its own (a model sheet, the pose maker, a turntable, the silhouettes) has RwActorState.idle 0 and none of the idle layer: it keeps the pose as posed. A pose keyed by hand on the timeline (Timeline 1.37 Actor.poses) takes the idle layer out as it comes in: idle is one less the strongest keyed pose's weight, so a held pose is posed as it was made. The breathing goes on under it.

What it does

How Size
Breath The breathing cycle (Actor.breathing), and the breath a line takes: in before it (from half a second before, deeper for a harder line), out through it, back to the cycle over 0.6 s after the style's motion.idle.breathing; the chest rises 2.2 cm at full amplitude
Weight Every 4.2 s or so (each shift up to half that late, at a seeded moment) the weight goes over to the other foot, 55 to 100% of the way, over 1.1 s; standing, the hips slide over a planted foot and the free knee eases; seated, the body shifts over in the seat and drifts forward and back. Each line also starts with a shift (from half a second before it to half a second after) the style's motion.idle.fidget
Leaning into a line While talking (from a quarter second before the line to 0.6 s after it), the chest leans in and moves on the line's beats (about two a second), the shoulders lifting on them and hanging arms bending a little at the elbow more for an excited, angry or loud line
Settling After a gesture or a walk ends, the chest dips and comes back, the head keeping the eyes level, hanging arms swinging once, over 0.9 s the gesture's intensity
Eye darts Every 11 frames the eyes may flick to a glance near where they look, held; fewer while looking at something or talking the style's motion.idle.eyeDarts
Head The speaking accents nod harder on an excited line the expression's energy

Energy. Each emotion moves a body by its energy, from -1 (still: grief, fear) to 1 (excited): excited 1, angry 0.9, surprised 0.8, happy and determined 0.6, amused 0.5, annoyed 0.4, curious, smug and disgusted 0.3, neutral 0, deadpan, tender and embarrassed -0.3, bored -0.4, tired and worried -0.5, sad and afraid -0.8. A positive energy grows the lean, the beats and the head's accents; a negative one shrinks the whole idle layer, to about half in grief or fear.

The style. Everything but the breath is drawn at full size at motion.idle.fidget 0.2 (the demo's Saturday Morning) and scales with it, to none at 0. A style that leaves its idle dials out gets the blank style's (fidget 0.15, eye darts 0.1). No field was added.

Measuring it

node tools/body-check.ts <show> --episode <id> compiles the episode and runs the engine's probe command (RwBodyProbe): every frame played as a render plays it but not drawn, and for each character, where its floor point and each of its bones are on the picture, and its drawn head's box (head: hair and headwear with it, the box round the head's polygons as drawn; for a 3D figure, round every surface on its head bone, RwCharacterFigure.head_screen_rect), which core/test/engine-heads.test.ts holds the framing score's heads to. From that it reports (tools/lib/body-motion.ts):

  • Per speaking shot (a shot over a line spoken on screen, its speaker in the picture): the longest the speaker's body stays still, and how much the body and the face move a frame. A body is still while no point below its neck ranges over more than 1.25% of the picture's height, or 2 cm at its own scale where that is fewer pixels (a body small in a wide shot), measured from its own floor point and scale, so a camera move does not count. Before the idle layer Otto's breath moved his elbow 1.1% of the picture in his medium shot, and the audit saw that as still; this measure does too.
  • Per cued gesture: whether its hands are in the picture from its stroke to the end of its hold (or for 0.35 s after the stroke), and if not, whether its character is off camera or the frame's edge cuts the hands off. A crowd's reaction is one gesture, seen when three of its extras are (CROWD_SEEN): a viewer reads a cheer from a few cheering people in the picture, however many more cheer out of it.
  • With --pixels, the audit's own measure: every speaking shot drawn, and the mean change between frames, in levels, in the body's region of the picture against the face's.

It fails when a body stays still more than 2 s while its character talks, or a cued gesture is not seen.

Before and after

The cold open as it ships and The Salvage Claim directed by the heuristic director, at 1280x720 on lavapipe (2026-10-11). The longest still stretch of the speaker's body in each speaking shot, in seconds; over 2 s fails.

Episode Shot Line Before After
Cold open sh020 Otto, l01 (excited, loud) 3.46 1.08
sh040 Otto, l03 (curious) 1.92 1.21
sh050 Chief, l04 (deadpan) 1.67 1.33
sh060 Otto, l05 (excited, loud) 0.92 0.33
sh080 Chief, l06 (deadpan, soft) 2.13 0.92
The Salvage Claim sc01 sh030 Otto, l01 4.04 1.42
sc01 sh040 Chief, l02 2.00 1.08
sc01 sh050 Otto, l03 1.54 1.33
sc01 sh060 Chief, l04 (arms folded) 3.71 1.83
sc01 sh070 Chief, l05 0.42 0.42
sc02 sh040 Otto, l01 (walking) 0.08 0.08
sc02 sh050 Chief, l02 2.13 1.17
sc02 sh070 Otto, l03 1.08 0.67
sc02 sh080 Chief, l04 2.58 1.33
sc02 sh100 Chief, l05 1.33 0.71
sc02 sh110 Otto, l06 1.25 0.58
sc02 sh120 Chief, l07 1.54 1.00

The one gesture either episode cues out of the picture is The Salvage Claim's heuristic thumbs-up on Otto's first line, below the frame of a medium shot: gesture framing's to fix.

Faces that read as their feelings

The product audit's follow-up: June's afraid "GRANDPA!" in Night Ferry read as a delighted grin. The line carried surprised (the reading took "backs away, wide-eyed" as surprise; the staging-places branch reads a retreat with wide eyes as fear), and a face that neither smiles nor frowns opened its mouth into a D: the corners at the top over a deep bowl, which is how a grin is drawn. Such a mouth now opens rounded, its corners a quarter of the way down; a smile still opens into the D and a frown into an arch.

tools/faces-check.sh draws every emotion's face, at rest and shouting, for a few characters on one contact sheet (the demo cast, the showcase captains and the style swatch's character by default, or the character files given), and fails when fear, anger or grief draws a mouth that turns up in any lip-sync shape (RwFaces): an open mouth whose corners sit in the top 22% of its height, a shut one whose ends rise over its middle, or, under a walrus mustache, the mustache's ends lifted above where they hang on a neutral face. character/rw_expression_test.gd holds the same for the demo and showcase casts.