SoNavigationDragger.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2005 Jürgen Riegel <juergen.riegel@web.de>              *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 #include "PreCompiled.h"
00024 
00025 #include <Inventor/nodes/SoAntiSquish.h>
00026 #include <Inventor/nodes/SoRotation.h>
00027 #include <Inventor/nodes/SoSeparator.h>
00028 #include <Inventor/nodes/SoSurroundScale.h>
00029 #include <Inventor/nodes/SoTransform.h>
00030 #include <Inventor/sensors/SoFieldSensor.h>
00031 
00032 // Include files for child dragger classes.
00033 #include <Inventor/draggers/SoRotateCylindricalDragger.h>
00034 //#include "TranslateRadialDragger.h"
00035 #include <Inventor/draggers/SoTranslate1Dragger.h>
00036 
00037 // Include file for our new class.
00038 #include "SoNavigationDragger.h"
00039 
00040 // Include file the binaray of SoNavigationDraggerLayout.iv, the layout of the dragger.
00041 #include "SoNavigationDraggerLayout.h"
00042 
00043 // This file contains RotTransDragger::geomBuffer, which 
00044 // describes the default geometry resources for this class.
00045 //#include "RotTransDraggerGeom.h"
00046 
00047 SO_KIT_SOURCE(RotTransDragger);
00048 
00049 
00050 //  Initializes the type ID for this dragger node. This
00051 //  should be called once after SoInteraction::init().
00052 void
00053 RotTransDragger::initClass()
00054 {
00055    SO_KIT_INIT_CLASS(RotTransDragger, SoDragger, "Dragger");    
00056 }
00057 
00058 RotTransDragger::RotTransDragger()
00059 {
00060    SO_KIT_CONSTRUCTOR(RotTransDragger);
00061 
00062    // Don't create "surroundScale" by default. It's only put 
00063    // to use if this dragger is used within a manipulator.
00064    SO_KIT_ADD_CATALOG_ENTRY(surroundScale, SoSurroundScale, TRUE,
00065                             topSeparator, geomSeparator, TRUE);
00066    // Create an anti-squish node by default.
00067    SO_KIT_ADD_CATALOG_ENTRY(antiSquish, SoAntiSquish, FALSE,
00068                             topSeparator, geomSeparator, TRUE);
00069    SO_KIT_ADD_CATALOG_ENTRY(translator, SoTranslate1Dragger,
00070                             TRUE, topSeparator, geomSeparator,
00071                             TRUE);
00072    SO_KIT_ADD_CATALOG_ENTRY(XRotatorSep, SoSeparator, FALSE,
00073                             topSeparator, geomSeparator, FALSE);
00074    SO_KIT_ADD_CATALOG_ENTRY(XRotatorRot, SoRotation, TRUE,
00075                             XRotatorSep,0 , FALSE);
00076    SO_KIT_ADD_CATALOG_ENTRY(XRotator,SoRotateCylindricalDragger,
00077                             TRUE, XRotatorSep, 0,TRUE);
00078 
00079    SO_KIT_ADD_CATALOG_ENTRY(YRotator, SoRotateCylindricalDragger,
00080                             TRUE, topSeparator, geomSeparator, TRUE);
00081 
00082    SO_KIT_ADD_CATALOG_ENTRY(ZRotatorSep, SoSeparator, FALSE,
00083                             topSeparator, geomSeparator, FALSE);
00084    SO_KIT_ADD_CATALOG_ENTRY(ZRotatorRot, SoRotation, TRUE,
00085                             ZRotatorSep,0 ,FALSE);
00086    SO_KIT_ADD_CATALOG_ENTRY(ZRotator, SoRotateCylindricalDragger,
00087                             TRUE, ZRotatorSep, 0,TRUE);
00088 
00089    // Read geometry resources. Only do this the first time we
00090    // construct one. 'geomBuffer' contains our compiled in
00091    // defaults. The user can override these by specifying new
00092    // scene graphs in the file:
00093    // $(SO_DRAGGER_DIR)/rotTransDragger.iv"
00094    if (SO_KIT_IS_FIRST_INSTANCE())
00095      readDefaultParts("SoNavigationDraggerLayout.iv", 
00096                                           NavigationDraggerLayout,
00097                       strlen(NavigationDraggerLayout));
00098 
00099    // Fields that always show current state of the dragger.
00100    SO_KIT_ADD_FIELD(rotation, (0.0, 0.0, 0.0, 1.0));
00101    SO_KIT_ADD_FIELD(translation, (0.0, 0.0, 0.0));
00102 
00103    // Creates parts list and default parts for this nodekit.
00104    SO_KIT_INIT_INSTANCE();
00105 
00106    // Make the anti-squish node surround the biggest dimension
00107    SoAntiSquish *myAntiSquish =
00108             SO_GET_ANY_PART(this, "antiSquish", SoAntiSquish);
00109    myAntiSquish->sizing = SoAntiSquish::BIGGEST_DIMENSION;
00110 
00111    // Create the simple draggers that comprise this dragger.
00112    // This dragger has four simple pieces:  
00113    //    1 TranslateRadialDragger
00114    //    3 RotateCylindricalDraggers
00115    // In the constructor, we just call SO_GET_ANY_PART to
00116    // build each dragger.
00117    // Within the setUpConnections() method, we will
00118    // take care of giving these draggers new geometry and 
00119    // establishing their callbacks.
00120 
00121    // Create the translator dragger.    
00122    SoDragger *tDragger = SO_GET_ANY_PART(this, "translator", 
00123                          SoTranslate1Dragger);
00124    (void)tDragger;
00125 
00126    // Create the XRotator dragger.    
00127    SoDragger *XDragger = SO_GET_ANY_PART(this, "XRotator", 
00128                          SoRotateCylindricalDragger);
00129    (void)XDragger;
00130 
00131    // Create the YRotator dragger.    
00132    SoDragger *YDragger = SO_GET_ANY_PART(this, "YRotator", 
00133                          SoRotateCylindricalDragger);
00134    (void)YDragger;
00135 
00136    // Create the ZRotator dragger.    
00137    SoDragger *ZDragger = SO_GET_ANY_PART(this, "ZRotator", 
00138                          SoRotateCylindricalDragger);
00139    (void)ZDragger;
00140 
00141    // Set rotations in "XRotatorRot" and "ZRotatorRot" parts.
00142    // These parts will orient the draggers from their default 
00143    // (rotating about Y) to the desired configurations.
00144    // By calling 'setAnyPartAsDefault' instead of 'setAnyPart'
00145    // we ensure that they will not be written out, unless
00146    // they are changed later on.
00147    SoRotation *XRot = new SoRotation;
00148    XRot->rotation.setValue(
00149      SbRotation(SbVec3f(0,1,0), SbVec3f(1,0,0)));
00150    setAnyPartAsDefault("XRotatorRot", XRot);
00151 
00152    SoRotation *ZRot = new SoRotation;
00153    ZRot->rotation.setValue(
00154      SbRotation(SbVec3f(0,1,0), SbVec3f(0,0,1)));
00155    setAnyPartAsDefault("ZRotatorRot", ZRot);
00156 
00157    // Updates the fields when motionMatrix changes 
00158    addValueChangedCallback(&RotTransDragger::valueChangedCB);
00159 
00160    // Updates motionMatrix when either field changes.
00161    rotFieldSensor = new SoFieldSensor(
00162                         &RotTransDragger::fieldSensorCB, this);
00163    rotFieldSensor->setPriority(0);
00164    translFieldSensor = new SoFieldSensor(
00165                            &RotTransDragger::fieldSensorCB,this);
00166    translFieldSensor->setPriority(0);
00167 
00168    setUpConnections(TRUE, TRUE);
00169 }
00170 
00171 RotTransDragger::~RotTransDragger()
00172 {
00173    if (rotFieldSensor!=NULL)
00174      delete rotFieldSensor;
00175    if (translFieldSensor!=NULL)
00176      delete translFieldSensor;
00177 }
00178 
00179 SbBool
00180 RotTransDragger::setUpConnections(SbBool onOff, SbBool doItAlways)
00181 {
00182    if (!doItAlways && connectionsSetUp == onOff)
00183      return onOff;
00184 
00185    if (onOff) {
00186      // We connect AFTER base class.
00187      SoDragger::setUpConnections(onOff, doItAlways);
00188 
00189      // For each of the simple draggers that compries this:
00190      // [a]Call setPart after looking up our replacement parts 
00191      //    in the global dictionary.
00192      // [b]Add the invalidateSurroundScaleCB as a start and end
00193      //    callback. When using a surroundScale node, these 
00194      //    trigger it to recalculate a bounding box at the 
00195      //    beginning and end of dragging.
00196      // [c]Register the dragger as a 'childDragger' of this 
00197      //    one. This has the following effects: 
00198      //    [1] This dragger's callbacks will be invoked 
00199      //        following the child manip's callbacks.  
00200      //    [2] When the child is dragged, the child's motion 
00201      //        will be transferred into motion of the entire 
00202      //        dragger.
00203       SoDragger *tD =
00204                (SoDragger *) getAnyPart("translator", FALSE);
00205       // [a] Set up the parts in the child dragger...
00206       tD->setPartAsDefault("translator",
00207                            "rotTransTranslatorTranslator");
00208       tD->setPartAsDefault("translatorActive",
00209                            "rotTransTranslatorTranslatorActive");
00210       tD->setPartAsDefault("feedback",
00211                            "rotTransTranslatorFeedback");
00212       tD->setPartAsDefault("feedbackActive",
00213                            "rotTransTranslatorFeedbackActive");
00214       // [b] and [c] Add the callbacks and register the child
00215       tD->addStartCallback(
00216                &RotTransDragger::invalidateSurroundScaleCB, this);
00217       tD->addFinishCallback(
00218                &RotTransDragger::invalidateSurroundScaleCB, this);
00219       registerChildDragger(tD);
00220 
00221       SoDragger *XD =
00222                (SoDragger *) getAnyPart("XRotator", FALSE);
00223       // [a] Set up the parts in the child dragger...
00224       XD->setPartAsDefault("rotator",
00225                            "rotTransRotatorRotator");
00226       XD->setPartAsDefault("rotatorActive",
00227                            "rotTransRotatorRotatorActive");
00228       XD->setPartAsDefault("feedback",
00229                            "rotTransRotatorFeedback");
00230       XD->setPartAsDefault("feedbackActive",
00231                            "rotTransRotatorFeedbackActive");
00232       // [b] and [c] Add the callbacks and register the child
00233       XD->addStartCallback(
00234                &RotTransDragger::invalidateSurroundScaleCB, this);
00235       XD->addFinishCallback(
00236                &RotTransDragger::invalidateSurroundScaleCB, this);
00237       registerChildDragger(XD);
00238 
00239       SoDragger *YD =
00240                (SoDragger *) getAnyPart("YRotator", FALSE);
00241       // [a] Set up the parts in the child dragger...
00242       YD->setPartAsDefault("rotator",
00243                            "rotTransRotatorRotator");
00244       YD->setPartAsDefault("rotatorActive",
00245                            "rotTransRotatorRotatorActive");
00246       YD->setPartAsDefault("feedback",
00247                            "rotTransRotatorFeedback");
00248       YD->setPartAsDefault("feedbackActive",
00249                            "rotTransRotatorFeedbackActive");
00250       // [b] and [c] Add the callbacks and register the child
00251       YD->addStartCallback(
00252                &RotTransDragger::invalidateSurroundScaleCB, this);
00253       YD->addFinishCallback(
00254                &RotTransDragger::invalidateSurroundScaleCB, this);
00255       registerChildDragger(YD);
00256 
00257       SoDragger *ZD =
00258                (SoDragger *) getAnyPart("ZRotator", FALSE);
00259       // [a] Set up the parts in the child dragger...
00260       ZD->setPartAsDefault("rotator",
00261                            "rotTransRotatorRotator");
00262       ZD->setPartAsDefault("rotatorActive",
00263                            "rotTransRotatorRotatorActive");
00264       ZD->setPartAsDefault("feedback",
00265                            "rotTransRotatorFeedback");
00266       ZD->setPartAsDefault("feedbackActive",
00267                            "rotTransRotatorFeedbackActive");
00268       // [b] and [c] Add the callbacks and register the child
00269       ZD->addStartCallback(
00270                &RotTransDragger::invalidateSurroundScaleCB, this);
00271       ZD->addFinishCallback(
00272                &RotTransDragger::invalidateSurroundScaleCB, this);
00273       registerChildDragger(ZD);
00274 
00275 
00276      // Call the sensor CB to make things up-to-date.
00277      fieldSensorCB(this, NULL);
00278 
00279      // Connect the field sensors
00280      if (translFieldSensor->getAttachedField() != &translation)
00281         translFieldSensor->attach(&translation);
00282      if (rotFieldSensor->getAttachedField() != &rotation)
00283         rotFieldSensor->attach(&rotation);
00284    }
00285    else {
00286      // We disconnect BEFORE base class.
00287 
00288      // Remove the callbacks from the child draggers,
00289      // and unregister them as children.
00290       SoDragger *tD =
00291                (SoDragger *) getAnyPart("translator", FALSE);
00292       tD->removeStartCallback(
00293                &RotTransDragger::invalidateSurroundScaleCB, this);
00294       tD->removeFinishCallback(
00295                &RotTransDragger::invalidateSurroundScaleCB, this);
00296       unregisterChildDragger(tD);
00297 
00298       SoDragger *XD =
00299                (SoDragger *) getAnyPart("XRotator", FALSE);
00300       XD->removeStartCallback(
00301                &RotTransDragger::invalidateSurroundScaleCB, this);
00302       XD->removeFinishCallback(
00303                &RotTransDragger::invalidateSurroundScaleCB, this);
00304       unregisterChildDragger(XD);
00305 
00306       SoDragger *YD =
00307                (SoDragger *) getAnyPart("YRotator", FALSE);
00308       YD->removeStartCallback(
00309                &RotTransDragger::invalidateSurroundScaleCB, this);
00310       YD->removeFinishCallback(
00311                &RotTransDragger::invalidateSurroundScaleCB, this);
00312       unregisterChildDragger(YD);
00313 
00314       SoDragger *ZD =
00315                (SoDragger *) getAnyPart("ZRotator", FALSE);
00316       ZD->removeStartCallback(
00317                &RotTransDragger::invalidateSurroundScaleCB, this);
00318       ZD->removeFinishCallback(
00319                &RotTransDragger::invalidateSurroundScaleCB, this);
00320       unregisterChildDragger(ZD);
00321 
00322      // Disconnect the field sensors.
00323      if (translFieldSensor->getAttachedField()!=NULL)
00324         translFieldSensor->detach();
00325      if (rotFieldSensor->getAttachedField()!=NULL)
00326         rotFieldSensor->detach();
00327 
00328      SoDragger::setUpConnections(onOff, doItAlways);
00329    }
00330 
00331    return !(connectionsSetUp = onOff);
00332 }
00333 
00334 // Called when the motionMatrix changes. Sets the "translation"
00335 // and "rotation" fields based on the new motionMatrix
00336 void
00337 RotTransDragger::valueChangedCB(void *, SoDragger *inDragger)
00338 {
00339    RotTransDragger *myself = (RotTransDragger *) inDragger;
00340 
00341    // Factor the motionMatrix into its parts
00342    SbMatrix motMat = myself->getMotionMatrix();
00343    SbVec3f   trans, scale;
00344    SbRotation rot, scaleOrient;
00345    motMat.getTransform(trans, rot, scale, scaleOrient);
00346 
00347    // Set the fields. Disconnect the sensors while doing so.
00348    myself->rotFieldSensor->detach();
00349    myself->translFieldSensor->detach();
00350    if (myself->rotation.getValue() != rot)
00351      myself->rotation = rot;
00352    if (myself->translation.getValue() != trans)
00353      myself->translation = trans;
00354    myself->rotFieldSensor->attach(&myself->rotation);
00355    myself->translFieldSensor->attach(&myself->translation);
00356 }
00357 
00358 // If the "translation" or "rotation" field changes, changes
00359 // the motionMatrix accordingly.
00360 void
00361 RotTransDragger::fieldSensorCB(void *inDragger, SoSensor *)
00362 {
00363    RotTransDragger *myself = (RotTransDragger *) inDragger;
00364 
00365    SbMatrix motMat = myself->getMotionMatrix();
00366    myself->workFieldsIntoTransform(motMat);
00367 
00368    myself->setMotionMatrix(motMat);
00369 }
00370 
00371 // When any child dragger starts or ends a drag, tell the
00372 // "surroundScale" part (if it exists) to invalidate its 
00373 // current bounding box value.
00374 void 
00375 RotTransDragger::invalidateSurroundScaleCB(void *parent, SoDragger *)
00376 {
00377    RotTransDragger *myParentDragger = (RotTransDragger *) parent;
00378 
00379    // Invalidate the surroundScale, if it exists.
00380    SoSurroundScale *mySS = SO_CHECK_PART(
00381             myParentDragger, "surroundScale", SoSurroundScale);
00382    if (mySS != NULL)
00383       mySS->invalidate();
00384 }
00385 
00386 void
00387 RotTransDragger::setDefaultOnNonWritingFields()
00388 {
00389    // The nodes pointed to by these part-fields may 
00390    // change after construction, but we
00391    // don't want to write them out.
00392    surroundScale.setDefault(TRUE);
00393    antiSquish.setDefault(TRUE);
00394 
00395    SoDragger::setDefaultOnNonWritingFields();
00396 }

Generated on Wed Nov 23 19:00:40 2011 for FreeCAD by  doxygen 1.6.1