Added ability to subclass from osg::Object to provide custom user data functionality. A new UserDataContainer provides the

default implementation of the user data functionality.
This commit is contained in:
Robert Osfield
2011-06-07 13:02:20 +00:00
parent 848ec5e770
commit 7f9a6aa49d
9 changed files with 502 additions and 214 deletions

View File

@@ -172,6 +172,8 @@ SET(TARGET_H
${HEADER_PATH}/TriangleFunctor
${HEADER_PATH}/TriangleIndexFunctor
${HEADER_PATH}/Uniform
${HEADER_PATH}/UserDataContainer
${HEADER_PATH}/ValueObject
${HEADER_PATH}/Vec2
${HEADER_PATH}/Vec2b
${HEADER_PATH}/Vec2d
@@ -337,6 +339,7 @@ SET(TARGET_SRC
TransferFunction.cpp
Transform.cpp
Uniform.cpp
UserDataContainer.cpp
Version.cpp
VertexProgram.cpp
View.cpp

View File

@@ -11,6 +11,7 @@
* OpenSceneGraph Public License for more details.
*/
#include <osg/Object>
#include <osg/UserDataContainer>
namespace osg
{
@@ -28,7 +29,7 @@ Object::Object(const Object& obj,const CopyOp& copyop):
{
if (copyop.getCopyFlags()&osg::CopyOp::DEEP_COPY_USERDATA)
{
_userDataContainer = new UserDataContainer(*obj._userDataContainer, copyop);
_userDataContainer = obj.getUserDataContainer()->clone(copyop);
}
else
{
@@ -43,146 +44,87 @@ void Object::setThreadSafeRefUnref(bool threadSafe)
if (_userDataContainer.valid()) _userDataContainer->setThreadSafeRefUnref(threadSafe);
}
osg::Object* Object::getOrCreateUserDataContainer()
{
if (!_userDataContainer) _userDataContainer = new UserDataContainer();
return _userDataContainer.get();
}
void Object::setUserData(Referenced* obj)
{
getOrCreateUserDataContainer()->_userData = obj;
getOrCreateUserDataContainer()->setUserData(obj);
}
Referenced* Object::getUserData()
{
return _userDataContainer.valid() ? _userDataContainer->_userData.get() : 0;
return _userDataContainer.valid() ? _userDataContainer->getUserData() : 0;
}
const Referenced* Object::getUserData() const
{
return _userDataContainer.valid() ? _userDataContainer->_userData.get() : 0;
return _userDataContainer.valid() ? _userDataContainer->getUserData() : 0;
}
unsigned int Object::addUserObject(Object* obj)
{
// make sure the UserDataContainer exists
getOrCreateUserDataContainer();
// make sure that the object isn't already in the container
unsigned int i = getUserObjectIndex(obj);
if (i<_userDataContainer->_objectList.size())
{
// object already in container so just return.
return i;
}
unsigned int pos = _userDataContainer->_objectList.size();
// object not already on user data container so add it in.
_userDataContainer->_objectList.push_back(obj);
return pos;
return getOrCreateUserDataContainer()->addUserObject(obj);
}
void Object::removeUserObject(unsigned int i)
{
if (_userDataContainer.valid() && i<_userDataContainer->_objectList.size())
{
_userDataContainer->_objectList.erase(_userDataContainer->_objectList.begin()+i);
}
if (_userDataContainer.valid()) _userDataContainer->removeUserObject(i);
}
void Object::setUserObject(unsigned int i, Object* obj)
{
// make sure the UserDataContainer exists
getOrCreateUserDataContainer();
if (i<_userDataContainer->_objectList.size())
{
_userDataContainer->_objectList[i] = obj;
}
// make sure the UserDataContainer exists
getOrCreateUserDataContainer()->setUserObject(i,obj);
}
Object* Object::getUserObject(unsigned int i)
{
if (_userDataContainer.valid() && i<_userDataContainer->_objectList.size())
{
return _userDataContainer->_objectList[i].get();
}
return 0;
return _userDataContainer.valid() ? _userDataContainer->getUserObject(i) : 0;
}
const Object* Object::getUserObject(unsigned int i) const
{
if (_userDataContainer.valid() && i<_userDataContainer->_objectList.size())
{
return _userDataContainer->_objectList[i].get();
}
return 0;
}
unsigned int Object::getUserObjectIndex(const osg::Object* obj, unsigned int startPos) const
{
if (_userDataContainer.valid())
{
for(unsigned int i = startPos; i < _userDataContainer->_objectList.size(); ++i)
{
if (_userDataContainer->_objectList[i]==obj) return i;
}
return _userDataContainer->_objectList.size();
}
return 0;
}
unsigned int Object::getUserObjectIndex(const std::string& name, unsigned int startPos) const
{
if (_userDataContainer.valid())
{
for(unsigned int i = startPos; i < _userDataContainer->_objectList.size(); ++i)
{
Object* obj = _userDataContainer->_objectList[i].get();
if (obj && obj->getName()==name) return i;
}
return _userDataContainer->_objectList.size();
}
return 0;
}
Object* Object::getUserObject(const std::string& name, unsigned int startPos)
{
if (_userDataContainer.valid())
{
unsigned int i = getUserObjectIndex(name, startPos);
return (i<_userDataContainer->_objectList.size()) ? _userDataContainer->_objectList[i].get() : 0;
}
else
{
return 0;
}
}
const Object* Object::getUserObject(const std::string& name, unsigned int startPos) const
{
if (_userDataContainer.valid())
{
unsigned int i = getUserObjectIndex(name, startPos);
return (i<_userDataContainer->_objectList.size()) ? _userDataContainer->_objectList[i].get() : 0;
}
else
{
return 0;
}
return _userDataContainer.valid() ? _userDataContainer->getUserObject(i) : 0;
}
unsigned int Object::getNumUserObjects() const
{
return _userDataContainer.valid() ? _userDataContainer->_objectList.size() : 0;
return _userDataContainer.valid() ? _userDataContainer->getNumUserObjects() : 0;
}
unsigned int Object::getUserObjectIndex(const osg::Object* obj, unsigned int startPos) const
{
return _userDataContainer.valid() ? _userDataContainer->getUserObjectIndex(obj, startPos) : 0;
}
unsigned int Object::getUserObjectIndex(const std::string& name, unsigned int startPos) const
{
return _userDataContainer.valid() ? _userDataContainer->getUserObjectIndex(name, startPos) : 0;
}
Object* Object::getUserObject(const std::string& name, unsigned int startPos)
{
return getUserObject(getUserObjectIndex(name, startPos));
}
const Object* Object::getUserObject(const std::string& name, unsigned int startPos) const
{
return getUserObject(getUserObjectIndex(name, startPos));
}
void Object::setDescriptions(const DescriptionList& descriptions)
{
getOrCreateUserDataContainer()->_descriptionList = descriptions;
getOrCreateUserDataContainer()->setDescriptions(descriptions);
}
Object::DescriptionList& Object::getDescriptions()
{
return getOrCreateUserDataContainer()->_descriptionList;
return getOrCreateUserDataContainer()->getDescriptions();
}
static OpenThreads::Mutex s_mutex_StaticDescriptionList;
@@ -195,61 +137,29 @@ static const Object::DescriptionList& getStaticDescriptionList()
const Object::DescriptionList& Object::getDescriptions() const
{
if (_userDataContainer.valid()) return _userDataContainer->_descriptionList;
if (_userDataContainer.valid()) return _userDataContainer->getDescriptions();
else return getStaticDescriptionList();
}
std::string& Object::getDescription(unsigned int i)
{
return getOrCreateUserDataContainer()->_descriptionList[i];
return getOrCreateUserDataContainer()->getDescriptions()[i];
}
const std::string& Object::getDescription(unsigned int i) const
{
if (_userDataContainer.valid()) return _userDataContainer->_descriptionList[i];
if (_userDataContainer.valid()) return _userDataContainer->getDescriptions()[i];
else return getStaticDescriptionList()[i];
}
unsigned int Object::getNumDescriptions() const
{
return _userDataContainer.valid() ? _userDataContainer->_descriptionList.size() : 0;
return _userDataContainer.valid() ? _userDataContainer->getDescriptions().size() : 0;
}
void Object::addDescription(const std::string& desc)
{
getOrCreateUserDataContainer()->_descriptionList.push_back(desc);
getOrCreateUserDataContainer()->getDescriptions().push_back(desc);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// UserDataContainer
//
Object::UserDataContainer::UserDataContainer():
Referenced(true)
{
}
Object::UserDataContainer::UserDataContainer(const UserDataContainer& udc, const osg::CopyOp& copyop):
Referenced(true)
{
_userData = udc._userData;
_descriptionList = udc._descriptionList;
}
void Object::UserDataContainer::setThreadSafeRefUnref(bool threadSafe)
{
Referenced::setThreadSafeRefUnref(threadSafe);
if (_userData.valid()) _userData->setThreadSafeRefUnref(threadSafe);
for(ObjectList::iterator itr = _objectList.begin();
itr != _objectList.end();
++itr)
{
(*itr)->setThreadSafeRefUnref(threadSafe);
}
}
} // end of namespace osg

View File

@@ -0,0 +1,156 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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.
*/
#include <osg/UserDataContainer>
namespace osg
{
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// UserDataContainer
//
UserDataContainer::UserDataContainer():
Object(true)
{
}
UserDataContainer::UserDataContainer(const UserDataContainer& udc, const osg::CopyOp& copyop):
Object(udc, copyop)
{
_userData = udc._userData;
_descriptionList = udc._descriptionList;
}
void UserDataContainer::setThreadSafeRefUnref(bool threadSafe)
{
Object::setThreadSafeRefUnref(threadSafe);
if (_userData.valid()) _userData->setThreadSafeRefUnref(threadSafe);
for(ObjectList::iterator itr = _objectList.begin();
itr != _objectList.end();
++itr)
{
(*itr)->setThreadSafeRefUnref(threadSafe);
}
}
void UserDataContainer::setUserData(Referenced* obj)
{
_userData = obj;
}
Referenced* UserDataContainer::getUserData()
{
return _userData.get();
}
const Referenced* UserDataContainer::getUserData() const
{
return _userData.get();
}
unsigned int UserDataContainer::addUserObject(Object* obj)
{
// make sure that the object isn't already in the container
unsigned int i = getUserObjectIndex(obj);
if (i<_objectList.size())
{
// object already in container so just return.
return i;
}
unsigned int pos = _objectList.size();
// object not already on user data container so add it in.
_objectList.push_back(obj);
return pos;
}
void UserDataContainer::removeUserObject(unsigned int i)
{
if (i<_objectList.size())
{
_objectList.erase(_objectList.begin()+i);
}
}
void UserDataContainer::setUserObject(unsigned int i, Object* obj)
{
if (i<_objectList.size())
{
_objectList[i] = obj;
}
}
Object* UserDataContainer::getUserObject(unsigned int i)
{
if (i<_objectList.size())
{
return _objectList[i].get();
}
return 0;
}
const Object* UserDataContainer::getUserObject(unsigned int i) const
{
if (i<_objectList.size())
{
return _objectList[i].get();
}
return 0;
}
unsigned int UserDataContainer::getNumUserObjects() const
{
return _objectList.size();
}
unsigned int UserDataContainer::getUserObjectIndex(const osg::Object* obj, unsigned int startPos) const
{
for(unsigned int i = startPos; i < _objectList.size(); ++i)
{
if (_objectList[i]==obj) return i;
}
return _objectList.size();
}
unsigned int UserDataContainer::getUserObjectIndex(const std::string& name, unsigned int startPos) const
{
for(unsigned int i = startPos; i < _objectList.size(); ++i)
{
Object* obj = _objectList[i].get();
if (obj && obj->getName()==name) return i;
}
return _objectList.size();
}
void UserDataContainer::setDescriptions(const DescriptionList& descriptions)
{
_descriptionList = descriptions;
}
Object::DescriptionList& UserDataContainer::getDescriptions()
{
return _descriptionList;
}
const Object::DescriptionList& UserDataContainer::getDescriptions() const
{
return _descriptionList;
}
} // end of namespace osg

View File

@@ -77,6 +77,12 @@ REGISTER_OBJECT_WRAPPER( Node,
ADD_OBJECT_SERIALIZER( CullCallback, osg::NodeCallback, NULL ); // _cullCallback
ADD_BOOL_SERIALIZER( CullingActive, true ); // _cullingActive
ADD_HEXINT_SERIALIZER( NodeMask, 0xffffffff ); // _nodeMask
ADD_USER_SERIALIZER( Descriptions ); // _descriptions
ADD_USER_SERIALIZER( Descriptions ); // _descriptions, deprecated
UPDATE_TO_VERSION( 77 )
{
REMOVE_SERIALIZER( Descriptions );
}
ADD_OBJECT_SERIALIZER( StateSet, osg::StateSet, NULL ); // _stateset
}

View File

@@ -27,35 +27,6 @@ static bool writeUserData( osgDB::OutputStream& os, const osg::Object& obj )
return true;
}
static bool checkUserObjects( const osg::Object& obj )
{
return obj.getNumUserObjects()>0;
}
static bool readUserObjects( osgDB::InputStream& is, osg::Object& obj )
{
unsigned int size = is.readSize(); is >> osgDB::BEGIN_BRACKET;
for( unsigned int i=0; i<size; ++i )
{
osg::Object* read_object = is.readObject();
if (read_object) obj.addUserObject( read_object );
}
is >> osgDB::END_BRACKET;
return true;
}
static bool writeUserObjects( osgDB::OutputStream& os, const osg::Object& obj )
{
unsigned int numObjects = obj.getNumUserObjects();
os.writeSize(numObjects); os << osgDB::BEGIN_BRACKET << std::endl;
for ( unsigned int i=0; i<numObjects; ++i )
{
os << obj.getUserObject(i);
}
os << osgDB::END_BRACKET << std::endl;
return true;
}
REGISTER_OBJECT_WRAPPER( Object,
/*new osg::Object*/NULL,
osg::Object,
@@ -69,10 +40,11 @@ REGISTER_OBJECT_WRAPPER( Object,
ADD_ENUM_VALUE( UNSPECIFIED );
END_ENUM_SERIALIZER(); // _dataVariance
ADD_USER_SERIALIZER( UserData ); // _userData
ADD_USER_SERIALIZER( UserData ); // _userData, deprecated
UPDATE_TO_VERSION( 77 )
{
ADD_USER_SERIALIZER( UserObjects ); // _userData
REMOVE_SERIALIZER( UserData );
ADD_OBJECT_SERIALIZER( UserDataContainer, osg::Object, NULL );
}
}

View File

@@ -0,0 +1,102 @@
#include <osg/UserDataContainer>
#include <osgDB/ObjectWrapper>
#include <osgDB/InputStream>
#include <osgDB/OutputStream>
static bool checkUDC_UserData( const osg::UserDataContainer& udc )
{
return dynamic_cast<const osg::Object*>(udc.getUserData())!=0;
}
static bool readUDC_UserData( osgDB::InputStream& is, osg::UserDataContainer& udc )
{
is >> osgDB::BEGIN_BRACKET;
osg::Object* object = is.readObject();
if(object) udc.setUserData(object);
is >> osgDB::END_BRACKET;
return true;
}
static bool writeUDC_UserData( osgDB::OutputStream& os, const osg::UserDataContainer& udc )
{
os << osgDB::BEGIN_BRACKET << std::endl;
os.writeObject(dynamic_cast<const osg::Object*>(udc.getUserData()));
os << osgDB::END_BRACKET << std::endl;
return true;
}
// _descriptions
static bool checkUDC_Descriptions( const osg::UserDataContainer& udc )
{
return udc.getNumDescriptions()>0;
}
static bool readUDC_Descriptions( osgDB::InputStream& is, osg::UserDataContainer& udc )
{
unsigned int size = is.readSize(); is >> osgDB::BEGIN_BRACKET;
for ( unsigned int i=0; i<size; ++i )
{
std::string value;
is.readWrappedString( value );
udc.addDescription( value );
}
is >> osgDB::END_BRACKET;
return true;
}
static bool writeUDC_Descriptions( osgDB::OutputStream& os, const osg::UserDataContainer& udc )
{
const osg::Object::DescriptionList& slist = udc.getDescriptions();
os.writeSize(slist.size()); os << osgDB::BEGIN_BRACKET << std::endl;
for ( osg::Object::DescriptionList::const_iterator itr=slist.begin();
itr!=slist.end(); ++itr )
{
os.writeWrappedString( *itr );
os << std::endl;
}
os << osgDB::END_BRACKET << std::endl;
return true;
}
static bool checkUDC_UserObjects( const osg::UserDataContainer& udc )
{
return udc.getNumUserObjects()>0;
}
static bool readUDC_UserObjects( osgDB::InputStream& is, osg::UserDataContainer& udc )
{
unsigned int size = is.readSize(); is >> osgDB::BEGIN_BRACKET;
for( unsigned int i=0; i<size; ++i )
{
osg::Object* read_object = is.readObject();
if (read_object) udc.addUserObject( read_object );
}
is >> osgDB::END_BRACKET;
return true;
}
static bool writeUDC_UserObjects( osgDB::OutputStream& os, const osg::UserDataContainer& udc )
{
unsigned int numObjects = udc.getNumUserObjects();
os.writeSize(numObjects); os << osgDB::BEGIN_BRACKET << std::endl;
for ( unsigned int i=0; i<numObjects; ++i )
{
os << udc.getUserObject(i);
}
os << osgDB::END_BRACKET << std::endl;
return true;
}
REGISTER_OBJECT_WRAPPER( UserDataContainer,
new osg::UserDataContainer,
osg::UserDataContainer,
"osg::Object osg::UserDataContainer" )
{
ADD_USER_SERIALIZER( UDC_UserData ); // _userData
ADD_USER_SERIALIZER( UDC_Descriptions ); // _descriptions
ADD_USER_SERIALIZER( UDC_UserObjects ); // _userData
}