TimeWarp Controller for Maya
Art-direct slow motion in warped time. Ship it in real time. Never hand-fix a mistimed key again.
timewarpScale attribute
STEP 2 · YOU ARE HERE
TimeWarpController.py
Authors the slow motion and bakes speed onto timewarpScale
STEP 3
CamRigBake.py
Exports a clean world-space camera carrying timewarpScale to Unreal
Maya can play a scene back in slow motion. What it cannot do is let you animate a camera while it does. If you have ever tried, you already know something went wrong. You probably never found out what.
Maya's scene timewarp is a curve that maps warped time, what your timeline reads, to normalized time, where every animation curve in your scene actually lives. Put the playhead at warped frame 100 and Maya evaluates the scene at normalized frame 20. The viewport shows you frame 20. The timeline says 100.
The timewarp is applied on evaluation, not on authoring. So when you set a key on your camera, Maya stamps it at the current time, 100, into a curve that lives in normalized space, where 100 is a completely different moment in the shot. The pose you were looking at was frame 20. Your key just landed eighty frames from where you meant it.
There is no error and no warning. The key exists, it holds a real value, the curve looks populated. The offset scales with warp depth, so it is small early and enormous after a few slow-motion beats, which makes it read like drift or randomness instead of a systematic space mismatch. Without knowing the cause, this is close to undebuggable.
The rule this forces:
- Shape time in TIMEWARPED state. The only state where you can feel the slow motion you are directing.
- Animate the camera in NORMALIZED state. Identity curve, timeline frame equals curve frame, keys land where you put them.
- Review in TIMEWARPED state. Normalized-authored camera motion, played back through the warp. The actual shot.
Then loop. Done by hand, that is fragile and unforgiving, because normalizing the curve destroys the warp you just spent an hour building. This tool makes each phase a button.
One-click system setup. Builds the entire node network on first use: the timewarp curve, the control locator, the driving expression, and the state manager. Detects an existing timewarp and adopts it without touching your keys.
Slow motion by preset. Pick a duration from 3 to 8 frames and a scale from 8x to 36x, then apply at the playhead. Keys downstream shift automatically and the playback range extends to match. Delete a period and the gap closes cleanly behind it.
Two states, two buttons. Switch between TIMEWARPED and NORMALIZED at will. The tool tells you when you are already in the state you asked for, so you never double-flatten a curve by accident.
Auto-key the rig at every warp boundary. Propagates the warp's key times onto every keyable, non-driven channel of the selected rig. Times only, never values, so your camera pose is untouched and you simply gain keys marking exactly where the speed changes. It records your current state, forces NORMALIZED to do the work, and restores what you started with, even if something errors midway.
Dilation analysis. Outputs every normalized frame time with its playback speed to six decimals, in the Script Editor and in a scrollable window, without disturbing the state you were in.
Bake to camera or bake to bone. Write per-segment speed onto the rig camera's timewarpScale for Unreal, or onto a fresh root joint's scaleX for engines that read time scale from a bone. Both are non-destructive and both produce stepped keys at real-time positions.
Navigation that follows you between states. Previous and Next jump between warp periods and return the correct frame for whichever state you are in, warped starts when warped, normalized starts when normalized. The same button lands on the same dramatic beat either way.
Every decision below exists because someone tested this tool inside Maya. The most important ones came from builds that ran without error and were still wrong, because with two time spaces in play, code can read the wrong curve and produce results that look plausible. Only testing in Maya exposed those failures, and each fix became a rule below.
States persist as real nodes. Both the master warped curve and the normalized curve are stored as animCurveTT nodes wired to a hidden holder locator. Unconnected anim curves get garbage collected on save, and losing your master warp mid-shot is unrecoverable. This is the difference between a state system and a time bomb.
One speed calculation, two bakes. Segment math lives in a single function feeding both the bone bake and the camera bake, so a bone export and a camera export can never disagree about how fast frame 40 was moving.
The curve finder has four fallbacks. Including one through the control locator, because disabling the scene timewarp drops the time1.timewarpIn connection and a naive lookup goes blind. Navigation and analysis keep working with the warp switched off.
Editing operations are state-aware. Apply and delete both operate on the master warped curve regardless of which state you are looking at. That sounds obvious written down. It was not.
Sixteen hours and roughly fifty rounds of prompt, generate, test in Maya, diagnose, re-prompt. It is by far the longest of the three tools, and the reason is that most of those rounds were not spent building. They were spent finding out what was actually wrong.
The tool got caught by the exact trap it exists to manage. Applying a slow-motion period and deleting one both worked correctly in TIMEWARPED state and silently misbehaved in NORMALIZED, because the operations were reading whichever curve was currently live rather than always addressing the master warped curve. In normalized state that curve is an identity, so the edits landed in the wrong space. Nothing errored. It took several attempts to fix, and it is the reason apply and delete are now hard-wired to the master curve instead of to the current state.
That is the shape of the whole build. The code the model produced was rarely wrong on its face. It was wrong in Maya, in ways only visible by scrubbing a timeline and noticing a beat had moved. My job was to catch that, work out which of two time spaces the failure lived in, and explain it precisely enough for the model to act on. The AI wrote 1,169 lines. I wrote the diagnosis for each of about fifty failures, which is the work that actually took the time.
Baking requires TIMEWARPED state and stops with a message otherwise, because speed cannot be derived from an identity curve. Snap Keys to Integers alters timing and cannot be undone, so it confirms before running. The system uses fixed scene-level node names, meaning one timewarp system per scene, by design, since scene timewarp is itself a scene-level feature. Export in normalized time so the baked speed curve stays aligned with camera motion.
The trick was reframing "time-warp" as ordinary, bakeable data. Once slow-motion timing is just a keyed value on a camera, it stops being a Maya-only effect and becomes something any engine can read. Naming the right representation is most of the design.
The other lesson is about where AI assistance actually breaks down. A model can write a state machine correctly and still produce a tool that is wrong, because the code was addressing the wrong one of two time spaces. No amount of reading the output catches that. It only shows up when you run it, and only if you already know what correct looks like.
The script as it runs. Maya 2026, Python, no external dependencies.
Written by AI under my direction. Read it; that is the point.
Hands CamRigBake.py a camera whose timewarpScale is keyed in real time, with stepped tangents, ready to export.