home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / inventor / noodle / WorldInfo.c++ < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  10.5 KB  |  410 lines

  1. /*
  2.  * Copyright (C) 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  |   Classes:
  19.  |    WorldInfo
  20.  |
  21.  |   Author(s): Paul Isaacs
  22.  |
  23.  */
  24.  
  25.  
  26. #include <stdio.h>
  27. #include <Inventor/SbLinear.h>
  28. #include <Inventor/SoDB.h>
  29. #include <Inventor/SoLists.h>
  30. #include <Inventor/SbViewportRegion.h>
  31. #include <Inventor/SoPickedPoint.h>
  32.  
  33. #include <Inventor/actions/SoGetBoundingBoxAction.h>
  34. #include <Inventor/actions/SoSearchAction.h>
  35. #include <Inventor/manips/SoHandleBoxManip.h>
  36. #include <Inventor/nodes/SoSelection.h>
  37. #include <Inventor/nodes/SoSeparator.h>
  38. #include <Inventor/errors/SoDebugError.h>
  39.  
  40. #include "WorldInfo.h"
  41. #include "GeneralizedCylinder.h"
  42.  
  43. WorldInfo::WorldInfo()
  44. {
  45.     // Make worldRoot
  46.     worldRoot = new SoSeparator;
  47.     worldRoot->ref();
  48.  
  49.     // Add selection node.
  50.  
  51.     selector = new SoSelection;
  52.     worldRoot->addChild(selector);
  53.     selector->addSelectionCallback( &WorldInfo::selectionCB, this );
  54.     selector->addDeselectionCallback( &WorldInfo::deselectionCB, this );
  55.     selector->setPickFilterCallback( &WorldInfo::pickFilterCB, this );
  56.  
  57.     // Put sceneRoot under selector
  58.     sceneRoot = new SoSeparator;
  59.     selector->addChild( sceneRoot );
  60.  
  61.     // Create the deletedNoodles list. We store them so they can be un-deleted.
  62.     deletedNoodles = new SoNodeList;
  63.     
  64.     // This piece will be dragged in z whenever the activePlane moves.
  65.         currentNoodle = NULL;
  66.  
  67.     // Initialize other variables.
  68.     fileName = NULL;
  69.  
  70.     manipType = SoTransform::getClassTypeId();
  71. }
  72.  
  73. WorldInfo::~WorldInfo()
  74. {
  75.     if ( worldRoot ) worldRoot->unref();
  76.     if ( deletedNoodles ) delete deletedNoodles;
  77. }
  78.  
  79. /////////////////////////////////////////////////////////////////////
  80. // Set the type of manipulator being used to move selected noodles.
  81. // Then install one in each selected noodle.
  82. //
  83. void    
  84. WorldInfo::setManipType( SoType newType )
  85.     if ( newType == manipType)
  86.     return;
  87.  
  88.     if ( ! newType.isDerivedFrom( SoTransform::getClassTypeId() ))
  89.     return;
  90.  
  91.     manipType = newType; 
  92.  
  93.     // Get all selections; replace their transforms with the new type.
  94.     const SoPathList *pl = selector->getList();
  95.     for (int i = 0; i < selector->getNumSelected(); i++ ) {
  96.  
  97.     SoNode *t = (*pl)[i]->getTail();
  98.     if (t->isOfType(GeneralizedCylinder::getClassTypeId()))
  99.         ((GeneralizedCylinder *)t)->changeTransformType(newType);
  100.     }
  101. }
  102.  
  103. /////////////////////////////////////////////////////////////////////
  104. // Returns a copy of the scene with all noodles replaced by subgraphs
  105. // of standard inventor nodes.
  106. SoSeparator *
  107. WorldInfo::getVanillaSceneCopy()
  108. {
  109.     if (sceneRoot == NULL)
  110.     return NULL;
  111.  
  112.     SoSeparator *myCopy = (SoSeparator *) sceneRoot->copy();
  113.     myCopy->ref();
  114.  
  115.     // Replace every GeneralizedCylinder  in the copy with just the 
  116.     // data that draws, removing the nodekit.
  117.     SoSearchAction *sa = new SoSearchAction;
  118.     sa->setType( GeneralizedCylinder::getClassTypeId() );
  119.     sa->setInterest( SoSearchAction::ALL );
  120.     sa->apply( myCopy );
  121.     SoPathList *genCylPaths = &(sa->getPaths());
  122.     SoFullPath *myPath;
  123.     SoNode              *myParent;
  124.     GeneralizedCylinder *gc;
  125.     SoGroup             *parentGroup;
  126.  
  127.     for ( int i = 0; i < genCylPaths->getLength(); i++ ) {
  128.     myPath = (SoFullPath *) (*genCylPaths)[i];
  129.     myParent = myPath->getNode( myPath->getLength() - 2 );
  130.     gc = (GeneralizedCylinder *) myPath->getTail();
  131.     if ( myParent->isOfType( SoGroup::getClassTypeId() ) == FALSE ) {
  132.         fprintf(stderr,"Error converting scene to vanilla. Found a \n");
  133.         fprintf(stderr,"non-group parent of the generalized cyliinder\n");
  134.         break;
  135.     }
  136.     parentGroup = (SoGroup *) myParent;
  137.     SoSeparator *vanillaObject = gc->makeVanillaVersion();
  138.     parentGroup->replaceChild( gc, vanillaObject );
  139.     }
  140.  
  141.     // Delete the search action BEFORE unrefNodelete. This takes
  142.     // count down to 1.
  143.     delete sa;
  144.  
  145.     // Take count from 1 to 0
  146.     myCopy->unrefNoDelete();
  147.  
  148.     return myCopy;
  149. }
  150.  
  151. void 
  152. WorldInfo::setScene( SoSeparator *newScene )
  153. {
  154.     if (newScene == sceneRoot)
  155.     return;
  156.  
  157.     // Deselect everything.
  158.     selector->deselectAll();
  159.  
  160.     // Always have at least an empty separator in the scene.
  161.     if (newScene == NULL)
  162.     newScene = new SoSeparator;
  163.  
  164.     if (sceneRoot == NULL) {
  165. #ifdef DEBUG
  166.     SoDebugError::post("WorldInfo::setScene", "old sceneRoot is NULL");
  167. #endif
  168.     selector->insertChild( newScene, 0 );
  169.     }
  170.     else
  171.         selector->replaceChild( sceneRoot, newScene );
  172.  
  173.     sceneRoot = newScene;
  174.  
  175.     // Now, select the first noodle in the scene
  176.     setFirstNoodleCurrent();
  177. }
  178.  
  179. SbBool
  180. WorldInfo::isSceneEmpty()
  181. {
  182.     if (sceneRoot == NULL) {
  183. #ifdef DEBUG
  184.     SoDebugError::post("WorldInfo::setScene", "old sceneRoot is NULL");
  185. #endif
  186.     return TRUE;
  187.     }
  188.     else 
  189.     return ( sceneRoot->getNumChildren() == 0);
  190. }
  191.  
  192. void 
  193. WorldInfo::setFileName( char *newFileName )
  194. {
  195.     if (newFileName == NULL)
  196.     fileName = NULL;
  197.     else
  198.     fileName = strdup( newFileName );
  199. }
  200.  
  201. void 
  202. WorldInfo::addNoodle( GeneralizedCylinder *newNoodle )
  203. {
  204.     if (newNoodle == NULL)
  205.     return;
  206.     sceneRoot->addChild( newNoodle );
  207. }
  208.  
  209. void 
  210. WorldInfo::deleteNoodle( GeneralizedCylinder *victim )
  211. {
  212.     // See if victim is in the selection list...
  213.     // We'd prefer to delete based on selection path, if possible, since we
  214.     // can then deselect.
  215.     SoFullPath *victimPath = NULL;
  216.     for (int i = 0; i < selector->getNumSelected(); i++ ) {
  217.     if ( ((SoNodeKitPath *)selector->getPath(i))->getTail() == victim ) {
  218.         victimPath = (SoFullPath *) selector->getPath(i);
  219.         victimPath->ref();
  220.         break;
  221.     }
  222.     }
  223.     if (victimPath) {
  224.         // deselect old one if it is selected...
  225.     selector->deselect(victimPath);
  226.     }
  227.     else {
  228.         // If it wasn't a selection, get a path to it...
  229.     SoSearchAction sa;
  230.     sa.setNode( victim );
  231.     sa.setInterest( SoSearchAction::FIRST );
  232.         SbBool wasSearchingKits = SoBaseKit::isSearchingChildren();
  233.         SoBaseKit::setSearchingChildren(TRUE);
  234.     sa.apply( selector );
  235.         SoBaseKit::setSearchingChildren(wasSearchingKits);
  236.     victimPath = (SoFullPath *) sa.getPath();
  237.     if (victimPath)
  238.         victimPath->ref();
  239.     }
  240.  
  241.     if ( ! victimPath )
  242.     return;
  243.  
  244.     // Remove piece from parent.
  245.     if (victimPath != NULL) {
  246.     // Get index of victim in the path...
  247.     for (int objInd = victimPath->getLength() - 1; objInd >= 0; objInd --) {
  248.         if ( victimPath->getNode(objInd) == victim )
  249.         break;
  250.     }
  251.     SoNode *parent = NULL;
  252.     SoType bkt = SoBaseKit::getClassTypeId();
  253.     // Remove victim from its parent.
  254.     // For parent, if there's a nodekit above victim, use that first kit.
  255.         for (int pInd = objInd - 1; pInd >= 0; pInd --) {
  256.         if (victimPath->getNode(pInd)->isOfType( bkt ) ) {
  257.             parent = victimPath->getNode(pInd);
  258.             SoBaseKit *k = (SoBaseKit *)parent;
  259.             k->setPart( k->getPartString(victim), NULL );
  260.             break;
  261.         }
  262.         }
  263.     // Otherwise, use the first node above victim.
  264.         if ( parent == NULL ) {
  265.         parent = victimPath->getNodeFromTail( 1 );
  266.         if (parent->isOfType( SoGroup::getClassTypeId() ))
  267.             ((SoGroup *)parent)->removeChild( victim );
  268.         }
  269.  
  270.     }
  271.     victimPath->unref();
  272. }
  273.  
  274.  
  275. void 
  276. WorldInfo::deleteCurrentNoodle()
  277. {
  278.     if (currentNoodle == NULL)
  279.     return;
  280.  
  281.     currentNoodle->ref();
  282.     deleteNoodle( currentNoodle );
  283.     deletedNoodles->append( currentNoodle );
  284.     currentNoodle->unref();
  285. }
  286.  
  287. GeneralizedCylinder * 
  288. WorldInfo::undeleteNoodle()
  289. {
  290.     int num = deletedNoodles->getLength();
  291.     if ( num <= 0)
  292.     return NULL;
  293.  
  294.     GeneralizedCylinder *theNoodle 
  295.     = (GeneralizedCylinder *) (*deletedNoodles)[num - 1];
  296.  
  297.     theNoodle->ref();
  298.  
  299.     addNoodle( theNoodle );
  300.  
  301.     // Since we're undeleting the noodle, make it the only selection.
  302.     selector->deselectAll();
  303.     selector->select( theNoodle );
  304.  
  305.     setCurrentNoodle( theNoodle );
  306.  
  307.     theNoodle->unrefNoDelete();
  308.  
  309.     deletedNoodles->remove( num - 1);
  310.  
  311.     return theNoodle;
  312. }
  313.  
  314. GeneralizedCylinder *
  315. WorldInfo::setFirstNoodleCurrent()
  316. {
  317.     if (sceneRoot == NULL)
  318.     return NULL;
  319.  
  320.     SoSearchAction sa;
  321.     sa.setType( GeneralizedCylinder::getClassTypeId() );
  322.     sa.apply( sceneRoot );
  323.     SoPath *pathToFirst = sa.getPath();
  324.     if (pathToFirst == NULL)
  325.     return NULL;
  326.  
  327.     GeneralizedCylinder *first = (GeneralizedCylinder *) pathToFirst->getTail();
  328.  
  329.     // Since we're undeleting the noodle, make it the only selection.
  330.     selector->deselectAll();
  331.     selector->select( first );
  332.  
  333.     setCurrentNoodle( first );
  334.  
  335.     return first;
  336. }
  337.  
  338. GeneralizedCylinder * 
  339. WorldInfo::addNewNoodle()
  340. {
  341.     GeneralizedCylinder *newOne = new GeneralizedCylinder;
  342.     newOne->ref();
  343.  
  344.     addNoodle( newOne );
  345.  
  346.     // Since we're adding a new noodle, make it the only selection.
  347.     selector->deselectAll();
  348.     selector->select( newOne );
  349.  
  350.     setCurrentNoodle( newOne );
  351.     newOne->unrefNoDelete();
  352.  
  353.     return newOne;
  354. }
  355.  
  356. void
  357. WorldInfo::setCurrentNoodle( GeneralizedCylinder *newNoodle )
  358. {
  359.     currentNoodle = newNoodle;
  360.  
  361.     // Add a manipulator if necessary...
  362.     if (currentNoodle)
  363.     currentNoodle->changeTransformType( getManipType() );
  364. }
  365.  
  366. void
  367. WorldInfo::selectionCB(void *userData, SoPath *selectPath)
  368. {
  369.     // Return if pickFilter truncated path down to nothing.
  370.     if (selectPath->getLength() == 0)
  371.     return;
  372.  
  373.     WorldInfo *myself = (WorldInfo *) userData;
  374.  
  375.     SoNodeKitPath *nkPath = (SoNodeKitPath *) selectPath;
  376.     GeneralizedCylinder *g = (GeneralizedCylinder *) nkPath->getTail();
  377.  
  378.     myself->setCurrentNoodle( g );
  379. }
  380.  
  381. void
  382. WorldInfo::deselectionCB(void *, SoPath *deselectPath)
  383. {
  384.     if (deselectPath->getLength() == 0)
  385.     return;
  386.  
  387.     SoNodeKitPath *nkPath = (SoNodeKitPath *) deselectPath;
  388.     GeneralizedCylinder *g = (GeneralizedCylinder *) nkPath->getTail();
  389.  
  390.     g->changeTransformType( SoTransform::getClassTypeId() );
  391. }
  392.  
  393. SoPath *
  394. WorldInfo::pickFilterCB(void *data, const SoPickedPoint *pick )
  395. {
  396.     WorldInfo *myself = (WorldInfo *) data;
  397.  
  398.     SoPath *filteredPath = NULL;
  399.     SoFullPath *fullP = (SoFullPath *) pick->getPath();
  400.  
  401.     // Go up the path, and keep popping nodes until the tail is a
  402.     // Generalized Cylinder kit...
  403.     while ( fullP->getLength() > 0 &&
  404.     ! fullP->getTail()->isOfType( GeneralizedCylinder::getClassTypeId() ) )
  405.     fullP->pop();
  406.  
  407.     return fullP;
  408. }
  409.