1.2. Actions, State, and Elements

The Inventor database maintains a traversal state that is used when an action is applied to a scene graph. As described in The Inventor Mentor , the traversal state is a class (SoState) used by Inventor to store state information during execution of an action. Typically, the scene graph is traversed from top to bottom and from left to right. The traversal state is modified by the nodes encountered during this traversal. State is the way nodes in the scene graph communicate with each other. For example, shape nodes need to know whether the draw style is INVISIBLE in order to know whether to draw themselves. They use the draw-style element in the state to find out.

For simplicity and extensibility, each integral piece of information in the state is stored in a separate element . For example, the current diffuse color of the material is stored in an instance of the SoDiffuseColorElement class.

Each action class has its own notion of enabling certain elements. These elements are enabled when an instance of the action is created. By default, all elements in the state are disabled, which means that they can't be set or inquired. Both nodes and actions can enable the elements they require in the state for a particular action class. The list of elements to enable is set up ahead of time, typically in the initClass() method for the node or action before instances of either are constructed. The macro SO_ENABLE() provides a convenient way for nodes to enable elements for a particular action class. For example, the SoPickStyle( C++ | Java | .NET ) node requires the pick-style element when picking, so its initClass() method enables this element in the pick action as follows:


C++
SO_ENABLE(SoPickAction, SoPickStyleElement);

A side effect of this call is that SoPickStyleElement( C++ | Java | .NET ) is also enabled in the SoRayPickAction( C++ | Java | .NET ) class, which is derived from SoPickAction( C++ | Java | .NET ). Each action class inherits the enabled elements of its parent.

The SoGLRenderAction( C++ | Java | .NET ) enables the SoViewportRegionElement( C++ | Java | .NET ), because the action is responsible for setting up this element in the state (the viewport region is specified in the action's constructor). This is how the SoGLRenderAction( C++ | Java | .NET ) enables the SoViewportRegionElement( C++ | Java | .NET ):


C++
enableElement(SoViewportRegionElement::getClassTypeId());

(Nodes typically use the SO_ENABLE() macro, and actions use the enableElement() method, since it's simple.) It doesn't hurt to enable an element in the state more than once (for example, a node and an action might enable the same element). If you are using the debugging library and you try to set or inquire an element that has not been enabled, an error message is printed. (See Appendix A, Error Handling.)

When an action is applied to a scene graph, the action builds an instance of SoState and passes a list of enabled elements to the state constructor. (If the list changes after an action is constructed, the action automatically rebuilds its state to include the newly enabled elements the next time the action is applied.)

Adding new element classes to Inventor is described in Chapter 5.

When a node is traversed, it may need to change the value of certain elements in the state. For the SoDrawStyle( C++ | Java | .NET ) node, the code to change the current value of the lineWidth element looks like this:


C++
if (! lineWidth.isIgnored())
   SoLineWidthElement::set(action->state, this,
                           lineWidth.getValue());

In this fragment, this is the node that is setting the value, and lineWidth.getValue() is the new value for the element.

Each enabled element has its own stack in the state with a unique stack index. Separators save and restore the state by pushing and popping these element stacks. The top element in the stack contains the current value for that element during traversal. Here is a brief summary of what happens behind the scenes when a node sets the value of an element in the state:

Figure 1.3, “ Nodes, Actions, Elements, and State summarizes the relationship among nodes, actions, elements, and the state.


Each element provides a static get() method that returns its value from the top element in the stack. For example,


C++
width = SoLineWidthElement::get(state);

returns the line width from the top element in the stack. Elements with multiple values provide a different sequence of get() methods, as described in Chapter 2.

Supported element classes are listed here. The class name of each listed element is preceded by So and followed by Element. For brevity, the names are abbreviated in this list. Thus, the first item is SoAmbientColorElement( C++ ).

These elements store information about the current set of materials:

These elements store information about the current lighting model and light source:

These elements store information relevant to textures:

These elements contain information about how to draw and interact with shapes:

These elements store profile information (for 3D text and NURBS surfaces):

These elements store information about transformations:

These elements are related to text objects:

These elements hold information about current GL modes:

These elements hold information about viewing:

These elements hold traversal information:

Many of the elements named above have GL-specific versions that are used only for rendering. The following elements have only GL versions: