(Advanced) Inventor provides a mechanism for automatic event handling by “smart” nodes, which can be summarized as follows:
SoNode, 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, 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 asks the next child to handle the event.
The SoGroup uses the isHandled() method of SoHandleEventAction 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 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, 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, 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 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 Creating Draggers and Manipulators, for information on creating your own manipulator.)
A node can request that all subsequent events be sent directly to it until further notice. This request is called grabbing. For example, after receiving a mouse-button-down event, a manipulator might grab all subsequent events until a mouse-button-up event occurs. The setGrabber() method is called on the handle event action, with the manipulator as argument (this):
C++ :
C# :
Java :
The handle event action now applies the action directly to the grabbing node instead of to the scene graph root. To stop grabbing events, the manipulator uses the releaseGrabber() method:
C++ :
C# :
Java :
If the node calls releaseGrabber() for an event but did not handle the event, the handle event action initiates a traversal at the root and passes the event to the entire scene graph. For example, manipulators grab after a mouse- press event. However, if a mouse release occurs with no mouse motion in between, the manipulator ungrabs and does not handle the event. The event is then passed to the scene graph for processing.
The getGrabber() method returns the node that is currently grabbing events. (See SoHandleEventAction in the Open Inventor C++ Reference Manual.)
Grabbing events in the scene graph does not perform an X server grab.
An SoSelection node, derived from SoGroup, is typically inserted near the top of the scene graph, as shown in Inserting an SoSelection Node . When the handle event action is applied to an SoSelection node, it traverses its children in the same way as SoGroup. However, if none of its children handles the event, the selection node itself handles it.
When a left-mouse-button event occurs, the SoSelection object needs to know which node was picked. It calls the getPickedPoint() method on the handle event action. (SoSelection 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 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 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.
After receiving the pick information, the SoSelection class implements the appropriate selection policy. Currently, you can choose one of three
selection policies with the policy field. SoSelection keeps track of the selection list for you. Selected objects can be highlighted by the render area (see Highlighting Selected Objects). The default selection policy, SoSelection::SHIFT, is as follows:
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 node. You can then call select(), deselect(), toggle(), and deselectAll() on the SoSelection node to implement your new selection policy. An additional alternative is to derive your own class from SoSelection.
See 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 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 with the setEvent() method. Here is how the nodes in Scene Graph with Manipulators respond during the handle event action traversal: