-
Notifications
You must be signed in to change notification settings - Fork 703
Description
Is your feature request related to a problem? Please describe.
The current event delegation mechanism in Slicer is based on Slicer-specific interactor styles, namely vtkMRMLThreeDViewInteractorStyle and vtkMRMLSliceViewInteractorStyle, which are derived from vtkMRMLViewInteractorStyle and, ultimately, vtkInteractorStyle3D.
These styles handle interaction events by adding observers for events like EnterEvent, LeaveEvent, and MouseMoveEvent, and subsequently call functions like vtkMRMLViewInteractorStyle::OnEnter(), vtkMRMLViewInteractorStyle::OnLeave(), or vtkMRMLViewInteractorStyle::OnMouseMove().
In each of these On<EventName>() functions, delegation to displayable managers and their associated widgets is performed, and if a given event isn't intercepted, the default behavior for <EventName> implemented in vtkInteractorStyle3D is executed by calling this->Superclass::On<EventName>(). The snippet below illustrates this:
if (!this->DelegateInteractionEventToDisplayableManagers(vtkCommand::<EventName>Event))
{
return;
}
this->Superclass::On<EventName>();However, a limitation arises when default event handling implemented in specific interactor styles (e.g., vtkOpenXRInteractorStyle or vtkOpenVRInteractorStyle) needs to be executed when not delegated.
Describe the solution you'd like
Refactor Interactor Styles
Refactor vtkMRMLThreeDViewInteractorStyle and vtkMRMLSliceViewInteractorStyle to derive from vtkObject and implement event delegation to MRML displayable managers and associated widgets by observing the interactor style. Depending on the observed event, default interactor style behavior would be executed using one of the following approaches:
- Setting Abort Flag: For events such as
Move3D,Button3D,Menu3D, and others where thevtkInteractorStyleclass checks if the event was aborted, we will set an abort flag. - Explicit Call of
On<EventName>(): For other events, we would explicitly call the correspondingOn<EventName>()function. To support this, the existing methodvtkMRMLAbstractThreeDViewDisplayableManager::PassThroughInteractorStyleEventwill be used and updated as needed.
The interactor style will be associated with its corresponding displayable manager group, allowing access to the MRML scene and registered displayable managers.
Renaming Interactor Styles
To faciliate review of changes introduced in the first phase of the refactoring, the rename the classes will happen in in a second phase. This will help avoid future confusion.
More specifically, we will ename the classes vtkMRMLThreeDViewInteractorStyle to vtkMRMLThreeDViewInteractorObserver and vtkMRMLSliceViewInteractorStyle to vtkMRMLSliceViewInteractorObserver.
Access to CameraNode from vtkMRMLThreeDViewInteractorStyle
Access to the CameraNode will be updated in the following places:
- In
qMRMLThreeDView, the code can be refactored to retrieve the camera node from thevtkMRMLCameraDisplayableManagerby callingqMRMLThreeDView::displayableManagerByClassName(). - In
vtkMRMLThreeDViewInteractorStyle, the camera node will be accessed through the displayable manager group following the refactoring described above.
Default Interactor Styles
- For 3D views, the default interactor style will be
vtkInteractorStyleTrackballCamera. - For 2D views, the default interactor style will be
vtkInteractorStyleUser.
Whenever possible, Slicer-specific behavior will be added either to vtkMRMLThreeDViewInteractorStyle (renamed vtkMRMLThreeDViewInteractorObserver in Phase 2) or to displayable managers to ensure that switching the interactor style does not affect critical functionality.
Describe alternatives you've considered
An alternative would be duplicating the code currently implemented in VTK-specific interactor styles. However, this approach is error-prone and unsustainable.
Additional context
This proposal was created following discussion with @LucasGandel while discussing the following issue: