UsdLayerManager/openspec/changes/undo-redo-scene-editing/specs/command-history/spec.md

3.5 KiB

ADDED Requirements

Requirement: ICommand interface

The system SHALL provide an ICommand pure-virtual interface with Execute(), Undo(), and GetDescription() methods that all reversible operations implement.

Scenario: Execute runs the operation

  • WHEN ICommand::Execute() is called on a newly created command
  • THEN the operation is applied to the USD stage and the scene reflects the new state

Scenario: Undo reverses the operation

  • WHEN ICommand::Undo() is called after Execute()
  • THEN the USD stage returns to the state it was in before Execute() was called

Requirement: CommandHistory stack management

The system SHALL maintain two stacks (undo stack, redo stack). Push(cmd) executes the command, pushes it onto the undo stack, and clears the redo stack. Undo() pops from the undo stack, calls Undo() on the command, and pushes it onto the redo stack. Redo() pops from the redo stack, calls Execute() on the command, and pushes it back onto the undo stack.

Scenario: Push clears redo stack

  • WHEN the user undoes two steps and then makes a new edit
  • THEN the redo stack is cleared and the new command is the top of the undo stack

Scenario: Undo with empty stack is a no-op

  • WHEN CommandHistory::Undo() is called and the undo stack is empty
  • THEN no crash occurs and the scene is unchanged

Scenario: Redo with empty stack is a no-op

  • WHEN CommandHistory::Redo() is called and the redo stack is empty
  • THEN no crash occurs and the scene is unchanged

Requirement: Ctrl+Z / Ctrl+Y hotkeys

The application SHALL process Ctrl+Z to invoke Undo() and Ctrl+Y (and Ctrl+Shift+Z) to invoke Redo() during the ImGui main loop, unless an ImGui text input widget has keyboard focus.

Scenario: Ctrl+Z triggers undo

  • WHEN the user presses Ctrl+Z and the undo stack is non-empty
  • THEN the most recent command is undone and the viewport reflects the reverted state

Scenario: Ctrl+Y triggers redo

  • WHEN the user presses Ctrl+Y and the redo stack is non-empty
  • THEN the most recent undone command is reapplied and the viewport reflects the restored state

Scenario: Hotkeys ignored in text inputs

  • WHEN an ImGui InputText widget has keyboard focus and the user presses Ctrl+Z
  • THEN ImGui handles the keypress as text-widget undo and CommandHistory::Undo() is NOT called

Requirement: Edit menu Undo/Redo items

The application SHALL provide Edit → Undo and Edit → Redo menu items. Each item SHALL display the description of the command that would be affected. Items SHALL be greyed out (disabled) when the respective stack is empty.

Scenario: Undo item shows command description

  • WHEN the undo stack is non-empty and the Edit menu is opened
  • THEN the Undo item reads "Undo: " and is enabled

Scenario: Undo item disabled when stack empty

  • WHEN the undo stack is empty and the Edit menu is opened
  • THEN the Undo item is greyed out and clicking it has no effect

Requirement: History cleared on stage lifecycle events

The system SHALL call CommandHistory::Clear() whenever a stage is opened, closed, or replaced, so that stale USD object references cannot be dereferenced.

Scenario: History clears on stage open

  • WHEN the user opens a new USD file
  • THEN both undo and redo stacks are empty after the stage loads

Scenario: History clears on stage close

  • WHEN the user closes the current stage
  • THEN both undo and redo stacks are empty