/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 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. */ // Written by Wang Rui, (C) 2010 #ifndef OSGDB_OBJECTWRAPPER #define OSGDB_OBJECTWRAPPER #include namespace osgDB { typedef std::vector StringList; extern OSGDB_EXPORT void split( const std::string& src, StringList& list, char separator=' ' ); class OSGDB_EXPORT BaseCompressor : public osg::Referenced { public: BaseCompressor() {} void setName( const std::string& name ) { _name = name; } const std::string& getName() const { return _name; } virtual bool compress( std::ostream&, const std::string& ) = 0; virtual bool decompress( std::istream&, std::string& ) = 0; protected: std::string _name; }; struct FinishedObjectReadCallback : public osg::Referenced { virtual void objectRead(osgDB::InputStream& is, osg::Object& obj) = 0; }; class OSGDB_EXPORT ObjectWrapper : public osg::Referenced { public: typedef std::vector< osg::ref_ptr > SerializerList; typedef std::vector< osg::ref_ptr > FinishedObjectReadCallbackList; ObjectWrapper( osg::Object* proto, const std::string& name, const std::string& associates ); ObjectWrapper( osg::Object* proto, const std::string& domain, const std::string& name, const std::string& associates ); void setUpdatedVersion( int ver ) { _version = ver; } int getUpdatedVersion() const { return _version; } const osg::Object* getProto() const { return _proto.get(); } const std::string& getName() const { return _name; } const StringList& getAssociates() const { return _associates; } void addSerializer( BaseSerializer* s, BaseSerializer::Type t=BaseSerializer::RW_UNDEFINED ); void markSerializerAsRemoved( const std::string& name ); BaseSerializer* getSerializer( const std::string& name ); void addFinishedObjectReadCallback ( FinishedObjectReadCallback* forc) { _finishedObjectReadCallbacks.push_back(forc); } bool read( InputStream&, osg::Object& ); bool write( OutputStream&, const osg::Object& ); bool readSchema( const StringList& properties, const std::vector& types ); void writeSchema( StringList& properties, std::vector& types ); void resetSchema() { if ( _backupSerializers.size()>0 ) _serializers = _backupSerializers; } protected: ObjectWrapper() : _version(0) {} virtual ~ObjectWrapper() {} osg::ref_ptr _proto; std::string _domain; std::string _name; StringList _associates; SerializerList _serializers; SerializerList _backupSerializers; std::vector _typeList; FinishedObjectReadCallbackList _finishedObjectReadCallbacks; int _version; // Last updated version of the wrapper }; struct UpdateWrapperVersionProxy { UpdateWrapperVersionProxy( ObjectWrapper* w, int v ): _wrapper(w) { _lastVersion = w->getUpdatedVersion(); w->setUpdatedVersion(v); } ~UpdateWrapperVersionProxy() { _wrapper->setUpdatedVersion(_lastVersion); } ObjectWrapper* _wrapper; int _lastVersion; }; class Registry; class OSGDB_EXPORT ObjectWrapperManager : public osg::Referenced { public: // Wrapper handlers void addWrapper( ObjectWrapper* wrapper ); void removeWrapper( ObjectWrapper* wrapper ); ObjectWrapper* findWrapper( const std::string& name ); typedef std::map< std::string, osg::ref_ptr > WrapperMap; WrapperMap& getWrapperMap() { return _wrappers; } const WrapperMap& getWrapperMap() const { return _wrappers; } // Compressor handlers void addCompressor( BaseCompressor* compressor ); void removeCompressor( BaseCompressor* compressor ); BaseCompressor* findCompressor( const std::string& name ); typedef std::map< std::string, osg::ref_ptr > CompressorMap; CompressorMap& getCompressorMap() { return _compressors; } const CompressorMap& getCompressorMap() const { return _compressors; } typedef std::map IntLookupMap; IntLookup::Value getValue( const std::string& group, const std::string& str ) { return findLookup(group).getValue(str.c_str()); } const std::string& getString( const std::string& group, IntLookup::Value value ) { return findLookup(group).getString(value); } protected: friend class osgDB::Registry; ObjectWrapperManager(); virtual ~ObjectWrapperManager(); WrapperMap _wrappers; CompressorMap _compressors; IntLookup& findLookup( const std::string& group ) { IntLookupMap::iterator itr = _globalMap.find(group); if ( itr!=_globalMap.end() ) return itr->second; else return _globalMap["GL"]; } IntLookupMap _globalMap; }; class OSGDB_EXPORT RegisterWrapperProxy { public: typedef void (*AddPropFunc)( ObjectWrapper* ); RegisterWrapperProxy( osg::Object* proto, const std::string& name, const std::string& associates, AddPropFunc func ); virtual ~RegisterWrapperProxy(); protected: osg::ref_ptr _wrapper; }; class OSGDB_EXPORT RegisterCustomWrapperProxy { public: typedef void (*AddPropFunc)( const char*, ObjectWrapper* ); RegisterCustomWrapperProxy( osg::Object* proto, const std::string& domain, const std::string& name, const std::string& associates, AddPropFunc func ); virtual ~RegisterCustomWrapperProxy(); protected: osg::ref_ptr _wrapper; }; #define REGISTER_OBJECT_WRAPPER(NAME, PROTO, CLASS, ASSOCIATES) \ extern "C" void wrapper_serializer_##NAME(void) {} \ extern void wrapper_propfunc_##NAME(osgDB::ObjectWrapper*); \ static osgDB::RegisterWrapperProxy wrapper_proxy_##NAME( \ PROTO, #CLASS, ASSOCIATES, &wrapper_propfunc_##NAME); \ typedef CLASS MyClass; \ void wrapper_propfunc_##NAME(osgDB::ObjectWrapper* wrapper) #define REGISTER_OBJECT_WRAPPER2(NAME, PROTO, CLASS, CLASSNAME, ASSOCIATES) \ extern "C" void wrapper_serializer_##NAME(void) {} \ extern void wrapper_propfunc_##NAME(osgDB::ObjectWrapper*); \ static osgDB::RegisterWrapperProxy wrapper_proxy_##NAME( \ PROTO, CLASSNAME, ASSOCIATES, &wrapper_propfunc_##NAME); \ typedef CLASS MyClass; \ void wrapper_propfunc_##NAME(osgDB::ObjectWrapper* wrapper) #define REGISTER_CUSTOM_OBJECT_WRAPPER(DOMAIN, NAME, PROTO, CLASS, ASSOCIATES) \ extern "C" void wrapper_serializer_##NAME(void) {} \ extern void wrapper_propfunc_##NAME(const char*, osgDB::ObjectWrapper*); \ static osgDB::RegisterCustomWrapperProxy wrapper_proxy_##NAME( \ PROTO, #DOMAIN, #CLASS, ASSOCIATES, &wrapper_propfunc_##NAME); \ typedef CLASS MyClass; \ void wrapper_propfunc_##NAME(const char* domain, osgDB::ObjectWrapper* wrapper) #define REGISTER_CUSTOM_OBJECT_WRAPPER2(DOMAIN, NAME, PROTO, CLASS, CLASSNAME, ASSOCIATES) \ extern "C" void wrapper_serializer_##NAME(void) {} \ extern void wrapper_propfunc_##NAME(const char*, osgDB::ObjectWrapper*); \ static osgDB::RegisterCustomWrapperProxy wrapper_proxy_##NAME( \ PROTO, #DOMAIN, CLASSNAME, ASSOCIATES, &wrapper_propfunc_##NAME); \ typedef CLASS MyClass; \ void wrapper_propfunc_##NAME(const char* domain, osgDB::ObjectWrapper* wrapper) class OSGDB_EXPORT RegisterCompressorProxy { public: RegisterCompressorProxy( const std::string& name, BaseCompressor* compressor ); ~RegisterCompressorProxy(); protected: osg::ref_ptr _compressor; }; #define REGISTER_COMPRESSOR(NAME, CLASS) \ extern "C" void wrapper_compressor_##CLASS(void) {} \ static osgDB::RegisterCompressorProxy compressor_proxy_##CLASS(NAME, new CLASS); } #endif