/*! Set the node compatibility mask for node type \a nodetype. The mask specifies for which file formats the node is supported. \COIN_FUNCTION_EXTENSION \sa getCompatibilityMode() \since Coin 2.0 */ void SoNode::setCompatibilityTypes(const SoType & nodetype, const uint32_t bitmask) { assert(compatibility_dict); assert(nodetype.isDerivedFrom(SoNode::getClassTypeId())); compatibility_dict->put(nodetype.getKey(), bitmask); }
/*! This method makes a new class's instantiation method override the instantiation method of an existing class. The new type should be a C++ subclass of the original class type, but this won't be checked though. If \c NULL is passed as the second argument, the type will be considered uninstantiable -- it does not revert the configuration to the default setting as one might think. Here's a \e complete code examples which shows how to fully override a built-in Coin node class, so that a) your application-specific extension class gets instantiated instead of the built-in class upon scenegraph import, and b) it gets written out properly upon export: \code #include <Inventor/SoDB.h> #include <Inventor/actions/SoWriteAction.h> #include <Inventor/errors/SoDebugError.h> #include <Inventor/nodes/SoSeparator.h> #include <Inventor/nodes/SoWWWInline.h> ////// MyWWWInline //////////////////////////////////////////////////// class MyWWWInline : public SoWWWInline { SO_NODE_HEADER(MyWWWInline); public: static void initClass(void); MyWWWInline(void); protected: virtual ~MyWWWInline(); virtual SbBool readInstance(SoInput * in, unsigned short flags); virtual const char * getFileFormatName(void) const; }; SO_NODE_SOURCE(MyWWWInline); MyWWWInline::MyWWWInline(void) { SO_NODE_CONSTRUCTOR(MyWWWInline); // Fool the library to believe this is an internal class, so it gets // written out in the same manner as the built-in classes, instead // of as en extension class. There are slight differences, which you // want to avoid when overriding a class like we do with MyWWWInline // vs SoWWWInline here. this->isBuiltIn = TRUE; } MyWWWInline::~MyWWWInline() { } void MyWWWInline::initClass(void) { SO_NODE_INIT_CLASS(MyWWWInline, SoWWWInline, "SoWWWInline"); // Override instantiation method, so we get MyWWWInline instead of // SoWWWInline instances upon scenegraph import. (void)SoType::overrideType(SoWWWInline::getClassTypeId(), MyWWWInline::createInstance); } // Override SoBase::getFileFormatName() to make node get written as // "WWWInline" instead of "MyWWWInline". const char * MyWWWInline::getFileFormatName(void) const { return "WWWInline"; } SbBool MyWWWInline::readInstance(SoInput * in, unsigned short flags) { SoDebugError::postInfo("MyWWWInline::readInstance", "hepp"); return SoWWWInline::readInstance(in, flags); } ////// main() ///////////////////////////////////////////////////////// int main(int argc, char ** argv) { SoDB::init(); MyWWWInline::initClass(); const char * ivscene = "#Inventor V2.1 ascii\n\n" "Separator {" " WWWInline { }" "}"; SoInput in; in.setBuffer((void *)ivscene, strlen(ivscene)); SoSeparator * root = SoDB::readAll(&in); root->ref(); SoOutput out; SoWriteAction wa(&out); wa.apply(root); root->unref(); return 0; } \endcode */ const SoType SoType::overrideType(const SoType originalType, const instantiationMethod method) { (*SoType::typedatalist)[(int)originalType.getKey()]->method = method; return originalType; }
SbBool SoType::isDerivedFrom(const SoType parent) const { assert(!this->isBad()); if (parent.isBad()) { #if COIN_DEBUG SoDebugError::postWarning("SoType::isDerivedFrom", "can't compare type '%s' against an invalid type", this->getName().getString()); #endif // COIN_DEBUG return FALSE; } SoType type = *this; do { #if COIN_DEBUG && 0 // debug SoDebugError::postInfo("SoType::isDerivedFrom", "this: '%s' parent: '%s'", type.getName().getString(), parent.getName().getString()); #endif // debug if (type == parent) return TRUE; type = (*SoType::typedatalist)[(int)type.getKey()]->parent; } while (!type.isBad()); return FALSE; }
/*! Get the node compatibility mask for node type \a nodetype. The return value will be a bit mask of SoNode::NodeType flags, containing one or several flags. \COIN_FUNCTION_EXTENSION \since Coin 2.0 */ uint32_t SoNode::getCompatibilityTypes(const SoType & nodetype) { assert(compatibility_dict); assert(nodetype.isDerivedFrom(SoNode::getClassTypeId())); uint32_t tmp; if (compatibility_dict->get(nodetype.getKey(), tmp)) { return tmp; } return SoNode::EXTENSION; }
const SoType SoType::createType(const SoType parent, const SbName name, const instantiationMethod method, const uint16_t data) { #if COIN_DEBUG // We don't use SoType::fromName() to test if a type with this name // already exists to avoid loading extension nodes in this context. // You should be able to "override" dynamically loadable nodes in program // code. // FIXME: We ought to factor out and expose this functionality - testing // if a class type is already loaded and registered - in the public API. // 20040831 larsa (ref could-have-been-used-to-fix-upgrader-slowness-bug) int16_t discard; if (type_dict->get(name.getString(), discard)) { SoDebugError::post("SoType::createType", "a type with name ``%s'' already created", name.getString()); return SoType::fromName(name.getString()); } #endif // COIN_DEBUG #if COIN_DEBUG && 0 // debug SoDebugError::postInfo("SoType::createType", "%s", name.getString()); #endif // debug SoType newType; newType.index = SoType::typedatalist->getLength(); SoTypeData * typeData = new SoTypeData(name, newType, TRUE, data, parent, method); SoType::typedatalist->append(typeData); // add to dictionary for fast lookup type_dict->put(name.getString(), newType.getKey()); return newType; }