File: [Development] / inventor / lib / nodekits / src / upgraders / SoV1NkParts.c++ (download)
Revision 1.2, Tue Sep 25 00:45:47 2001 UTC (16 years, 1 month ago) by jlim
Branch: MAIN
CVS Tags: release-2_1_5-9, release-2_1_5-8, release-2_1_5-10, HEAD Changes since 1.1: +2 -2
lines
Various changes:
* Fixed Bug 63 and 64.
* Handled nonstandard sed location.
* Used for-loop in man page install.
* Included casts for 64-bit builds.
* Added placeholder for FreeBSD options.
* Included unistd.h for getopt() and stdlib.h for malloc().
* Implemented SoText[23] workaround for glibc-2.2.* iconv().
* Split long lines in SoHandleBoxDraggerGeom.h and
SoTransformerDraggerGeom.h in lib/interaction/src/draggers/geom.
* Added IV_NO_OVERLAYS/OIV_NO_OVERLAYS variables to disable overlay planes.
|
/*
*
* Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/NoticeExplan/
*
*/
/*
* Copyright (C) 1990,91 Silicon Graphics, Inc.
*
_______________________________________________________________________
______________ S I L I C O N G R A P H I C S I N C . ____________
|
| $Revision: 1.2 $
|
| Classes:
| SoV1NodekitParts
|
| Author(s) : Paul Isaacs and Thad Beier
|
______________ S I L I C O N G R A P H I C S I N C . ____________
_______________________________________________________________________
*/
#include <Inventor/SoDB.h>
#include <Inventor/misc/upgraders/SoV1NodekitParts.h>
#include <Inventor/misc/upgraders/SoV1BaseKit.h>
#include <Inventor/SoPath.h>
#include <Inventor/errors/SoDebugError.h>
#include <stdlib.h>
////////////////////////////////////////////////////////////////////////
//
// Class:
// SoV1NodekitParts
//
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
//
// Description:
// Constructor
//
// Use: internal
SoV1NodekitParts::SoV1NodekitParts( SoV1BaseKit *rootOfKit,
SoV1NodekitParts *partsSoFar )
//
////////////////////////////////////////////////////////////////////////
{
catalog = rootOfKit->getNodekitCatalog(); // assign the catalog
numEntries = catalog->getNumEntries(); // make an empty node list
nodeList = new ( SoNode *[numEntries] );
int i;
for ( i = 0; i < numEntries; i++ )
nodeList[i] = NULL;
// make rootOfKit be the entry in the nodeList for 'this'
const int partNum = catalog->getPartNumber( "this" );
if ( partNum == SO_V1_CATALOG_NAME_NOT_FOUND ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitParts::SoV1NodekitParts",
"can't find entry for top node in catalog");
#endif
}
else if ( rootOfKit == NULL ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitParts::SoV1NodekitParts",
"given root node is NULL");
#endif
}
else if (catalog->getType(partNum) != rootOfKit->getTypeId()){
#ifdef DEBUG
SoDebugError::post("SoV1NodekitParts::SoV1NodekitParts",
"given root node is of wrong type");
#endif
}
else {
nodeList[partNum] = rootOfKit;
}
// copy parts that already exist in 'partsSoFar' into this
// partsList
if ( partsSoFar != NULL ) {
for (i = 0; i < partsSoFar->numEntries; i++ ) {
if ( partsSoFar->nodeList[i] != NULL
&& partsSoFar->nodeList[i] != rootOfKit ) {
// the part exists already in 'partsSoFar'
// find the entry in the newly constructed list that
// corresponds to it.
// first, get name from 'partsSoFar'
const SbName partName = partsSoFar->catalog->getName( i );
// now, find corresponding entry in THIS list
const int oldPartNum = catalog->getPartNumber( partName );
if ( oldPartNum != SO_V1_CATALOG_NAME_NOT_FOUND )
nodeList[oldPartNum] = partsSoFar->nodeList[i];
}
}
}
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Destructor
//
// Use: internal
SoV1NodekitParts::~SoV1NodekitParts()
//
////////////////////////////////////////////////////////////////////////
{
// delete the nodelist
delete [ /*numEntries*/ ] nodeList;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Creates the node for the part asked for.
// If the part already exists, then just return TRUE without doing anything
// If not, it creates the part and all necessary parts up to the top of
// of the nodekit, and places them properly as children in the graph.
//
// Note:
// this routine will NOT search for the requested part name within the
// catalogs of its child parts.
//
// Use: internal
SbBool
SoV1NodekitParts::makePart( const int partNum )
//
////////////////////////////////////////////////////////////////////////
{
if ( !partFoundCheck( partNum ) )
return FALSE;
// if the part is already in the Node list, just return TRUE
if ( verifyPartExistence( partNum ) )
return TRUE;
// create the node
const SoNode *inst = (const SoNode *)
catalog->getDefaultType( partNum ).createInstance();
#ifdef DEBUG
if ( inst == NULL ) {
SoDebugError::post("SoV1NodekitParts::makePart",
"Can't make part %s. It belongs to an abstract class. Bad parts catalog", catalog->getName(partNum).getString());
abort();
}
#endif
nodeList[partNum] = (SoNode *) inst;
nodeList[partNum]->ref(); // temporarily ref it, until it has a parent
// if it is the topmost part in the nodekit, just return TRUE
if ( catalog->getParentName( partNum ) == "" ) {
nodeList[partNum]->unref(); // undo the temporary ref
return TRUE;
}
// create its parent part
if ( !makePart( catalog->getParentPartNumber( partNum ) ) ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitParts::makePart",
"can't make parent for part named %s",
catalog->getName(partNum).getString() );
#endif
nodeList[partNum]->unref(); // undo the temporary ref
return FALSE;
}
int parentPartNum = catalog->getParentPartNumber( partNum );
// find the next closest right sibling that already exists
int sibPartNum, searchPartNum;
for( sibPartNum = -1,
searchPartNum = catalog->getRightSiblingPartNumber( partNum );
sibPartNum == -1 && searchPartNum != SO_V1_CATALOG_NAME_NOT_FOUND;
searchPartNum = catalog->getRightSiblingPartNumber(searchPartNum )) {
if ( verifyPartExistence( searchPartNum ) )
sibPartNum = searchPartNum;
}
SoGroup *parentNode = (SoGroup *) nodeList[parentPartNum];
if (sibPartNum == -1 ) {
// no right sibling is made yet, so just add this as a child to parent
parentNode->addChild( nodeList[partNum] );
}
else {
// find that sibling's index in the parent
int sibIndex = parentNode->findChild(nodeList[sibPartNum]);
// insert this node as the new child at that index
parentNode->insertChild( nodeList[partNum], sibIndex );
}
nodeList[partNum]->unref(); // undo the temporary ref
return TRUE;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Replaces the node described with the one passed in.
//
// If the part already exists, then the current part is removed from
// its parent and the node list.
//
// Next, the new part is put in the list and made the child of its parent.
//
// Note:
// this routine will NOT search for the requested part name within the
// catalogs of its child parts.
//
// Use: internal
SbBool
SoV1NodekitParts::replacePart( const int partNum, SoNode *newPartNode )
//
////////////////////////////////////////////////////////////////////////
{
if ( !partFoundCheck( partNum ) )
return FALSE;
int parentPartNum = catalog->getParentPartNumber( partNum );
// make sure the node given is of the proper type
if ( newPartNode != NULL
&& !newPartNode->isOfType( catalog->getType( partNum ) ) ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitParts::replacePart",
"the given part is not of the correct type");
#endif
return FALSE;
}
// if an old part is already in the Node list...
if ( verifyPartExistence( partNum ) ) {
// disconnect the child from its parent
((SoGroup *)nodeList[parentPartNum])->removeChild( nodeList[partNum] );
}
// set the part!
nodeList[partNum] = newPartNode;
// if we only set the node to NULL, then just return
if ( newPartNode == NULL)
return TRUE;
// if it is the topmost part in the nodekit, just return TRUE
if ( catalog->getParentName( partNum ) == "" )
return TRUE;
// create its parent part
if ( !makePart( catalog->getParentPartNumber( partNum ) ) ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitParts::replacePart",
"can't make parent for part named %s",
catalog->getName(partNum).getString() );
#endif
return FALSE;
}
// find the next closest right sibling that already exists
int sibPartNum, searchPartNum;
for( sibPartNum = -1,
searchPartNum = catalog->getRightSiblingPartNumber( partNum );
sibPartNum == -1 && searchPartNum != SO_V1_CATALOG_NAME_NOT_FOUND;
searchPartNum = catalog->getRightSiblingPartNumber( searchPartNum)) {
if ( verifyPartExistence( searchPartNum ) )
sibPartNum = searchPartNum;
}
SoGroup *parentNode = (SoGroup *) nodeList[parentPartNum];
if (sibPartNum == -1 ) {
// no right sibling is made yet, so just add this as a child to parent
parentNode->addChild( nodeList[partNum] );
}
else {
// find that sibling's index in the parent
int sibIndex = parentNode->findChild(nodeList[sibPartNum]);
// insert this node as the new child at that index
parentNode->insertChild( nodeList[partNum], sibIndex );
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Gets the part asked for
// Note:
// this routine will NOT search for the requested part name within the
// catalogs of its child parts.
//
// Use: private
SoNode *
SoV1NodekitParts::getPartFromThisCatalog( const int partNum,
SbBool makeIfNeeded, SbBool leafCheck,
SbBool publicCheck )
//
////////////////////////////////////////////////////////////////////////
{
if ( !partFoundCheck( partNum ) )
return FALSE;
if ( leafCheck ) {
if ( !partIsLeafCheck( partNum ) )
return FALSE;
}
if ( publicCheck ) {
if ( !partIsPublicCheck( partNum ) )
return FALSE;
}
// Don't do this check any more. For this reduced version of SoBaseKit,
// allow parts that are lists to be returned with getAnyPart()
//XXX if ( !partIsNotListCheck( partNum ) )
//XXX return FALSE;
if ( makeIfNeeded == FALSE ) {
// just return whatever you can find
if ( partNum != SO_V1_CATALOG_NAME_NOT_FOUND
&& verifyPartExistence(partNum) )
return ( nodeList[ partNum ] );
else
return NULL;
}
// otherwise, we need to make the part
if ( makePart( partNum ) == TRUE )
return ( nodeList[ partNum ] ); // it was made O.K.
else
return NULL; // it didn't get made properly
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Sets the part given by nameOfPart
// Note:
// this routine will NOT search for the requested part name within the
// catalogs of its child parts.
//
// Use: private
SbBool
SoV1NodekitParts::setPartFromThisCatalog( const int partNum,
SoNode *newPartNode, SbBool anyPart )
//
////////////////////////////////////////////////////////////////////////
{
if ( !partFoundCheck( partNum ) )
return FALSE;
if ( !anyPart ) {
if ( !partIsLeafCheck( partNum ) )
return FALSE;
if ( !partIsPublicCheck( partNum ) )
return FALSE;
if ( !partIsNotListCheck( partNum ) )
return FALSE;
}
// otherwise, we need to replace the part that is currently being used
return( replacePart( partNum, newPartNode ) );
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Gets the part asked for
//
// Use: protected
SoNode *
SoV1NodekitParts::getAnyPart( const SbName &nameOfPart, SbBool makeIfNeeded,
SbBool leafCheck, SbBool publicCheck )
//
////////////////////////////////////////////////////////////////////////
{
// ONLY ALLOW SINGLE NAME PARTS...
if ( strrchr( nameOfPart.getString(), '.' ) != NULL ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitParts::getAnyPart",
"part name %s is not a single-word part",
nameOfPart.getString());
#endif
return NULL;
}
// DON'T ALLOW BRACKETS, WHICH SIGNIFY INDEXING INTO A LIST
// IN THE NEW NODEKITS.
if ( strrchr( nameOfPart.getString(), '[') != NULL ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitParts::getAnyPart",
"part name %s contains an index, which is illegal",
nameOfPart.getString());
#endif
return FALSE;
}
// IS THE REQUESTED PART IN THIS CATALOG?
int partNum = catalog->getPartNumber( nameOfPart );
if ( partNum != SO_V1_CATALOG_NAME_NOT_FOUND )
// IF SO, THEN GET IT FROM THIS CATALOG
return ( getPartFromThisCatalog( partNum, makeIfNeeded,leafCheck,
publicCheck));
else {
// ELSE, SEARCH THE CATALOG RECURSIVELY FOR THE DESIRED PART
// we need to pass a list to the recursive search saying which
// types of nodes we have already checked. This avoids infinite
// loop (does chicken contain egg? does egg contain chicken? etc...)
SbPList *typesChecked = new SbPList();
int thisPartNum = catalog->getPartNumber( "this" );
typesChecked->append(
(void *) catalog->getType(thisPartNum).getName().getString() );
for (int i = 0; i < numEntries; i++ ) {
// does it lie within this 'intermediary' part?
if ( catalog->recursiveSearch(i,nameOfPart,typesChecked) == TRUE){
delete typesChecked; // don't need this anymore
// if not making parts and 'intermediary' is NULL...
if ( makeIfNeeded == FALSE && !verifyPartExistence( i ) )
return NULL;
// create the intermediary part...
if ( !makePart( i ) )
return NULL; // error making the part
// NOTE: it's okay to cast the node into a base kit here,
// since the recursive search would only have worked
// if it was a nodekit
// UGLY, yes, but it works.
#ifdef DEBUG
// supposedly unnecessary type checking:
if ( !nodeList[i]->isOfType( SoV1BaseKit::getClassTypeId() ) )
return NULL;
#endif
SoV1BaseKit *intermediary = (SoV1BaseKit *) nodeList[i];
// now that intermediary is built, get the part from within it
return(intermediary->getAnyPart(nameOfPart,
SoNode::getClassTypeId(), makeIfNeeded,
leafCheck, publicCheck ));
}
}
delete typesChecked; // don't need this anymore
}
// IF YOU GOT HERE, THE PART COULD NOT BE FOUND
#ifdef DEBUG
SoDebugError::post("SoV1NodekitParts::getAnyPart",
"entry named %s not found. returning NULL",
nameOfPart.getString() );
#endif
return NULL;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Sets the given part with the node passed in as an argument.
// Returns TRUE if successful, FALSE if not.
//
// Use: private
SbBool
SoV1NodekitParts::setAnyPart( const SbName &nameOfPart, SoNode *newPartNode,
SbBool anyPart )
//
////////////////////////////////////////////////////////////////////////
{
// JUST SINGLE NAME PARTS...
if ( strrchr( nameOfPart.getString(), '.' ) != NULL ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitParts::setAnyPart",
"part name %s is not a single-word part",
nameOfPart.getString());
#endif
return FALSE;
}
// DON'T ALLOW BRACKETS, WHICH SIGNIFY INDEXING INTO A LIST
// IN THE NEW NODEKITS?
if ( strrchr( nameOfPart.getString(), '[') != NULL ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitParts::setAnyPart",
"part name %s contains an index, which is illegal",
nameOfPart.getString());
#endif
return FALSE;
}
// NOT A LIST ITEM, IF WE GOT HERE.
// IS THE REQUESTED PART IN THIS CATALOG?
int partNum = catalog->getPartNumber( nameOfPart );
if ( partNum != SO_V1_CATALOG_NAME_NOT_FOUND )
// IF SO, THEN SET IT USING THIS CATALOG
return ( setPartFromThisCatalog( partNum, newPartNode, anyPart ) );
else {
// ELSE, SEARCH THE CATALOG RECURSIVELY FOR THE DESIRED PART
// we need to pass a list to the recursive search saying which
// types of nodes we have already checked. This avoids infinite
// loop (does chicken contain egg? does egg contain chicken? etc...)
SbPList *typesChecked = new SbPList();
int thisPartNum = catalog->getPartNumber( "this" );
typesChecked->append(
(void *) catalog->getType(thisPartNum).getName().getString() );
for (int i = 0; i < numEntries; i++ ) {
// does it lie within this 'intermediary' part?
if ( catalog->recursiveSearch(i,nameOfPart,typesChecked) == TRUE){
delete typesChecked; // don't need this anymore
// create the intermediary part...
if ( !makePart( i ) )
return FALSE; // error making the part
// NOTE: it's okay to cast the node into a base kit here,
// since the recursive search would only have worked
// if it was a nodekit
// UGLY, yes, but it works.
#ifdef DEBUG
// supposedly unnecessary type checking:
if ( !nodeList[i]->isOfType( SoV1BaseKit::getClassTypeId() ) )
return FALSE;
#endif
SoV1BaseKit *intermediary = (SoV1BaseKit *) nodeList[i];
// now that intermediary is built, set the part within it
return(intermediary->setAnyPart(nameOfPart, newPartNode,
anyPart ));
}
}
delete typesChecked; // don't need this anymore
}
// IF YOU GOT HERE, THE PART COULD NOT BE FOUND
#ifdef DEBUG
SoDebugError::post("SoV1NodekitParts::setAnyPart",
"entry named %s not found. returning NULL",
nameOfPart.getString() );
#endif
return FALSE;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// error if partNum is not legal
//
SbBool
SoV1NodekitParts::partFoundCheck( int partNum )
{
if ( partNum == SO_V1_CATALOG_NAME_NOT_FOUND ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitParts::partFoundCheck",
"can't find part");
#endif
return FALSE;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// error if partNum is not a leaf
//
SbBool
SoV1NodekitParts::partIsLeafCheck( int partNum )
{
if ( catalog->isLeaf( partNum ) == FALSE ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitParts::partIsLeafCheck",
"can't return the part %s because it is not a leaf node in the nodekit's structure. returning NULL",
catalog->getName( partNum ).getString() );
#endif
return FALSE;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// error if partNum is not public
//
SbBool
SoV1NodekitParts::partIsPublicCheck( int partNum )
{
if ( catalog->isPublic( partNum ) == FALSE ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitParts::partIsPublicCheck",
"can't return the part %s because it is not a public node in the nodekit's structure returning NULL instead",
catalog->getName( partNum ).getString() );
#endif
return FALSE;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// error if partNum is not a list
//
SbBool
SoV1NodekitParts::partIsNotListCheck( int partNum )
{
if ( catalog->isList( partNum ) == TRUE ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitParts::partIsNotListCheck",
"can't return the part %s because it is a list in the nodekit's structure Lists must be accessed throught the methods in the nodekit. returning NULL instead",
catalog->getName(partNum).getString() );
#endif
return FALSE;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// This checks that a part still exists as the child of its parent,
// and so on up to 'this'
// It needs to be called as protection against outside parties deciding to
// delete nodes in the kit.
// If the integrity of the kit is broken, routines which call
// 'checkPartIntegrity' will know to create new parts instead, or
// perhaps return NULL.
//
SbBool
SoV1NodekitParts::verifyPartExistence( int partNum )
{
SoNode *part = nodeList[partNum];
// is the part there?
if ( part == NULL )
return FALSE;
// is the part the top of the catalog? Then we're OK
if ( partNum == catalog->getPartNumber( "this" ) )
return TRUE;
int parentPartNum = catalog->getParentPartNumber( partNum );
SoGroup *parent = (SoGroup *) nodeList[parentPartNum];
// parent should exist.
if ( parent == NULL )
return FALSE;
// part should be a valid child of parent
if ( parent->findChild( part ) < 0 )
return FALSE;
// verify the parent
return( verifyPartExistence( parentPartNum ) );
}