SoView2DExtensions

Introduction

The SoView2D module allows the display of slices or slabs of an attached image volume in a 2D viewer. The functionality of the SoView2D can be extended using modules of the SoView2DExtension framework. These modules fulfill several functions:

  • Modification of the display of the image data in the viewer (zooming, panning, slicing, and modification of the transfer function)
  • Generation and modification of geometry (Markers, CSOs, etc.)
  • Display of additional data/information (annotations, overlays, geometry including Open Inventor and GVR projected onto the slab).

If you need better control over events, use Managed Interaction (refer to Managed Interaction).

General Usage and Scene Graph Traversal

Extensions are inserted into the scene graph to the left of the SoView2D. They are not treated like other Open Inventor nodes! Although they are traversed in the normal way (top to bottom, left to right), they are not rendered during traversal and do not evaluate events during traversal. The traversal serves only one purpose: all extensions that belong to a SoView2D are collected in a list. Once the SoView2D executes an action (rendering, event evaluation), it applies this action to the extensions in the list. The following image illustrates this behavior:

Images/SoView2DExtensionGraphTraversal.png

What happens during traversal?

  1. SoView2DSlicePan is added to the extension list
  2. SoView2DAnnotation is added to the extension list
  3. The action (rendering, event evaluation) is applied to the SoView2D. The SoView2D applies this action to the extensions in the list, starting with SoView2DSlicePan.

Common Parameters

There are several parameters that are common to all extensions. Most of them are normally hidden on the automatic panel. Not all of them are used in every extension!

Rendering

Field Function
color Sets the color that should be used for rendering.
drawingOn Controls whether the extension should render itself.
renderOnSlab Controls whether the extension should be rendered on all slab slices.
clipToSlice Controls whether the rendering should be clipped to the slice.

Events

Field Function
color Sets the color that should be used for rendering.
drawingOn Controls whether the extension should render itself.
renderOnSlab Controls whether the extension should be rendered on all slab slices.
editingOn Controls whether the extension should edit objects on mouse events.
selectionTolerance Sets the selection tolerance in pixels.
setEventHandled Controls whether the event should be set as ‘handled’ if it is indeed consumed by this extension.
ignoreHandledEvents Controls whether events that have been handled/consumed by previous extensions should be ignored.
button1 Sets the mouse mask for button 1
button2 Sets the mouse mask for button 2
button3 Sets the mouse mask for button 3
shift Shift modifier for the mouse mask
control Control modifier for the mouse mask
alt Alt modifier for the mouse mask
needsValidVoxel Controls whether an event is only evaluated if it occurred on a valid voxel.
maskValid Shows whether the incoming event meets the criteria of the mouse mask. It is updated from inside the module. Do not set it!
cursorShape Sets the cursor shape if the mouse mask fits and mouseEvents are evaluated.
wantsAllEvents Controls whether ALL events should be evaluated. If it is disabled, events are only evaluated if the mouse mask gets valid. However, consumed events will not be evaluated if ignoreHandledEvents is set to true.
wantsKeyEvents Controls whether keyboard events should be evaluated.
wantsMouseWheelEvents Controls whether mouse wheel events should be evaluated.

Mouse Masks

Incoming events can be filtered by button number and special keys. An event is processed only if the criteria for all buttons and special keys are met.

There are three states for a button and key filter:

  • Pressed: the button or key must be pressed
  • Released: the button or key must be released
  • Ignored: the state of the button or key does not affect the processing of the event

The field maskValid indicates for an incoming event if it fulfills all criteria of the mask. This means that every extension can be used to detect mouse clicks.

Event Handling and Consumption

Depending on the used mouse masks, several extensions might evaluate the same event. This can be avoided due to event consumption. This means that an extension can set an event as ‘handled’ (if the field setEventHandled is set to true) if the extension really performed an interaction.

Subsequent extensions can then decide whether to evaluate this event again (if ignoreHandledEvents is false) or to ignore it (if ignoreHandledEvents is true).

Using this mechanism, several behaviors can be implemented. For example, while dragging a SoView2DPlane, SoView2DSliceZoom will not change the zoom factor. You do not need to assign different button and key masks to your extensions.

Evaluation Order

If certain extensions do not evaluate an event because it has been handled previously, the order of event evaluation in the extensions becomes more important. The leftmost extension is evaluated first by default and, therefore, evaluates every event according to the mouse mask.

Subsequent extensions might not evaluate the event due to the settings. Keep this in mind during scene graph design!

In most cases, it makes sense to arrange extensions that generate or modify geometry (SoView2DPlane, SoView2DMarkerEditor, etc.) to the left of extensions that do not need any clickable geometry (SoView2DSliceZoom, SoView2DSliceShift, SoView2DAutoCenter,etc.).

Rendering Order

The evaluation order (left to right) is also used for rendering by default. This means that the rightmost extension is rendered last and might occlude previous extensions. The result may be that a completely occluded extension evaluates an event while the visible one does not.

The SoView2D has a field reverseDrawingOrder that allows for the inversion of this behavior. If it is set to true, the rightmost extension will be rendered first, and the leftmost last. In this case, the appearance matches the evaluation of the events. The default value of this field is false.

Cooperative Mode

In several modules (SoView2DMarkerEditor, SoView2DRectangle, SoView2DPosition), there exists a “Cooperative” mode that controls whether the handled flag of the event is set or read.

In those modules, setEventHandled and ignoreHandledEvents have no consequence at the moment (although they are available in the automatic panel). These modules ignore handled events by default and set events as handled if the cooperative mode is enabled. This means that they can cooperate with all other extensions as well. However, their behavior cannot be parameterized in the same way.

Extension Grouping

To implement complex event consumption strategies, you can use the SoView2DExtensionSeparator module. This module groups its child extensions and manages their rendering order and event consumption.

Coordination with Other Open Inventor Nodes

There are other nodes that handle events, such as SoMouseGrabber (which will be used as an example for now). To coordinate event consumption between such nodes and SoView2DExtensions, the order of the nodes is very important. There are only two essential variants:

  1. If you want a SoMouseGrabber to handle the event before any extension, it must be placed to the left of the SoView2D. Its position in relation to the extensions is absolutely irrelevant. If it is positioned to the left of the SoView2D, it handles the event before the SoView2D and, consequently, before ALL extensions that belong to that SoView2D due to the way extensions are treated during traversal (see General Usage and Scene Graph Traversal). There is no way to place a SoMouseGrabber such that it handles an event between two extensions! If the mouse grabber consumes the event (fields setEventHandled and setWheelEventHandled), the SoView2D will not receive this event, and therefore no extension can handle it.
  2. If you want SoView2DExtensions to handle events before the SoMouseGrabber, then the SoMouseGrabber must be placed to the right of the SoView2D. The extensions might consume an event as described previously. If you want the SoMouseGrabber to handle the event, even if it has been consumed by the extensions, you must set the option Pass handled-flag to Inventor of the SoView2D to false. If you set it to true, the event will not be forwarded to any node after the SoView2D!

The same applies to other Open Inventor nodes in addition to the event consumption of SoMouseGrabber. There are currently no fields in other nodes that are equivalent to setEventHandled and setWheelEventHandled.