5011d994e8
of iterating through the list of available reader writer, whilst handling cases where the list itself changes size during iteration through the list. Previous size changes during iteration was cause invalid iterators, which in turn was causing a crash.
336 lines
14 KiB
C++
336 lines
14 KiB
C++
/* -*-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.
|
|
*/
|
|
|
|
#ifndef OSGDB_REGISTRY
|
|
#define OSGDB_REGISTRY 1
|
|
|
|
#include <osg/ref_ptr>
|
|
#include <osg/ArgumentParser>
|
|
|
|
#include <osgDB/DynamicLibrary>
|
|
#include <osgDB/ReaderWriter>
|
|
#include <osgDB/DotOsgWrapper>
|
|
|
|
#include <vector>
|
|
#include <map>
|
|
#include <string>
|
|
#include <deque>
|
|
|
|
|
|
namespace osgDB {
|
|
|
|
/** basic structure for custom runtime inheritance checking */
|
|
struct basic_type_wrapper {
|
|
virtual bool matches(const osg::Object *proto) const = 0;
|
|
};
|
|
|
|
/** a class template that checks inheritance between a given
|
|
Object's class and a class defined at compile time through
|
|
the template parameter T.
|
|
This is used in conjunction with readObjectOfType() to
|
|
specify an abstract class as reference type.
|
|
**/
|
|
template<class T>
|
|
struct type_wrapper: basic_type_wrapper {
|
|
bool matches(const osg::Object *proto) const
|
|
{
|
|
return dynamic_cast<const T*>(proto) != 0;
|
|
}
|
|
};
|
|
|
|
/** list of directories to search through which searching for files. */
|
|
typedef std::deque<std::string> FilePathList;
|
|
|
|
/**
|
|
Registry is a singleton factory which stores
|
|
the reader/writers which are linked in
|
|
at runtime for reading non-native file formats.
|
|
|
|
The RegisterDotOsgWrapperProxy can be used to automatically register
|
|
DotOsgWrappers, at runtime with the Registry. A DotOsgWrapper encapsulates
|
|
the functions that can read and write to the .osg for each osg::Object.
|
|
|
|
The RegisterReaderWriterProxy can be used to automatically
|
|
register at runtime a reader/writer with the Registry.
|
|
*/
|
|
class OSGDB_EXPORT Registry : public osg::Referenced
|
|
{
|
|
public:
|
|
|
|
static Registry* instance();
|
|
|
|
/** read the command line arguments.*/
|
|
void readCommandLine(osg::ArgumentParser& commandLine);
|
|
|
|
/** register an .fileextension alias to mapExt toExt, the later
|
|
* should the the extension name of the readerwriter plugin library.
|
|
* For example to map .tif files to the tiff loader, use
|
|
* addExtAlias("tif","tiff") which will enable .tif to be read
|
|
* by the libdb_tiff readerwriter plugin.*/
|
|
void addFileExtensionAlias(const std::string mapExt, const std::string toExt);
|
|
|
|
void addDotOsgWrapper(DotOsgWrapper* wrapper);
|
|
void removeDotOsgWrapper(DotOsgWrapper* wrapper);
|
|
|
|
void addReaderWriter(ReaderWriter* rw);
|
|
void removeReaderWriter(ReaderWriter* rw);
|
|
|
|
/** create the platform specific library name associated with file.*/
|
|
std::string createLibraryNameForFile(const std::string& fileName);
|
|
|
|
/** create the platform specific library name associated with file extension.*/
|
|
std::string createLibraryNameForExtension(const std::string& ext);
|
|
|
|
/** create the platform specific library name associated with nodekit library name.*/
|
|
std::string createLibraryNameForNodeKit(const std::string& name);
|
|
|
|
/** find the library in the SG_LIBRARY_PATH and load it.*/
|
|
bool loadLibrary(const std::string& fileName);
|
|
/** close the attached library with specified name.*/
|
|
bool closeLibrary(const std::string& fileName);
|
|
|
|
/** get a reader writer which handles specified extension.*/
|
|
ReaderWriter* getReaderWriterForExtension(const std::string& ext);
|
|
|
|
osg::Object* readObjectOfType(const osg::Object& compObj,Input& fr);
|
|
osg::Object* readObjectOfType(const basic_type_wrapper &btw, Input& fr);
|
|
|
|
osg::Object* readObject(Input& fr);
|
|
osg::Image* readImage(Input& fr);
|
|
osg::Drawable* readDrawable(Input& fr);
|
|
osg::StateAttribute* readStateAttribute(Input& fr);
|
|
osg::Node* readNode(Input& fr);
|
|
|
|
bool writeObject(const osg::Object& obj,Output& fw);
|
|
|
|
|
|
ReaderWriter::ReadResult readObject(const std::string& fileName,bool useObjectCache);
|
|
ReaderWriter::WriteResult writeObject(const osg::Object& obj, const std::string& fileName);
|
|
|
|
ReaderWriter::ReadResult readImage(const std::string& fileName,bool useObjectCache);
|
|
ReaderWriter::WriteResult writeImage(const osg::Image& obj, const std::string& fileName);
|
|
|
|
ReaderWriter::ReadResult readHeightField(const std::string& fileName,bool useObjectCache);
|
|
ReaderWriter::WriteResult writeHeightField(const osg::HeightField& obj, const std::string& fileName);
|
|
|
|
ReaderWriter::ReadResult readNode(const std::string& fileName,bool useObjectCache);
|
|
ReaderWriter::WriteResult writeNode(const osg::Node& node, const std::string& fileName);
|
|
|
|
void setCreateNodeFromImage(bool flag) { _createNodeFromImage = flag; }
|
|
bool getCreateNodeFromImage() const { return _createNodeFromImage; }
|
|
|
|
void setOptions(ReaderWriter::Options* opt) { _options = opt; }
|
|
ReaderWriter::Options* getOptions() { return _options.get(); }
|
|
const ReaderWriter::Options* getOptions() const { return _options.get(); }
|
|
|
|
|
|
/** initilize both the Data and Library FilePaths, by default called by the
|
|
* constructor, so it should only be required if you want to force
|
|
* the re-reading of environmental variables.*/
|
|
void initFilePathLists() { initDataFilePathList(); initLibraryFilePathList(); }
|
|
|
|
/** initilize the Data FilePath by reading the OSG_FILE_PATH environmental variable.*/
|
|
void initDataFilePathList();
|
|
|
|
/** Set the data file path using a list of paths stored in a FilePath, which is used when search for data files.*/
|
|
void setDataFilePathList(const FilePathList& filepath) { _dataFilePath = filepath; }
|
|
|
|
/** Set the data file path using a single string deliminated either with ';' (Windows) or ':' (All other platforms), which is used when search for data files.*/
|
|
void setDataFilePathList(const std::string& paths) { _dataFilePath.clear(); convertStringPathIntoFilePathList(paths,_dataFilePath); }
|
|
|
|
/** get the data file path which is used when search for data files.*/
|
|
FilePathList& getDataFilePathList() { return _dataFilePath; }
|
|
|
|
/** get the const data file path which is used when search for data files.*/
|
|
const FilePathList& getDataFilePathList() const { return _dataFilePath; }
|
|
|
|
/** initilize the Library FilePath by reading the OSG_LIBRARY_PATH
|
|
* and the appropriate system environmental variables*/
|
|
void initLibraryFilePathList();
|
|
|
|
/** Set the library file path using a list of paths stored in a FilePath, which is used when search for data files.*/
|
|
void setLibraryFilePathList(const FilePathList& filepath) { _libraryFilePath = filepath; }
|
|
|
|
/** Set the library file path using a single string deliminated either with ';' (Windows) or ':' (All other platforms), which is used when search for data files.*/
|
|
void setLibraryFilePathList(const std::string& paths) { _libraryFilePath.clear(); convertStringPathIntoFilePathList(paths,_libraryFilePath); }
|
|
|
|
/** get the library file path which is used when search for library (dso/dll's) files.*/
|
|
FilePathList& getLibraryFilePathList() { return _libraryFilePath; }
|
|
|
|
/** get the const library file path which is used when search for library (dso/dll's) files.*/
|
|
const FilePathList& getLibraryFilePathList() const { return _libraryFilePath; }
|
|
|
|
/** convert a string containing a list of paths deliminated either with ';' (Windows) or ':' (All other platforms) into FilePath represetation.*/
|
|
static void convertStringPathIntoFilePathList(const std::string& paths,FilePathList& filepath);
|
|
|
|
|
|
/** For each object in the cache which has an reference count greater than 1
|
|
* (and therefore referenced by elsewhere in the application) set the time stamp
|
|
* for that object in the cache to specified time.
|
|
* This would typically be called once per frame by applications which are doing database paging,
|
|
* and need to prune objects that are no longer required.
|
|
* Time value is time in sceonds.*/
|
|
void updateTimeStampOfObjectsInCacheWithExtenalReferences(double currentTime);
|
|
|
|
/** Removed object in the cache which have a time stamp at or before the specified expiry time.
|
|
* This would typically be called once per frame by applications which are doing database paging,
|
|
* and need to prune objects that are no longer required, and called after the a called
|
|
* after the call to updateTimeStampOfObjectsInCacheWithExtenalReferences(currentTime).
|
|
* Note, the currentTime is not the expiryTime, one would typically set the expiry time
|
|
* to a fixed amount of time before currentTime, such as expiryTime = currentTime-10.0.
|
|
* Time value is time in sceonds.*/
|
|
void removeExpiredObjectsInCache(double expiryTime);
|
|
|
|
/** Remove all objects in the cache regardless of having external references or expiry times.*/
|
|
void clearObjectCache();
|
|
|
|
/** Add a filename,object,timestamp tripple to the Registry::ObjectCache.*/
|
|
void addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp = 0.0);
|
|
|
|
/** Set whether the Registry::ObjectCache should be used by default.*/
|
|
void setUseObjectCacheHint(bool useObjectCache) { _useObjectCacheHint = useObjectCache; }
|
|
|
|
/** Get whether the Registry::ObjectCache should be used by default.*/
|
|
bool getUseObjectCacheHint() const { return _useObjectCacheHint; }
|
|
|
|
/** get the attached library with specified name.*/
|
|
DynamicLibrary* getLibrary(const std::string& fileName);
|
|
|
|
typedef std::vector< osg::ref_ptr<ReaderWriter> > ReaderWriterList;
|
|
|
|
protected:
|
|
|
|
virtual ~Registry();
|
|
|
|
typedef std::map< std::string, osg::ref_ptr<DotOsgWrapper> > DotOsgWrapperMap;
|
|
typedef std::vector< osg::ref_ptr<DynamicLibrary> > DynamicLibraryList;
|
|
typedef std::map< std::string, std::string> ExtensionAliasMap;
|
|
|
|
typedef std::pair<osg::ref_ptr<osg::Object>, double > ObjectTimeStampPair;
|
|
typedef std::map<std::string, ObjectTimeStampPair > ObjectCache;
|
|
|
|
/** constructor is private, as its a singleton, preventing
|
|
construction other than via the instance() method and
|
|
therefore ensuring only one copy is ever constructed*/
|
|
Registry();
|
|
|
|
/** get the attached library with specified name.*/
|
|
DynamicLibraryList::iterator getLibraryItr(const std::string& fileName);
|
|
|
|
bool _createNodeFromImage;
|
|
|
|
osg::Object* readObject(DotOsgWrapperMap& dowMap,Input& fr);
|
|
|
|
void eraseWrapper(DotOsgWrapperMap& wrappermap,DotOsgWrapper* wrapper);
|
|
|
|
ReaderWriter::ReadResult readObject(const std::string& fileName);
|
|
ReaderWriter::ReadResult readImage(const std::string& fileName);
|
|
ReaderWriter::ReadResult readHeightField(const std::string& fileName);
|
|
ReaderWriter::ReadResult readNode(const std::string& fileName);
|
|
|
|
DotOsgWrapperMap _objectWrapperMap;
|
|
DotOsgWrapperMap _imageWrapperMap;
|
|
DotOsgWrapperMap _drawableWrapperMap;
|
|
DotOsgWrapperMap _stateAttrWrapperMap;
|
|
DotOsgWrapperMap _nodeWrapperMap;
|
|
|
|
DotOsgWrapperMap _classNameWrapperMap;
|
|
|
|
ReaderWriterList _rwList;
|
|
DynamicLibraryList _dlList;
|
|
|
|
bool _openingLibrary;
|
|
|
|
// map to alias to extensions to plugins.
|
|
ExtensionAliasMap _extAliasMap;
|
|
|
|
// options to pass to reader writers.
|
|
osg::ref_ptr<ReaderWriter::Options> _options;
|
|
|
|
FilePathList _dataFilePath;
|
|
FilePathList _libraryFilePath;
|
|
|
|
bool _useObjectCacheHint;
|
|
ObjectCache _objectCache;
|
|
|
|
};
|
|
|
|
/** read the command line arguments.*/
|
|
inline void readCommandLine(osg::ArgumentParser& parser)
|
|
{
|
|
Registry::instance()->readCommandLine(parser);
|
|
}
|
|
|
|
/** Proxy class for automatic registration of DotOsgWrappers with the Registry.*/
|
|
class RegisterDotOsgWrapperProxy
|
|
{
|
|
public:
|
|
|
|
RegisterDotOsgWrapperProxy(osg::Object* proto,
|
|
const std::string& name,
|
|
const std::string& associates,
|
|
DotOsgWrapper::ReadFunc readFunc,
|
|
DotOsgWrapper::WriteFunc writeFunc,
|
|
DotOsgWrapper::ReadWriteMode readWriteMode=DotOsgWrapper::READ_AND_WRITE)
|
|
{
|
|
if (Registry::instance())
|
|
{
|
|
_wrapper = new DotOsgWrapper(proto,name,associates,readFunc,writeFunc,readWriteMode);
|
|
Registry::instance()->addDotOsgWrapper(_wrapper.get());
|
|
}
|
|
}
|
|
|
|
~RegisterDotOsgWrapperProxy()
|
|
{
|
|
if (Registry::instance())
|
|
{
|
|
Registry::instance()->removeDotOsgWrapper(_wrapper.get());
|
|
}
|
|
}
|
|
|
|
protected:
|
|
osg::ref_ptr<DotOsgWrapper> _wrapper;
|
|
};
|
|
|
|
/** Proxy class for automatic registration of reader/writers with the Registry.*/
|
|
template<class T>
|
|
class RegisterReaderWriterProxy
|
|
{
|
|
public:
|
|
RegisterReaderWriterProxy()
|
|
{
|
|
if (Registry::instance())
|
|
{
|
|
_rw = new T;
|
|
Registry::instance()->addReaderWriter(_rw.get());
|
|
}
|
|
}
|
|
|
|
~RegisterReaderWriterProxy()
|
|
{
|
|
if (Registry::instance())
|
|
{
|
|
Registry::instance()->removeReaderWriter(_rw.get());
|
|
}
|
|
}
|
|
|
|
T* get() { return _rw.get(); }
|
|
|
|
protected:
|
|
osg::ref_ptr<T> _rw;
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|