Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: Add cancel action for interaction handles #7600

Merged
merged 1 commit into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion Libs/MRML/Core/vtkMRMLTransformNode.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ else
}

// copy the center of transformation
node->SetCenterOfTransformation(this->GetCenterOfTransformation());
this->SetCenterOfTransformation(node->GetCenterOfTransformation());

this->Modified();
this->TransformModified();
Expand Down
79 changes: 67 additions & 12 deletions Libs/MRML/DisplayableManager/vtkMRMLInteractionWidget.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
}

//----------------------------------------------------------------------
Expand Down Expand Up @@ -432,6 +443,9 @@ bool vtkMRMLInteractionWidget::ProcessInteractionEvent(vtkMRMLInteractionEventDa
case WidgetEventJumpCursor:
processedEvent = ProcessJumpCursor(eventData);
break;
case WidgetEventCancel:
processedEvent = ProcessCancelEvent(eventData);
break;
default:
break;
}
Expand Down Expand Up @@ -468,6 +482,8 @@ void vtkMRMLInteractionWidget::StartWidgetInteraction(vtkMRMLInteractionEventDat
}
rep->InteractingOn();

this->SaveInitialState();

double startEventPos[2]
{
static_cast<double>(eventData->GetDisplayPosition()[0]),
Expand All @@ -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;
}

//----------------------------------------------------------------------
Expand All @@ -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);
Expand All @@ -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];
Expand All @@ -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 };
Expand Down Expand Up @@ -1009,3 +1022,45 @@ void vtkMRMLInteractionWidget::SetActiveComponentIndex(int index)
vtkSmartPointer<vtkMRMLInteractionWidgetRepresentation> 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<vtkMRMLNode>::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();
}
20 changes: 14 additions & 6 deletions Libs/MRML/DisplayableManager/vtkMRMLInteractionWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,13 @@
#ifndef vtkMRMLInteractionWidget_h
#define vtkMRMLInteractionWidget_h

// MRMLDisplayableManager includes
#include "vtkMRMLDisplayableManagerExport.h"

#include "vtkMRMLAbstractWidget.h"

// MRML includes
#include <vtkMRMLNode.h>

class vtkMRMLAbstractViewNode;
class vtkMRMLApplicationLogic;
class vtkMRMLDisplayNode;
Expand Down Expand Up @@ -68,16 +71,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
};

Expand Down Expand Up @@ -129,6 +134,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);
Expand All @@ -143,10 +153,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<vtkMRMLNode> OriginalStateNode{ nullptr };

private:
vtkMRMLInteractionWidget(const vtkMRMLInteractionWidget&) = delete;
Expand Down
8 changes: 6 additions & 2 deletions Modules/Loadable/Markups/MRML/vtkMRMLMarkupsPlaneNode.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -938,3 +938,9 @@ void vtkSlicerMarkupsInteractionWidget::FlipROIHandles(bool flipLRHandle, bool f

displayNode->SetActiveComponent(displayNode->GetActiveComponentType(), index);
}

//-------------------------------------------------------------------------
vtkMRMLNode* vtkSlicerMarkupsInteractionWidget::GetMRMLNode()
{
return this->GetMarkupsNode();
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ class VTK_SLICER_MARKUPS_MODULE_VTKWIDGETS_EXPORT vtkSlicerMarkupsInteractionWid

bool ProcessWidgetMenu(vtkMRMLInteractionEventData* eventData) override;

vtkMRMLNode* GetMRMLNode() override;

protected:
vtkSlicerMarkupsInteractionWidget();
~vtkSlicerMarkupsInteractionWidget() override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

//----------------------------------------------------------------------
Expand Down Expand Up @@ -414,3 +417,9 @@ bool vtkMRMLTransformHandleWidget::ProcessJumpCursor(vtkMRMLInteractionEventData

return Superclass::ProcessJumpCursor(eventData);
}

//-------------------------------------------------------------------------
vtkMRMLNode* vtkMRMLTransformHandleWidget::GetMRMLNode()
{
return this->GetTransformNode();
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

==============================================================================*/


///
/// \class vtkMRMLTransformHandleWidget
/// \brief Process interaction events to update state of interaction widgets
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down