Open Inventor Release 2024.2.0
 
Loading...
Searching...
No Matches
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 receives an X event).
  3. The render area translates the event into an SoEvent.
  4. The SoEvent 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 stops traversing the scene graph and the node handles the event. The following sections describe how different types of nodes implement SoHandleEventAction.

SoNode

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.

SoGroup

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.

SoManipulator

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.)

Grabbing

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++ :

handleEA->setGrabber( this );

C# :

handleEA.SetGrabber( this );

Java :

handleEA.setGrabber( this );

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++ :

handleEA->releaseGrabber();

C# :

handleEA.ReleaseGrabber();

Java :

handleEA.releaseGrabber();

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.

SoSelection

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.

Inserting an SoSelection Node

Picking

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.

Selection Policy

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:

  • If the user clicks the left mouse button on a node, SoSelection 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 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 clears the selection list. With the SoSelection::SINGLE policy, only one object can be selected at a time. This policy is as follows:
  • If the user clicks the left mouse button on a node, SoSelection clears the selection list and adds the node to the list.
  • If the user clicks the left mouse button on nothing, SoSelection clears the selection list. With the SoSelection::TOGGLE policy, multiple objects can be selected at a time. This policy is as follows:
  • If the user clicks the left mouse button on a node, SoSelection toggles that node's selection status (that is, it adds the node to the list if it was not previously selected, or it removes the node from the list if it was previously selected).
  • If the user clicks the left mouse button on nothing, SoSelection does nothing.

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.

Finding the Event Handler

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:

  1. The SoSeparator 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.

Scene Graph with Manipulators
  1. 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.
  2. 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. Since it was hit, it then calls setHandled() and handles the event. In 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 object handles the event.

Picking a Shape Node