osgDB Wrapper Associates Revision Tagging
This commit is contained in:
parent
dcac0c1611
commit
2ac8379cfc
@ -50,12 +50,21 @@ struct FinishedObjectReadCallback : public osg::Referenced
|
||||
virtual void objectRead(osgDB::InputStream& is, osg::Object& obj) = 0;
|
||||
};
|
||||
|
||||
struct OSGDB_EXPORT ObjectWrapperAssociate
|
||||
{
|
||||
ObjectWrapperAssociate(std::string name):_firstVersion(0),_lastVersion(INT_MAX),_name(name){}
|
||||
int _firstVersion;
|
||||
int _lastVersion;
|
||||
std::string _name;
|
||||
};
|
||||
|
||||
class OSGDB_EXPORT ObjectWrapper : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
typedef std::vector< BaseSerializer::Type > TypeList;
|
||||
typedef std::vector< osg::ref_ptr<BaseSerializer> > SerializerList;
|
||||
typedef std::vector< osg::ref_ptr<FinishedObjectReadCallback> > FinishedObjectReadCallbackList;
|
||||
typedef std::list<ObjectWrapperAssociate> RevisionAssociateList;
|
||||
typedef osg::Object* CreateInstanceFunc();
|
||||
|
||||
ObjectWrapper( CreateInstanceFunc* createInstanceFunc, const std::string& name,
|
||||
@ -69,7 +78,8 @@ public:
|
||||
osg::Object* createInstance() const { return _createInstanceFunc(); }
|
||||
const std::string& getDomain() const { return _domain; }
|
||||
const std::string& getName() const { return _name; }
|
||||
const StringList& getAssociates() const { return _associates; }
|
||||
|
||||
const RevisionAssociateList& getAssociates() const { return _associates; }
|
||||
|
||||
SerializerList& getSerializerList() { return _serializers; }
|
||||
const SerializerList& getSerializerList() const { return _serializers; }
|
||||
@ -79,6 +89,10 @@ public:
|
||||
|
||||
void addSerializer( BaseSerializer* s, BaseSerializer::Type t=BaseSerializer::RW_UNDEFINED );
|
||||
void markSerializerAsRemoved( const std::string& name );
|
||||
|
||||
void markAssociateAsRemoved(const std::string& name);
|
||||
void markAssociateAsAdded(const std::string& name);
|
||||
|
||||
BaseSerializer* getLastSerializer() { return _serializers.empty() ? 0 : _serializers.back().get(); }
|
||||
BaseSerializer* getSerializer( const std::string& name );
|
||||
BaseSerializer* getSerializer( const std::string& name, BaseSerializer::Type& type);
|
||||
@ -99,6 +113,8 @@ public:
|
||||
MethodObjectMap& getMethodObjectMap() { return _methodObjectMap; }
|
||||
const MethodObjectMap& getMethodObjectMap() const { return _methodObjectMap; }
|
||||
|
||||
void setupAssociatesRevisionsInheritanceIfRequired();
|
||||
|
||||
protected:
|
||||
ObjectWrapper() : _version(0) {}
|
||||
virtual ~ObjectWrapper() {}
|
||||
@ -106,13 +122,16 @@ protected:
|
||||
CreateInstanceFunc* _createInstanceFunc;
|
||||
std::string _domain;
|
||||
std::string _name;
|
||||
StringList _associates;
|
||||
RevisionAssociateList _associates;
|
||||
SerializerList _serializers;
|
||||
SerializerList _backupSerializers;
|
||||
TypeList _typeList;
|
||||
FinishedObjectReadCallbackList _finishedObjectReadCallbacks;
|
||||
MethodObjectMap _methodObjectMap;
|
||||
int _version; // Last updated version of the wrapper
|
||||
//simulate associate revisions inheritance
|
||||
bool _isAssociatesRevisionsInheritanceDone;
|
||||
static void splitAssociates( const std::string& src, ObjectWrapper::RevisionAssociateList& list, char separator=' ' );
|
||||
};
|
||||
|
||||
struct UpdateWrapperVersionProxy
|
||||
|
@ -1880,6 +1880,12 @@ protected:
|
||||
#define UPDATE_TO_VERSION_SCOPED(VER) \
|
||||
osgDB::UpdateWrapperVersionProxy uwvp(wrapper, (VER));
|
||||
|
||||
#define ADDED_ASSOCIATE(STR) \
|
||||
wrapper->markAssociateAsAdded( STR );
|
||||
|
||||
#define REMOVED_ASSOCIATE(STR) \
|
||||
wrapper->markAssociateAsRemoved( STR );
|
||||
|
||||
#define REMOVE_SERIALIZER(PROP) \
|
||||
wrapper->markSerializerAsRemoved( #PROP );
|
||||
|
||||
|
@ -509,12 +509,12 @@ bool ClassInterface::getSupportedProperties(const osg::Object* object, PropertyM
|
||||
|
||||
if (searchAssociates)
|
||||
{
|
||||
const osgDB::StringList& associates = ow->getAssociates();
|
||||
for(osgDB::StringList::const_iterator aitr = associates.begin();
|
||||
const ObjectWrapper::RevisionAssociateList& associates = ow->getAssociates();
|
||||
for(ObjectWrapper::RevisionAssociateList::const_iterator aitr = associates.begin();
|
||||
aitr != associates.end();
|
||||
++aitr)
|
||||
{
|
||||
osgDB::ObjectWrapper* associate_wrapper = osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper(*aitr);
|
||||
osgDB::ObjectWrapper* associate_wrapper = osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper(aitr->_name);
|
||||
if (associate_wrapper)
|
||||
{
|
||||
const osgDB::ObjectWrapper::SerializerList& associate_serializers = associate_wrapper->getSerializerList();
|
||||
@ -560,12 +560,12 @@ bool ClassInterface::isObjectOfType(const osg::Object* object, const std::string
|
||||
return false;
|
||||
}
|
||||
|
||||
const osgDB::StringList& associates = ow->getAssociates();
|
||||
for(osgDB::StringList::const_iterator aitr = associates.begin();
|
||||
const ObjectWrapper::RevisionAssociateList& associates = ow->getAssociates();
|
||||
for(ObjectWrapper::RevisionAssociateList::const_iterator aitr = associates.begin();
|
||||
aitr != associates.end();
|
||||
++aitr)
|
||||
{
|
||||
if ((*aitr)==compoundClassName) return true;
|
||||
if ((aitr->_name)==compoundClassName) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -584,12 +584,12 @@ bool ClassInterface::run(void* objectPtr, const std::string& compoundClassName,
|
||||
if (mo->run(objectPtr, inputParameters, outputParameters)) return true;
|
||||
}
|
||||
|
||||
const osgDB::StringList& associates = ow->getAssociates();
|
||||
for(osgDB::StringList::const_iterator aitr = associates.begin();
|
||||
const ObjectWrapper::RevisionAssociateList& associates = ow->getAssociates();
|
||||
for(ObjectWrapper::RevisionAssociateList::const_iterator aitr = associates.begin();
|
||||
aitr != associates.end();
|
||||
++aitr)
|
||||
{
|
||||
osgDB::ObjectWrapper* aow = osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper(*aitr);
|
||||
osgDB::ObjectWrapper* aow = osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper(aitr->_name);
|
||||
if (aow)
|
||||
{
|
||||
const ObjectWrapper::MethodObjectMap& methodObjectMap = aow->getMethodObjectMap();
|
||||
@ -620,12 +620,12 @@ bool ClassInterface::hasMethod(const std::string& compoundClassName, const std::
|
||||
ObjectWrapper::MethodObjectMap::const_iterator oitr = ow_methodObjectMap.find(methodName);
|
||||
if (oitr!=ow_methodObjectMap.end()) return true;
|
||||
|
||||
const osgDB::StringList& associates = ow->getAssociates();
|
||||
for(osgDB::StringList::const_iterator aitr = associates.begin();
|
||||
const ObjectWrapper::RevisionAssociateList& associates = ow->getAssociates();
|
||||
for(ObjectWrapper::RevisionAssociateList::const_iterator aitr = associates.begin();
|
||||
aitr != associates.end();
|
||||
++aitr)
|
||||
{
|
||||
osgDB::ObjectWrapper* aow = osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper(*aitr);
|
||||
osgDB::ObjectWrapper* aow = osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper(aitr->_name);
|
||||
if (aow)
|
||||
{
|
||||
const ObjectWrapper::MethodObjectMap& methodObjectMap = aow->getMethodObjectMap();
|
||||
|
@ -905,26 +905,36 @@ osg::ref_ptr<osg::Object> InputStream::readObjectFields( const std::string& clas
|
||||
<< className << std::endl;
|
||||
return NULL;
|
||||
}
|
||||
int inputVersion = getFileVersion(wrapper->getDomain());
|
||||
|
||||
osg::ref_ptr<osg::Object> obj = existingObj ? existingObj : wrapper->createInstance();
|
||||
_identifierMap[id] = obj;
|
||||
if ( obj.valid() )
|
||||
{
|
||||
const StringList& associates = wrapper->getAssociates();
|
||||
for ( StringList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr )
|
||||
const ObjectWrapper::RevisionAssociateList& associates = wrapper->getAssociates();
|
||||
for ( ObjectWrapper::RevisionAssociateList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr )
|
||||
{
|
||||
ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(*itr);
|
||||
if ( !assocWrapper )
|
||||
if ( itr->_firstVersion <= inputVersion &&
|
||||
inputVersion <= itr->_lastVersion)
|
||||
{
|
||||
OSG_WARN << "InputStream::readObject(): Unsupported associated class "
|
||||
<< *itr << std::endl;
|
||||
continue;
|
||||
}
|
||||
_fields.push_back( assocWrapper->getName() );
|
||||
assocWrapper->read( *this, *obj );
|
||||
if ( getException() ) return NULL;
|
||||
ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(itr->_name);
|
||||
if ( !assocWrapper )
|
||||
{
|
||||
OSG_WARN << "InputStream::readObject(): Unsupported associated class "
|
||||
<< itr->_name << std::endl;
|
||||
continue;
|
||||
}
|
||||
_fields.push_back( assocWrapper->getName() );
|
||||
assocWrapper->read( *this, *obj );
|
||||
if ( getException() ) return NULL;
|
||||
|
||||
_fields.pop_back();
|
||||
_fields.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* OSG_INFO << "InputStream::readObject():"<<className<<" Ignoring associated class due to version mismatch"
|
||||
<< itr->_name<<"["<<itr->_firstVersion <<","<<itr->_lastVersion <<"]for version "<<inputVersion<< std::endl;*/
|
||||
}
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
|
@ -80,6 +80,24 @@ void osgDB::split( const std::string& src, StringList& list, char separator )
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectWrapper::splitAssociates( const std::string& src, ObjectWrapper::RevisionAssociateList& list, char separator )
|
||||
{
|
||||
std::string::size_type start = src.find_first_not_of(separator);
|
||||
while ( start!=std::string::npos )
|
||||
{
|
||||
std::string::size_type end = src.find_first_of(separator, start);
|
||||
if ( end!=std::string::npos )
|
||||
{
|
||||
list.push_back( ObjectWrapperAssociate(std::string(src, start, end-start)) );
|
||||
start = src.find_first_not_of(separator, end);
|
||||
}
|
||||
else
|
||||
{
|
||||
list.push_back( ObjectWrapperAssociate(std::string(src, start, src.size()-start)) );
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ObjectWrapper
|
||||
@ -87,19 +105,72 @@ void osgDB::split( const std::string& src, StringList& list, char separator )
|
||||
ObjectWrapper::ObjectWrapper( CreateInstanceFunc* createInstanceFunc, const std::string& name,
|
||||
const std::string& associates )
|
||||
: osg::Referenced(),
|
||||
_createInstanceFunc(createInstanceFunc), _name(name), _version(0)
|
||||
_createInstanceFunc(createInstanceFunc), _name(name), _version(0),_isAssociatesRevisionsInheritanceDone(false)
|
||||
{
|
||||
split( associates, _associates );
|
||||
splitAssociates( associates, _associates );
|
||||
}
|
||||
|
||||
ObjectWrapper::ObjectWrapper( CreateInstanceFunc* createInstanceFunc, const std::string& domain, const std::string& name,
|
||||
const std::string& associates )
|
||||
: osg::Referenced(),
|
||||
_createInstanceFunc(createInstanceFunc), _domain(domain), _name(name), _version(0)
|
||||
_createInstanceFunc(createInstanceFunc), _domain(domain), _name(name), _version(0),_isAssociatesRevisionsInheritanceDone(false)
|
||||
{
|
||||
split( associates, _associates );
|
||||
splitAssociates( associates, _associates );
|
||||
}
|
||||
|
||||
void ObjectWrapper::setupAssociatesRevisionsInheritanceIfRequired()
|
||||
{
|
||||
if(!_isAssociatesRevisionsInheritanceDone)
|
||||
{
|
||||
///for each associate wrapper
|
||||
for ( ObjectWrapper::RevisionAssociateList::const_iterator itr=_associates.begin(); itr!=_associates.end(); ++itr )
|
||||
{
|
||||
ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(itr->_name);
|
||||
if ( assocWrapper && assocWrapper != this )
|
||||
{
|
||||
///crawl association revisions in associates
|
||||
for ( ObjectWrapper::RevisionAssociateList::const_iterator itr2=assocWrapper->getAssociates().begin(); itr2!=assocWrapper->getAssociates().end(); ++itr2 )
|
||||
{
|
||||
for ( ObjectWrapper::RevisionAssociateList::iterator itr3=_associates.begin(); itr3!=_associates.end(); ++itr3 )
|
||||
{
|
||||
///they share associates
|
||||
if(itr3->_name==itr2->_name)
|
||||
{
|
||||
itr3->_firstVersion=itr3->_firstVersion>itr2->_firstVersion? itr3->_firstVersion:itr2->_firstVersion;
|
||||
itr3->_lastVersion=itr3->_lastVersion<itr2->_lastVersion? itr3->_lastVersion:itr2->_lastVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_isAssociatesRevisionsInheritanceDone=true;
|
||||
}
|
||||
|
||||
}
|
||||
void ObjectWrapper::markAssociateAsAdded(const std::string& name)
|
||||
{
|
||||
for ( ObjectWrapper::RevisionAssociateList:: iterator itr=_associates.begin(); itr!=_associates.end(); ++itr )
|
||||
{
|
||||
if(itr->_name==name)
|
||||
{
|
||||
itr->_firstVersion=_version;
|
||||
return;
|
||||
}
|
||||
}
|
||||
OSG_NOTIFY(osg::WARN)<<"ObjectWrapper::associateAddedAtVersion: Associate class "<<name<<" not defined for wrapper "<<_name<<std::endl;
|
||||
}
|
||||
void ObjectWrapper::markAssociateAsRemoved(const std::string& name)
|
||||
{
|
||||
for ( ObjectWrapper::RevisionAssociateList:: iterator itr=_associates.begin(); itr!=_associates.end(); ++itr )
|
||||
{
|
||||
if(itr->_name==name)
|
||||
{
|
||||
itr->_lastVersion = _version-1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
OSG_NOTIFY(osg::WARN)<<"ObjectWrapper::associateRemovedAtVersion: Associate class "<<name<<" not defined for wrapper "<<_name<<std::endl;
|
||||
}
|
||||
void ObjectWrapper::addSerializer( BaseSerializer* s, BaseSerializer::Type t )
|
||||
{
|
||||
s->_firstVersion = _version;
|
||||
@ -127,9 +198,9 @@ BaseSerializer* ObjectWrapper::getSerializer( const std::string& name )
|
||||
return itr->get();
|
||||
}
|
||||
|
||||
for ( StringList::const_iterator itr=_associates.begin(); itr!=_associates.end(); ++itr )
|
||||
for ( RevisionAssociateList::const_iterator itr=_associates.begin(); itr!=_associates.end(); ++itr )
|
||||
{
|
||||
const std::string& assocName = *itr;
|
||||
const std::string& assocName = itr->_name;
|
||||
ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName);
|
||||
if ( !assocWrapper )
|
||||
{
|
||||
@ -163,9 +234,9 @@ BaseSerializer* ObjectWrapper::getSerializer( const std::string& name, BaseSeria
|
||||
}
|
||||
}
|
||||
|
||||
for ( StringList::const_iterator itr=_associates.begin(); itr!=_associates.end(); ++itr )
|
||||
for ( RevisionAssociateList::const_iterator itr=_associates.begin(); itr!=_associates.end(); ++itr )
|
||||
{
|
||||
const std::string& assocName = *itr;
|
||||
const std::string& assocName = itr->_name;
|
||||
ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName);
|
||||
if ( !assocWrapper )
|
||||
{
|
||||
@ -681,17 +752,22 @@ ObjectWrapper* ObjectWrapperManager::findWrapper( const std::string& name )
|
||||
{
|
||||
std::string libName = std::string( name, 0, posDoubleColon );
|
||||
|
||||
ObjectWrapper* found=0;
|
||||
std::string nodeKitLib = osgDB::Registry::instance()->createLibraryNameForNodeKit(libName);
|
||||
if ( osgDB::Registry::instance()->loadLibrary(nodeKitLib)==osgDB::Registry::LOADED )
|
||||
return findWrapper(name);
|
||||
found= findWrapper(name);
|
||||
|
||||
std::string pluginLib = osgDB::Registry::instance()->createLibraryNameForExtension(std::string("serializers_")+libName);
|
||||
if ( osgDB::Registry::instance()->loadLibrary(pluginLib)==osgDB::Registry::LOADED )
|
||||
return findWrapper(name);
|
||||
found= findWrapper(name);
|
||||
|
||||
pluginLib = osgDB::Registry::instance()->createLibraryNameForExtension(libName);
|
||||
if ( osgDB::Registry::instance()->loadLibrary(pluginLib)==osgDB::Registry::LOADED )
|
||||
return findWrapper(name);
|
||||
found= findWrapper(name);
|
||||
|
||||
if (found) found->setupAssociatesRevisionsInheritanceIfRequired();
|
||||
|
||||
return found;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -645,44 +645,54 @@ void OutputStream::writeObjectFields( const osg::Object* obj, const std::string&
|
||||
<< name << std::endl;
|
||||
return;
|
||||
}
|
||||
int outputVersion = getFileVersion(wrapper->getDomain());
|
||||
|
||||
const StringList& associates = wrapper->getAssociates();
|
||||
for ( StringList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr )
|
||||
const ObjectWrapper::RevisionAssociateList& associates = wrapper->getAssociates();
|
||||
for ( ObjectWrapper::RevisionAssociateList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr )
|
||||
{
|
||||
const std::string& assocName = *itr;
|
||||
ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName);
|
||||
if ( !assocWrapper )
|
||||
if ( itr->_firstVersion <= outputVersion &&
|
||||
outputVersion <= itr->_lastVersion)
|
||||
{
|
||||
OSG_WARN << "OutputStream::writeObject(): Unsupported associated class "
|
||||
<< assocName << std::endl;
|
||||
continue;
|
||||
}
|
||||
else if ( _useSchemaData )
|
||||
{
|
||||
if ( _inbuiltSchemaMap.find(assocName)==_inbuiltSchemaMap.end() )
|
||||
const std::string& assocName = itr->_name;
|
||||
ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName);
|
||||
if ( !assocWrapper )
|
||||
{
|
||||
StringList properties;
|
||||
ObjectWrapper::TypeList types;
|
||||
assocWrapper->writeSchema( properties, types );
|
||||
|
||||
unsigned int size = osg::minimum( properties.size(), types.size() );
|
||||
if ( size>0 )
|
||||
OSG_WARN << "OutputStream::writeObject(): Unsupported associated class "
|
||||
<< assocName << std::endl;
|
||||
continue;
|
||||
}
|
||||
else if ( _useSchemaData )
|
||||
{
|
||||
if ( _inbuiltSchemaMap.find(assocName)==_inbuiltSchemaMap.end() )
|
||||
{
|
||||
std::stringstream propertiesStream;
|
||||
for ( unsigned int i=0; i<size; ++i )
|
||||
StringList properties;
|
||||
ObjectWrapper::TypeList types;
|
||||
assocWrapper->writeSchema( properties, types );
|
||||
|
||||
unsigned int size = osg::minimum( properties.size(), types.size() );
|
||||
if ( size>0 )
|
||||
{
|
||||
propertiesStream << properties[i] << ":" << types[i] << " ";
|
||||
std::stringstream propertiesStream;
|
||||
for ( unsigned int i=0; i<size; ++i )
|
||||
{
|
||||
propertiesStream << properties[i] << ":" << types[i] << " ";
|
||||
}
|
||||
_inbuiltSchemaMap[assocName] = propertiesStream.str();
|
||||
}
|
||||
_inbuiltSchemaMap[assocName] = propertiesStream.str();
|
||||
}
|
||||
}
|
||||
_fields.push_back( assocWrapper->getName() );
|
||||
|
||||
assocWrapper->write( *this, *obj );
|
||||
if ( getException() ) return;
|
||||
|
||||
_fields.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
/*OSG_INFO << "OutputStream::writeObject():"<<name<<" Ignoring associated class due to version mismatch "
|
||||
<< itr->_name<<"["<<itr->_firstVersion <<","<<itr->_lastVersion <<"]for output version "<<outputVersion<< std::endl;*/
|
||||
}
|
||||
_fields.push_back( assocWrapper->getName() );
|
||||
|
||||
assocWrapper->write( *this, *obj );
|
||||
if ( getException() ) return;
|
||||
|
||||
_fields.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user