@acransac/vtk.js
Version:
Visualization Toolkit for the Web
164 lines (139 loc) • 5.32 kB
JavaScript
import macro from 'vtk.js/Sources/macro';
import vtkPointPicker from 'vtk.js/Sources/Rendering/Core/PointPicker';
const MAX_POINTS = 3;
export default function widgetBehavior(publicAPI, model) {
model.classHierarchy.push('vtkAngleWidgetProp');
let isDragging = null;
const picker = vtkPointPicker.newInstance();
picker.setPickFromList(1);
// --------------------------------------------------------------------------
// Display 2D
// --------------------------------------------------------------------------
publicAPI.setDisplayCallback = (callback) =>
model.representations[0].setDisplayCallback(callback);
// --------------------------------------------------------------------------
// Interactor events
// --------------------------------------------------------------------------
function ignoreKey(e) {
return e.altKey || e.controlKey || e.shiftKey;
}
// --------------------------------------------------------------------------
// Left press: Select handle to drag
// --------------------------------------------------------------------------
publicAPI.handleLeftButtonPress = (e) => {
if (
!model.activeState ||
!model.activeState.getActive() ||
!model.pickable ||
ignoreKey(e)
) {
return macro.VOID;
}
picker.initializePickList();
picker.setPickList(publicAPI.getNestedProps());
if (
model.activeState === model.widgetState.getMoveHandle() &&
model.widgetState.getHandleList().length < MAX_POINTS
) {
// Commit handle to location
const moveHandle = model.widgetState.getMoveHandle();
const newHandle = model.widgetState.addHandle();
newHandle.setOrigin(...moveHandle.getOrigin());
newHandle.setColor(moveHandle.getColor());
newHandle.setScale1(moveHandle.getScale1());
} else {
isDragging = true;
model.openGLRenderWindow.setCursor('grabbing');
model.interactor.requestAnimation(publicAPI);
}
publicAPI.invokeStartInteractionEvent();
return macro.EVENT_ABORT;
};
// --------------------------------------------------------------------------
// Mouse move: Drag selected handle / Handle follow the mouse
// --------------------------------------------------------------------------
publicAPI.handleMouseMove = (callData) => {
if (
model.pickable &&
model.manipulator &&
model.activeState &&
model.activeState.getActive() &&
!ignoreKey(callData)
) {
model.manipulator.setOrigin(model.activeState.getOrigin());
model.manipulator.setNormal(model.camera.getDirectionOfProjection());
const worldCoords = model.manipulator.handleEvent(
callData,
model.openGLRenderWindow
);
if (
worldCoords.length &&
(model.activeState === model.widgetState.getMoveHandle() || isDragging)
) {
model.activeState.setOrigin(worldCoords);
publicAPI.invokeInteractionEvent();
return macro.EVENT_ABORT;
}
}
if (model.hasFocus) {
model.widgetManager.disablePicking();
}
return macro.VOID;
};
// --------------------------------------------------------------------------
// Left release: Finish drag / Create new handle
// --------------------------------------------------------------------------
publicAPI.handleLeftButtonRelease = () => {
if (isDragging && model.pickable) {
model.openGLRenderWindow.setCursor('pointer');
model.widgetState.deactivate();
model.interactor.cancelAnimation(publicAPI);
publicAPI.invokeEndInteractionEvent();
} else if (model.activeState !== model.widgetState.getMoveHandle()) {
model.widgetState.deactivate();
}
if (
(model.hasFocus && !model.activeState) ||
(model.activeState && !model.activeState.getActive())
) {
publicAPI.invokeEndInteractionEvent();
model.widgetManager.enablePicking();
model.interactor.render();
}
// Don't make any more points
if (model.widgetState.getHandleList().length === MAX_POINTS) {
publicAPI.loseFocus();
}
isDragging = false;
};
// --------------------------------------------------------------------------
// Focus API - modeHandle follow mouse when widget has focus
// --------------------------------------------------------------------------
publicAPI.grabFocus = () => {
if (
!model.hasFocus &&
model.widgetState.getHandleList().length < MAX_POINTS
) {
model.activeState = model.widgetState.getMoveHandle();
model.activeState.activate();
model.activeState.setVisible(true);
model.interactor.requestAnimation(publicAPI);
publicAPI.invokeStartInteractionEvent();
}
model.hasFocus = true;
};
// --------------------------------------------------------------------------
publicAPI.loseFocus = () => {
if (model.hasFocus) {
model.interactor.cancelAnimation(publicAPI);
publicAPI.invokeEndInteractionEvent();
}
model.widgetState.deactivate();
model.widgetState.getMoveHandle().deactivate();
model.widgetState.getMoveHandle().setVisible(false);
model.activeState = null;
model.hasFocus = false;
model.widgetManager.enablePicking();
model.interactor.render();
};
}