# Transformation Flow and Synchronization System This document describes how transformations are applied and synchronized between the interactive 3D viewport, the visualization puppets, and the underlying mathematical models within the `uLib` framework. ## Architecture Overview The system follows a Model-View-Controller (MVC) like pattern where: - **Model**: `uLib::AffineTransform` (or derived classes like `ContainerBox`). - **View/Puppet**: `uLib::Vtk::Puppet` (and specialized derivations like `Vtk::Assembly`). - **Controller/Interaction**: `vtkHandlerWidget` (the transformation gizmo). --- ## 1. Interaction Flow (Gizmo -> Model) When a user interacts with the `vtkHandlerWidget` (dragging arrows, rings, or cubes), the following chain of events occurs: ```mermaid sequenceDiagram participant User participant HW as vtkHandlerWidget participant VP as vtkViewport participant P as vtkPuppet participant M as uLib Model User->>HW: Drag handle (MouseMove) HW->>HW: Calculate Delta Matrix (op) HW->>HW: Total = StartState * op HW->>HW: Decompose Total into P, O, S HW->>P: SetPosition, SetOrientation, SetScale HW-->>VP: Invoke InteractionEvent VP->>P: SyncFromVtk() P->>P: Get local matrix from VTK Prop P->>M: SetMatrix(matrix) M-->>M: Update local properties (P, O, S) M-->>P: Emit Updated signal P->>P: Puppet::Update() P->>P: (Redundant sanity write to Prop) ``` ### Key Principles: - **Single Source of Truth**: The `uLib::AffineTransform` is the owner of the transformation state. - **Internal TRS vs UserMatrix**: We apply transformations directly to VTK's internal `Position`, `Orientation`, and `Scale` properties. This ensures the data is "visible" to VTK actors and simplifies decomposition. - **Cumulative Bias Avoidance**: The `HandlerWidget` calculates transformations relative to the state at the start of the click, preventing numerical drift during a single drag operation. --- ## 2. Synchronization Loop Resolution To prevent infinite loops and "double-transformation" artifacts (especially in assemblies), the following protections are in place: 1. **Hierarchy Isolation**: The `Puppet` base class distinguishes between the **Root Property** (which receives the puppet's master transformation) and **Sub-Parts** (which only receive appearance updates like color/visibility). This prevents parts from inheriting the same displacement twice. 2. **Re-entrancy Guards**: Puppets use an `m_InUpdate` flag to prevent a feedback loop where `SyncFromVtk` triggers a Model Update, which then re-triggers the Puppet Update. 3. **Signal Blocking**: In specialized cases (like `vtkAssembly`), `m_BlockUpdate` is used to prevent the model-to-puppet push during a puppet-to-model sync. --- ## 3. Undo System (Ctrl-Z) ### Current Implementation (Delta Chain) Currently, the system maintains a `m_TransformChain` of delta matrices. - **Record**: After every drag, a delta matrix ($M_{delta} = M_{end} \cdot M_{start}^{-1}$) is appended to the chain. - **Undo**: The last delta is removed, and the prop is reconstructed by reapplying the remaining chain from a `BaseMatrix`. ### Planned Improvement (TRS Snapshots) We are migrating to a `uLib::TRS` snapshot system for Undo. - **Record**: At the start of a drag, the current `TRS` state of the object is pushed to the `m_UndoStack`. - **Undo**: The top `TRS` is popped and applied directly to the model. This approach is more robust because: - It eliminates matrix multiplication error accumulation. - It bypasses rotation convention/order issues (Gimbal lock in deltas). - It returns the object to exactly its previous property values.