void SoSFPath::fixCopy(SbBool copyConnections) // //////////////////////////////////////////////////////////////////////// { if (value != NULL) { // If the head of the path has been copied, then each of the // other nodes in the path must have been copied as // well. Change the copied path to start at the copy and go // through the copied nodes. SoNode *headCopy = (SoNode *) SoFieldContainer::findCopy(value->getHead(), copyConnections); if (headCopy != NULL) { // Create a new path through the copied nodes SoPath *pathCopy = new SoPath(headCopy); pathCopy->ref(); for (int i = 1; i < ((SoFullPath *) value)->getLength(); i++) pathCopy->append(value->getIndex(i)); setVal(pathCopy); pathCopy->unref(); } } }
void ModList::selectAllId(SoNode *node, int count) { SoPath *path = new SoPath(node); _allId = findToken(path); #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL1) cerr << "ModList::selectAllId: Select All on " << _allId << endl; #endif if (_allId > 0) { _numSel += count - _selList[_allId]; _selList[_allId] = count; if (_numSel == 1) _oneSel = _allId; } path->unref(); }
////////////////////////////////////////////////////////////////////////////// // // beginTraversal - have the base class render the passed scene graph, // then render highlights for our selection node. // void SoLineHighlightRenderAction::apply(SoNode *node) // ////////////////////////////////////////////////////////////////////////////// { // Render the scene SoGLRenderAction::apply(node); // Render the highlight? if (! hlVisible) return; // Add the rendering localRoot beneath our local scene graph localRoot // so that we can find a path from localRoot to the selection node // which is under the render root. localRoot->addChild(node); // Find the selection node under the local root static SoSearchAction *sa = NULL; if (sa == NULL) sa = new SoSearchAction; else sa->reset(); sa->setFind(SoSearchAction::TYPE); sa->setInterest(SoSearchAction::FIRST); sa->setType(SoSelection::getClassTypeId()); sa->apply(localRoot); SoPath *hlPath = sa->getPath(); if (hlPath != NULL) { hlPath = hlPath->copy(); hlPath->ref(); // Make sure something is selected SoSelection *sel = (SoSelection *) hlPath->getTail(); if (sel->getNumSelected() > 0) { // Keep the length from the root to the selection // as an optimization so we can reuse this data int reusablePathLength = hlPath->getLength(); // For each selection path, create a new path rooted under our localRoot for (int j = 0; j < sel->getNumSelected(); j++) { // Continue the path down to the selected object. // No need to deal with p[0] since that is the sel node. SoFullPath *p = (SoFullPath *) sel->getPath(j); SoNode *pathTail = p->getTail(); if ( pathTail->isOfType(SoBaseKit::getClassTypeId())) { // Find the last nodekit on the path. SoNode *kitTail = ((SoNodeKitPath *)p)->getTail(); // Extend the selectionPath until it reaches this last kit. SoFullPath *fp = (SoFullPath *) p; int k = 0; do { hlPath->append(fp->getIndex(++k)); } while ( fp->getNode(k) != kitTail ); } else { for (int k = 1; k < p->getLength(); k++) hlPath->append(p->getIndex(k)); } // Render the shape with the local draw style to make the highlight SoGLRenderAction::apply(hlPath); // Restore hlPath for reuse hlPath->truncate(reusablePathLength); } } hlPath->unref(); } // Remove the rendering localRoot from our local scene graph localRoot->removeChild(node); }
void SoSurroundScale::updateMySurroundParams(SoAction *action, const SbMatrix &myInv ) // //////////////////////////////////////////////////////////////////////// { const SoFullPath *curPath = (const SoFullPath *) action->getCurPath(); int curPathLength = curPath->getLength(); // If the container node is out of range, just return. int numUpCon = (int) numNodesUpToContainer.getValue(); if ( (numUpCon <= 0) || (numUpCon > (curPathLength - 1)) ){ cachedScale.setValue(1,1,1); cachedInvScale.setValue(1,1,1); cachedTranslation.setValue(0,0,0); cacheOK = FALSE; return; } // CHECK TO SEE IF OUR CACHED VALUES ARE OKAY // IF SO, JUST RETURN if ( cacheOK ) return; // Find the path to apply the bounding box action to. It should end // 'numUpCon' above this one. SoPath *applyPath = curPath->copy(0, (curPathLength - numUpCon)); applyPath->ref(); // See if there is a node to do a reset at. If so, build a resetPath SoPath *resetPath = NULL; int numUpReset = (int) numNodesUpToReset.getValue(); if (numUpReset >= 0 && (numUpReset < numUpCon) ) { // Build a path ending at the reset node. resetPath = curPath->copy(0, curPathLength - numUpReset ); resetPath->ref(); } SoFullPath *fullResetPath = (SoFullPath *) resetPath; // Create a getBoundingBox action // Set the reset path if we have one. // Apply the bounding box action and find out how big the box was. // Temporarily set the ignoreInBbox flag TRUE, so we don't infinite loop! SbViewportRegion vpRegion(0,0); SoState *state = action->getState(); vpRegion = SoViewportRegionElement::get(state); static SoGetBoundingBoxAction *boundingBoxAction = NULL; if (boundingBoxAction == NULL) boundingBoxAction = new SoGetBoundingBoxAction(vpRegion); else boundingBoxAction->setViewportRegion(vpRegion); if (fullResetPath) boundingBoxAction->setResetPath( fullResetPath, FALSE, SoGetBoundingBoxAction::BBOX); SbBool oldFlag = isIgnoreInBbox(); setIgnoreInBbox( TRUE ); boundingBoxAction->apply( applyPath ); setIgnoreInBbox( oldFlag ); SbXfBox3f &myXfBox = boundingBoxAction->getXfBoundingBox(); // Transform the box into our local space, then project it. myXfBox.transform( myInv ); SbBox3f myBox = myXfBox.project(); // Get the scale for this node to add to the ctm. if (myBox.isEmpty()) { cachedScale.setValue(1,1,1); cachedInvScale.setValue(1,1,1); cachedTranslation.setValue(0,0,0); cacheOK = TRUE; return; } else { float x, y, z; myBox.getSize(x,y,z); cachedScale.setValue( .5*x, .5*y, .5*z ); float minLength = .01 * cachedScale.length(); // Macro defined just before beginning of this method. FUDGE(cachedScale[0],minLength); FUDGE(cachedScale[1],minLength); FUDGE(cachedScale[2],minLength); // Find the inverse values for (int j = 0; j < 3; j++ ) cachedInvScale[j] = 1.0 / cachedScale[j]; } // Get the translation for this node to add to the ctm. // This will get the cube centered about the bbox center. // If the bounding box is not centered at the origin, we have to // move the cube to the correct place. if (doTranslations) cachedTranslation = 0.5 * ( myBox.getMin() + myBox.getMax() ); else cachedTranslation.setValue(0,0,0); // Establish the cached values to save us some time later... cacheOK = TRUE; if (resetPath) resetPath->unref(); if (applyPath) applyPath->unref(); }
/*! Empty method in Coin. Can be used by subclasses to be told when status change. */ void SoFCSelection::redrawHighlighted(SoAction * action , SbBool doHighlight ) { //Base::Console().Log("SoFCSelection::redrawHighlighted() (%p) doHigh=%d \n",this,doHighlight?1:0); #ifdef NO_FRONTBUFFER #else // If we are about to highlight, and there is something else highlighted, // that something else needs to unhighlight. if (doHighlight && currenthighlight != NULL && !(*((SoFullPath *)action->getCurPath()) == *currenthighlight)) { SoNode *tail = currenthighlight->getTail(); if (tail->isOfType( SoFCSelection::getClassTypeId())) ((SoFCSelection *)tail)->redrawHighlighted(action, FALSE); else { // Just get rid of the path. It's no longer valid for redraw. currenthighlight->unref(); currenthighlight = NULL; } } SoPath *pathToRender; // save the path to ourself for later de-highlight if (doHighlight) { if (currenthighlight != NULL) currenthighlight->unref(); currenthighlight = (SoFullPath *) action->getCurPath()->copy(); currenthighlight->ref(); // We will be rendering this new path to highlight it pathToRender = currenthighlight; pathToRender->ref(); } // delete our path if we are no longer highlighted else { if (currenthighlight) { // We will be rendering this old path to unhighlight it pathToRender = currenthighlight; pathToRender->ref(); currenthighlight->unref(); currenthighlight = NULL; } } // If highlighting is forced on for this node, we don't need this special render. if (highlightMode.getValue() != AUTO) { pathToRender->unref(); return; } SoState *state = action->getState(); //void* window; //void* context; //void *display; QGLWidget* window; SoGLRenderAction *glAction; //SoWindowElement::get(state, window, context, display, glAction); SoGLWidgetElement::get(state, window); SoGLRenderActionElement::get(state, glAction); // If we don't have a current window, then simply return... if (window == 0 /*|| context == NULL || display == NULL*/ || glAction == NULL) return; window->makeCurrent(); #ifndef WIN32 // set the current window //glXMakeCurrent(display, window, context); #endif // render into the front buffer (save the current buffering type) GLint whichBuffer; glGetIntegerv(GL_DRAW_BUFFER, &whichBuffer); if (whichBuffer != GL_FRONT) glDrawBuffer(GL_FRONT); highlighted = TRUE; glAction->apply(pathToRender); highlighted = FALSE; // restore the buffering type if (whichBuffer != GL_FRONT) glDrawBuffer((GLenum)whichBuffer); glFlush(); pathToRender->unref(); #endif }
void SoDragPointDragger::metaKeyChangeCB( void *, SoDragger *inDragger ) // //////////////////////////////////////////////////////////////////////// { SoDragPointDragger *dp = (SoDragPointDragger *) inDragger; SoHandleEventAction *ha = dp->getHandleEventAction(); // We care if the shift key is down for drawing feedback. const SoEvent *event = dp->getEvent(); dp->shftDown = event->wasShiftDown(); // Don't check for grabber yet. // CONTROL key press overrides if the grabber is a childDragger. // [1] We only respond to CONTROL key press events. if ( !SO_KEY_PRESS_EVENT(event, LEFT_CONTROL) && !SO_KEY_PRESS_EVENT(event, RIGHT_CONTROL)) return; //[2] Should we return? // Stay here if there's no grabber and the mouse is over us, // or over a surrogate part. // Stay here if we are the grabber. // Stay here if our currentDragger is grabbing events. // Return if anyone else is grabbing. SbBool takeIt = FALSE; if ( ha->getGrabber() == NULL ) { // grabber is NULL... const SoPickedPoint *p = ha->getPickedPoint(); if ( p && p->getPath()) { // Are we on the pickPath? // Or is the path a surrogate path for us or any draggers // contained within us? if ( p->getPath()->containsNode(dp) || dp->isPathSurrogateInMySubgraph(p->getPath()) ) takeIt = TRUE; } } else if ( ha->getGrabber() == dp ) takeIt = TRUE; else if ( ha->getGrabber() == dp->currentDragger ) takeIt = TRUE; else takeIt = FALSE; if ( !takeIt ) return; //[3] Now, switch the set of visible draggers... dp->showNextDraggerSet(); //[4] If a child is grabbing, release events and hand it all over to // the next one... SoDragger *oldDragger = dp->currentDragger; if (oldDragger) { // Ref the oldDragger. oldDragger->ref(); // Release the grabber. This will call grabEventsCleanUp() if // the grabber is a dragger. ha->releaseGrabber(); // If there was an oldDragger, // [a] select a new dragger to grab events. // [b] Set up a plane or line projector oriented like newDragger. // [c] Find out where current mouse position intersects that new // plane or line. The new gesture will continue from there. SoDragger *newDragger; SbVec3f projPt; SbLineProjector lp; SbPlaneProjector pp; lp.setViewVolume( dp->getViewVolume() ); pp.setViewVolume( dp->getViewVolume() ); lp.setWorkingSpace( dp->getLocalToWorldMatrix() ); pp.setWorkingSpace( dp->getLocalToWorldMatrix() ); if ( oldDragger == dp->xTranslator.getValue() ) { newDragger = (SoDragger *) dp->yTranslator.getValue(); lp.setLine( SbLine( SbVec3f(0,0,0), SbVec3f(0,1,0))); projPt = lp.project(dp->getNormalizedLocaterPosition()); } else if ( oldDragger == dp->yTranslator.getValue() ) { newDragger = (SoDragger *) dp->zTranslator.getValue(); lp.setLine( SbLine( SbVec3f(0,0,0), SbVec3f(0,0,1))); projPt = lp.project(dp->getNormalizedLocaterPosition()); } else if ( oldDragger == dp->zTranslator.getValue() ) { newDragger = (SoDragger *) dp->xTranslator.getValue(); lp.setLine( SbLine( SbVec3f(0,0,0), SbVec3f(1,0,0))); projPt = lp.project(dp->getNormalizedLocaterPosition()); } else if ( oldDragger == dp->yzTranslator.getValue() ) { newDragger = (SoDragger *) dp->xzTranslator.getValue(); pp.setPlane( SbPlane( SbVec3f(0,1,0), SbVec3f(0,0,0))); projPt = pp.project(dp->getNormalizedLocaterPosition()); } else if ( oldDragger == dp->xzTranslator.getValue() ) { newDragger = (SoDragger *) dp->xyTranslator.getValue(); pp.setPlane( SbPlane( SbVec3f(0,0,1), SbVec3f(0,0,0))); projPt = pp.project(dp->getNormalizedLocaterPosition()); } else if ( oldDragger == dp->xyTranslator.getValue() ) { newDragger = (SoDragger *) dp->yzTranslator.getValue(); pp.setPlane( SbPlane( SbVec3f(1,0,0), SbVec3f(0,0,0))); projPt = pp.project(dp->getNormalizedLocaterPosition()); } // unref oldDragger. We don't need it any more. oldDragger->unref(); // Give newDragger our handleEvent action. newDragger->setHandleEventAction(ha); // Cast the projPt into world space for the new starting point. dp->getLocalToWorldMatrix().multVecMatrix(projPt,projPt); newDragger->setStartingPoint( projPt ); // Give the newDragger a path to itself SoPath *pathToDragger; // We must ref() & unref() dpThisPath to dispose of it. SoPath *dpThisPath = dp->createPathToThis(); if (dpThisPath) dpThisPath->ref(); pathToDragger = dp->createPathToPart( dp->getPartString(newDragger), TRUE, dpThisPath ); if (dpThisPath) dpThisPath->unref(); if (pathToDragger) pathToDragger->ref(); newDragger->setTempPathToThis( pathToDragger ); if (pathToDragger) pathToDragger->unref(); // Give the newDragger our viewing information. newDragger->setViewVolume(dp->getViewVolume()); newDragger->setViewportRegion(dp->getViewportRegion()); // Set the grabber. This will call starting callbacks on the new // grabber, as well as it's registered parent, moi! ha->setGrabber( newDragger ); } //[5] set handled ha->setHandled(); }