Interaction filters
Restrict which objects the user may select, pick or move with the viewport's InteractionController.
import {
type PointerIntersections, type SceneObject, type SceneObjectFilter, Viewer, ViewportOperator,
} from '@stereograph/teiaviewer';
/**
* The viewport's `InteractionController` tells the operators which objects the user may select,
* pick (raycast) and move with the transform tool: an object is kept when it allows it itself
* (`isSelectable`, `isRaycastable`, `isTransformable`) and every filter added returns true.
*/
const viewer = new Viewer();
const { interactionController } = viewer.viewport;
// The objects of the loaded model only are selectable (not the measures, zones…).
const onlyLoadedObjects: SceneObjectFilter = (object) => {
return object.controller === viewer.scene.bimMeshController;
};
// The hidden storeys are seen through: neither picked nor selected.
const hiddenStoreys = new Set<string>(['Storey-2']);
const notInHiddenStorey: SceneObjectFilter = (object) => !hiddenStoreys.has(object.uuid);
// Nothing moves with the transform tool while the model is locked.
let isModelLocked = true;
const unlessLocked: SceneObjectFilter = () => !isModelLocked;
interactionController.addSelectionFilter(onlyLoadedObjects);
interactionController.addRaycastFilter(notInHiddenStorey);
interactionController.addTransformFilter(unlessLocked);
// Unlocks the model: the filters are read at each interaction, nothing to update.
isModelLocked = false;
// Removed with the same function (e.g. in a plugin's `onUnregister`).
interactionController.removeTransformFilter(unlessLocked);
/**
* An operator follows them as the default one does: the interaction controller's checks are
* filters of the objects under the pointer.
*/
export class InspectOperator extends ViewportOperator {
readonly name = 'InspectOperator';
override onPointerClick(_event: PointerEvent, intersections: PointerIntersections) {
const { interactionController: controller } = this._viewport;
// The first object the user may pick, the others seen through.
const hit = intersections.getFirst(controller.isObjectRaycastable);
const object: SceneObject | null = hit?.object ?? null;
if (object && controller.isObjectSelectable(object)) {
console.info(`${object.uuid} may be selected`, controller.isObjectTransformable(object));
}
}
}