diff --git a/include/osgDB/InputStream b/include/osgDB/InputStream index 6736fe809..df7cfc327 100644 --- a/include/osgDB/InputStream +++ b/include/osgDB/InputStream @@ -69,6 +69,7 @@ public: virtual ~InputStream(); bool isBinary() const { return _in->isBinary(); } + int getFileVersion() const { return _fileVersion; } const osgDB::Options* getOptions() const { return _options.get(); } // Serialization related functions @@ -159,6 +160,7 @@ protected: ArrayMap _arrayMap; IdentifierMap _identifierMap; + int _fileVersion; int _byteSwap; bool _useSchemaData; bool _forceReadingImage; diff --git a/include/osgDB/ObjectWrapper b/include/osgDB/ObjectWrapper index 0e8a94b6a..27dc011dd 100644 --- a/include/osgDB/ObjectWrapper +++ b/include/osgDB/ObjectWrapper @@ -50,33 +50,39 @@ public: ObjectWrapper( osg::Object* proto, const std::string& name, const std::string& associates ); + void setUpdatedVersion( int ver ) { _version = ver; } 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 ) { _serializers.push_back(s); } + + void addSerializer( BaseSerializer* s, BaseSerializer::Type t=BaseSerializer::RW_UNDEFINED ) + { s->_version = _version; _serializers.push_back(s); _typeList.push_back(static_cast(t)); } + + 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 ); - void writeSchema( StringList& properties ); + + 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() {} + ObjectWrapper() : _version(0) {} virtual ~ObjectWrapper() {} - + osg::ref_ptr _proto; std::string _name; StringList _associates; SerializerList _serializers; SerializerList _backupSerializers; + std::vector _typeList; FinishedObjectReadCallbackList _finishedObjectReadCallbacks; + int _version; // Last updated version of the wrapper }; class Registry; @@ -143,6 +149,7 @@ protected: }; #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); \ @@ -150,6 +157,7 @@ protected: 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); \ @@ -167,6 +175,7 @@ protected: }; #define REGISTER_COMPRESSOR(NAME, CLASS) \ + extern "C" void wrapper_compressor_##CLASS(void) {} \ static osgDB::RegisterCompressorProxy compressor_proxy_##CLASS(NAME, new CLASS); } diff --git a/include/osgDB/Registry b/include/osgDB/Registry index 0c6e1801d..1306a0994 100644 --- a/include/osgDB/Registry +++ b/include/osgDB/Registry @@ -637,6 +637,14 @@ struct PluginFunctionProxy extern "C" void dotosgwrapper_##classname(void); \ static osgDB::PluginFunctionProxy proxy_dotosgwrapper_##classname(dotosgwrapper_##classname); +#define USE_SERIALIZER_WRAPPER(classname) \ + extern "C" void wrapper_serializer_##classname(void); \ + static osgDB::PluginFunctionProxy proxy_serializer_##classname(wrapper_serializer_##classname); + +#define USE_COMPRESSOR_WRAPPER(classname) \ + extern "C" void wrapper_serializer_##classname(void); \ + static osgDB::PluginFunctionProxy proxy_compressor_##classname(wrapper_compressor_##classname); + #define REGISTER_OSGPLUGIN(ext, classname) \ extern "C" void osgdb_##ext(void) {} \ static osgDB::RegisterReaderWriterProxy g_proxy_##classname; diff --git a/include/osgDB/Serializer b/include/osgDB/Serializer index bf28e6796..d8d377487 100644 --- a/include/osgDB/Serializer +++ b/include/osgDB/Serializer @@ -116,11 +116,23 @@ public: class BaseSerializer : public osg::Referenced { + friend class ObjectWrapper; public: - BaseSerializer() {} + enum Type + { + RW_UNDEFINED = 0, RW_USER, RW_OBJECT, RW_IMAGE, RW_LIST, + RW_BOOL, RW_SHORT, RW_USHORT, RW_INT, RW_UINT, RW_FLOAT, RW_DOUBLE, + RW_VEC2F, RW_VEC2D, RW_VEC3F, RW_VEC3D, RW_VEC4F, RW_VEC4D, RW_QUAT, RW_PLANE, + RW_MATRIXF, RW_MATRIXD, RW_MATRIX, RW_GLENUM, RW_STRING, RW_ENUM + }; + + BaseSerializer() : _version(0) {} virtual bool read( InputStream&, osg::Object& ) = 0; virtual bool write( OutputStream&, const osg::Object& ) = 0; virtual const std::string& getName() const = 0; + +protected: + int _version; // Library version when the serializer is added, or removed (neg value) }; template @@ -767,117 +779,117 @@ public: #define ADD_USER_SERIALIZER(PROP) \ wrapper->addSerializer( new osgDB::UserSerializer( \ - #PROP, &check##PROP, &read##PROP, &write##PROP) ) + #PROP, &check##PROP, &read##PROP, &write##PROP), osgDB::BaseSerializer::RW_USER ) #define ADD_BOOL_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::PropByValSerializer< MyClass, bool >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_BOOL ) #define ADD_SHORT_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::PropByValSerializer< MyClass, short >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_SHORT ) #define ADD_USHORT_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::PropByValSerializer< MyClass, unsigned short >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_USHORT ) #define ADD_HEXSHORT_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::PropByValSerializer< MyClass, unsigned short >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP, true) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP, true), osgDB::BaseSerializer::RW_USHORT ) #define ADD_INT_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::PropByValSerializer< MyClass, int >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_INT ) #define ADD_UINT_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::PropByValSerializer< MyClass, unsigned int >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_UINT ) #define ADD_GLINT_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::PropByValSerializer< MyClass, GLint >( \ - #PROP, ((int)(DEF)), &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, ((int)(DEF)), &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_INT ) #define ADD_HEXINT_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::PropByValSerializer< MyClass, unsigned int >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP, true) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP, true), osgDB::BaseSerializer::RW_UINT ) #define ADD_FLOAT_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::PropByValSerializer< MyClass, float >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_FLOAT ) #define ADD_DOUBLE_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::PropByValSerializer< MyClass, double >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_DOUBLE ) #define ADD_VEC2F_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::PropByRefSerializer< MyClass, osg::Vec2f >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_VEC2F ) #define ADD_VEC2D_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::PropByRefSerializer< MyClass, osg::Vec2d >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_VEC2D ) #define ADD_VEC2_SERIALIZER(PROP, DEF) ADD_VEC2F_SERIALIZER(PROP, DEF) #define ADD_VEC3F_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::PropByRefSerializer< MyClass, osg::Vec3f >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_VEC3F ) #define ADD_VEC3D_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::PropByRefSerializer< MyClass, osg::Vec3d >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_VEC3D ) #define ADD_VEC3_SERIALIZER(PROP, DEF) ADD_VEC3F_SERIALIZER(PROP, DEF) #define ADD_VEC4F_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::PropByRefSerializer< MyClass, osg::Vec4f >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_VEC4F ) #define ADD_VEC4D_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::PropByRefSerializer< MyClass, osg::Vec4d >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_VEC4D ) #define ADD_VEC4_SERIALIZER(PROP, DEF) ADD_VEC4F_SERIALIZER(PROP, DEF) #define ADD_QUAT_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::PropByRefSerializer< MyClass, osg::Quat >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_QUAT ) #define ADD_PLANE_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::PropByRefSerializer< MyClass, osg::Plane >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_PLANE ) #define ADD_MATRIXF_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::PropByRefSerializer< MyClass, osg::Matrixf >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_MATRIXF ) #define ADD_MATRIXD_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::PropByRefSerializer< MyClass, osg::Matrixd >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_MATRIXD ) #define ADD_MATRIX_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::MatrixSerializer< MyClass >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_MATRIX ) #define ADD_GLENUM_SERIALIZER(PROP, TYPE, DEF) \ wrapper->addSerializer( new osgDB::GLenumSerializer< MyClass, TYPE >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_GLENUM ) #define ADD_STRING_SERIALIZER(PROP, DEF) \ wrapper->addSerializer( new osgDB::StringSerializer< MyClass >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_STRING ) #define ADD_OBJECT_SERIALIZER(PROP, TYPE, DEF) \ wrapper->addSerializer( new osgDB::ObjectSerializer< MyClass, TYPE >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_OBJECT ) #define ADD_IMAGE_SERIALIZER(PROP, TYPE, DEF) \ wrapper->addSerializer( new osgDB::ImageSerializer< MyClass, TYPE >( \ - #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_IMAGE ) #define ADD_LIST_SERIALIZER(PROP, TYPE) \ wrapper->addSerializer( new osgDB::ListSerializer< MyClass, TYPE >( \ - #PROP, &MyClass::get##PROP, &MyClass::set##PROP) ) + #PROP, &MyClass::get##PROP, &MyClass::set##PROP), osgDB::BaseSerializer::RW_LIST ) #define BEGIN_ENUM_SERIALIZER(PROP, DEF) \ { typedef osgDB::EnumSerializer MySerializer; \ @@ -899,7 +911,6 @@ public: osg::ref_ptr serializer = new MySerializer( \ #PROP, PROPERTIES_CLASS::DEF, &MyClass::get##PROP, &MyClass::set##PROP) - #define ADD_ENUM_VALUE(VALUE) \ serializer->add(#VALUE, MyClass::VALUE) @@ -907,7 +918,14 @@ public: serializer->add(#VALUE, CLASS::VALUE) #define END_ENUM_SERIALIZER() \ - wrapper->addSerializer(serializer.get()); } + wrapper->addSerializer(serializer.get(), osgDB::BaseSerializer::RW_ENUM); } + +// VERSION CONTROL OPERATORS +#define UPDATE_TO_VERSION(VER) \ + wrapper->setUpdatedVersion( (VER) ); + +#define REMOVE_SERIALIZER(PROP) \ + wrapper->markSerializerAsRemoved( #PROP ); } diff --git a/src/osgDB/InputStream.cpp b/src/osgDB/InputStream.cpp index 32e81563b..04692738f 100644 --- a/src/osgDB/InputStream.cpp +++ b/src/osgDB/InputStream.cpp @@ -24,46 +24,26 @@ using namespace osgDB; static std::string s_lastSchema; InputStream::InputStream( const osgDB::Options* options ) - : _byteSwap(0), _useSchemaData(false), _forceReadingImage(false), _dataDecompress(0) + : _fileVersion(0), _byteSwap(0), _useSchemaData(false), _forceReadingImage(false), _dataDecompress(0) { if ( !options ) return; _options = options; std::string schema; - StringList optionList; - split( options->getOptionString(), optionList ); - for ( StringList::iterator itr=optionList.begin(); itr!=optionList.end(); ++itr ) + if ( options->getPluginStringData("ForceReadingImage")=="true" ) + _forceReadingImage = true; + if ( !options->getPluginStringData("SchemaFile").empty() ) { - const std::string& option = *itr; - if ( option=="Ascii" ) + schema = options->getPluginStringData("SchemaFile"); + if ( s_lastSchema!=schema ) { - // Omit this - } - else if ( option=="ForceReadingImage" ) - { - _forceReadingImage = true; - } - else - { - StringList keyAndValues; - split( option, keyAndValues, '=' ); - if ( keyAndValues.size()<2 ) continue; - - if ( keyAndValues[0]=="SchemaFile" ) - { - schema = keyAndValues[1]; - if ( s_lastSchema!=schema ) - { - osgDB::ifstream schemaStream( schema.c_str(), std::ios::in ); - if ( !schemaStream.fail() ) readSchema( schemaStream ); - schemaStream.close(); - s_lastSchema = schema; - } - } - else - OSG_WARN << "InputStream: Unknown option " << option << std::endl; + osgDB::ifstream schemaStream( schema.c_str(), std::ios::in ); + if ( !schemaStream.fail() ) readSchema( schemaStream ); + schemaStream.close(); + s_lastSchema = schema; } } + if ( schema.empty() ) { resetSchema(); @@ -733,13 +713,8 @@ InputStream::ReadType InputStream::start( InputIterator* inIterator ) *this >> PROPERTY("#Generator") >> osgName >> osgVersion; } - // Check file version - if ( version!=PLUGIN_VERSION ) - { - OSG_WARN << "InputStream: Input data version " << version - << " may be incompatible with current reader version " - << PLUGIN_VERSION << std::endl; - } + // Record file version for back-compatibility checking of wrappers + _fileVersion = version; _fields.pop_back(); return type; } @@ -793,9 +768,25 @@ void InputStream::setWrapperSchema( const std::string& name, const std::string& return; } - StringList schema; + StringList schema, methods, keyAndValue; + std::vector types; split( properties, schema ); - wrapper->readSchema( schema ); + for ( StringList::iterator itr=schema.begin(); itr!=schema.end(); ++itr ) + { + split( *itr, keyAndValue, ':' ); + if ( keyAndValue.size()>1 ) + { + methods.push_back( keyAndValue.front() ); + types.push_back( atoi(keyAndValue.back().c_str()) ); + } + else + { + methods.push_back( *itr ); + types.push_back( 0 ); + } + keyAndValue.clear(); + } + wrapper->readSchema( methods, types ); } void InputStream::resetSchema() diff --git a/src/osgDB/ObjectWrapper.cpp b/src/osgDB/ObjectWrapper.cpp index 39cb75096..ddf45cfba 100644 --- a/src/osgDB/ObjectWrapper.cpp +++ b/src/osgDB/ObjectWrapper.cpp @@ -86,17 +86,77 @@ void osgDB::split( const std::string& src, StringList& list, char separator ) ObjectWrapper::ObjectWrapper( osg::Object* proto, const std::string& name, const std::string& associates ) : osg::Referenced(), - _proto(proto), _name(name) + _proto(proto), _name(name), _version(0) { split( associates, _associates ); } +void ObjectWrapper::markSerializerAsRemoved( const std::string& name ) +{ + for ( SerializerList::iterator itr=_serializers.begin(); itr!=_serializers.end(); ++itr ) + { + // When a serializer is marked as 'removed', it means that this serializer won't be used any more + // from specified OSG version (by macro UPDATE_TO_VERSION). The read() functions of higher versions + // will thus ignore it according to the sign and value of the _version variable. + if ( (*itr)->getName()==name ) + (*itr)->_version = -_version; + } +} + +BaseSerializer* ObjectWrapper::getSerializer( const std::string& name ) +{ + for ( SerializerList::iterator itr=_serializers.begin(); itr!=_serializers.end(); ++itr ) + { + if ( (*itr)->getName()==name ) + return *itr; + } + + for ( StringList::const_iterator itr=_associates.begin(); itr!=_associates.end(); ++itr ) + { + const std::string& assocName = *itr; + ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName); + if ( !assocWrapper ) + { + osg::notify(osg::WARN) << "ObjectWrapper::getSerializer(): Unsupported associated class " + << assocName << std::endl; + continue; + } + + for ( SerializerList::iterator aitr=assocWrapper->_serializers.begin(); + aitr!=assocWrapper->_serializers.end(); ++aitr ) + { + if ( (*aitr)->getName()==name ) + return *aitr; + } + } + return NULL; +} + bool ObjectWrapper::read( InputStream& is, osg::Object& obj ) { bool readOK = true; for ( SerializerList::iterator itr=_serializers.begin(); itr!=_serializers.end(); ++itr ) { + int serializerVersion = (*itr)->_version; + if ( serializerVersion!=0 ) + { + if ( serializerVersion<0 ) + { + serializerVersion = -serializerVersion; + + // The serializer is removed from a specified version, + // and the file in reading is at the same or higher version, ignore it. + if ( is.getFileVersion()>=serializerVersion ) continue; + } + else + { + // The serializer is added at a specified version, + // but the file in reading is at a lower version, ignore it. + if ( is.getFileVersion()read(is, obj) ) continue; OSG_WARN << "ObjectWrapper::read(): Error reading property " << _name << "::" << (*itr)->getName() << std::endl; @@ -127,8 +187,9 @@ bool ObjectWrapper::write( OutputStream& os, const osg::Object& obj ) return writeOK; } -bool ObjectWrapper::readSchema( const StringList& properties ) +bool ObjectWrapper::readSchema( const StringList& properties, const std::vector& ) { + // FIXME: At present, I didn't do anything to determine serializers from their types... if ( !_backupSerializers.size() ) _backupSerializers = _serializers; _serializers.clear(); @@ -169,13 +230,19 @@ bool ObjectWrapper::readSchema( const StringList& properties ) return size==_serializers.size(); } -void ObjectWrapper::writeSchema( StringList& properties ) +void ObjectWrapper::writeSchema( StringList& properties, std::vector& types ) { for ( SerializerList::iterator itr=_serializers.begin(); itr!=_serializers.end(); ++itr ) { properties.push_back( (*itr)->getName() ); } + + for ( std::vector::iterator itr=_typeList.begin(); + itr!=_typeList.end(); ++itr ) + { + types.push_back( (*itr) ); + } } //////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/osgDB/OutputStream.cpp b/src/osgDB/OutputStream.cpp index 2db0cd2a1..85cd38a4d 100644 --- a/src/osgDB/OutputStream.cpp +++ b/src/osgDB/OutputStream.cpp @@ -18,6 +18,7 @@ #include #include #include +#include using namespace osgDB; @@ -27,39 +28,19 @@ OutputStream::OutputStream( const osgDB::Options* options ) if ( !options ) return; _options = options; - StringList optionList; - split( options->getOptionString(), optionList ); - for ( StringList::iterator itr=optionList.begin(); itr!=optionList.end(); ++itr ) + if ( options->getPluginStringData("SchemaData")=="true" ) + _useSchemaData = true; + if ( !options->getPluginStringData("SchemaFile").empty() ) + _schemaName = options->getPluginStringData("SchemaFile"); + if ( !options->getPluginStringData("Compressor").empty() ) + _compressorName = options->getPluginStringData("Compressor"); + if ( !options->getPluginStringData("WriteImageHint").empty() ) { - const std::string& option = *itr; - if ( option=="Ascii" ) - { - // Omit this - } - else if ( option=="SchemaData" ) - { - _useSchemaData = true; - } - else - { - StringList keyAndValues; - split( option, keyAndValues, '=' ); - if ( keyAndValues.size()<2 ) continue; - - if ( keyAndValues[0]=="SchemaFile" ) - _schemaName = keyAndValues[1]; - else if ( keyAndValues[0]=="Compressor" ) - _compressorName = keyAndValues[1]; - else if ( keyAndValues[0]=="WriteImageHint" ) - { - if ( keyAndValues[1]=="IncludeData" ) _writeImageHint = WRITE_INLINE_DATA; - else if ( keyAndValues[1]=="IncludeFile" ) _writeImageHint = WRITE_INLINE_FILE; - else if ( keyAndValues[1]=="UseExternal" ) _writeImageHint = WRITE_USE_EXTERNAL; - else if ( keyAndValues[1]=="WriteOut" ) _writeImageHint = WRITE_EXTERNAL_FILE; - } - else - OSG_WARN << "OutputStream: Unknown option " << option << std::endl; - } + std::string hintString = options->getPluginStringData("WriteImageHint"); + if ( hintString=="IncludeData" ) _writeImageHint = WRITE_INLINE_DATA; + else if ( hintString=="IncludeFile" ) _writeImageHint = WRITE_INLINE_FILE; + else if ( hintString=="UseExternal" ) _writeImageHint = WRITE_USE_EXTERNAL; + else if ( hintString=="WriteOut" ) _writeImageHint = WRITE_EXTERNAL_FILE; } } @@ -490,16 +471,18 @@ void OutputStream::writeObjectFields( const osg::Object* obj ) if ( _inbuiltSchemaMap.find(assocName)==_inbuiltSchemaMap.end() ) { StringList properties; - assocWrapper->writeSchema( properties ); - if ( properties.size()>0 ) + std::vector types; + assocWrapper->writeSchema( properties, types ); + + unsigned int size = osg::minimum( properties.size(), types.size() ); + if ( size>0 ) { - std::string propertiesString; - for ( StringList::iterator sitr=properties.begin(); sitr!=properties.end(); ++sitr ) + std::stringstream propertiesStream; + for ( unsigned int i=0; ifirst << " ="; StringList properties; - wrapper->writeSchema( properties ); - if ( properties.size()>0 ) + std::vector types; + wrapper->writeSchema( properties, types ); + + std::string propertiesString; + unsigned int size = osg::minimum( properties.size(), types.size() ); + for ( unsigned int i=0; i