## 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