diff --git a/Libs/MRML/Core/vtkMRMLTransformNode.cxx b/Libs/MRML/Core/vtkMRMLTransformNode.cxx index d5a62419bec..811c0d89fe5 100644 --- a/Libs/MRML/Core/vtkMRMLTransformNode.cxx +++ b/Libs/MRML/Core/vtkMRMLTransformNode.cxx @@ -340,7 +340,7 @@ else } // copy the center of transformation - node->SetCenterOfTransformation(this->GetCenterOfTransformation()); + this->SetCenterOfTransformation(node->GetCenterOfTransformation()); this->Modified(); this->TransformModified(); diff --git a/Libs/MRML/DisplayableManager/vtkMRMLInteractionWidget.cxx b/Libs/MRML/DisplayableManager/vtkMRMLInteractionWidget.cxx index f8ee6bf56be..7476ba0dd59 100644 --- a/Libs/MRML/DisplayableManager/vtkMRMLInteractionWidget.cxx +++ b/Libs/MRML/DisplayableManager/vtkMRMLInteractionWidget.cxx @@ -42,8 +42,6 @@ vtkMRMLInteractionWidget::vtkMRMLInteractionWidget() { this->LastEventPosition[0] = 0.0; this->LastEventPosition[1] = 0.0; - this->StartEventOffsetPosition[0] = 0.0; - this->StartEventOffsetPosition[1] = 0.0; // Update active component this->SetEventTranslation(WidgetStateIdle, vtkCommand::MouseMoveEvent, vtkEvent::AnyModifier, WidgetEventMouseMove); @@ -79,6 +77,19 @@ vtkMRMLInteractionWidget::vtkMRMLInteractionWidget() this->SetEventTranslation(interactionHandleState, vtkCommand::MouseMoveEvent, vtkEvent::NoModifier, WidgetEventMouseMove); this->SetEventTranslation(interactionHandleState, vtkCommand::Move3DEvent, vtkEvent::NoModifier, WidgetEventMouseMove); } + + int interactionStates[4] = + { + WidgetStateTranslate, + WidgetStateRotate, + WidgetStateScale, + WidgetStateUniformScale + }; + for (int interactionState : interactionStates) + { + this->SetEventTranslation(interactionState, vtkCommand::RightButtonPressEvent, vtkEvent::NoModifier, WidgetEventCancel); + this->SetKeyboardEventTranslation(interactionState, vtkEvent::NoModifier, 0, 0, "Escape", WidgetEventCancel); + } } //---------------------------------------------------------------------- @@ -432,6 +443,9 @@ bool vtkMRMLInteractionWidget::ProcessInteractionEvent(vtkMRMLInteractionEventDa case WidgetEventJumpCursor: processedEvent = ProcessJumpCursor(eventData); break; + case WidgetEventCancel: + processedEvent = ProcessCancelEvent(eventData); + break; default: break; } @@ -468,6 +482,8 @@ void vtkMRMLInteractionWidget::StartWidgetInteraction(vtkMRMLInteractionEventDat } rep->InteractingOn(); + this->SaveInitialState(); + double startEventPos[2] { static_cast(eventData->GetDisplayPosition()[0]), @@ -477,9 +493,6 @@ void vtkMRMLInteractionWidget::StartWidgetInteraction(vtkMRMLInteractionEventDat // save the cursor position this->LastEventPosition[0] = startEventPos[0]; this->LastEventPosition[1] = startEventPos[1]; - - this->StartEventOffsetPosition[0] = 0; - this->StartEventOffsetPosition[1] = 0; } //---------------------------------------------------------------------- @@ -496,7 +509,7 @@ void vtkMRMLInteractionWidget::EndWidgetInteraction() //---------------------------------------------------------------------- void vtkMRMLInteractionWidget::TranslateWidget(double eventPos[2]) { - double lastEventPos_World[3] = { 0.0, 0.0, 0.0 }; + double previousEventPos_World[3] = { 0.0, 0.0, 0.0 }; double eventPos_World[3] = { 0.0, 0.0, 0.0 }; vtkMRMLInteractionWidgetRepresentation* rep = vtkMRMLInteractionWidgetRepresentation::SafeDownCast(this->WidgetRep); @@ -511,7 +524,7 @@ void vtkMRMLInteractionWidget::TranslateWidget(double eventPos[2]) double eventPos_Slice[3] = { 0.0, 0.0, 0.0 }; eventPos_Slice[0] = this->LastEventPosition[0]; eventPos_Slice[1] = this->LastEventPosition[1]; - rep->GetSliceToWorldCoordinates(eventPos_Slice, lastEventPos_World); + rep->GetSliceToWorldCoordinates(eventPos_Slice, previousEventPos_World); eventPos_Slice[0] = eventPos[0]; eventPos_Slice[1] = eventPos[1]; @@ -526,21 +539,21 @@ void vtkMRMLInteractionWidget::TranslateWidget(double eventPos[2]) 0.0, 0.0, 1.0 }; if (!rep->GetPointPlacer()->ComputeWorldPosition(this->Renderer, - this->LastEventPosition, lastEventPos_World, orientation_World)) + this->LastEventPosition, previousEventPos_World, orientation_World)) { return; } if (!rep->GetPointPlacer()->ComputeWorldPosition(this->Renderer, - eventPos, lastEventPos_World, eventPos_World, orientation_World)) + eventPos, previousEventPos_World, eventPos_World, orientation_World)) { return; } } double translationVector_World[3] = { 0.0, 0.0, 0.0 }; - translationVector_World[0] = eventPos_World[0] - lastEventPos_World[0]; - translationVector_World[1] = eventPos_World[1] - lastEventPos_World[1]; - translationVector_World[2] = eventPos_World[2] - lastEventPos_World[2]; + translationVector_World[0] = eventPos_World[0] - previousEventPos_World[0]; + translationVector_World[1] = eventPos_World[1] - previousEventPos_World[1]; + translationVector_World[2] = eventPos_World[2] - previousEventPos_World[2]; int index = this->GetActiveComponentIndex(); double translationAxis_World[3] = { 0.0, 0.0, 0.0 }; @@ -1009,3 +1022,45 @@ void vtkMRMLInteractionWidget::SetActiveComponentIndex(int index) vtkSmartPointer rep = vtkMRMLInteractionWidgetRepresentation::SafeDownCast(this->WidgetRep); rep->SetActiveComponentIndex(index); } + +//------------------------------------------------------------------------- +bool vtkMRMLInteractionWidget::ProcessCancelEvent(vtkMRMLInteractionEventData* eventData) +{ + this->RestoreInitialState(); + return this->ProcessEndMouseDrag(eventData); +} + +//------------------------------------------------------------------------- +void vtkMRMLInteractionWidget::SaveInitialState() +{ + vtkMRMLNode* node = this->GetMRMLNode(); + if (!node) + { + vtkErrorMacro("SaveInitialState: Invalid transform node"); + return; + } + + this->OriginalStateNode = vtkSmartPointer::Take(node->CreateNodeInstance()); + this->OriginalStateNode->CopyContent(node); +} + +//------------------------------------------------------------------------- +void vtkMRMLInteractionWidget::RestoreInitialState() +{ + if (!this->OriginalStateNode) + { + vtkErrorMacro("RestoreInitialState: Original state node is not set"); + return; + } + + vtkMRMLNode* node = this->GetMRMLNode(); + if (!node) + { + vtkErrorMacro("RestoreInitialState: Invalid transform node"); + return; + } + + node->CopyContent(this->OriginalStateNode); + this->OriginalStateNode = nullptr; + this->WidgetRep->NeedToRenderOn(); +} diff --git a/Libs/MRML/DisplayableManager/vtkMRMLInteractionWidget.h b/Libs/MRML/DisplayableManager/vtkMRMLInteractionWidget.h index 5e057322402..9f58e0f7262 100644 --- a/Libs/MRML/DisplayableManager/vtkMRMLInteractionWidget.h +++ b/Libs/MRML/DisplayableManager/vtkMRMLInteractionWidget.h @@ -68,16 +68,18 @@ class VTK_MRML_DISPLAYABLEMANAGER_EXPORT vtkMRMLInteractionWidget WidgetStateOnTranslationHandle = WidgetStateInteraction_First, // hovering over a translation interaction handle WidgetStateOnRotationHandle, // hovering over a rotation interaction handle WidgetStateOnScaleHandle, // hovering over a scale interaction handle + WidgetStateUniformScale, // uniform scaling WidgetStateInteraction_Last }; /// Widget events enum { - WidgetEventReserved = WidgetEventUser, // this events is only to prevent other widgets from processing an event - WidgetStateUniformScale, + WidgetEventInteraction_First = WidgetEventUser, + WidgetEventReserved = WidgetEventInteraction_First, // this events is only to prevent other widgets from processing an event WidgetEventUniformScaleStart, WidgetEventUniformScaleEnd, + WidgetEventCancel, WidgetEventInteraction_Last }; @@ -129,6 +131,11 @@ class VTK_MRML_DISPLAYABLEMANAGER_EXPORT vtkMRMLInteractionWidget virtual bool ProcessWidgetUniformScaleStart(vtkMRMLInteractionEventData* eventData); virtual bool ProcessEndMouseDrag(vtkMRMLInteractionEventData* eventData); virtual bool ProcessJumpCursor(vtkMRMLInteractionEventData* eventData); + virtual bool ProcessCancelEvent(vtkMRMLInteractionEventData* eventData); + + virtual vtkMRMLNode* GetMRMLNode() = 0; + virtual void SaveInitialState(); + virtual void RestoreInitialState(); // Jump to the handle position for the given type and index. Returns true if successful. virtual bool JumpToHandlePosition(int type, int index); @@ -143,10 +150,8 @@ class VTK_MRML_DISPLAYABLEMANAGER_EXPORT vtkMRMLInteractionWidget /// Variables for translate/rotate/scale double LastEventPosition[2]; - double StartEventOffsetPosition[2]; - bool ConvertDisplayPositionToWorld(const int displayPos[2], - double worldPos[3], double worldOrientationMatrix[9], double* refWorldPos = nullptr); + vtkSmartPointer OriginalStateNode{ nullptr }; private: vtkMRMLInteractionWidget(const vtkMRMLInteractionWidget&) = delete; diff --git a/Modules/Loadable/Markups/MRML/vtkMRMLMarkupsPlaneNode.cxx b/Modules/Loadable/Markups/MRML/vtkMRMLMarkupsPlaneNode.cxx index 068bda5f9f7..a512d46531f 100644 --- a/Modules/Loadable/Markups/MRML/vtkMRMLMarkupsPlaneNode.cxx +++ b/Modules/Loadable/Markups/MRML/vtkMRMLMarkupsPlaneNode.cxx @@ -103,12 +103,11 @@ void vtkMRMLMarkupsPlaneNode::CopyContent(vtkMRMLNode* anode, bool deepCopy/*=tr MRMLNodeModifyBlocker blocker(this); vtkMRMLCopyBeginMacro(anode); vtkMRMLCopyEnumMacro(PlaneType); - vtkMRMLCopyIntMacro(MaximumNumberOfControlPoints); - vtkMRMLCopyIntMacro(RequiredNumberOfControlPoints); vtkMRMLCopyEnumMacro(SizeMode); vtkMRMLCopyVectorMacro(Size, double, 2); vtkMRMLCopyVectorMacro(Normal, double, 3); vtkMRMLCopyVectorMacro(Center, double, 3); + vtkMRMLCopyVectorMacro(PlaneBounds, double, 4); vtkMRMLCopyFloatMacro(AutoSizeScalingFactor); vtkMRMLCopyEndMacro(); @@ -126,10 +125,15 @@ void vtkMRMLMarkupsPlaneNode::PrintSelf(ostream& os, vtkIndent indent) { Superclass::PrintSelf(os,indent); vtkMRMLPrintBeginMacro(os, indent); + vtkMRMLPrintEnumMacro(PlaneType); vtkMRMLPrintEnumMacro(SizeMode); vtkMRMLPrintVectorMacro(Size, double, 2); + vtkMRMLPrintVectorMacro(Normal, double, 3); + vtkMRMLPrintVectorMacro(Center, double, 3); + vtkMRMLPrintVectorMacro(PlaneBounds, double, 4); vtkMRMLPrintFloatMacro(AutoSizeScalingFactor); vtkMRMLPrintMatrix4x4Macro(ObjectToBaseMatrix); + vtkMRMLPrintMatrix4x4Macro(BaseToNodeMatrix); vtkMRMLPrintEndMacro(); } diff --git a/Modules/Loadable/Markups/VTKWidgets/vtkSlicerMarkupsInteractionWidget.cxx b/Modules/Loadable/Markups/VTKWidgets/vtkSlicerMarkupsInteractionWidget.cxx index 93072018889..2f527da1135 100644 --- a/Modules/Loadable/Markups/VTKWidgets/vtkSlicerMarkupsInteractionWidget.cxx +++ b/Modules/Loadable/Markups/VTKWidgets/vtkSlicerMarkupsInteractionWidget.cxx @@ -938,3 +938,9 @@ void vtkSlicerMarkupsInteractionWidget::FlipROIHandles(bool flipLRHandle, bool f displayNode->SetActiveComponent(displayNode->GetActiveComponentType(), index); } + +//------------------------------------------------------------------------- +vtkMRMLNode* vtkSlicerMarkupsInteractionWidget::GetMRMLNode() +{ + return this->GetMarkupsNode(); +} diff --git a/Modules/Loadable/Markups/VTKWidgets/vtkSlicerMarkupsInteractionWidget.h b/Modules/Loadable/Markups/VTKWidgets/vtkSlicerMarkupsInteractionWidget.h index 052c1baab70..3295f396403 100644 --- a/Modules/Loadable/Markups/VTKWidgets/vtkSlicerMarkupsInteractionWidget.h +++ b/Modules/Loadable/Markups/VTKWidgets/vtkSlicerMarkupsInteractionWidget.h @@ -82,6 +82,8 @@ class VTK_SLICER_MARKUPS_MODULE_VTKWIDGETS_EXPORT vtkSlicerMarkupsInteractionWid bool ProcessWidgetMenu(vtkMRMLInteractionEventData* eventData) override; + vtkMRMLNode* GetMRMLNode() override; + protected: vtkSlicerMarkupsInteractionWidget(); ~vtkSlicerMarkupsInteractionWidget() override; diff --git a/Modules/Loadable/Transforms/MRMLDM/vtkMRMLTransformHandleWidget.cxx b/Modules/Loadable/Transforms/MRMLDM/vtkMRMLTransformHandleWidget.cxx index 9fc85b472cb..7f22f19eeaf 100644 --- a/Modules/Loadable/Transforms/MRMLDM/vtkMRMLTransformHandleWidget.cxx +++ b/Modules/Loadable/Transforms/MRMLDM/vtkMRMLTransformHandleWidget.cxx @@ -51,6 +51,9 @@ vtkMRMLTransformHandleWidget::vtkMRMLTransformHandleWidget() // Handle interactions this->SetEventTranslationClickAndDrag(WidgetStateOnTranslationHandle, vtkCommand::LeftButtonPressEvent, vtkEvent::AltModifier, WidgetStateTranslateTransformCenter, WidgetEventTranslateTransformCenterStart, WidgetEventTranslateTransformCenterEnd); + + this->SetEventTranslation(WidgetStateTranslateTransformCenter, vtkCommand::RightButtonPressEvent, vtkEvent::NoModifier, WidgetEventCancel); + this->SetKeyboardEventTranslation(WidgetStateTranslateTransformCenter, vtkEvent::NoModifier, 0, 0, "Escape", WidgetEventCancel); } //---------------------------------------------------------------------- @@ -414,3 +417,9 @@ bool vtkMRMLTransformHandleWidget::ProcessJumpCursor(vtkMRMLInteractionEventData return Superclass::ProcessJumpCursor(eventData); } + +//------------------------------------------------------------------------- +vtkMRMLNode* vtkMRMLTransformHandleWidget::GetMRMLNode() +{ + return this->GetTransformNode(); +} diff --git a/Modules/Loadable/Transforms/MRMLDM/vtkMRMLTransformHandleWidget.h b/Modules/Loadable/Transforms/MRMLDM/vtkMRMLTransformHandleWidget.h index 03a5f509397..481df7a3b11 100644 --- a/Modules/Loadable/Transforms/MRMLDM/vtkMRMLTransformHandleWidget.h +++ b/Modules/Loadable/Transforms/MRMLDM/vtkMRMLTransformHandleWidget.h @@ -18,7 +18,6 @@ ==============================================================================*/ - /// /// \class vtkMRMLTransformHandleWidget /// \brief Process interaction events to update state of interaction widgets @@ -33,16 +32,17 @@ #include "vtkMRMLInteractionWidget.h" +class vtkIdList; +class vtkMatrix4x4; class vtkMRMLAbstractViewNode; class vtkMRMLApplicationLogic; class vtkMRMLDisplayableNode; class vtkMRMLInteractionEventData; class vtkMRMLInteractionNode; -class vtkIdList; -class vtkPolyData; -class vtkTransform; class vtkMRMLTransformDisplayNode; class vtkMRMLTransformNode; +class vtkPolyData; +class vtkTransform; class VTK_SLICER_TRANSFORMS_MODULE_MRMLDISPLAYABLEMANAGER_EXPORT vtkMRMLTransformHandleWidget : public vtkMRMLInteractionWidget @@ -92,6 +92,8 @@ class VTK_SLICER_TRANSFORMS_MODULE_MRMLDISPLAYABLEMANAGER_EXPORT vtkMRMLTransfor void ApplyTransform(vtkTransform* transform) override; + vtkMRMLNode* GetMRMLNode() override; + private: vtkMRMLTransformHandleWidget(const vtkMRMLTransformHandleWidget&) = delete; void operator=(const vtkMRMLTransformHandleWidget&) = delete;