Reze Studio’s undo/redo system is built around a single insight: the studio needs to feel snappy during slider drags and keyframe moves — operations that fire dozens of updates per second — without creating hundreds of micro-entries in the history stack. It solves this with a commit/snapshot model: during a drag the live clip is mutated in place for zero-overhead previewing, and only when the gesture ends does the studio take a clean snapshot and push it onto the history stack. The result is one undo step per gesture, regardless of how many intermediate frames were painted.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/AmyangXYZ/reze-studio/llms.txt
Use this file to discover all available pages before exploring further.
Keyboard Shortcuts
| Key | Action |
|---|---|
Ctrl / ⌘ + Z | Undo last committed edit |
Ctrl / ⌘ + Shift + Z | Redo |
⌘ + Y | Redo (macOS alternate) |
What Goes on the History Stack
Only committed edits are recorded. A committed edit is any operation that callscommit() in context/studio-context.ts. That includes:
Pose changes
Releasing a rotation or translation slider, finishing a viewport gizmo drag — one entry per gesture.
Keyframe insert
Pressing the Insert button in the Properties Inspector or completing the first pose change at a frame with no existing keyframe.
Keyframe delete
Clicking Delete in the Properties Inspector or pressing the Delete key with a keyframe selected.
Keyframe move (retime)
Releasing a dragged diamond in the dopesheet — one entry regardless of drag distance.
Track Simplify
Running the keyframe-reduction algorithm on the selected bone track.
Track Clear
Wiping all keyframes from the selected bone track.
The Commit / Snapshot Model
The core problem the model solves is this: slider preview mutatesBoneKeyframe objects in place for performance (the engine shares the same track arrays). If undo simply kept the previous clip reference, it would point to an object whose values have already been overwritten by the preview. History would contain the current state, not the past state.
The solution is clipSnapshot — an immutable deep clone of the clip taken at the last commit boundary:
commit() is called:
- The incoming clip is finalised (frame count is extended if needed).
- A deep clone of the finalised clip is stored as the new
clipSnapshot. - The previous
clipSnapshot(the state before this edit) is pushed ontopast. futureis cleared — committing a new edit discards any redo history.
undo() is called:
- The last entry is popped from
past. - The current
clipSnapshotis prepended tofuture. - The popped snapshot is deep-cloned and set as the live
clip, and stored as the newclipSnapshot.
clip can be freely mutated during the next preview session without corrupting any history entry.
History Limit
past array is capped at 100 entries. When the 101st commit arrives, the oldest entry (past[0]) is dropped:
What Does NOT Go on the Stack
The rationale: VMD and PMX loads swap out the entire document and model simultaneously. Allowing undo back through a model swap would leave the animation in a state that references bones from a different model — the engine and inspector would desync. Clearing history on load keeps the store consistent.The past and future Arrays in Practice
Here is a walk-through of the state arrays across a typical editing session:
past and future is a deep clone — modifying the live clip during the next preview session never touches stored history.