How to adjust interactor style behavior for vtkRemoteView

I’m successfully using vtkRemoteView to display images rendered in a (C++) server application. Now I would like to change some of the default interaction behavior. E.g. as a first step I would like to suppress right-click completely (aka send no event for right clicks to the backend).

However, I can’t seem to understand how this would be supposed to work with vtkRemoteView. It always sets up a new instance of vtkInteractorStyleRemoteMouse on construction and I did not find an appropriate way to e.g. use my own InteractorStyle implementation here. Only getters are provided for the vtkRenderWindowInteractor and vtkInteractorStyle. I could use vtkRemoteView.getInteractor().setInteractorStyle(), but that does not seem to make sense, since this will not update the interactorStyle in the model of vtkRemoteView.

Am I missing something obvious here?

Not fully sure but you might be able to consume the event before vtk.js capture it.

Otherwise, things are pretty tightly bundled into that class. You may want to create your own implementation of that class to match what you are looking for…

Thanks for your input.

Since there needs to be further, more complex changes to the interaction behavior, I will be going to replace vtkRemoteView.

Make sense. At least the vtkRemoteView give you a baseline on what is expected. :wink:

good morning, I have a problem and I think it may have to do with this. I am making a module to render a 2D image and add a widget to it.
This is the code to load the image:

const render2D = async (vtk2DRefs, imgSrc) => {
const renderWindow = vtkRenderWindow.newInstance();

const renderer = vtkRenderer.newInstance();
renderer.setBackground([242 / 255, 246 / 255, 254 / 255]);

const mapper = vtkImageSliceMapper.newInstance();
const actor = vtkImageSlice.newInstance();

const data = vtkImageData.newInstance();

async function loadImage(src) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.src = src;
    img.onload = () => resolve(img);
    img.onerror = (error) => reject(error);
  });
}

const img = await loadImage(imgSrc);
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');

canvas.width = img.width;
canvas.height = img.height;

ctx.drawImage(img, 0, 0);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);

const imageDataArray = new Uint8Array(imageData.data);
const dataArray = vtkDataArray.newInstance({
  numberOfComponents: 4,
  values: imageDataArray
});

data.setDimensions(img.width, img.height, 1);
data.setSpacing(1, 1, 1);
data.setOrigin(0, 0, 0);
data.getPointData().setScalars(dataArray);

mapper.setInputData(data);
actor.setMapper(mapper);
actor.rotateX(180);

const openGLRenderWindow = vtkOpenGLRenderWindow.newInstance();
renderWindow.addView(openGLRenderWindow);
openGLRenderWindow.setContainer(vtkContainerRef.current);


const interactor = vtkRenderWindowInteractor.newInstance();
interactor.setView(openGLRenderWindow);
interactor.initialize();
interactor.setContainer(vtkContainerRef.current);

interactor.setInteractorStyle(vtkInteractorStyleTrackballCamera.newInstance())

openGLRenderWindow.setSize(
  vtkContainerRef.current.clientWidth,
  vtkContainerRef.current.clientHeight
);

renderer.addViewProp(actor);
renderWindow.addRenderer(renderer);


const widgetManagerForms = vtkWidgetManager.newInstance()
widgetManagerForms.setRenderer(renderer)
widgetManagerForms.disablePicking()
// setWidgetsManagerForms(widgetManagerForms)

// const widgetManagerArrow = vtkWidgetManager.newInstance()
// widgetManagerArrow.setRenderer(renderer)
// widgetManagerArrow.disablePicking()
// setWidgetsManagerArrow(widgetManagerArrow)

// const widgetManagerLabel = vtkWidgetManager.newInstance()
// widgetManagerLabel.setRenderer(renderer)
// widgetManagerLabel.disablePicking()
// setWidgetsManagerLabel(widgetManagerLabel)


vtk2DRefs.current = {
  widgetManagerForms,
  renderWindow,
  mapper,
  actor,
  renderer,
  openGLRenderWindow,
  interactor,
};

renderer.resetCamera();
renderWindow.render();

};

and this is the code to add a vtkEllipseWidget:
const AddCircle = () => {
const widget = vtkEllipseWidget.newInstance({
modifierBehavior: {
None: {
[BehaviorCategory.PLACEMENT]: ShapeBehavior[BehaviorCategory.PLACEMENT].CLICK_AND_DRAG,
[BehaviorCategory.POINTS]: ShapeBehavior[BehaviorCategory.POINTS].DIAMETER,
[BehaviorCategory.RATIO]: ShapeBehavior[BehaviorCategory.RATIO].RADIUS
}
}
})

const handle = vtk2DRefs.current.widgetManagerForms.addWidget(widget, ViewTypes.YZ_PLANE)
vtk2DRefs.current.widgetManagerForms.grabFocus(widget)

handle.setActiveColor(0, 0)

handle.getRepresentations()[0].getMapper().setScalarVisibility(false)
handle.getRepresentations()[0].getActor().getProperty().setColor(8 / 255, 29 / 255, 73 / 255)
handle.getRepresentations()[1].getMapper().setScalarVisibility(false)
handle.getRepresentations()[1].getActor().getProperty().setColor(8 / 255, 29 / 255, 73 / 255)

handle.getRepresentations()[1].setDrawBorder(true)
handle.getRepresentations()[1].setDrawFace(false)
handle.getRepresentations()[1].setOpacity(1)

handle.onStartInteractionEvent(() => {
  setCurrentHandle(handle)
})

}

so, the problem is that when i do:
const handle = vtk2DRefs.current.widgetManagerForms.addWidget(widget, ViewTypes.YZ_PLANE)

the interaction with the 2D image (zoom and rotate) are crashed