Skip to content

Commit

Permalink
BUG: Fix integration with updated Slicer event delegation and VTK Ope…
Browse files Browse the repository at this point in the history
…nVR API

Addressing issues highlighted in Slicer/Slicer@1cc3b2c62, this commit introduces
the `vtkVirtualRealityViewInteractorObserver` class. This addition streamlines
event delegation to MRML displayable managers and their associated widgets
by leveraging observation of the interactor style.

The modification enables the `vtkVirtualRealityViewInteractorStyle` to inherit
from `vtkOpenVRInteractorStyle`, eliminating the need for redundant code
implementation and duplication.

It also updates the use of `MapInputToAction()` to map "eventId to state"
following the VTK refactoring introduced in Kitware/VTK@b7f02e622 (update
openvr to action based input model).

Co-authored-by: Lucas Gandel <[email protected]>
  • Loading branch information
jcfr and LucasGandel committed Dec 16, 2023
1 parent 53a9549 commit eeaac5a
Show file tree
Hide file tree
Showing 9 changed files with 543 additions and 302 deletions.
2 changes: 2 additions & 0 deletions VirtualReality/MRML/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ set(${KIT}_SRCS
vtkMRML${MODULE_NAME}LayoutNode.h
vtk${MODULE_NAME}ViewInteractor.cxx
vtk${MODULE_NAME}ViewInteractor.h
vtk${MODULE_NAME}ViewInteractorObserver.cxx
vtk${MODULE_NAME}ViewInteractorObserver.h
vtk${MODULE_NAME}ViewInteractorStyle.cxx
vtk${MODULE_NAME}ViewInteractorStyle.h
)
Expand Down
58 changes: 38 additions & 20 deletions VirtualReality/MRML/vtkVirtualRealityViewInteractor.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -195,18 +195,21 @@ void vtkVirtualRealityViewInteractor::SetTriggerButtonFunction(std::string funct
return;
}

// The "eventId to state" mapping (see call to `MapInputToAction` below) applies to right and left
// controller buttons because they are bound to the same eventId:
// - `vtk_openvr_binding_*.json` files define the "button to action" mapping
// - `vtkOpenVRInteractorStyle()` contructor defines the "action to eventId" mapping

if (functionId.empty())
{
vrInteractorStyle->MapInputToAction(vtkEventDataDevice::RightController, vtkEventDataDeviceInput::Trigger, VTKIS_NONE);
vrInteractorStyle->MapInputToAction(vtkEventDataDevice::LeftController, vtkEventDataDeviceInput::Trigger, VTKIS_NONE);
vrInteractorStyle->MapInputToAction(vtkCommand::Select3DEvent, VTKIS_NONE);

this->GestureEnabledButtons.clear();
this->GestureEnabledButtons.push_back(static_cast<int>(vtkEventDataDeviceInput::Grip));
}
else if (!functionId.compare(vtkVirtualRealityViewInteractor::GetButtonFunctionIdForGrabObjectsAndWorld()))
{
vrInteractorStyle->MapInputToAction(vtkEventDataDevice::RightController, vtkEventDataDeviceInput::Trigger, VTKIS_POSITION_PROP);
vrInteractorStyle->MapInputToAction(vtkEventDataDevice::LeftController, vtkEventDataDeviceInput::Trigger, VTKIS_POSITION_PROP);
vrInteractorStyle->MapInputToAction(vtkCommand::Select3DEvent, VTKIS_POSITION_PROP);

this->GestureEnabledButtons.clear();
this->GestureEnabledButtons.push_back(static_cast<int>(vtkEventDataDeviceInput::Grip));
Expand All @@ -227,10 +230,14 @@ void vtkVirtualRealityViewInteractor::SetGestureButtonToTrigger()
vtkWarningMacro("SetGestureButtonToTrigger: Current interactor style is not a VR interactor style");
return;
}
vrInteractorStyle->MapInputToAction(vtkEventDataDevice::RightController, vtkEventDataDeviceInput::Trigger, VTKIS_POSITION_PROP);
vrInteractorStyle->MapInputToAction(vtkEventDataDevice::LeftController, vtkEventDataDeviceInput::Trigger, VTKIS_POSITION_PROP);
vrInteractorStyle->MapInputToAction(vtkEventDataDevice::RightController, vtkEventDataDeviceInput::Grip, VTKIS_NONE);
vrInteractorStyle->MapInputToAction(vtkEventDataDevice::LeftController, vtkEventDataDeviceInput::Grip, VTKIS_NONE);

// The update "action to (eventId|function)" mapping (see call to `AddAction` below) applies to
// right and left controller buttons because they are bound to the same eventId:
// - "vtk_openvr_binding_*.json" defines the "button -> action" mapping
// - vtkOpenVRInteractorStyle defines the "action -> eventId" mapping
this->AddAction("/actions/vtk/in/TriggerAction", /*isAnalog=*/false,
[this](vtkEventData* ed) { this->HandleComplexGestureEvents(ed); });
this->AddAction("/actions/vtk/in/ComplexGestureAction", vtkCommand::Select3DEvent, /*isAnalog=*/false);

