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:

What happens during traversal?
SoView2DSlicePan
is added to the extension listSoView2DAnnotation
is added to the extension list- The action (rendering, event evaluation) is applied to the
SoView2D
. TheSoView2D
applies this action to the extensions in the list, starting withSoView2DSlicePan
.
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:
- If you want a
SoMouseGrabber
to handle the event before any extension, it must be placed to the left of theSoView2D
. 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. - 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 totrue
, 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.