예제 #1
0
void
SoActionMethodList::setUp()
////////////////////////////////////////////////////////////////////////
{
    if (numValidTypes == SoType::getNumTypes())
	return;		// Already set up the table

    // SoNode's slot must be filled in.  If this action doesn't have a
    // parent action, it is filled in with the null action.  If it
    // does have a parent action, a dummy action is used, and the
    // table is overwritten with the parent's method wherever the
    // dummy action appears in a second pass.
    int i = SoNode::getActionMethodIndex(SoNode::getClassTypeId());
    if ((*this)[i] == NULL) {
	if (parent == NULL)
	    (*this)[i] = SoAction::nullAction;
	else
	    (*this)[i] = dummyAction;
    }

    // Next, find all nodes derived from SoNode (note: it is a good
    // thing we don't have to do this often, since getAllDerivedFrom
    // must look through the entire list of types).
    SoTypeList nodes;
    SoType::getAllDerivedFrom(SoNode::getClassTypeId(), nodes);

    // Now, for any empty slots, fill in the slot from a parent with a
    // non-NULL slot:
    for (i = 0; i < nodes.getLength(); i++) {
	SoType n = nodes[i];
	if ((*this)[SoNode::getActionMethodIndex(n)] == NULL) {
	    (*this)[SoNode::getActionMethodIndex(n)] =
		parentMethod(n);
	}
    }

    // Inherit any undefined methods from parent class
    if (parent != NULL) {
	parent->setUp();

	for (i = 0; i < getLength(); i++) {

	    SoActionMethod	&method = (*this)[i];

	    if (method == dummyAction)
		method = (*parent)[i];
	}
    }

    numValidTypes = SoType::getNumTypes();
}
예제 #2
0
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());
	    }
	}
    }
}