5. Setting the Selection Callback

Summary

In this chapter, we will walk through finishing our WebViewer callbacks, in particular, the selectionArray callback.

Concepts


By default, HOOPS Communicator enables the Selection and Navigate operators, so you should already be able to interact with the model in this mainViewer. Try clicking on one of the parts on your model to see the selection operator at work. It should highlight, indicating selection - but what else is happening? We can see there are fields for model and node information in our application, but nothing is populated. We will write a selectionArray callback to populate these fields.

Because we are only interacting in our mainViewer object, we only need to add this selectionArray callback on the mainViewer. Let's look at what information we might want to query from the model and display. We can see fields for the model file name, the file type, node name, node ID, and node transform information. There are additional fields and information you can query of course, and those data items can follow this same pattern.

The selectionArray callback fires whenever Communicator detects a selection event. The callback will query the current state of the selectionManager to see which nodes have been selected by the user and currently are being tracked by the WebViewer. While the default is to just highlight one node, we can select multiple nodes as well. All currently active and selected nodes are passed to the selectionArray callback each time the callback is invoked.

Given this information, we can use the NodeSelectionEvent array returned by the selectionArray callback to gather information or operate on that particular selection. First we will ensure the printingPlane object was not selected by the user. Since this was a mesh created a run time rather than a model we wish to query and manipulate, we want it removed if it was selected. We can do this by comparing the nodeId of the printing plane (which we obtained at the time of creation of the printingPlane and stored as a property of the class) to the nodeIds of the NodeSelectionEvent array items. If the ID is found, we will remove it from the selection array. If it was the only item that fired the callback event, exit the callback function.

// Adding functionality for a selection callback in the mainViewer
selectionArray: (selectionEvents) => {
// Do Not Want the Build Plate as a Part of any Model Selection Events
const ppNodeId = this._printSurfaces[0].getNodeId(); // Node Id of the build plate
// Return the selection IDs for the current selections, check if the printing plane
// was selected in the results - if so, remove it
const selectionIds = selectionEvents.map(sEvent => sEvent.getSelection().getNodeId());
const foundIndex = selectionIds.indexOf(ppNodeId);
if (foundIndex != -1) {
mainViewer.selectionManager.remove(selectionEvents[foundIndex].getSelection());
selectionEvents.splice(foundIndex, 1);
}
// If the printing plane was the only result, no other selections fired
// this callback, so exit
if (selectionEvents.length == 0)
return;
}

If there were other selections that occurred, we will take the first result of the selection array and display its information. We already have obtained the selection nodeId, so we can now just use the appropriate getter method on the model class to obtain further information. Once this information is obtained, we can update the DOM placeholder elements for this info.

const nodeId = selectionEvents[0].getSelection().getNodeId();
const modelFileName = mainViewer.model.getModelFileNameFromNode(nodeId);
const modelFileFormat = mainViewer.model.getModelFileTypeFromNode(nodeId);
document.getElementById("model-file-name").innerHTML = modelFileName || "N/A";
document.getElementById("model-file-type").innerHTML = Communicator.FileType[modelFileFormat] || "N/A";
document.getElementById("node-id").innerHTML = nodeId.toString() || "Unknown";
document.getElementById("node-name").innerHTML = mainViewer.model.getNodeName(nodeId) || "Node Name Not Defined";

Rerunning your application, you should now see the "Inspector" component update values depending on the node selection from the user. You may click on the same node again to highlight its parent node and see information higher in the model tree. By default, the selection operator will highlight the sub-entity of the node (i.e. the edge, face, etc), but clicking again will display the entire node information (as it then selects its parent node). This is configurable with a custom selection operator and setting the appropriate "pick configuration".