File: [Development] / inventor / apps / examples / Toolmaker / 08.Manips / Coordinate3Manip.c++ (download)
Revision 1.2, Sun Oct 29 15:04:16 2000 UTC (17 years 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: +1 -1
lines
Eliminated or reduced compiler errors and warnings, as tested with
egcs-2.91.66 (on Red Hat 6.0) and gcc 2.96 (on Red Hat 6.2).
|
/*
*
* 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/
*
*/
/*-------------------------------------------------------------
* This is an example from the Inventor Toolmaker,
* chapter 8, example 19
*
* Source file for "Coordinate3Manip"
*----------------------------------------------------------*/
#include <Inventor/actions/SoCallbackAction.h>
#include <Inventor/actions/SoGLRenderAction.h>
#include <Inventor/actions/SoGetBoundingBoxAction.h>
#include <Inventor/actions/SoGetMatrixAction.h>
#include <Inventor/actions/SoHandleEventAction.h>
#include <Inventor/actions/SoPickAction.h>
#include <Inventor/actions/SoSearchAction.h>
#include <Inventor/draggers/SoDragPointDragger.h>
#include <Inventor/errors/SoDebugError.h>
#include <Inventor/fields/SoSFInt32.h>
#include <Inventor/nodes/SoGroup.h>
// Include file for our new class
#include "Coordinate3Manip.h"
SO_NODE_SOURCE(Coordinate3Manip);
// Initializes the type ID for this manipulator node. This
// should be called once after SoInteraction::init().
void
Coordinate3Manip::initClass()
{
SO_NODE_INIT_CLASS(Coordinate3Manip, SoCoordinate3, "Coordinate3");
}
Coordinate3Manip::Coordinate3Manip()
{
children = new SoChildList(this);
SO_NODE_CONSTRUCTOR(Coordinate3Manip);
// Create the new 'editIndex' field
SO_NODE_ADD_FIELD(editIndex, (0));
// Create the field sensor
pointFieldSensor = new SoFieldSensor(
&Coordinate3Manip::fieldSensorCB, this);
pointFieldSensor->setPriority(0);
pointFieldSensor->attach(&point);
// Create a new SoDragPointDragger and use
// it for our child-dragger.
setDragger(new SoDragPointDragger);
}
Coordinate3Manip::~Coordinate3Manip()
{
// Important to do this because dragger may have callbacks
// to this node.
setDragger(NULL);
if (pointFieldSensor)
delete pointFieldSensor;
delete children;
}
// Sets the dragger to be the given node...
// Adds it as a child and adds a valueChangedCallback
// on the child to tell this node when the dragger moves.
void
Coordinate3Manip::setDragger(SoDragger *newDragger)
{
SoDragger *oldDragger = getDragger();
if (oldDragger) {
oldDragger->removeValueChangedCallback(
&Coordinate3Manip::valueChangedCB,this);
children->remove(0);
}
if (newDragger) {
if (children->getLength() > 0)
children->set(0, newDragger);
else
children->append(newDragger);
// Call the fieldSensorCB to transfer our values
// into the new dragger.
Coordinate3Manip::fieldSensorCB(this, NULL);
newDragger->addValueChangedCallback(
&Coordinate3Manip::valueChangedCB,this);
}
}
// Returns value of the current dragger.
SoDragger *
Coordinate3Manip::getDragger()
{
if (children->getLength() > 0) {
SoNode *n = (*children)[0];
if (n->isOfType(SoDragger::getClassTypeId()))
return ((SoDragger *) n);
else {
#ifdef DEBUG
SoDebugError::post("Coordinate3Manip::getDragger",
"Child is not a dragger!");
#endif
}
}
return NULL;
}
// Description:
// Replaces the tail of the path with this manipulator.
//
// [1] Tail of fullpath must be correct type, or we return.
// [2] If path has a nodekit, we try to use setPart() to insert manip.
// otherwise:
// [3] Path must be long enough, or we return without replacing.
// [4] Second to last node must be a group, or we return without replacing.
// [5] Copy values from node we are replacing into this manip
// [6] Replace this manip as the child.
// [7] Do not ref or unref anything. Assume that the user knows what
// they're doing.
// [8] Do not fiddle with either node's field connections. Assume that the
// user knows what they're doing.
//
SbBool
Coordinate3Manip::replaceNode(SoPath *inPath)
{
SoFullPath *myFullPath = (SoFullPath *) inPath;
SoNode *myFullPTail = myFullPath->getTail();
if (myFullPTail->isOfType(SoCoordinate3::getClassTypeId()) == FALSE ) {
#ifdef DEBUG
SoDebugError::post("Coordinate3Manip::replaceNode",
"End of path is not an SoCoordinate3");
#endif
return FALSE;
}
SoNode *pTail = inPath->getTail();
if ( pTail->isOfType(SoBaseKit::getClassTypeId())) {
// Okay, we've got a nodekit here! Let's do this right...
// If myFullPTail is a part in the kit, then we've got to follow
// protocol and let the kit set the part itself.
SoBaseKit *lastKit = (SoBaseKit *) ((SoNodeKitPath *)inPath)->getTail();
SbString partName = lastKit->getPartString(inPath);
if ( partName != "" ) {
SoCoordinate3 *oldPart
= (SoCoordinate3 *) lastKit->getPart(partName, TRUE);
if (oldPart != NULL) {
// detach the sensor while copying the values.
pointFieldSensor->detach();
point = oldPart->point;
Coordinate3Manip::fieldSensorCB(this, NULL);
pointFieldSensor->attach(&point);
lastKit->setPart(partName, this);
return TRUE;
}
else {
// Although the part's there, we couldn't get at it.
// Some kind of problem going on
return FALSE;
}
}
// If it's not a part, that means it's contained within a subgraph
// underneath a part. For example, it's within the 'contents'
// separator of an SoWrapperKit. In that case, the nodekit doesn't
// care and we just continue on through...
}
if ( myFullPath->getLength() < 2 ) {
#ifdef DEBUG
SoDebugError::post("Coordinate3Manip::replaceNode",
"Path is too short!");
#endif
return FALSE;
}
SoNode *parent = myFullPath->getNodeFromTail( 1 );
if (parent->isOfType( SoGroup::getClassTypeId() ) == FALSE ) {
#ifdef DEBUG
SoDebugError::post("Coordinate3Manip::replaceNode",
"Parent node is not a group.!");
#endif
return FALSE;
}
ref();
// detach the sensor while copying the values.
pointFieldSensor->detach();
point = ((SoCoordinate3 *)myFullPTail)->point;
Coordinate3Manip::fieldSensorCB(this, NULL);
pointFieldSensor->attach(&point);
((SoGroup *)parent)->replaceChild(myFullPTail, this);
unrefNoDelete();
return TRUE;
}
// Replaces tail of path (which should be this manipulator)
// with the given SoCoordinate3 node.
//
// [1] Tail of fullpath must be this node, or we return.
// [2] If path has a nodekit, we try to use setPart() to insert new node.
// otherwise:
// [3] Path must be long enough, or we return without replacing.
// [4] Second to last node must be a group, or we return without replacing.
// [5] Copy values from node we are replacing into this manip
// [6] Replace this manip as the child.
// [7] Do not ref or unref anything. Assume that the user knows what
// they're doing.
// [8] Do not fiddle with either node's field connections. Assume that the
// user knows what they're doing.
//
SbBool
Coordinate3Manip::replaceManip(SoPath *path,
SoCoordinate3 *newOne) const
{
SoFullPath *myFullPath = (SoFullPath *) path;
SoNode *myFullPTail = myFullPath->getTail();
if (myFullPTail != (SoNode *) this ) {
#ifdef DEBUG
SoDebugError::post("Coordinate3Manip::replaceManip",
"Child to replace is not this manip!");
#endif
return FALSE;
}
SoNode *pTail = path->getTail();
if ( pTail->isOfType(SoBaseKit::getClassTypeId())) {
// Okay, we've got a nodekit here! Let's do this right...
// If myFullPTail is a part in the kit, then we've got to follow
// protocol and let the kit set the part itself.
SoBaseKit *lastKit = (SoBaseKit *) ((SoNodeKitPath *)path)->getTail();
SbString partName = lastKit->getPartString(path);
if ( partName != "" ) {
if (newOne == NULL)
newOne = new SoCoordinate3;
newOne->ref();
newOne->point = point;
lastKit->setPart(partName, newOne);
newOne->unrefNoDelete();
return TRUE;
}
// If it's not a part, that means it's contained within a subgraph
// underneath a part. For example, it's within the 'contents'
// separator of an SoWrapperKit. In that case, the nodekit doesn't
// care and we just continue on through...
}
if ( myFullPath->getLength() < 2 ) {
#ifdef DEBUG
SoDebugError::post("Coordinate3Manip::replaceManip",
"Path is too short!");
#endif
return FALSE;
}
SoNode *parent = myFullPath->getNodeFromTail(1);
if (!parent->isOfType(SoGroup::getClassTypeId())) {
#ifdef DEBUG
SoDebugError::post("Coordinate3Manip::replaceManip",
"Parent node is not a group.!");
#endif
return FALSE;
}
if (newOne == NULL)
newOne = new SoCoordinate3;
newOne->ref();
newOne->point = point;
((SoGroup *)parent)->replaceChild((Coordinate3Manip *)this, newOne);
newOne->unrefNoDelete();
return TRUE;
}
// Creates and returns an exact copy...
SoNode *
Coordinate3Manip::copy(SbBool copyConnections) const
{
// Create a copy of the node and fieldData
Coordinate3Manip *newManip = (Coordinate3Manip *)
SoCoordinate3::copy(copyConnections);
// Copy the children
for (int i = 0; i < children->getLength(); i++)
newManip->children->append(
(*children)[i]->copy(copyConnections));
return newManip;
}
// Returns the child list...
SoChildList *
Coordinate3Manip::getChildren() const
{
return children;
}
void
Coordinate3Manip::doAction(SoAction *action)
{
int numIndices;
const int *indices;
if (action->getPathCode(numIndices, indices)
== SoAction::IN_PATH)
children->traverse(action, 0, indices[numIndices - 1]);
else
children->traverse(action);
}
// These functions implement all actions for Coordinate3Manip.
void
Coordinate3Manip::getMatrix(SoGetMatrixAction *action)
{
int numIndices;
const int *indices;
switch (action->getPathCode(numIndices, indices)) {
case SoAction::NO_PATH:
break;
case SoAction::IN_PATH:
children->traverse(action, 0,indices[numIndices - 1]);
break;
case SoAction::BELOW_PATH:
break;
case SoAction::OFF_PATH:
children->traverse(action);
break;
}
}
void
Coordinate3Manip::callback(SoCallbackAction *action)
{
Coordinate3Manip::doAction(action);
SoCoordinate3::callback(action);
}
void
Coordinate3Manip::getBoundingBox(
SoGetBoundingBoxAction *action)
{
SbVec3f totalCenter(0,0,0);
int numCenters = 0;
int numIndices;
const int *indices;
int lastChild;
if (action->getPathCode(numIndices, indices)
== SoAction::IN_PATH)
lastChild = indices[numIndices - 1];
else
lastChild = getNumChildren() - 1;
// Traverse the children
for (int i = 0; i <= lastChild; i++) {
children->traverse(action, i, i);
if (action->isCenterSet()) {
totalCenter += action->getCenter();
numCenters++;
action->resetCenter();
}
}
// Traverse this as an SoCoordinate3
SoCoordinate3::getBoundingBox(action);
if (action->isCenterSet()) {
totalCenter += action->getCenter();
numCenters++;
action->resetCenter();
}
// Now, set the center to be the average:
if (numCenters != 0)
action->setCenter(totalCenter / numCenters, FALSE);
}
void
Coordinate3Manip::GLRender(SoGLRenderAction *action)
{
Coordinate3Manip::doAction(action);
SoCoordinate3::GLRender(action);
}
void
Coordinate3Manip::handleEvent(SoHandleEventAction *action)
{
Coordinate3Manip::doAction(action);
SoCoordinate3::handleEvent(action);
}
void
Coordinate3Manip::pick(SoPickAction *action)
{
Coordinate3Manip::doAction(action);
SoCoordinate3::pick(action);
}
void
Coordinate3Manip::search(SoSearchAction *action)
{
// See if the caller is searching for this
SoCoordinate3::search(action);
// DONT TRAVERSE CHILDREN DURING SEARCH!!! THEY ARE PRIVATE
}
void
Coordinate3Manip::valueChangedCB(void *inManip,
SoDragger *inDragger)
{
Coordinate3Manip *manip = (Coordinate3Manip *) inManip;
SbMatrix motMat = inDragger->getMotionMatrix();
SbVec3f location = motMat[3];
// Disconnect the field sensor
manip->pointFieldSensor->detach();
int ind = (int) manip->editIndex.getValue();
// Set value of the point if it's different.
if (ind < manip->point.getNum()) {
if (manip->point[ind] != location)
manip->point.set1Value(ind,location);
}
// Reconnect the field sensors
manip->pointFieldSensor->attach(&(manip->point));
}
void
Coordinate3Manip::fieldSensorCB(void *inManip, SoSensor *)
{
Coordinate3Manip *manip = (Coordinate3Manip *) inManip;
int ind = manip->editIndex.getValue();
// Set value of the point if it's different.
if (ind < manip->point.getNum()) {
SoDragger *dragger = manip->getDragger();
if (dragger) {
SbVec3f location = manip->point[ind];
SbMatrix newMat = dragger->getMotionMatrix();
newMat[3][0] = location[0];
newMat[3][1] = location[1];
newMat[3][2] = location[2];
dragger->setMotionMatrix(newMat);
}
}
}