void SoXipImageOverlayManager::updateSliceMap() { // Removes all the previous entries mSliceMap.clear(); SoSearchAction sa; sa.setInterest( SoSearchAction::ALL ); sa.setType( SoXipShapeList::getClassTypeId() ); sa.setSearchingAll( TRUE ); sa.apply( mShapeSwitch ); SoPathList paths = sa.getPaths(); for( int i = 0; i < paths.getLength(); ++ i ) { SbString label = ((SoXipShapeList *) paths[i]->getTail())->label.getValue().getString(); int sliceIndex; if( sscanf( label.getString(), "%d", &sliceIndex ) != 1 ) { SoDebugError::post( __FILE__, "Invalid label found '%s'", label.getString() ); continue ; } mSliceMap[ sliceIndex ] = (SoXipShapeList *) paths[i]->getTail(); } }
void SoAction::apply(const SoPathList &pathList, SbBool obeysRules) // //////////////////////////////////////////////////////////////////////// { // Check for empty path list if (pathList.getLength() == 0) return; // If path list obeys the rules, just apply the action to it if (obeysRules) { apply(pathList, pathList, TRUE); return; } // // Otherwise, we may have to break it into smaller lists that do // obey the rules // // First, sort the paths SoPathList sortedPathList(pathList); sortedPathList.sort(); // Remove any duplicate paths and any paths that continue through // the tail node of another path sortedPathList.uniquify(); int numPaths = sortedPathList.getLength(); // If all the remaining paths have the same head, just apply to // the sorted path list const SoNode *firstHead = sortedPathList[0]->getHead(); if (sortedPathList[numPaths-1]->getHead() == firstHead) apply(sortedPathList, pathList, TRUE); // Otherwise, we have to break the path list into smaller ones else splitPathList(sortedPathList, pathList); }
void SoAction::splitPathList(const SoPathList &sortedList, const SoPathList &origPathList) // //////////////////////////////////////////////////////////////////////// { int numPaths, curStart, i; SoNode *curHead; numPaths = sortedList.getLength(); // Create a list to hold one of the split lists SoPathList splitList(numPaths); // Split list while there are still paths to examine curStart = 0; while (curStart < numPaths) { // Gather all paths with same head curHead = sortedList[curStart]->getHead(); splitList.append(sortedList[curStart]); for (i = curStart + 1; i < numPaths; i++) { if (sortedList[i]->getHead() != curHead) break; splitList.append(sortedList[i]); } // Apply action to split list. Indicate that it's the last // path list if there are no more paths after these. apply(splitList, origPathList, i >= numPaths); // Prepare for next set of paths splitList.truncate(0); curStart = i; } }
////////////////////////////////////////////////////////////////////////////// // // Description: // Convert the passed byte stream to a path list. // The caller should delete the returned path list when done with it. // // Use: static, public // SoPathList * SoByteStream::unconvert(void *data, uint32_t numBytes) // ////////////////////////////////////////////////////////////////////////////// { if (data == NULL) { SoDebugError::post("SoByteStream::unconvert", "data is NULL"); return NULL; } if (numBytes == 0) { SoDebugError::post("SoByteStream::unconvert", "numBytes is 0"); return NULL; } SoInput in; SoPathList *pathList = new SoPathList; SoPath *path = NULL; in.setBuffer((void *) data, (size_t) numBytes); // Try to read paths while ((SoDB::read(&in, path) != FALSE) && (path != NULL)) pathList->append(path); // If that failed, try reading the scene as a node if (pathList->getLength() == 0) { in.setBuffer((void *) data, (size_t) numBytes); // reset SoSeparator *sep = SoDB::readAll(&in); // read again if (sep != NULL) { path = new SoPath(sep); pathList->append(path); } } return pathList; }
void IfWeeder::findMaterialsAndShapes(SoNode *root) { // Since we know the structure of the given scene graph (which is // after fixing has occurred), we can be efficient here. Just // search for all materials in the scene. For each material, the // shapes affected by it must be under the separator that is the // material's parent node. So just search for all shapes under // that separator, making sure that the path to the shape comes // after the material. // First, create a dictionary so we can tell when we've found a // multiple instance of a material SbDict materialDict; // Search for all materials in the scene SoSearchAction sa; sa.setType(SoMaterial::getClassTypeId()); sa.setInterest(SoSearchAction::ALL); sa.apply(root); // Set up another search action to find all shapes using a // material. Note that we have to search for all node types that // should be considered shapes. SoSearchAction sa2; sa2.setInterest(SoSearchAction::ALL); // These are the shape types SoTypeList shapeTypes; IfTypes::getShapeTypes(&shapeTypes); // Process each material, adding new ones to the list materialList = new SbPList; for (int i = 0; i < sa.getPaths().getLength(); i++) { const SoPath *path = (const SoPath *) sa.getPaths()[i]; ASSERT(path->getLength() > 1); ASSERT(path->getTail()->getTypeId() == SoMaterial::getClassTypeId()); SoMaterial *material = (SoMaterial *) path->getTail(); // Add to the dictionary if necessary, or use the existing // entry void *entryPtr; IfWeederMaterialEntry *entry; if (materialDict.find((unsigned long) material, entryPtr)) { entry = (IfWeederMaterialEntry *) entryPtr; if (! entry->canWeed) continue; } else { entry = new IfWeederMaterialEntry; entry->material = material; entry->canWeed = TRUE; materialDict.enter((unsigned long) material, entry); materialList->append(entry); } // If any node above the material in the path is an opaque // group, we can't really weed this material int j; for (j = path->getLength() - 2; j >= 0; j--) { if (IfTypes::isOpaqueGroupType(path->getNode(j)->getTypeId())) { entry->canWeed = FALSE; break; } } if (! entry->canWeed) continue; ASSERT(path->getNodeFromTail(1)-> isOfType(SoSeparator::getClassTypeId())); SoSeparator *parent = (SoSeparator *) path->getNodeFromTail(1); int materialIndex = path->getIndexFromTail(0); // Find all shapes using the material, adding them to the list // of shapes in the material's entry. Store all the paths to // them in this list SoPathList pathsToShapes; for (int type = 0; type < shapeTypes.getLength(); type++) { sa2.setType(shapeTypes[type]); sa2.apply(parent); for (j = 0; j < sa2.getPaths().getLength(); j++) pathsToShapes.append(sa2.getPaths()[j]); } for (j = 0; j < pathsToShapes.getLength(); j++) { const SoPath *shapePath = (const SoPath *) pathsToShapes[j]; // We can't weed the material at all if a shape other than // the one we created is found SoType tailType = shapePath->getTail()->getTypeId(); if (tailType != SoIndexedTriangleStripSet::getClassTypeId() && tailType != SoIndexedFaceSet::getClassTypeId()) { entry->canWeed = FALSE; break; } // Make sure the shape comes after the material and does // not get its materials from a vertex property // node. else if (shapePath->getIndex(1) > materialIndex) { SoIndexedShape *is = (SoIndexedShape *) shapePath->getTail(); // ??? If the shape's materialIndex field has the // ??? default value, we assume that it might have to // ??? access all the material values. To check, we would // ??? have to look at the coordIndex values if the // ??? material binding is not OVERALL. This change could // ??? not be done in time for the release. See bug 311071. if (is->materialIndex.getNum() == 1 && is->materialIndex[0] < 0) { entry->canWeed = FALSE; break; } SoVertexProperty *vp = (SoVertexProperty *) is->vertexProperty.getValue(); if (vp == NULL || vp->orderedRGBA.getNum() == 0) entry->shapes.append(shapePath->getTail()); } } } }