=========
Selection
=========

There are a few differnt types of selection available in |HCNOW|. This tutorial employs the simplest form - "pick from point", which selects the object under the cursor. Selection results are return in selection events, which we will intercept to interpret and highlight them. 

In order to do this, we'll need to set up an event callback for the ``selectionArray`` event. Notice here that if we detect a selection on the printing plane, we explicitly remove it from the selection results, as the plane is something we don't want to select.

.. code-block:: ts

    this.hwv.setCallbacks({
    
    // ...
    
    selectionArray: (selectionEvents) => {
        const ppNodeId = this.printingPlane.getNodeId(); // Node Id of the build plane

        // 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) {
            this.hwv.selectionManager.remove(selectionEvents[foundIndex].getSelection());
            selectionEvents.splice(foundIndex, 1);
        }

        // If the printing plane was the only result, then no other selections fired
        // this callback, so exit
        if (selectionEvents.length == 0) {
            return;
        }

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

        // ...
        
        
Assuming the user selected a valid object, the line ``const nodeId = selectionEvents[0].getSelection().getNodeId();`` will assign the selection to the ``nodeId`` variable. You can then use this value to perform any related processing your application requires. In our case, we are using it to get the filename and file format, then using it to update information in some of the UI widgets.

Note that selection and the visual response (usually highlighting of some kind) are two separate actions. The operator in the tutorial application does its highlighting using the selection :doc:`operator </prog_guide/viewing/operators/standard-operators>`. An operator is what performs an action in response to user input, usually in response to some kind of callback event.

.. image:: images/additive-manufacturing-selection.png

More about selection can be found :doc:`here </prog_guide/viewing/selection-and-picking>`.

Lastly, notice the last part of the function updates the matrix text at the lower right portion of the window:

.. code-block:: ts

        // ...

        this.setMatrixText(this.hwv.model.getNodeNetMatrix(nodeId));
      
    },
    
    // ...
    
    setMatrixText(matrix) {
    const ids =
       ['m11', 'm21', 'm31', 'm41',
        'm12', 'm22', 'm32', 'm42',
        'm13', 'm23', 'm33', 'm43',
        'm14', 'm24', 'm34', 'm44'];
    for (let [index, id] of ids.entries()) {
        document.getElementById(id).innerHTML = matrix.m[index].toFixed(1);
    }


.. image:: images/additive-manufacturing-selection-matrix.png


Selection handles
-----------------

Selection handles are small controls located around a selected object. These controls allow the user to manipulate the selected object independently of the others. For example, the user is able to translate and rotate an individual part using an object's handles. 

The following video demonstrates what we will be building in this section.

.. video:: ../../_assets/videos/handleOp.mp4

In order to show the object handles in the tutorial application, first select the object, then click the "Show Handles" button in the lower right panel. The logic to link that button to the logic can be seeing in *Application.ts*:

.. code-block:: ts

    document.getElementById("handles-button")!.onclick = () => this.addHandle();
    
    // ...
    
    addHandle() {
        // Need to gather the selected node IDs to know which nodes
        // will be affected by the transformation
        let nodeIds: number[] = [];
        const selectionItems = this.hwv.selectionManager.getResults();
        selectionItems.map((selectionItem) => {
            nodeIds.push(selectionItem.getNodeId());
        });

        // Ensure the user has made a selection before trying to add handles
        if (selectionItems.length !== 0) {
            let handlesOp = this.hwv.view.operatorManager.getOperator(OperatorId.Handle);
            handlesOp.addHandles(nodeIds);
            handlesOp.showHandles();
            this.hwv.view.operatorManager.push(OperatorId.Handle);
        } 
        
        // ...
    }

The logic associated with manipulating the selection handles are managed by the `HandleOperator <https://docs.techsoft3d.com/hoops/visualize-web/latest/api_ref/viewing/classes/Operators.HandleOperator.html>`_. Of course, your application can use any logic it needs to perform these actions. The ``HandleOperator`` that is packaged with |HCNOW| simply demonstrates one way to do it.