29 May 2017
Controlling components selection in the Viewer
This week post illustrates how you can control the selectability of any components in the Forge Viewer. There may be scenarii where you want to enforce or restrict user selection to a specific group of components, that either match a given property, based on their parent component or a set of predefined dbIds...
There are three interaction paths you need to control to achieve that:
- The selection event handler for AGGREGATE_SELECTION_CHANGED_EVENT: this event is fired when a component is selected by the user. Your application can get access to the list of selected dbIds from the event callback arguments. If the component should not be selectable, you can cancel the selection by calling viewer.clearSelection() at this point. Because selecting a component has to be a synchronous operation for the user, you need build in advance a list of allowed/rejected dbIds in order to be able to decide synchronously in the event to call clearSelection or not.
- The second selection path is through right-click context menu: you can implement a custom context menu handler and use viewer.setContextMenu() to replace the original menu handler. This gives you the ability to perform a synchronous check on the selected dbId to decide wether or not the menu should be displayed for a specific component. You can find an example of a custom context menu extension there.
- The third interaction you may want to control is user hovering the mouse over the model: you would need to prevent highlighting a component that cannot be selected but keep the normal behaviour for components which can. This can be achieved by using a custom tool and implementing some synchronous logic in the handleMouseMove callback.
The SelectionFilter extension is an example of such implementation. It generates a treeview that represents the model structure, allowing to specify exactly which components can be selected or not. An active switch means the component is selectable. There is also some internal logic in the tree that will disable all child components if a parent is disabled. Internally the extension maintains a table of all dbIds set to a boolean value to indicate if each component is selectable or not.
Another remarkable aspect of this extension is that it supports multiple models loaded in the same scene. This is possible with not much more complexity because it is using my base class MultiModelExtensionBase, exposed in a previous post: Preparing your viewing application for multi-model workflows.
You can have a play with the live version of the SelectionFilter there and refer to the full source code on github. Use the Model Loader to add an extra model to the scene and control selectability of various components in each model.