/*
*
* 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 Mentor
* chapter 10, example 1.
*
* The scene graph has 4 objects which may be
* selected by picking with the left mouse button
* (use shift key to extend the selection to more
* than one object).
*
* Hitting the up arrow key will increase the size of
* each selected object; hitting down arrow will decrease
* the size of each selected object.
*-----------------------------------------------------------*/
#include <stdlib.h>
#include <Inventor/Sb.h>
#include <Inventor/Xt/SoXt.h>
#include <Inventor/Xt/SoXtRenderArea.h>
#include <Inventor/actions/SoBoxHighlightRenderAction.h>
#include <Inventor/actions/SoSearchAction.h>
#include <Inventor/events/SoKeyboardEvent.h>
#include <Inventor/nodes/SoCone.h>
#include <Inventor/nodes/SoCube.h>
#include <Inventor/nodes/SoCylinder.h>
#include <Inventor/nodes/SoDirectionalLight.h>
#include <Inventor/nodes/SoEventCallback.h>
#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/nodes/SoNode.h>
#include <Inventor/nodes/SoPerspectiveCamera.h>
#include <Inventor/nodes/SoSphere.h>
#include <Inventor/nodes/SoSelection.h>
#include <Inventor/nodes/SoSeparator.h>
#include <Inventor/nodes/SoTransform.h>
// Function prototypes
void myKeyPressCB(void *, SoEventCallback *);
void myScaleSelection(SoSelection *, float);
// Global data
SbViewportRegion viewportRegion;
SoTransform *cubeTransform, *sphereTransform,
*coneTransform, *cylTransform;
int
main(int , char **argv)
{
// Print out usage message
printf("Left mouse button - selects object\n");
printf("<shift>Left mouse button - selects multiple objects\n");
printf("Up and Down arrows - scale selected objects\n");
// Initialize Inventor and Xt
Widget myWindow = SoXt::init(argv[0]);
if (myWindow == NULL) exit(1);
// Create and set up the selection node
SoSelection *selectionRoot = new SoSelection;
selectionRoot->ref();
selectionRoot->policy = SoSelection::SHIFT;
// Add a camera and some light
SoPerspectiveCamera *myCamera = new SoPerspectiveCamera;
selectionRoot->addChild(myCamera);
selectionRoot->addChild(new SoDirectionalLight);
///////////////////////////////////////////////////////////////
// CODE FOR The Inventor Mentor STARTS HERE (part 1)
// An event callback node so we can receive key press events
SoEventCallback *myEventCB = new SoEventCallback;
myEventCB->addEventCallback(
SoKeyboardEvent::getClassTypeId(),
myKeyPressCB, selectionRoot);
selectionRoot->addChild(myEventCB);
// CODE FOR The Inventor Mentor ENDS HERE
///////////////////////////////////////////////////////////////
// Add some geometry to the scene
// a red cube
SoSeparator *cubeRoot = new SoSeparator;
SoMaterial *cubeMaterial = new SoMaterial;
cubeTransform = new SoTransform;
cubeRoot->addChild(cubeTransform);
cubeRoot->addChild(cubeMaterial);
cubeRoot->addChild(new SoCube);
cubeTransform->translation.setValue(-2, 2, 0);
cubeMaterial->diffuseColor.setValue(.8, 0, 0);
selectionRoot->addChild(cubeRoot);
// a blue sphere
SoSeparator *sphereRoot = new SoSeparator;
SoMaterial *sphereMaterial = new SoMaterial;
sphereTransform = new SoTransform;
sphereRoot->addChild(sphereTransform);
sphereRoot->addChild(sphereMaterial);
sphereRoot->addChild(new SoSphere);
sphereTransform->translation.setValue(2, 2, 0);
sphereMaterial->diffuseColor.setValue(0, 0, .8);
selectionRoot->addChild(sphereRoot);
// a green cone
SoSeparator *coneRoot = new SoSeparator;
SoMaterial *coneMaterial = new SoMaterial;
coneTransform = new SoTransform;
coneRoot->addChild(coneTransform);
coneRoot->addChild(coneMaterial);
coneRoot->addChild(new SoCone);
coneTransform->translation.setValue(2, -2, 0);
coneMaterial->diffuseColor.setValue(0, .8, 0);
selectionRoot->addChild(coneRoot);
// a magenta cylinder
SoSeparator *cylRoot = new SoSeparator;
SoMaterial *cylMaterial = new SoMaterial;
cylTransform = new SoTransform;
cylRoot->addChild(cylTransform);
cylRoot->addChild(cylMaterial);
cylRoot->addChild(new SoCylinder);
cylTransform->translation.setValue(-2, -2, 0);
cylMaterial->diffuseColor.setValue(.8, 0, .8);
selectionRoot->addChild(cylRoot);
// Create a render area for viewing the scene
SoXtRenderArea *myRenderArea = new SoXtRenderArea(myWindow);
myRenderArea->setSceneGraph(selectionRoot);
myRenderArea->setGLRenderAction(new SoBoxHighlightRenderAction());
myRenderArea->redrawOnSelectionChange(selectionRoot);
myRenderArea->setTitle("Adding Event Callbacks");
// Make the camera see the whole scene
viewportRegion = myRenderArea->getViewportRegion();
myCamera->viewAll(selectionRoot, viewportRegion, 2.0);
// Show our application window, and loop forever...
myRenderArea->show();
SoXt::show(myWindow);
SoXt::mainLoop();
}
///////////////////////////////////////////////////////////////
// CODE FOR The Inventor Mentor STARTS HERE (part 2)
// If the event is down arrow, then scale down every object
// in the selection list; if the event is up arrow, scale up.
// The userData is the selectionRoot from main().
void
myKeyPressCB(void *userData, SoEventCallback *eventCB)
{
SoSelection *selection = (SoSelection *) userData;
const SoEvent *event = eventCB->getEvent();
// check for the Up and Down arrow keys being pressed
if (SO_KEY_PRESS_EVENT(event, UP_ARROW)) {
myScaleSelection(selection, 1.1);
eventCB->setHandled();
} else if (SO_KEY_PRESS_EVENT(event, DOWN_ARROW)) {
myScaleSelection(selection, 1.0/1.1);
eventCB->setHandled();
}
}
// CODE FOR The Inventor Mentor ENDS HERE
///////////////////////////////////////////////////////////////
// Scale each object in the selection list
void
myScaleSelection(SoSelection *selection, float sf)
{
SoPath *selectedPath;
SoTransform *xform;
SbVec3f scaleFactor;
int i,j;
// Scale each object in the selection list
for (i = 0; i < selection->getNumSelected(); i++) {
selectedPath = selection->getPath(i);
xform = NULL;
// Look for the shape node, starting from the tail of the
// path. Once we know the type of shape, we know which
// transform to modify
for (j=0; j < selectedPath->getLength() &&
(xform == NULL); j++) {
SoNode *n = (SoNode *)selectedPath->getNodeFromTail(j); if (n->isOfType(SoCube::getClassTypeId())) {
xform = cubeTransform;
} else if (n->isOfType(SoCone::getClassTypeId())) {
xform = coneTransform;
} else if (n->isOfType(SoSphere::getClassTypeId())) {
xform = sphereTransform;
} else if (n->isOfType(SoCylinder::getClassTypeId())) { xform = cylTransform;
}
}
// Apply the scale
scaleFactor = xform->scaleFactor.getValue();
scaleFactor *= sf;
xform->scaleFactor.setValue(scaleFactor);
}
}