OpenSceneGraph/include/osgDB/Serializer
Robert Osfield 6df7dbf626 Improved the handling of matrices in serialization so that it's more reliable,
change was to use doubles for reading and writing matrices regardless of type of Matrix
being serialized.

Change does break backwards compatibility though, so code
path supporting original format has been left in for the
time being.  However, this code is not reliable enough and
is over complicated compared to the simplified handling.   Once
the new code has been bedded down for a while I'll remove this code block.
2010-10-04 15:23:19 +00:00

915 lines
28 KiB
C++

/* -*-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__SERIALIZER
#define OSGDB__SERIALIZER
#include <osg/ref_ptr>
#include <osg/Notify>
#include <osg/Object>
#include <osgDB/InputStream>
#include <osgDB/OutputStream>
#include <string>
#include <sstream>
namespace osgDB
{
#ifndef OBJECT_CAST
#define OBJECT_CAST static_cast
#endif
class IntLookup
{
public:
typedef int Value;
typedef std::map<std::string, Value> StringToValue;
typedef std::map<Value, std::string> ValueToString;
IntLookup() {}
unsigned int size() const { return _stringToValue.size(); }
void add( const char* str, Value value )
{
if ( _valueToString.find(value)!=_valueToString.end() )
{
osg::notify(osg::WARN) << "Duplicate enum value " << value
<< " with old string: " << _valueToString[value]
<< " and new string: " << str << std::endl;
}
_valueToString[value] = str;
_stringToValue[str] = value;
}
Value getValue( const char* str )
{
StringToValue::iterator itr = _stringToValue.find(str);
if ( itr==_stringToValue.end() )
{
Value value;
std::stringstream stream;
stream << str; stream >> value;
_stringToValue[str] = value;
return value;
}
return itr->second;
}
const std::string& getString( Value value )
{
ValueToString::iterator itr = _valueToString.find(value);
if ( itr==_valueToString.end() )
{
std::string str;
std::stringstream stream;
stream << value; stream >> str;
_valueToString[value] = str;
return _valueToString[value];
}
return itr->second;
}
protected:
StringToValue _stringToValue;
ValueToString _valueToString;
};
class UserLookupTableProxy
{
public:
typedef void (*AddValueFunc)( IntLookup* lookup );
UserLookupTableProxy( AddValueFunc func ) { if ( func ) (*func)(&_lookup); }
IntLookup _lookup;
};
#define BEGIN_USER_TABLE(NAME, CLASS) \
static void add_user_value_func_##NAME(osgDB::IntLookup*); \
static osgDB::UserLookupTableProxy s_user_lookup_table_##NAME(&add_user_value_func_##NAME); \
static void add_user_value_func_##NAME(osgDB::IntLookup* lookup) { typedef CLASS MyClass
#define ADD_USER_VALUE(VALUE) lookup->add(#VALUE, MyClass::VALUE)
#define END_USER_TABLE() }
#define USER_READ_FUNC(NAME, FUNCNAME) \
static int FUNCNAME(osgDB::InputStream& is) { \
int value; if (is.isBinary()) is >> value; \
else { std::string str; is >> str; \
value = (s_user_lookup_table_##NAME)._lookup.getValue(str.c_str()); } \
return value; }
#define USER_WRITE_FUNC(NAME, FUNCNAME) \
static void FUNCNAME(osgDB::OutputStream& os, int value) { \
if (os.isBinary()) os << value; \
else os << (s_user_lookup_table_##NAME)._lookup.getString(value); } \
class BaseSerializer : public osg::Referenced
{
public:
BaseSerializer() {}
virtual bool read( InputStream&, osg::Object& ) = 0;
virtual bool write( OutputStream&, const osg::Object& ) = 0;
virtual const std::string& getName() const = 0;
};
template<typename C>
class UserSerializer : public BaseSerializer
{
public:
typedef bool (*Checker)( const C& );
typedef bool (*Reader)( InputStream&, C& );
typedef bool (*Writer)( OutputStream&, const C& );
UserSerializer( const char* name, Checker cf, Reader rf, Writer wf )
: _name(name), _checker(cf), _reader(rf), _writer(wf) {}
virtual bool read( InputStream& is, osg::Object& obj )
{
C& object = OBJECT_CAST<C&>(obj);
if ( is.isBinary() )
{
bool ok = false; is >> ok;
if ( !ok ) return true;
}
else
{
if ( !is.matchString(_name) )
return true;
}
return (*_reader)(is, object);
}
virtual bool write( OutputStream& os, const osg::Object& obj )
{
const C& object = OBJECT_CAST<const C&>(obj);
bool ok = (*_checker)(object);
if ( os.isBinary() )
{
os << ok;
if ( !ok ) return true;
}
else
{
if ( !ok ) return true;
os << PROPERTY(_name.c_str());
}
return (*_writer)(os, object);
}
virtual const std::string& getName() const { return _name; }
protected:
std::string _name;
Checker _checker;
public:
Reader _reader;
Writer _writer;
};
template<typename P>
class TemplateSerializer : public BaseSerializer
{
public:
TemplateSerializer( const char* name )
: _name(name) {}
virtual bool read( InputStream& is, osg::Object& obj ) = 0;
virtual bool write( OutputStream& os, const osg::Object& obj ) = 0;
virtual const std::string& getName() const { return _name; }
protected:
std::string _name;
P _defaultValue;
};
template<typename C, typename P>
class PropByValSerializer : public TemplateSerializer<P>
{
public:
typedef TemplateSerializer<P> ParentType;
typedef P (C::*Getter)() const;
typedef void (C::*Setter)( P );
PropByValSerializer( const char* name, P def, Getter gf, Setter sf, bool useHex=false )
: ParentType(name), _getter(gf), _setter(sf), _useHex(useHex)
{ ParentType::_defaultValue = def; }
virtual bool read( InputStream& is, osg::Object& obj )
{
C& object = OBJECT_CAST<C&>(obj);
P value;
if ( is.isBinary() )
{
is >> value;
if ( ParentType::_defaultValue!=value )
(object.*_setter)( value );
}
else if ( is.matchString(ParentType::_name) )
{
if ( _useHex ) is >> std::hex;
is >> value;
if ( _useHex ) is >> std::dec;
(object.*_setter)( value );
}
return true;
}
virtual bool write( OutputStream& os, const osg::Object& obj )
{
const C& object = OBJECT_CAST<const C&>(obj);
P value = (object.*_getter)();
if ( os.isBinary() )
{
os << value;
}
else if ( ParentType::_defaultValue!=value )
{
os << PROPERTY((ParentType::_name).c_str());
if ( _useHex ) os << std::hex;
os << value;
if ( _useHex ) os << std::dec;
os << std::endl;
}
return true;
}
public:
Getter _getter;
Setter _setter;
protected:
bool _useHex;
};
template<typename C, typename P>
class PropByRefSerializer : public TemplateSerializer<P>
{
public:
typedef TemplateSerializer<P> ParentType;
typedef const P& CP;
typedef CP (C::*Getter)() const;
typedef void (C::*Setter)( CP );
PropByRefSerializer( const char* name, CP def, Getter gf, Setter sf )
: ParentType(name), _getter(gf), _setter(sf)
{ ParentType::_defaultValue = def; }
virtual bool read( InputStream& is, osg::Object& obj )
{
C& object = OBJECT_CAST<C&>(obj);
P value;
if ( is.isBinary() )
{
is >> value;
if ( ParentType::_defaultValue!=value )
(object.*_setter)( value );
}
else if ( is.matchString(ParentType::_name) )
{
is >> value;
(object.*_setter)( value );
}
return true;
}
virtual bool write( OutputStream& os, const osg::Object& obj )
{
const C& object = OBJECT_CAST<const C&>(obj);
CP value = (object.*_getter)();
if ( os.isBinary() )
{
os << value;
}
else if ( ParentType::_defaultValue!=value )
{
os << PROPERTY((ParentType::_name).c_str()) << value << std::endl;
}
return true;
}
public:
Getter _getter;
Setter _setter;
};
template<typename C>
class MatrixSerializer : public TemplateSerializer<osg::Matrix>
{
public:
typedef TemplateSerializer<osg::Matrix> ParentType;
typedef const osg::Matrix& (C::*Getter)() const;
typedef void (C::*Setter)( const osg::Matrix& );
MatrixSerializer( const char* name, const osg::Matrix& def, Getter gf, Setter sf )
: ParentType(name), _getter(gf), _setter(sf)
{ ParentType::_defaultValue = def; }
virtual bool read( InputStream& is, osg::Object& obj )
{
C& object = OBJECT_CAST<C&>(obj);
osg::Matrix value;
if ( is.isBinary() )
{
readMatrixImplementation( is, value );
if ( ParentType::_defaultValue!=value )
(object.*_setter)( value );
}
else if ( is.matchString(ParentType::_name) )
{
readMatrixImplementation( is, value );
(object.*_setter)( value );
}
return true;
}
virtual bool write( OutputStream& os, const osg::Object& obj )
{
const C& object = OBJECT_CAST<const C&>(obj);
const osg::Matrix& value = (object.*_getter)();
if ( os.isBinary() )
{
OSG_NOTICE<<"MatrixSerializer::write() binary"<<std::endl;
os << value;
}
else if ( ParentType::_defaultValue!=value )
{
OSG_NOTICE<<"MatrixSerializer::write() ascii, ParentType::_name="<<ParentType::_name<<std::endl;
os << PROPERTY((ParentType::_name).c_str()) << value << std::endl;
}
return true;
}
protected:
void readMatrixImplementation( InputStream& is, osg::Matrix& matrix )
{
#if 1
is >> matrix;
#else
if ( is.getUseFloatMatrix() )
{
osg::Matrixf realValue; is >> realValue;
matrix = realValue;
}
else
{
osg::Matrixd realValue; is >> realValue;
matrix = realValue;
}
#endif
}
public:
Getter _getter;
Setter _setter;
};
template<typename C, typename P>
class GLenumSerializer : public TemplateSerializer<P>
{
public:
typedef TemplateSerializer<P> ParentType;
typedef P (C::*Getter)() const;
typedef void (C::*Setter)( P );
GLenumSerializer( const char* name, P def, Getter gf, Setter sf )
: ParentType(name), _getter(gf), _setter(sf)
{ ParentType::_defaultValue = def; }
virtual bool read( InputStream& is, osg::Object& obj )
{
C& object = OBJECT_CAST<C&>(obj);
if ( is.isBinary() )
{
GLenum value; is >> value;
if ( ParentType::_defaultValue!=static_cast<P>(value) )
(object.*_setter)( static_cast<P>(value) );
}
else if ( is.matchString(ParentType::_name) )
{
DEF_GLENUM(value); is >> value;
(object.*_setter)( static_cast<P>(value.get()) );
}
return true;
}
virtual bool write( OutputStream& os, const osg::Object& obj )
{
const C& object = OBJECT_CAST<const C&>(obj);
const P value = (object.*_getter)();
if ( os.isBinary() )
{
os << static_cast<GLenum>(value);
}
else if ( ParentType::_defaultValue!=value )
{
os << PROPERTY((ParentType::_name).c_str()) << GLENUM(value) << std::endl;
}
return true;
}
public:
Getter _getter;
Setter _setter;
};
template<typename C>
class StringSerializer : public TemplateSerializer<std::string>
{
public:
typedef TemplateSerializer<std::string> ParentType;
typedef const std::string& (C::*Getter)() const;
typedef void (C::*Setter)( const std::string& );
StringSerializer( const char* name, const std::string& def, Getter gf, Setter sf )
: ParentType(name), _getter(gf), _setter(sf)
{ ParentType::_defaultValue = def; }
virtual bool read( InputStream& is, osg::Object& obj )
{
C& object = OBJECT_CAST<C&>(obj);
std::string value;
if ( is.isBinary() )
{
is >> value;
if ( ParentType::_defaultValue!=value )
(object.*_setter)( value );
}
else if ( is.matchString(ParentType::_name) )
{
is.readWrappedString( value );
if ( !value.empty() )
(object.*_setter)( value );
}
return true;
}
virtual bool write( OutputStream& os, const osg::Object& obj )
{
const C& object = OBJECT_CAST<const C&>(obj);
const std::string& value = (object.*_getter)();
if ( os.isBinary() )
{
os << value;
}
else if ( ParentType::_defaultValue!=value )
{
os << PROPERTY((ParentType::_name).c_str());
os.writeWrappedString( value );
os << std::endl;
}
return true;
}
public:
Getter _getter;
Setter _setter;
};
template<typename C, typename P>
class ObjectSerializer : public TemplateSerializer<P*>
{
public:
typedef TemplateSerializer<P*> ParentType;
typedef const P* (C::*Getter)() const;
typedef void (C::*Setter)( P* );
ObjectSerializer( const char* name, P* def, Getter gf, Setter sf )
: ParentType(name), _getter(gf), _setter(sf)
{ ParentType::_defaultValue = def; }
virtual bool read( InputStream& is, osg::Object& obj )
{
C& object = OBJECT_CAST<C&>(obj);
bool hasObject = false;
if ( is.isBinary() )
{
is >> hasObject;
if ( hasObject )
{
P* value = dynamic_cast<P*>( is.readObject() );
if ( ParentType::_defaultValue!=value )
(object.*_setter)( value );
}
}
else if ( is.matchString(ParentType::_name) )
{
is >> hasObject;
if ( hasObject )
{
is >> BEGIN_BRACKET;
P* value = dynamic_cast<P*>( is.readObject() );
if ( ParentType::_defaultValue!=value )
(object.*_setter)( value );
is >> END_BRACKET;
}
}
return true;
}
virtual bool write( OutputStream& os, const osg::Object& obj )
{
const C& object = OBJECT_CAST<const C&>(obj);
const P* value = (object.*_getter)();
bool hasObject = (value!=NULL);
if ( os.isBinary() )
{
os << hasObject;
os.writeObject( value );
}
else if ( ParentType::_defaultValue!=value )
{
os << PROPERTY((ParentType::_name).c_str()) << hasObject;
if ( hasObject )
{
os << BEGIN_BRACKET << std::endl;
os.writeObject( value );
os << END_BRACKET;
}
os << std::endl;
}
return true;
}
public:
Getter _getter;
Setter _setter;
};
template<typename C, typename P>
class ImageSerializer : public TemplateSerializer<P*>
{
public:
typedef TemplateSerializer<P*> ParentType;
typedef const P* (C::*Getter)() const;
typedef void (C::*Setter)( P* );
ImageSerializer( const char* name, P* def, Getter gf, Setter sf )
: ParentType(name), _getter(gf), _setter(sf)
{ ParentType::_defaultValue = def; }
virtual bool read( InputStream& is, osg::Object& obj )
{
C& object = OBJECT_CAST<C&>(obj);
bool hasObject = false;
if ( is.isBinary() )
{
is >> hasObject;
if ( hasObject )
{
P* value = dynamic_cast<P*>( is.readImage() );
if ( ParentType::_defaultValue!=value )
(object.*_setter)( value );
}
}
else if ( is.matchString(ParentType::_name) )
{
is >> hasObject;
if ( hasObject )
{
is >> BEGIN_BRACKET;
P* value = dynamic_cast<P*>( is.readImage() );
if ( ParentType::_defaultValue!=value )
(object.*_setter)( value );
is >> END_BRACKET;
}
}
return true;
}
virtual bool write( OutputStream& os, const osg::Object& obj )
{
const C& object = OBJECT_CAST<const C&>(obj);
const P* value = (object.*_getter)();
bool hasObject = (value!=NULL);
if ( os.isBinary() )
{
os << hasObject;
os.writeImage( value );
}
else if ( ParentType::_defaultValue!=value )
{
os << PROPERTY((ParentType::_name).c_str()) << hasObject;
if ( hasObject )
{
os << BEGIN_BRACKET << std::endl;
os.writeImage( value );
os << END_BRACKET;
}
os << std::endl;
}
return true;
}
public:
Getter _getter;
Setter _setter;
};
template<typename C, typename P, typename B>
class EnumSerializer : public TemplateSerializer<P>
{
public:
typedef TemplateSerializer<P> ParentType;
typedef P (C::*Getter)() const;
typedef B (C::*Setter)( P );
EnumSerializer( const char* name, P def, Getter gf, Setter sf )
: ParentType(name), _getter(gf), _setter(sf)
{ ParentType::_defaultValue = def; }
void add( const char* str, P value )
{ _lookup.add(str, static_cast<IntLookup::Value>(value)); }
P getValue( const char* str )
{ return static_cast<P>(_lookup.getValue(str)); }
const std::string& getString( P value )
{ return _lookup.getString(static_cast<IntLookup::Value>(value)); }
virtual bool read( InputStream& is, osg::Object& obj )
{
C& object = OBJECT_CAST<C&>(obj);
IntLookup::Value value;
if ( is.isBinary() )
{
is >> value;
if ( ParentType::_defaultValue!=static_cast<P>(value) )
(object.*_setter)( static_cast<P>(value) );
}
else if ( is.matchString(ParentType::_name) )
{
std::string str; is >> str;
(object.*_setter)( getValue(str.c_str()) );
}
return true;
}
virtual bool write( osgDB::OutputStream& os, const osg::Object& obj )
{
const C& object = OBJECT_CAST<const C&>(obj);
const P value = (object.*_getter)();
if ( os.isBinary() )
{
os << (IntLookup::Value)value;
}
else if ( ParentType::_defaultValue!=value )
{
os << PROPERTY((ParentType::_name).c_str()) << getString(value) << std::endl;
}
return true;
}
public:
Getter _getter;
Setter _setter;
protected:
IntLookup _lookup;
};
template<typename C, typename P>
class ListSerializer : public TemplateSerializer<P>
{
public:
typedef TemplateSerializer<P> ParentType;
typedef typename P::value_type ValueType;
typedef typename P::const_iterator ConstIterator;
typedef const P& (C::*Getter)() const;
typedef void (C::*Setter)( const P& );
ListSerializer( const char* name, Getter gf, Setter sf )
: ParentType(name), _getter(gf), _setter(sf) {}
virtual bool read( InputStream& is, osg::Object& obj )
{
C& object = OBJECT_CAST<C&>(obj);
unsigned int size = 0;
P list;
if ( is.isBinary() )
{
is >> size;
for ( unsigned int i=0; i<size; ++i )
{
ValueType value;
is >> value;
list.push_back( value );
}
if ( size>0 ) (object.*_setter)( list );
}
else if ( is.matchString(ParentType::_name) )
{
is >> size;
if ( size>0 ) is >> BEGIN_BRACKET;
for ( unsigned int i=0; i<size; ++i )
{
ValueType value;
is >> value;
list.push_back( value );
}
if ( size>0 )
{
is >> END_BRACKET;
(object.*_setter)( list );
}
}
return true;
}
virtual bool write( OutputStream& os, const osg::Object& obj )
{
const C& object = OBJECT_CAST<const C&>(obj);
const P& list = (object.*_getter)();
unsigned int size = (unsigned int)list.size();
if ( os.isBinary() )
{
os << size;
for ( ConstIterator itr=list.begin();
itr!=list.end(); ++itr )
{
os << (*itr);
}
}
else if ( size>0 )
{
os << PROPERTY((ParentType::_name).c_str()) << size << BEGIN_BRACKET << std::endl;
for ( ConstIterator itr=list.begin();
itr!=list.end(); ++itr )
{
os << (*itr);
}
os << std::endl;
os << END_BRACKET << std::endl;
}
return true;
}
public:
Getter _getter;
Setter _setter;
};
// ADDING MANIPULATORS
#define ADD_SERIALIZER(S) \
wrapper->addSerializer( (S) )
#define ADD_USER_SERIALIZER(PROP) \
wrapper->addSerializer( new osgDB::UserSerializer<MyClass>( \
#PROP, &check##PROP, &read##PROP, &write##PROP) )
#define ADD_BOOL_SERIALIZER(PROP, DEF) \
wrapper->addSerializer( new osgDB::PropByValSerializer< MyClass, bool >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) )
#define ADD_SHORT_SERIALIZER(PROP, DEF) \
wrapper->addSerializer( new osgDB::PropByValSerializer< MyClass, short >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) )
#define ADD_USHORT_SERIALIZER(PROP, DEF) \
wrapper->addSerializer( new osgDB::PropByValSerializer< MyClass, unsigned short >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) )
#define ADD_HEXSHORT_SERIALIZER(PROP, DEF) \
wrapper->addSerializer( new osgDB::PropByValSerializer< MyClass, unsigned short >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP, true) )
#define ADD_INT_SERIALIZER(PROP, DEF) \
wrapper->addSerializer( new osgDB::PropByValSerializer< MyClass, int >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) )
#define ADD_UINT_SERIALIZER(PROP, DEF) \
wrapper->addSerializer( new osgDB::PropByValSerializer< MyClass, unsigned int >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) )
#define ADD_GLINT_SERIALIZER(PROP, DEF) \
wrapper->addSerializer( new osgDB::PropByValSerializer< MyClass, GLint >( \
#PROP, ((int)(DEF)), &MyClass::get##PROP, &MyClass::set##PROP) )
#define ADD_HEXINT_SERIALIZER(PROP, DEF) \
wrapper->addSerializer( new osgDB::PropByValSerializer< MyClass, unsigned int >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP, true) )
#define ADD_FLOAT_SERIALIZER(PROP, DEF) \
wrapper->addSerializer( new osgDB::PropByValSerializer< MyClass, float >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) )
#define ADD_DOUBLE_SERIALIZER(PROP, DEF) \
wrapper->addSerializer( new osgDB::PropByValSerializer< MyClass, double >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) )
#define ADD_VEC2F_SERIALIZER(PROP, DEF) \
wrapper->addSerializer( new osgDB::PropByRefSerializer< MyClass, osg::Vec2f >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) )
#define ADD_VEC2D_SERIALIZER(PROP, DEF) \
wrapper->addSerializer( new osgDB::PropByRefSerializer< MyClass, osg::Vec2d >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) )
#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) )
#define ADD_VEC3D_SERIALIZER(PROP, DEF) \
wrapper->addSerializer( new osgDB::PropByRefSerializer< MyClass, osg::Vec3d >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) )
#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) )
#define ADD_VEC4D_SERIALIZER(PROP, DEF) \
wrapper->addSerializer( new osgDB::PropByRefSerializer< MyClass, osg::Vec4d >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) )
#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) )
#define ADD_PLANE_SERIALIZER(PROP, DEF) \
wrapper->addSerializer( new osgDB::PropByRefSerializer< MyClass, osg::Plane >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) )
#define ADD_MATRIXF_SERIALIZER(PROP, DEF) \
wrapper->addSerializer( new osgDB::PropByRefSerializer< MyClass, osg::Matrixf >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) )
#define ADD_MATRIXD_SERIALIZER(PROP, DEF) \
wrapper->addSerializer( new osgDB::PropByRefSerializer< MyClass, osg::Matrixd >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) )
#define ADD_MATRIX_SERIALIZER(PROP, DEF) \
wrapper->addSerializer( new osgDB::MatrixSerializer< MyClass >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) )
#define ADD_GLENUM_SERIALIZER(PROP, TYPE, DEF) \
wrapper->addSerializer( new osgDB::GLenumSerializer< MyClass, TYPE >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) )
#define ADD_STRING_SERIALIZER(PROP, DEF) \
wrapper->addSerializer( new osgDB::StringSerializer< MyClass >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) )
#define ADD_OBJECT_SERIALIZER(PROP, TYPE, DEF) \
wrapper->addSerializer( new osgDB::ObjectSerializer< MyClass, TYPE >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) )
#define ADD_IMAGE_SERIALIZER(PROP, TYPE, DEF) \
wrapper->addSerializer( new osgDB::ImageSerializer< MyClass, TYPE >( \
#PROP, DEF, &MyClass::get##PROP, &MyClass::set##PROP) )
#define ADD_LIST_SERIALIZER(PROP, TYPE) \
wrapper->addSerializer( new osgDB::ListSerializer< MyClass, TYPE >( \
#PROP, &MyClass::get##PROP, &MyClass::set##PROP) )
#define BEGIN_ENUM_SERIALIZER(PROP, DEF) \
{ typedef osgDB::EnumSerializer<MyClass, MyClass::PROP, void> MySerializer; \
osg::ref_ptr<MySerializer> serializer = new MySerializer( \
#PROP, MyClass::DEF, &MyClass::get##PROP, &MyClass::set##PROP)
#define BEGIN_ENUM_SERIALIZER2(PROP, TYPE, DEF) \
{ typedef osgDB::EnumSerializer<MyClass, TYPE, void> MySerializer; \
osg::ref_ptr<MySerializer> serializer = new MySerializer( \
#PROP, MyClass::DEF, &MyClass::get##PROP, &MyClass::set##PROP)
#define BEGIN_ENUM_SERIALIZER3(PROP, DEF) \
{ typedef osgDB::EnumSerializer<MyClass, MyClass::PROP, bool> MySerializer; \
osg::ref_ptr<MySerializer> serializer = new MySerializer( \
#PROP, MyClass::DEF, &MyClass::get##PROP, &MyClass::set##PROP)
#define BEGIN_ENUM_SERIALIZER4(PROPERTIES_CLASS, PROP, DEF) \
{ typedef osgDB::EnumSerializer<MyClass, PROPERTIES_CLASS::PROP, void> MySerializer; \
osg::ref_ptr<MySerializer> serializer = new MySerializer( \
#PROP, PROPERTIES_CLASS::DEF, &MyClass::get##PROP, &MyClass::set##PROP)
#define ADD_ENUM_VALUE(VALUE) \
serializer->add(#VALUE, MyClass::VALUE)
#define ADD_ENUM_CLASS_VALUE(CLASS, VALUE) \
serializer->add(#VALUE, CLASS::VALUE)
#define END_ENUM_SERIALIZER() \
wrapper->addSerializer(serializer.get()); }
}
#endif