UsdLayerManager/openspec/changes/undo-redo-scene-editing/tasks.md

5.2 KiB

1. Core Command Infrastructure

  • 1.1 Create src/core/CommandHistory.h — define ICommand pure-virtual interface (Execute, Undo, GetDescription) and CommandHistory class with Push, Undo, Redo, Clear, CanUndo, CanRedo, GetUndoDescription, GetRedoDescription
  • 1.2 Create src/core/CommandHistory.cpp — implement CommandHistory with undo/redo stacks (std::vector<std::unique_ptr<ICommand>>); Push executes command, pushes to undo stack, clears redo stack
  • 1.3 Add CommandHistory as a member of Application and pass CommandHistory* into all panel and manager constructors/init methods
  • 1.4 Call m_commandHistory.Clear() inside Application::RefreshManagers() so history resets on every stage lifecycle event
  • 1.5 Add CMakeLists.txt entries for all new source files (CommandHistory.cpp and all command .cpp files added in subsequent tasks)

2. Transform Commands

  • 2.1 Create src/core/commands/TransformCommand.h/.cpp — stores prim SdfPath, SdfLayerHandle edit target, and pre/post TRS (GfVec3d translate, GfVec3f rotate, GfVec3f scale); Execute() applies post-values, Undo() applies pre-values via UsdGeomXformCommonAPI + UsdEditContext
  • 2.2 Modify TransformManipulator — accept CommandHistory* in constructor/init; on drag-begin snapshot TRS into m_dragStartTRS; on drag-end (detect wasDrawing && !m_isDragging) push TransformCommand only when delta is non-zero
  • 2.3 Modify PropertyPanel — accept CommandHistory*; capture pre-edit TRS before field edit begins; push TransformCommand inside ImGui::IsItemDeactivatedAfterEdit() blocks for translate, rotate, and scale fields

3. Scene Hierarchy Commands

  • 3.1 Create src/core/commands/CreatePrimCommand.h/.cpp — stores SdfPath, TfToken typeName, SdfLayerHandle; Execute() calls stage->DefinePrim; Undo() calls stage->RemovePrim
  • 3.2 Create src/core/commands/DeletePrimCommand.h/.cpp — on construction serialises the target prim's spec via SdfCopySpec into an anonymous layer; Execute() removes the prim; Undo() restores from the anonymous layer via SdfCopySpec
  • 3.3 Create src/core/commands/AddReferenceCommand.h/.cpp — stores created prim path and SdfReference; Execute() wraps in Xform and adds reference; Undo() removes the prim
  • 3.4 Create src/core/commands/ReplaceReferenceCommand.h/.cpp — stores prim path, old SdfReference, new SdfReference; Execute() applies new reference; Undo() restores old
  • 3.5 Modify SceneHierarchyPanel — accept CommandHistory*; replace direct Application::CreatePrimOnStage calls with Push(CreatePrimCommand); replace direct delete with Push(DeletePrimCommand); replace AddReferenceToStage with Push(AddReferenceCommand); replace ProcessPendingReplaceRef with Push(ReplaceReferenceCommand)

4. Attribute Edit Commands

  • 4.1 Create src/core/commands/AttributeSetCommand.h/.cpp — stores std::string description, std::function<void()> executeFunc, std::function<void()> undoFunc; captures old value before set using UsdAttribute::Get<T> at the call site
  • 4.2 Modify PropertyManager::SetPropertyValue and SetPropertyValueInLayer — read old value, construct AttributeSetCommand with closures for old/new applies, push to CommandHistory

5. Layer Operation Commands

  • 5.1 Create src/core/commands/LayerCreateCommand.h/.cpp — stores layer file path and insertion index; Execute() calls LayerManager::CreateSublayer; Undo() calls LayerManager::RemoveSublayer
  • 5.2 Create src/core/commands/LayerRemoveCommand.h/.cpp — stores layer path and original index; Execute() removes; Undo() re-inserts at saved index
  • 5.3 Create src/core/commands/LayerReorderCommand.h/.cpp — stores full ordered-path list before and after; Execute() applies new order; Undo() restores old order by rewriting rootLayer->GetSubLayerPaths()
  • 5.4 Modify LayerPanel — accept CommandHistory*; wrap Create, Remove, MoveUp, and MoveDown calls with the corresponding commands

6. Hotkeys and Menu Integration

  • 6.1 In Application's main-loop (or ImGuiContext), detect Ctrl+Z and Ctrl+Y / Ctrl+Shift+Z key combinations when no ImGui text widget has input focus (!ImGui::GetIO().WantTextInput); call m_commandHistory.Undo() / m_commandHistory.Redo() accordingly
  • 6.2 Add Edit menu (or extend existing menu bar) with Undo and Redo items; display GetUndoDescription() / GetRedoDescription() in item labels; disable items via ImGui::BeginDisabled(!CanUndo()) / (!CanRedo())

7. Build and Verification

  • 7.1 Run cmake --preset default and cmake --build build --config Release — compilation succeeds; LNK1104 only occurs because UsdLayerManager.exe is currently running (expected)
  • 7.2 Run cmake --install build --config Release and launch install/bin/App.exe; manually verify: create a prim, undo removes it, redo restores it
  • 7.3 Manually verify gizmo drag undo: translate a prim with the Move gizmo, press Ctrl+Z, confirm prim returns to original position
  • 7.4 Run ctest --test-dir build -C Release and confirm all tests pass