SoDragger – base class for nodekits that move in response to click-drag-release mouse events
SoDragger is the base class for all nodekits you move by using the mouse to click-drag-and-release. More specifically, they are operated by a start (mouse button 1 pressed over dragger to pick it), followed by
dragging (mouse motion events are interpreted by the dragger and result in some form of motion and/or change to a field), followed by finish (mouse up).
Each dragger has a different paradigm for interpreting
mouse motion and changing its fields as a result. Draggers map 2D mouse motion into motion of a point on 3D lines, planes, spheres or cylinders. (See the
SbProjector reference pages.) Then they react to this motion
of a point through 3-space by scaling, translating, or rotating. For example,
SoTranslate2Dragger maps mouse motion onto a 3D plane, then translates to follow the cursor as it moves within that plane.
Every dragger has
fields
that describe its current state. Scaling draggers have a
scaleFactor field, rotational draggers have a
rotation field, etc. All draggers have the
isActive field, defined in this class. It is TRUE while the dragger is being dragged,
FALSE otherwise.
Draggers that have only one part to pick and one motion field are called
simple draggers. Examples are the
SoRotateDiscDragger,
SoScale1Dragger, and
SoTranslate2Dragger.
Draggers that create assemblies out of other draggers and then orchestrate the motion
of the whole assembly are call
composite draggers.
SoTransformBoxDragger is a composite dragger made entirely of simple draggers.
SoDirectionalLightDragger contains both a simple dragger (
SoRotateSphericalDragger) and a composite dragger (
SoDragPointDragger) When using a composite dragger, the fields of the
composite dragger are the ones you should work with. Draggers lower down in the assemblage usually have zeroed out values. For example, when you drag the face of a transformBox, an
SoTranslate2Dragger, the transformBox "steals"
the translation from the child dragger and transfers it up to the top of the composite dragger, where it effects all pieces of the assemblage.
Draggers always keep their fields up to date, including
while they are being dragged. So you can use field-to-field connections and engines to connect dragger values to other parts of your scene graph. Hence draggers can be easily utilized as input devices
for mouse-driven 3D interface elements. You can also register value-changed callbacks, which are called whenever any of the fields is changed.
Also, if you set the field of a dragger through some method
other than dragging, (by calling
setValue(), for example), the dragger's internal
SoFieldSensor will sense this and the dragger will move to satisfy that new value.
This makes it easy to constrain draggers to keep their fields
within certain limits: if the limit is exceeded, just set it back to the exceeded maximum or minimum. You can do this even as the dragger is in use, by constraining the field value within a value-changed
callback that you add with
addValueChangedCallback(). In this case, be sure to temporarily disable the other value-changed callbacks using
enableValueChangedCallbacks(). Doing this will prevent infinite-looping; changing the value followed by calling the
callbacks which change the value ad infinitum.
When you drag a dragger, the dragger only moves itself. Draggers do not change the state or affect objects that follow in the scene graph. For example a dragger
does not ever behave like an
SoTransform and change the current transformation matrix. Draggers are not transforms, even if they have field names like translation, rotation, scaleFactor. Many draggers, such as
SoTrackballDragger,
have a corresponding
SoTransformManip, in this case
SoTrackballManip. The manipulator is a subclass of
SoTransform, and affects other objects in the scene; it uses a trackball
dragger to provide its user interface. In this way, draggers are employed
extensively by manipulators. Callback functions on the dragger allow its employer to be notified of start, motion, finish, and value changes. In all cases, the callback function is passed a pointer to
the dragger which initiated the callback. (See the various man pages for more details on specific draggers and manipulators).
All draggers are nodekits. However, draggers do not list their parts in the
Parts section of the reference page. Instead, there is a section called Dragger Resources, more suited to describe the parts made available to the programmer. Because of space limitations, the Dragger
Resources section only appears in the online versions of the reference pages. Each dragger has some parts you can pick on, and other parts that replace them when they are
active or moving. These active parts
are often just the same geometry in another color. Draggers also have pieces for displaying feedback. Each of these pieces has a default scene graph, as well as a special function within the dragger.
Each part also has a
resource name. All this information is contained in the
DRAGGER RESOURCES section.
Since draggers are nodekits, you can set the parts in any instance of a dragger using
setPart().
But draggers also give each part a
resource name. When
a dragger builds a part, it looks in the global dictionary for the node with that
resourceName. By putting a new entry in the dictionary, you can override that default. The default part geometries are defined as resources
for each class, and each class has a file you can change to alter the defaults. The files are listed in each dragger's man page. You can make your program use different default resources for the parts
by copying the listed file from the directory
/usr/share/data/draggerDefaults into your own directory, editing the file, and then setting the environment variable
SO_DRAGGER_DIR to be a path to that directory.