Wang and others, One other item I forgot to mention that also tripped me up. Be careful with the use of osgUtil::Optimizer with custom serialization classes. Certain nodes (Group, MatrixTransform, etc) can be removed, replaced and/or reordered through optimization. If you subclass any of them, they could be swapped out with a non-subclassed instance. Again one of those things that could cause you to spend (way too much) time scratching your head on why things aren't working.
Thank you Wang for this serialization support. It is just what I needed to embed my special sauce into files for use later. Chuck On Apr 15, 2010, at 5:28 PM, Wang Rui wrote: > Hi Chuck, > > Thanks for the useful information. Hope it could be added to the wiki > page, as a good supplement of my origin serializer tutorial which is > written unpolished and in a hurry. :) > > I'm still waiting for decision of the submitted osgAnimation > serializers. After that I'll continue completing other core library > wrappers and have a taste to support the introspection mechanism, > which would be a lightweight replacement of osgIntrospection. > > Cheers, > > Wang Rui > > > 2010/4/16 Chuck Seberino <[email protected]>: >> I have been playing around with the new serialization support with 2.9.7 and >> wanted to share some of my findings. I think some of these might be useful >> for others looking to do the same. >> >> 1. Serialization support *requires* that you override the virtual methods >> for className() and libraryName(). If you don't, then things won't >> serialize properly and you might spend *LOTS* of time trying to figure out >> why... >> 2. You can provide serialization for a class that doesn't live in a >> namespace. Just specify global namespace. >> >> REGISTER_OBJECT_WRAPPER(NoNamespaceClass, >> new NoNamespaceClass, >> ::NoNamespaceClass, >> "osg::Object osg::Node ::NoNamespaceClass") { ... } >> >> 3. As long as you have item 1. you can still serialize a class without >> adding in additional accessors and mutators. This is useful if you have a >> class that you can't or don't want to change to add in the necessary set/get >> methods to satisfy serialization. A wrapper class can be created to do this >> for you. >> >> // Class that we don't want to expose get/set >> >> class NoGetSetClass : public osg::Node >> { >> public: >> >> ... >> virtual const char* className() const { return "NoGetSetClass"; } // name >> to match >> virtual const char* libraryName() const { return ""; } // no >> namespace >> protected: >> std::string _internalVariable; >> }; >> >> // Helper class that is used just for serialization purposes >> class SerializerForNoGetSetClass : public NoGetSetClass >> { >> public: >> >> ... >> const std::string& getVariable() const { return _internalVariable; } >> void setVariable(const std::string& str) { _internalVariable = str; } >> }; >> >> REGISTER_OBJECT_WRAPPER(NoGetSetClass, // Old name because >> this is what we match against >> >> new SerializerForNoGetSetClass, // Use helper class >> for get/set >> >> ::NoGetSetClass, >> >> "osg::Object osg::Node ::NoGetSetClass") >> >> { >> >> // Manually recreate macro to specify our serializer subclass >> >> wrapper->addSerializer(new >> osgDB::StringSerializer<SerializerForNoGetSetClass>("Variable", "default", >> &SerializerForNoGetSetClass::getVariable, >> &SerializerForNoGetSetClass::setVariable)); >> } >> >> The macros for ADD_*_SERIALIZER can't be used because we want to use our >> subclass instead of the original class we want serialized. When the >> serialization code is invoked, it matches the class type and classname >> properly with the old class, but constructs an instance of >> SerializerForNoGetSetClass to push and pull values. >> 4. You can specify more than one REGISTER_OBJECT_WRAPPER statement in a >> single compilation unit. The macro creates a typedef (typedef CLASS >> MyClass) that is used for the subsequent serialization commands. Calling >> the macro more than once will cause it to complain about the redefinition of >> MyClass. Since the purpose of the macro is to statically register a >> wrapper, it can be guarded by a namespace and still function just fine. >> >> // This macro creates a typedef >> >> REGISTER_OBJECT_WRAPPER(Class1, >> >> new Class1, >> >> ::Class1, >> >> "osg::Object ::Class1") >> { >> >> // We only require the typedef to be valid in here >> ... >> } >> >> // The typedef is still available here >> >> namespace { // Now this macro doesn't conflict with previous macro typedef >> REGISTER_OBJECT_WRAPPER(Class2, >> >> new Class2, >> >> ::Class2, >> >> "osg::Object ::Class2") >> { >> ... >> >> // The new typedef takes precedence because of namespace scope >> } >> } // namespace >> >> >> >> Hopefully these nuggets of information will help anyone else trying to get >> their own custom classes to serialize properly without pulling out too much >> hair. For those that don't know it, this wiki link is a good starting point >> http://www.openscenegraph.org/projects/osg/wiki/Support/KnowledgeBase/SerializationSupport >> >> Regards, >> Chuck Seberino >> >> _______________________________________________ >> osg-users mailing list >> [email protected] >> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org >> >> > _______________________________________________ > osg-users mailing list > [email protected] > http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org _______________________________________________ osg-users mailing list [email protected] http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

