10.4. How Nodes Handle Events: SoHandleEventAction

(Advanced) Inventor provides a mechanism for automatic event handling by “smart” nodes, which can be summarized as follows:

  1. The render area registers interest in particular events with its window system.

  2. The render area receives an event from its window system. (SoXtRenderArea( C++ ) receives an X event.)

  3. The render area translates the event into an SoEvent( C++ | Java | .NET ).

  4. TheSoEvent( C++ | Java | .NET ) is sent to the scene manager, which creates an instance of the SoHandleEventAction.

  5. (Advanced) The handle event action is applied to the top node of the scene graph. This action traverses the scene graph. Each node implements its own action behavior, as described in the following paragraphs. When a node is found to handle the event (typically a manipulator), the SoHandleEventAction( C++ | Java | .NET ) stops traversing the scene graph and the node handles the event.

The following sections describe how different types of nodes implement SoHandleEventAction( C++ | Java | .NET ).

SoNode( C++ | Java | .NET ), the base class for all nodes, does nothing for the handle event action. Therefore, all properties, transforms, shapes, cameras, and lights do nothing for this action.

When the handle event action is applied to an SoGroup( C++ | Java | .NET ), the group traverses its children from left to right, asking each child to handle the event. After each child, it checks to see if the event was handled. If it was, the handle event action ends its traversal of the scene graph. If the event was not handled, the SoGroup( C++ | Java | .NET ) asks the next child to handle the event.

The SoGroup( C++ | Java | .NET ) uses the isHandled() method of SoHandleEventAction( C++ | Java | .NET ) to find out if an event has been handled. When a node handles an event, it calls setHandled() on the handle event action.

Manipulators are the “smart” objects in the scene graph that handle certain kinds of events (see Chapter 17, Draggers and Manipulators for a more detailed discussion). Typically, a manipulator replaces a node in the scene graph with an editable version of that node. Using SoHandleBoxManip( C++ | Java | .NET ), you can change an object's size and position by replacing the transform node in the scene graph that affects the object with the handle-box manipulator. This manipulator then scales and translates itself in response to the user moving the mouse. Using SoTrackballManip( C++ | Java | .NET ), you can rotate an object around a center point by replacing the appropriate transform node in the scene graph with a

trackball manipulator. This manipulator then changes its rotation field in response to the user moving the mouse.

Manipulators, such as the trackball and handle box, require picking information in addition to the event type. These manipulators call getPickedPoint() on SoHandleEventAction( C++ | Java | .NET ) to see which object was picked. If the manipulator was picked, it handles the event. You can also create manipulators that do not require a hit on their geometry to be activated. (See The Inventor Toolmaker, Chapter 8, for information on creating your own manipulator.)

An SoSelection( C++ | Java | .NET ) node, derived from SoGroup( C++ | Java | .NET ), is typically inserted near the top of the scene graph, as shown in Figure 10.3, “ Inserting an SoSelection Node. When the handle event action is applied to an SoSelection( C++ | Java | .NET ) node, it traverses its children in the same way as SoGroup( C++ | Java | .NET ). However, if none of its children handles the event, the selection node itself handles it.


When a left-mouse-button event occurs, the SoSelection( C++ | Java | .NET ) object needs to know which node was picked. It calls the getPickedPoint() method on the handle event action. (SoSelection( C++ | Java | .NET ) checks the picked object on both mouse-down and mouse-up events to make sure that both events occurred over the same object. Specify FALSE for the setPickMatching() method to disable this feature, and SoSelection( C++ | Java | .NET ) will get the picked point only on mouse-up events.)

The handle event action performs the pick the first time a node in the scene graph requests information concerning the hit objects (picking is performed only when necessary). SoHandleEventAction( C++ | Java | .NET ) caches this picking information so that any subsequent nodes encountered during traversal, such as manipulators and the selection object, can have access to this information quickly. Only one pick (at most) is performed during the traversal for SoHandleEventAction( C++ | Java | .NET ).

After receiving the pick information, the SoSelection( C++ | Java | .NET ) class implements the appropriate selection policy. Currently, you can choose one of three

selection policies with the policy field. SoSelection( C++ | Java | .NET ) keeps track of the selection list for you. Selected objects can be highlighted by the render area (see the section called “Highlighting Selected Objects”). The default selection policy, SoSelection::SHIFT, is as follows:

  • If the user clicks the left mouse button on a node, SoSelection( C++ | Java | .NET ) clears the selection list and adds the node to the list.

  • If the user clicks the left mouse button on a node while pressing the Shift key, SoSelection( C++ | Java | .NET ) toggles the node's selection status (that is, if the node is currently in the selection list, it is removed from the list; if the node is not currently selected, it is added to the selection list).

  • If the user clicks the left mouse button on nothing, SoSelection( C++ | Java | .NET ) clears the selection list.

With the SoSelection::SINGLE policy, only one object can be selected at a time. This policy is as follows:

With the SoSelection::TOGGLE policy, multiple objects can be selected at a time. This policy is as follows:

[Tip]

Tip: Shift selection is the same as Single selection when the Shift key is not pressed, and Toggle selection when the Shift key is pressed.

If none of these selection policies meets your needs, you can implement your own custom selection policy by creating an event callback node and passing it a pointer to the SoSelection( C++ | Java | .NET ) node. You can then call select(), deselect(), toggle(), and deselectAll() on the SoSelection( C++ | Java | .NET ) node to implement your new selection policy. An additional alternative is to derive your own class from SoSelection( C++ | Java | .NET ).

See Section 10.7, “Selection” for more information on the selection list.

The following example illustrates the process of finding the event handler for a given event. Assume you have a scene graph containing several shape objects, with a handle-box manipulator that affects the transformation of an indexed face set. The scene graph also contains yourManip, a manipulator you've written that handles the middle mouse-button event. This scene graph is shown in Figure 10.4, “ Scene Graph with Manipulators.

If the user clicks the left mouse button on the handle box surrounding the face-set object on the screen, the scene manager receives the event and sends it to the SoHandleEventAction( C++ | Java | .NET ) with the setEvent() method. Here is how the nodes in Figure 10.4, “ Scene Graph with Manipulators respond during the handle event action traversal:

  1. The SoSeparator( C++ | Java | .NET ) group asks each child, from left to right in the scene graph, to handle the event.

  2. The yourManip node does not handle the event, since it handles only middle mouse-button events.


  3. The carGroup node traverses each of its children, from left to right, and asks them to handle the event. The third child, also a group, traverses its children from left to right.

  4. The handle-box manipulator node, which handles left mouse events, needs to know if it is in the picked path. It calls getPickedPoint() on the SoHandleEventAction( C++ | Java | .NET ). Since it was hit, it then calls setHandled() and handles the event.

In Figure 10.5, “ Picking a Shape Node, the scene graph contains a new instance of a face set (faceSet2). Suppose the user clicks on this face set instead of the handle box surrounding faceSet1. Since the handle-box manipulator is not contained in the pick path and has no effect on the pick path, it does not handle the event. In this case, the SoSelection( C++ | Java | .NET ) object handles the event.