this->GestureEnabledButtons.clear();
this->GestureEnabledButtons.push_back(static_cast<int>(vtkEventDataDeviceInput::Trigger));
Expand All @@ -246,10 +253,13 @@ void vtkVirtualRealityViewInteractor::SetGestureButtonToGrip()
return;
}

vrInteractorStyle->MapInputToAction(vtkEventDataDevice::RightController, vtkEventDataDeviceInput::Trigger, VTKIS_NONE);
vrInteractorStyle->MapInputToAction(vtkEventDataDevice::LeftController, vtkEventDataDeviceInput::Trigger, VTKIS_NONE);
vrInteractorStyle->MapInputToAction(vtkEventDataDevice::RightController, vtkEventDataDeviceInput::Grip, VTKIS_POSITION_PROP);
vrInteractorStyle->MapInputToAction(vtkEventDataDevice::LeftController, vtkEventDataDeviceInput::Grip, VTKIS_POSITION_PROP);
// The update "action to (eventId|function)" mapping (see call to `AddAction` below) applies to
// right and left controller buttons because they are bound to the same eventId:
// - "vtk_openvr_binding_*.json" defines the "button -> action" mapping
// - vtkOpenVRInteractorStyle defines the "action -> eventId" mapping
this->AddAction("/actions/vtk/in/TriggerAction", vtkCommand::Select3DEvent, /*isAnalog=*/false);
this->AddAction("/actions/vtk/in/ComplexGestureAction", /*isAnalog=*/false,
[this](vtkEventData* ed) { this->HandleComplexGestureEvents(ed); });

this->GestureEnabledButtons.clear();
this->GestureEnabledButtons.push_back(static_cast<int>(vtkEventDataDeviceInput::Grip));
Expand All @@ -265,10 +275,14 @@ void vtkVirtualRealityViewInteractor::SetGestureButtonToTriggerAndGrip()
return;
}

vrInteractorStyle->MapInputToAction(vtkEventDataDevice::RightController, vtkEventDataDeviceInput::Trigger, VTKIS_POSITION_PROP);
vrInteractorStyle->MapInputToAction(vtkEventDataDevice::LeftController, vtkEventDataDeviceInput::Trigger, VTKIS_POSITION_PROP);
vrInteractorStyle->MapInputToAction(vtkEventDataDevice::RightController, vtkEventDataDeviceInput::Grip, VTKIS_POSITION_PROP);
vrInteractorStyle->MapInputToAction(vtkEventDataDevice::LeftController, vtkEventDataDeviceInput::Grip, VTKIS_POSITION_PROP);
// The update "action to (eventId|function)" mapping (see call to `AddAction` below) applies to
// right and left controller buttons because they are bound to the same eventId:
// - "vtk_openvr_binding_*.json" defines the "button -> action" mapping
// - vtkOpenVRInteractorStyle defines the "action -> eventId" mapping
this->AddAction("/actions/vtk/in/TriggerAction", /*isAnalog=*/false,
[this](vtkEventData* ed) { this->HandleComplexGestureEvents(ed); });
this->AddAction("/actions/vtk/in/ComplexGestureAction", /*isAnalog=*/false,
[this](vtkEventData* ed) { this->HandleComplexGestureEvents(ed); });

this->GestureEnabledButtons.clear();
this->GestureEnabledButtons.push_back(static_cast<int>(vtkEventDataDeviceInput::Grip));
Expand All @@ -285,10 +299,14 @@ void vtkVirtualRealityViewInteractor::SetGestureButtonToNone()
return;
}

vrInteractorStyle->MapInputToAction(vtkEventDataDevice::RightController, vtkEventDataDeviceInput::Trigger, VTKIS_NONE);
vrInteractorStyle->MapInputToAction(vtkEventDataDevice::LeftController, vtkEventDataDeviceInput::Trigger, VTKIS_NONE);
vrInteractorStyle->MapInputToAction(vtkEventDataDevice::RightController, vtkEventDataDeviceInput::Grip, VTKIS_NONE);
vrInteractorStyle->MapInputToAction(vtkEventDataDevice::LeftController, vtkEventDataDeviceInput::Grip, VTKIS_NONE);
// The update "action to (eventId|function)" mapping (see call to `AddAction` below) applies to
// right and left controller buttons because they are bound to the same eventId:
// - "vtk_openvr_binding_*.json" defines the "button -> action" mapping
// - vtkOpenVRInteractorStyle defines the "action -> eventId" mapping
this->AddAction("/actions/vtk/in/TriggerAction", /*isAnalog=*/false,
[](vtkEventData* vtkNotUsed(ed)) { });
this->AddAction("/actions/vtk/in/ComplexGestureAction", /*isAnalog=*/false,
[](vtkEventData* vtkNotUsed(ed)) { });

this->GestureEnabledButtons.clear();
}
Loading

0 comments on commit eeaac5a

Please sign in to comment.