Ejemplo n.º 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();
}
Ejemplo n.º 2
0
/*!
  This method appends all the class types derived from \a type to \a list,
  and returns the number of types added to the list.  Internal types are not
  included in the list, nor are they counted.

  \a type itself is also added to the list, as a type is seen as a derivation
  of its own type.

  NB: do not write code which depends in any way on the order of the
  elements returned in \a list.

  Here is a small, stand-alone example which shows how this method can
  be used for introspection, listing all subclasses of the SoBase
  superclass:

  \code
  #include <stdio.h>
  #include <Inventor/SoDB.h>
  #include <Inventor/lists/SoTypeList.h>

  static void
  list_subtypes(SoType t, unsigned int indent = 0)
  {
    SoTypeList tl;
    SoType::getAllDerivedFrom(t, tl);

    for (unsigned int i=0; i < indent; i++) { printf("  "); }
    printf("%s\n", t.getName().getString());

    indent++;
    for (int j=0; j < tl.getLength(); j++) {
      if (tl[j].getParent() == t) { // only interested in direct descendents
        list_subtypes(tl[j], indent);
      }
    }
  }

  int
  main(void)
  {
    SoDB::init();

    list_subtypes(SoType::fromName("SoBase"));

    return 0;
  }
  \endcode
*/
int
SoType::getAllDerivedFrom(const SoType type, SoTypeList & list)
{
  assert(type != SoType::badType() && "argument is badType()");

  int counter = 0;
  int n = SoType::typedatalist->getLength();
  for (int i = 0; i < n; i++) {
    if ((*SoType::typedatalist)[i]) {
      SoType chktype = (*SoType::typedatalist)[i]->type;
      if (!chktype.isInternal() && chktype.isDerivedFrom(type)) {
        list.append(chktype);
        counter++;
      }
    }
  }
  return counter;
}
Ejemplo n.º 3
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());
	    }
	}
    }
}