/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace osg; using namespace osgDB; #if 0 // temporary test of autoregistering, not compiled by default. enum Methods { SET_1, SET_2, END }; typedef std::pair MethodPair; class Proxy { public: Proxy(MethodPair* methods) { std::cout<<"methods "< s_nodeFactory = new Registry; return s_nodeFactory.get(); } // definition of the Registry Registry::Registry() { // comment out because it was causing problems under OSX - causing it to crash osgconv when constucting ostream in osg::notify(). // notify(INFO) << "Constructing osg::Registry"<[:path]..","Paths for locating datafiles"); #else static osg::ApplicationUsageProxy Registry_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FILE_PATH [;path]..","Paths for locating datafiles"); #endif void Registry::initDataFilePathList() { // // set up data file paths // char *ptr; if( (ptr = getenv( "OSG_FILE_PATH" )) ) { //notify(DEBUG_INFO) << "OSG_FILE_PATH("<[:path]..","Paths for locating libraries/ plugins"); #else static osg::ApplicationUsageProxy Registry_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_LIBRARY_PATH [;path]..","Paths for locating libraries/ plugins"); #endif void Registry::initLibraryFilePathList() { // // set up library paths // char* ptr; if( (ptr = getenv( "OSG_LIBRARY_PATH")) ) { //notify(DEBUG_INFO) << "OSG_LIBRARY_PATH("<addCommandLineOption("-l ","Load the plugin"); arguments.getApplicationUsage()->addCommandLineOption("-e ","Load the plugin associated with handling files with specified extension"); arguments.getApplicationUsage()->addCommandLineOption("-O ","Provide an option string to reader/writers used to load databases"); } std::string value; while(arguments.read("-l",value)) { loadLibrary(value); } while(arguments.read("-e",value)) { std::string libName = createLibraryNameForExtension(value); loadLibrary(libName); } while(arguments.read("-O",value)) { setOptions(new osgDB::ReaderWriter::Options(value)); } } void Registry::addDotOsgWrapper(DotOsgWrapper* wrapper) { if (wrapper==0L) return; if (_openingLibrary) notify(INFO) << "Opening Library : "<< std::endl; notify(INFO) << "osg::Registry::addDotOsgWrapper("<getName()<<")"<< std::endl; const DotOsgWrapper::Associates& assoc = wrapper->getAssociates(); for(DotOsgWrapper::Associates::const_iterator itr=assoc.begin(); itr!=assoc.end(); ++itr) { notify(INFO) << " ("<<*itr<<")"<< std::endl; } const std::string& name = wrapper->getName(); const osg::Object* proto = wrapper->getPrototype(); _objectWrapperMap[name] = wrapper; if (proto) { std::string libraryName = proto->libraryName(); std::string compositeName = libraryName + "::" + name; _objectWrapperMap[compositeName] = wrapper; if (wrapper->getReadWriteMode()==DotOsgWrapper::READ_AND_WRITE) _classNameWrapperMap[proto->className()] = wrapper; if (dynamic_cast(proto)) { _imageWrapperMap[name] = wrapper; _imageWrapperMap[compositeName] = wrapper; } if (dynamic_cast(proto)) { _drawableWrapperMap[name] = wrapper; _drawableWrapperMap[compositeName] = wrapper; } if (dynamic_cast(proto)) { _stateAttrWrapperMap[name] = wrapper; _stateAttrWrapperMap[compositeName] = wrapper; } if (dynamic_cast(proto)) { _nodeWrapperMap[name] = wrapper; _nodeWrapperMap[compositeName] = wrapper; } } } // need to change to delete all instances of wrapper, since we // now can have a wrapper entered twice with the addition of the // library::class composite name. void Registry::eraseWrapper(DotOsgWrapperMap& wrappermap,DotOsgWrapper* wrapper) { typedef std::vector EraseList; EraseList eraseList; for(DotOsgWrapperMap::iterator witr=wrappermap.begin(); witr!=wrappermap.end(); ++witr) { if (witr->second==wrapper) eraseList.push_back(witr); } for(EraseList::iterator eitr=eraseList.begin(); eitr!=eraseList.end(); ++eitr) { wrappermap.erase(*eitr); } } void Registry::removeDotOsgWrapper(DotOsgWrapper* wrapper) { if (wrapper==0L) return; eraseWrapper(_objectWrapperMap,wrapper); eraseWrapper(_classNameWrapperMap,wrapper); eraseWrapper(_imageWrapperMap,wrapper); eraseWrapper(_drawableWrapperMap,wrapper); eraseWrapper(_stateAttrWrapperMap,wrapper); eraseWrapper(_nodeWrapperMap,wrapper); } void Registry::addReaderWriter(ReaderWriter* rw) { if (rw==0L) return; if (_openingLibrary) notify(INFO) << "Opening Library : "<< std::endl; notify(INFO) << "osg::Registry::addReaderWriter("<className()<<")"<< std::endl; _rwList.push_back(rw); } void Registry::removeReaderWriter(ReaderWriter* rw) { if (rw==0L) return; // notify(INFO) << "osg::Registry::removeReaderWriter();"<< std::endl; ReaderWriterList::iterator rwitr = std::find(_rwList.begin(),_rwList.end(),rw); if (rwitr!=_rwList.end()) { _rwList.erase(rwitr); } } void Registry::addFileExtensionAlias(const std::string mapExt, const std::string toExt) { if (mapExt!=toExt) _extAliasMap[mapExt] = toExt; } std::string Registry::createLibraryNameForFile(const std::string& fileName) { std::string ext = getLowerCaseFileExtension(fileName); return createLibraryNameForExtension(ext); } std::string Registry::createLibraryNameForExtension(const std::string& ext) { ExtensionAliasMap::iterator itr=_extAliasMap.find(ext); if (itr!=_extAliasMap.end()) return createLibraryNameForExtension(itr->second); #if defined(WIN32) // !! recheck evolving Cygwin DLL extension naming protocols !! NHV #ifdef __CYGWIN__ return "cygosgdb_"+ext+".dll"; #elif defined(__MINGW32__) return "libosgdb_"+ext+".dll"; #else #ifdef _DEBUG return "osgdb_"+ext+"d.dll"; #else return "osgdb_"+ext+".dll"; #endif #endif #elif macintosh return "osgdb_"+ext; #elif defined(__hpux__) // why don't we use PLUGIN_EXT from the makefiles here? return "osgdb_"+ext+".sl"; #else return "osgdb_"+ext+".so"; #endif } std::string Registry::createLibraryNameForNodeKit(const std::string& name) { #if defined(WIN32) // !! recheck evolving Cygwin DLL extension naming protocols !! NHV #ifdef __CYGWIN__ // [ return "cyg"+name+".dll"; #elif defined(__MINGW32__) return "lib"+name+".dll"; #else #ifdef _DEBUG return name+"d.dll"; #else return name+".dll"; #endif #endif #elif macintosh return name; #elif defined(__hpux__) // why don't we use PLUGIN_EXT from the makefiles here? return "lib"+name+".sl"; #else return "lib"+name+".so"; #endif } bool Registry::loadLibrary(const std::string& fileName) { DynamicLibrary* dl = getLibrary(fileName); if (dl) return false; _openingLibrary=true; dl = DynamicLibrary::loadLibrary(fileName); _openingLibrary=false; if (dl) { _dlList.push_back(dl); return true; } return false; } bool Registry::closeLibrary(const std::string& fileName) { DynamicLibraryList::iterator ditr = getLibraryItr(fileName); if (ditr!=_dlList.end()) { _dlList.erase(ditr); return true; } return false; } Registry::DynamicLibraryList::iterator Registry::getLibraryItr(const std::string& fileName) { DynamicLibraryList::iterator ditr = _dlList.begin(); for(;ditr!=_dlList.end();++ditr) { if ((*ditr)->getName()==fileName) return ditr; } return _dlList.end(); } DynamicLibrary* Registry::getLibrary(const std::string& fileName) { DynamicLibraryList::iterator ditr = getLibraryItr(fileName); if (ditr!=_dlList.end()) return ditr->get(); else return NULL; } ReaderWriter* Registry::getReaderWriterForExtension(const std::string& ext) { // record the existing reader writer. std::set rwOriginal; // first attemt one of the installed loaders for(ReaderWriterList::iterator itr=_rwList.begin(); itr!=_rwList.end(); ++itr) { rwOriginal.insert(itr->get()); if((*itr)->acceptsExtension(ext)) return (*itr).get(); } // now look for a plug-in to load the file. std::string libraryName = createLibraryNameForExtension(ext); notify(INFO) << "Now checking for plug-in "<get())==rwOriginal.end()) if((*itr)->acceptsExtension(ext)) return (*itr).get(); } } return NULL; } osg::Object* Registry::readObjectOfType(const osg::Object& compObj,Input& fr) { const char *str = fr[0].getStr(); if (str==NULL) return NULL; if (fr[0].matchWord("Use")) { if (fr[1].isString()) { Object* obj = fr.getObjectForUniqueID(fr[1].getStr()); if (obj && compObj.isSameKindAs(obj)) { fr+=2; return obj; } } else return NULL; } std::string name = str; DotOsgWrapperMap::iterator itr = _objectWrapperMap.find(name); if (itr==_objectWrapperMap.end()) { // not found so check if a library::class composite name. std::string token = fr[0].getStr(); std::string::size_type posDoubleColon = token.rfind("::"); if (posDoubleColon != std::string::npos) { // we have a composite name so now strip off the library name // are try to load it, and then retry the readObject to see // if we can recongise the objects. std::string libraryName = std::string(token,0,posDoubleColon); // first try the standard nodekit library. std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName); if (loadLibrary(nodeKitLibraryName)) return readObjectOfType(compObj,fr); // otherwise try the osgdb_ plugin library. std::string pluginLibraryName = createLibraryNameForExtension(libraryName); if (loadLibrary(pluginLibraryName)) return readObjectOfType(compObj,fr); } } else if (fr[1].isOpenBracket()) { DotOsgWrapper* wrapper = itr->second.get(); const osg::Object* proto = wrapper->getPrototype(); if (proto==NULL) { osg::notify(osg::WARN)<<"Token "<getAssociates(); osg::Object* obj = proto->cloneType(); while(!fr.eof() && fr[0].getNoNestedBrackets()>entry) { bool iteratorAdvanced = false; if (fr[0].matchWord("UniqueID") && fr[1].isString()) { fr.regisiterUniqueIDForObject(fr[1].getStr(),obj); fr += 2; iteratorAdvanced = true; } // read the local data by iterating through the associate // list, mapping the associate names to DotOsgWrapper's which // in turn have the appropriate functions. for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin(); aitr!=assoc.end(); ++aitr) { DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr); if (mitr!=_objectWrapperMap.end()) { // get the function to read the data... DotOsgWrapper::ReadFunc rf = mitr->second->getReadFunc(); if (rf && (*rf)(*obj,fr)) iteratorAdvanced = true; } } if (!iteratorAdvanced) fr.advanceOverCurrentFieldOrBlock(); } ++fr; // step over trailing '}' return obj; } return 0L; } // // read object from input iterator. // osg::Object* Registry::readObject(DotOsgWrapperMap& dowMap,Input& fr) { const char *str = fr[0].getStr(); if (str==NULL) return NULL; std::string name = str; DotOsgWrapperMap::iterator itr = dowMap.find(name); if (itr==dowMap.end()) { // not found so check if a library::class composite name. std::string token = fr[0].getStr(); std::string::size_type posDoubleColon = token.rfind("::"); if (posDoubleColon != std::string::npos) { // we have a composite name so now strip off the library name // are try to load it, and then retry the readObject to see // if we can recongise the objects. std::string libraryName = std::string(token,0,posDoubleColon); // first try the standard nodekit library. std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName); if (loadLibrary(nodeKitLibraryName)) return readObject(dowMap,fr); // otherwise try the osgdb_ plugin library. std::string pluginLibraryName = createLibraryNameForExtension(libraryName); if (loadLibrary(pluginLibraryName)) return readObject(dowMap,fr); } } else if (fr[1].isOpenBracket()) { DotOsgWrapper* wrapper = itr->second.get(); const osg::Object* proto = wrapper->getPrototype(); if (proto==NULL) { osg::notify(osg::WARN)<<"Token "<getAssociates(); osg::Object* obj = proto->cloneType(); while(!fr.eof() && fr[0].getNoNestedBrackets()>entry) { bool iteratorAdvanced = false; if (fr[0].matchWord("UniqueID") && fr[1].isString()) { fr.regisiterUniqueIDForObject(fr[1].getStr(),obj); fr += 2; iteratorAdvanced = true; } // read the local data by iterating through the associate // list, mapping the associate names to DotOsgWrapper's which // in turn have the appropriate functions. for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin(); aitr!=assoc.end(); ++aitr) { DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr); if (mitr!=_objectWrapperMap.end()) { // get the function to read the data... DotOsgWrapper::ReadFunc rf = mitr->second->getReadFunc(); if (rf && (*rf)(*obj,fr)) iteratorAdvanced = true; } } if (!iteratorAdvanced) fr.advanceOverCurrentFieldOrBlock(); } ++fr; // step over trailing '}' return obj; } return 0L; } // // read object from input iterator. // Object* Registry::readObject(Input& fr) { if (fr[0].matchWord("Use")) { if (fr[1].isString()) { Object* obj = fr.getObjectForUniqueID(fr[1].getStr()); if (obj) fr+=2; return obj; } else return NULL; } return readObject(_objectWrapperMap,fr); } // // read image from input iterator. // Image* Registry::readImage(Input& fr) { if (fr[0].matchWord("Use")) { if (fr[1].isString()) { Image* image = dynamic_cast(fr.getObjectForUniqueID(fr[1].getStr())); if (image) fr+=2; return image; } else return NULL; } osg::Object* obj = readObject(_imageWrapperMap,fr); osg::Image* image = dynamic_cast(obj); if (image) return image; else if (obj) obj->unref(); return NULL; } // // read drawable from input iterator. // Drawable* Registry::readDrawable(Input& fr) { if (fr[0].matchWord("Use")) { if (fr[1].isString()) { Drawable* drawable = dynamic_cast(fr.getObjectForUniqueID(fr[1].getStr())); if (drawable) fr+=2; return drawable; } else return NULL; } osg::Object* obj = readObject(_drawableWrapperMap,fr); osg::Drawable* drawable = dynamic_cast(obj); if (drawable) return drawable; else if (obj) obj->unref(); return NULL; } // // read drawable from input iterator. // StateAttribute* Registry::readStateAttribute(Input& fr) { if (fr[0].matchWord("Use")) { if (fr[1].isString()) { StateAttribute* attribute = dynamic_cast(fr.getObjectForUniqueID(fr[1].getStr())); if (attribute) fr+=2; return attribute; } else return NULL; } return dynamic_cast(readObject(_stateAttrWrapperMap,fr)); } // // read node from input iterator. // Node* Registry::readNode(Input& fr) { if (fr[0].matchWord("Use")) { if (fr[1].isString()) { Node* node = dynamic_cast(fr.getObjectForUniqueID(fr[1].getStr())); if (node) fr+=2; return node; } else return NULL; } osg::Object* obj = readObject(_nodeWrapperMap,fr); osg::Node* node = dynamic_cast(obj); if (node) return node; else if (obj) obj->unref(); return NULL; } // // Write object to output // bool Registry::writeObject(const osg::Object& obj,Output& fw) { if (obj.referenceCount()>1) { std::string uniqueID; if (fw.getUniqueIDForObject(&obj,uniqueID)) { fw.indent() << "Use " << uniqueID << std::endl; return true; } } std::string classname = obj.className(); DotOsgWrapperMap::iterator itr = _classNameWrapperMap.find(classname); if (itr==_classNameWrapperMap.end()) { // first try the standard nodekit library. std::string nodeKitLibraryName = createLibraryNameForNodeKit(obj.libraryName()); if (loadLibrary(nodeKitLibraryName)) return writeObject(obj,fw); // otherwise try the osgdb_ plugin library. std::string pluginLibraryName = createLibraryNameForExtension(obj.libraryName()); if (loadLibrary(pluginLibraryName)) return writeObject(obj,fw); } else { DotOsgWrapper* wrapper = itr->second.get(); const DotOsgWrapper::Associates& assoc = wrapper->getAssociates(); if (strcmp(obj.libraryName(),"osg")==0) { // member of the core osg, so no need to have composite library::class name. fw.indent() << wrapper->getName() << " {"<< std::endl; fw.moveIn(); } else { // member of the node kit so must use composite library::class name. fw.indent() << obj.libraryName()<<"::"<< wrapper->getName() << " {"<< std::endl; fw.moveIn(); } // write out the unique ID if required. if (obj.referenceCount()>1) { std::string uniqueID; fw.createUniqueIDForObject(&obj,uniqueID); fw.registerUniqueIDForObject(&obj,uniqueID); fw.indent() << "UniqueID " << uniqueID << std::endl; } // read the local data by iterating through the associate // list, mapping the associate names to DotOsgWrapper's which // in turn have the appropriate functions. for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin(); aitr!=assoc.end(); ++aitr) { DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr); if (mitr!=_objectWrapperMap.end()) { // get the function to read the data... DotOsgWrapper::WriteFunc wf = mitr->second->getWriteFunc(); if (wf) (*wf)(obj,fw); } } fw.moveOut(); fw.indent() << "}"<< std::endl; return true; } return false; } // // read object from specified file. // ReaderWriter::ReadResult Registry::readObject(const std::string& fileName) { // record the existing reader writer. std::set rwOriginal; // record the errors reported by readerwriters. typedef std::vector Results; Results results; // first attempt to load the file from existing ReaderWriter's for(ReaderWriterList::iterator itr=_rwList.begin(); itr!=_rwList.end(); ++itr) { rwOriginal.insert(itr->get());; ReaderWriter::ReadResult rr = (*itr)->readObject(fileName,_options.get()); if (rr.validObject()) return rr; else if (rr.error()) results.push_back(rr); } // now look for a plug-in to load the file. std::string libraryName = createLibraryNameForFile(fileName); if (loadLibrary(libraryName)) { for(ReaderWriterList::iterator itr=_rwList.begin(); itr!=_rwList.end(); ++itr) { if (rwOriginal.find(itr->get())==rwOriginal.end()) { ReaderWriter::ReadResult rr = (*itr)->readObject(fileName,_options.get()); if (rr.validObject()) return rr; else if (rr.error()) results.push_back(rr); } } } if (results.empty()) { return ReaderWriter::ReadResult("Warning: Could not find plugin to read objects from file \""+fileName+"\"."); } return results.front(); } ReaderWriter::ReadResult Registry::readObject(const std::string& fileName,bool useObjectCache) { std::string file = findDataFile( fileName ); if (file.empty()) return ReaderWriter::ReadResult("Warning: file \""+fileName+"\" not found."); if (useObjectCache) { // search for entry in the object cache. ObjectCache::iterator oitr=_objectCache.find(file); if (oitr!=_objectCache.end()) { notify(INFO)<<"returning cached instanced of "<second.first.get(); if (object) return object; else return ReaderWriter::ReadResult("Error file does not contain an osg::Object"); } PushAndPopDataPath tmpfile(getFilePath(file)); ReaderWriter::ReadResult rr = readObject(file); if (rr.validObject()) { // update cache with new entry. notify(INFO)<<"Adding to cache object "< rwOriginal; // record the errors reported by readerwriters. typedef std::vector Results; Results results; // first attempt to load the file from existing ReaderWriter's for(ReaderWriterList::iterator itr=_rwList.begin(); itr!=_rwList.end(); ++itr) { rwOriginal.insert(itr->get()); ReaderWriter::WriteResult rr = (*itr)->writeObject(obj,fileName,_options.get()); if (rr.success()) return rr; else if (rr.error()) results.push_back(rr); } // now look for a plug-in to save the file. std::string libraryName = createLibraryNameForFile(fileName); if (loadLibrary(libraryName)) { for(ReaderWriterList::iterator itr=_rwList.begin(); itr!=_rwList.end(); ++itr) { if (rwOriginal.find(itr->get())==rwOriginal.end()) { ReaderWriter::WriteResult rr = (*itr)->writeObject(obj,fileName,_options.get()); if (rr.success()) return rr; else if (rr.error()) results.push_back(rr); } } } if (results.empty()) { return ReaderWriter::WriteResult("Warning: Could not find plugin to write objects to file \""+fileName+"\"."); } return results.front(); } ReaderWriter::ReadResult Registry::readImage(const std::string& fileName) { // record the existing reader writer. std::set rwOriginal; // record the errors reported by readerwriters. typedef std::vector Results; Results results; // first attempt to load the file from existing ReaderWriter's for(ReaderWriterList::iterator itr=_rwList.begin(); itr!=_rwList.end(); ++itr) { rwOriginal.insert(itr->get()); ReaderWriter::ReadResult rr = (*itr)->readImage(fileName,_options.get()); if (rr.validImage()) return rr; else if (rr.error()) results.push_back(rr); } // now look for a plug-in to load the file. std::string libraryName = createLibraryNameForFile(fileName); if (loadLibrary(libraryName)) { for(ReaderWriterList::iterator itr=_rwList.begin(); itr!=_rwList.end(); ++itr) { if (rwOriginal.find(itr->get())==rwOriginal.end()) { ReaderWriter::ReadResult rr = (*itr)->readImage(fileName,_options.get()); if (rr.validImage()) return rr; else if (rr.error()) results.push_back(rr); } } } if (results.empty()) { return ReaderWriter::ReadResult("Warning: Could not find plugin to read image from file \""+fileName+"\"."); } return results.front(); } ReaderWriter::ReadResult Registry::readImage(const std::string& fileName,bool useObjectCache) { std::string file = findDataFile( fileName ); if (file.empty()) return ReaderWriter::ReadResult("Warning: file \""+fileName+"\" not found."); if (useObjectCache) { // search for entry in the object cache. ObjectCache::iterator oitr=_objectCache.find(file); if (oitr!=_objectCache.end()) { notify(INFO)<< "returning cached instanced of "<(oitr->second.first.get()); if (image) return image; else return ReaderWriter::ReadResult("Error file not of type osg::Image"); } PushAndPopDataPath tmpfile(getFilePath(file)); ReaderWriter::ReadResult rr = readImage(file); if (rr.validImage()) { // update cache with new entry. notify(INFO)<<"Adding to cache image "< rwOriginal; // record the errors reported by readerwriters. typedef std::vector Results; Results results; // first attempt to load the file from existing ReaderWriter's for(ReaderWriterList::iterator itr=_rwList.begin(); itr!=_rwList.end(); ++itr) { rwOriginal.insert(itr->get()); ReaderWriter::WriteResult rr = (*itr)->writeImage(image,fileName,_options.get()); if (rr.success()) return rr; else if (rr.error()) results.push_back(rr); } // now look for a plug-in to save the file. std::string libraryName = createLibraryNameForFile(fileName); if (loadLibrary(libraryName)) { for(ReaderWriterList::iterator itr=_rwList.begin(); itr!=_rwList.end(); ++itr) { if (rwOriginal.find(itr->get())==rwOriginal.end()) { ReaderWriter::WriteResult rr = (*itr)->writeImage(image,fileName,_options.get()); if (rr.success()) return rr; else if (rr.error()) results.push_back(rr); } } } if (results.empty()) { return ReaderWriter::WriteResult("Warning: Could not find plugin to write image to file \""+fileName+"\"."); } return results.front(); } ReaderWriter::ReadResult Registry::readNode(const std::string& fileName) { // record the existing reader writer. std::set rwOriginal; // record the errors reported by readerwriters. typedef std::vector Results; Results results; // first attempt to load the file from existing ReaderWriter's for(ReaderWriterList::iterator itr=_rwList.begin(); itr!=_rwList.end(); ++itr) { rwOriginal.insert(itr->get()); ReaderWriter::ReadResult rr = (*itr)->readNode(fileName,_options.get()); if (rr.validNode()) return rr; else if (rr.error()) results.push_back(rr); } // now look for a plug-in to load the file. std::string libraryName = createLibraryNameForFile(fileName); notify(INFO) << "Now checking for plug-in "<get())==rwOriginal.end()) { ReaderWriter::ReadResult rr = (*itr)->readNode(fileName,_options.get()); if (rr.validNode()) return rr; else if (rr.error()) results.push_back(rr); } } } // need to sort out. bool useObjectCache=true; if (_createNodeFromImage) { ReaderWriter::ReadResult rr = readImage(fileName,useObjectCache); if (rr.validImage()) return createGeodeForImage(rr.takeImage()); //else if (rr.error()) results.push_back(rr); } if (results.empty()) { return ReaderWriter::ReadResult("Warning: Could not find plugin to read nodes from file \""+fileName+"\"."); } return results.front(); } ReaderWriter::ReadResult Registry::readNode(const std::string& fileName,bool useObjectCache) { std::string file = findDataFile( fileName ); if (file.empty()) return ReaderWriter::ReadResult("Warning: file \""+fileName+"\" not found."); if (useObjectCache) { // search for entry in the object cache. ObjectCache::iterator oitr=_objectCache.find(file); if (oitr!=_objectCache.end()) { notify(INFO)<< "returning cached instanced of "<(oitr->second.first.get()); if (node) return node; else return ReaderWriter::ReadResult("Error file not of type osg::Node"); } PushAndPopDataPath tmpfile(getFilePath(file)); ReaderWriter::ReadResult rr = readNode(file); if (rr.validNode()) { // update cache with new entry. notify(INFO)<<"Adding to cache node "< rwOriginal; // record the errors reported by readerwriters. typedef std::vector Results; Results results; // first attempt to write the file from existing ReaderWriter's for(ReaderWriterList::iterator itr=_rwList.begin(); itr!=_rwList.end(); ++itr) { rwOriginal.insert(itr->get()); ReaderWriter::WriteResult rr = (*itr)->writeNode(node,fileName,_options.get()); if (rr.success()) return rr; else if (rr.error()) results.push_back(rr); } // now look for a plug-in to save the file. std::string libraryName = createLibraryNameForFile(fileName); if (loadLibrary(libraryName)) { for(ReaderWriterList::iterator itr=_rwList.begin(); itr!=_rwList.end(); ++itr) { if (rwOriginal.find(itr->get())==rwOriginal.end()) { ReaderWriter::WriteResult rr = (*itr)->writeNode(node,fileName,_options.get()); if (rr.success()) return rr; else if (rr.error()) results.push_back(rr); } } } if (results.empty()) { return ReaderWriter::WriteResult("Warning: Could not find plugin to write nodes to file \""+fileName+"\"."); } return results.front(); } void Registry::convertStringPathIntoFilePathList(const std::string& paths,FilePathList& filepath) { #if defined(WIN32) && !defined(__CYGWIN__) char delimitor = ';'; #else char delimitor = ':'; #endif if (!paths.empty()) { std::string::size_type start = 0; std::string::size_type end; while ((end = paths.find_first_of(delimitor,start))!=std::string::npos) { filepath.push_back(std::string(paths,start,end-start)); start = end+1; } filepath.push_back(std::string(paths,start,std::string::npos)); } } void Registry::updateTimeStampOfObjectsInCacheWithExtenalReferences(double currentTime) { // look for objects with external references and update their time stamp. for(ObjectCache::iterator itr=_objectCache.begin(); itr!=_objectCache.end(); ++itr) { // if ref count is greater the 1 the object has an external reference. if (itr->second.first->referenceCount()>1) { // so update it time stamp. itr->second.second = currentTime; } } } void Registry::removeExpiredObjectsInCache(double expiryTime) { typedef std::vector ObjectsToRemove; ObjectsToRemove objectsToRemove; // first collect all the exprired entries in the ObjectToRemove list. for(ObjectCache::iterator oitr=_objectCache.begin(); oitr!=_objectCache.end(); ++oitr) { if (oitr->second.second<=expiryTime) { // record the filename of the entry to use as key for deleting // afterwards/ objectsToRemove.push_back(oitr->first); } } // remove the entries from the _objectCaache. for(ObjectsToRemove::iterator ritr=objectsToRemove.begin(); ritr!=objectsToRemove.end(); ++ritr) { _objectCache.erase(*ritr); } } void Registry::clearObjectCache() { _objectCache.clear(); }