Refactored the UserDataContainer so that the osg::UserDataContainer is now a pure virtual base class,

with a osg::DefaultUserDataContainer subclassed from this.  The user object access methods have now all
been moved from osg::Object into the UserDataContainer class, except for the set/getUserData() methods
that are left in osg::Object for backwards compatibility, and the description list access methods have
been moved back into osg::Node.

main UserObject access methods are now all def
This commit is contained in:
Robert Osfield 2011-06-09 12:57:14 +00:00
parent 1016092720
commit 22bc0391c7
10 changed files with 317 additions and 234 deletions

View File

@ -32,25 +32,25 @@ namespace MyNamespace
{ {
/** Provide an simple example of customizing the default UserDataContainer.*/ /** Provide an simple example of customizing the default UserDataContainer.*/
class MyUserDataContainer : public osg::UserDataContainer class MyUserDataContainer : public osg::DefaultUserDataContainer
{ {
public: public:
MyUserDataContainer() {} MyUserDataContainer() {}
MyUserDataContainer(const MyUserDataContainer& udc, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY): MyUserDataContainer(const MyUserDataContainer& udc, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
UserDataContainer(udc, copyop) {} DefaultUserDataContainer(udc, copyop) {}
META_Object(MyNamespace, MyUserDataContainer) META_Object(MyNamespace, MyUserDataContainer)
virtual Object* getUserObject(unsigned int i) virtual Object* getUserObject(unsigned int i)
{ {
OSG_NOTICE<<"MyUserDataContainer::getUserObject("<<i<<")"<<std::endl; OSG_NOTICE<<"MyUserDataContainer::getUserObject("<<i<<")"<<std::endl;
return osg::UserDataContainer::getUserObject(i); return osg::DefaultUserDataContainer::getUserObject(i);
} }
virtual const Object* getUserObject(unsigned int i) const virtual const Object* getUserObject(unsigned int i) const
{ {
OSG_NOTICE<<"MyUserDataContainer::getUserObject("<<i<<") const"<<std::endl; OSG_NOTICE<<"MyUserDataContainer::getUserObject("<<i<<") const"<<std::endl;
return osg::UserDataContainer::getUserObject(i); return osg::DefaultUserDataContainer::getUserObject(i);
} }
@ -64,7 +64,7 @@ class MyUserDataContainer : public osg::UserDataContainer
REGISTER_OBJECT_WRAPPER( MyUserDataContainer, REGISTER_OBJECT_WRAPPER( MyUserDataContainer,
new MyNamespace::MyUserDataContainer, new MyNamespace::MyUserDataContainer,
MyNamespace::MyUserDataContainer, MyNamespace::MyUserDataContainer,
"osg::Object osg::UserDataContainer MyNamespace::MyUserDataContainer" ) "osg::Object osg::UserDataContainer osg::DefaultUserDataContainer MyNamespace::MyUserDataContainer" )
{ {
} }
@ -160,17 +160,21 @@ void testResults(osg::Node* node)
OSG_NOTICE<<"Height not found"<<std::endl; OSG_NOTICE<<"Height not found"<<std::endl;
} }
OSG_NOTICE<<"node->getNumUserObjects()="<<node->getNumUserObjects()<<std::endl; osg::UserDataContainer* udc = node->getUserDataContainer();
for(unsigned int i=0; i<node->getNumUserObjects(); ++i) if (udc)
{ {
MyGetValueVisitor mgvv; OSG_NOTICE<<"udc->getNumUserObjects()="<<udc->getNumUserObjects()<<std::endl;
osg::Object* userObject = node->getUserObject(i); for(unsigned int i=0; i<udc->getNumUserObjects(); ++i)
osg::ValueObject* valueObject = dynamic_cast<osg::ValueObject*>(userObject); {
OSG_NOTICE<<"userObject="<<userObject<<", className="<<userObject->className()<<", getName()="<<userObject->getName()<<" valueObject="<<valueObject<<" getNumeric "<<getNumeric<float>(userObject)<<" "; MyGetValueVisitor mgvv;
if (valueObject) valueObject->get(mgvv); osg::Object* userObject = udc->getUserObject(i);
OSG_NOTICE<<std::endl; osg::ValueObject* valueObject = dynamic_cast<osg::ValueObject*>(userObject);
OSG_NOTICE<<"userObject="<<userObject<<", className="<<userObject->className()<<", getName()="<<userObject->getName()<<" valueObject="<<valueObject<<" getNumeric "<<getNumeric<float>(userObject)<<" ";
if (valueObject) valueObject->get(mgvv);
OSG_NOTICE<<std::endl;
}
} }
OSG_NOTICE<<std::endl<<std::endl; OSG_NOTICE<<std::endl<<std::endl;
} }
@ -196,7 +200,7 @@ int main(int argc, char** argv)
osg::ref_ptr<osg::Drawable> drawable = new osg::Geometry; osg::ref_ptr<osg::Drawable> drawable = new osg::Geometry;
drawable->setName("myDrawable"); drawable->setName("myDrawable");
node->addUserObject(drawable.get()); node->getOrCreateUserDataContainer()->addUserObject(drawable.get());
node->setUserValue("fred",12); node->setUserValue("fred",12);
node->setUserValue("john",1.1); node->setUserValue("john",1.1);

View File

@ -318,6 +318,33 @@ class OSG_EXPORT Node : public Object
/** Return the node's const StateSet. Returns NULL if a stateset is not attached.*/ /** Return the node's const StateSet. Returns NULL if a stateset is not attached.*/
inline const osg::StateSet* getStateSet() const { return _stateset.get(); } inline const osg::StateSet* getStateSet() const { return _stateset.get(); }
/** A vector of std::string's which are used to describe the object.*/
typedef std::vector<std::string> DescriptionList;
/** Set the list of string descriptions.*/
void setDescriptions(const DescriptionList& descriptions);
/** Get the description list of the node.*/
DescriptionList& getDescriptions();
/** Get the const description list of the const node.*/
const DescriptionList& getDescriptions() const;
/** Get a single const description of the const node.*/
const std::string& getDescription(unsigned int i) const;
/** Get a single description of the node.*/
std::string& getDescription(unsigned int i);
/** Get the number of descriptions of the node.*/
unsigned int getNumDescriptions() const;
/** Add a description string to the node.*/
void addDescription(const std::string& desc);
/** Set the initial bounding volume to use when computing the overall bounding volume.*/ /** Set the initial bounding volume to use when computing the overall bounding volume.*/
void setInitialBound(const osg::BoundingSphere& bsphere) { _initialBound = bsphere; dirtyBound(); } void setInitialBound(const osg::BoundingSphere& bsphere) { _initialBound = bsphere; dirtyBound(); }

View File

@ -26,6 +26,7 @@ namespace osg {
// forward declare // forward declare
class State; class State;
class UserDataContainer;
#define _ADDQUOTES(def) #def #define _ADDQUOTES(def) #def
#define ADDQUOTES(def) _ADDQUOTES(def) #define ADDQUOTES(def) _ADDQUOTES(def)
@ -54,9 +55,9 @@ class OSG_EXPORT Object : public Referenced
and therefore cannot be constructed on its own, only derived and therefore cannot be constructed on its own, only derived
classes which override the clone and className methods are classes which override the clone and className methods are
concrete classes and can be constructed.*/ concrete classes and can be constructed.*/
inline Object():Referenced(),_dataVariance(UNSPECIFIED) {} inline Object():Referenced(),_dataVariance(UNSPECIFIED), _userDataContainer(0) {}
inline explicit Object(bool threadSafeRefUnref):Referenced(threadSafeRefUnref),_dataVariance(UNSPECIFIED) {} inline explicit Object(bool threadSafeRefUnref):Referenced(threadSafeRefUnref),_dataVariance(UNSPECIFIED),_userDataContainer(0) {}
/** Copy constructor, optional CopyOp object can be used to control /** Copy constructor, optional CopyOp object can be used to control
* shallow vs deep copying of dynamic data.*/ * shallow vs deep copying of dynamic data.*/
@ -121,17 +122,17 @@ class OSG_EXPORT Object : public Referenced
/** set the UserDataContainer object.*/ /** set the UserDataContainer object.*/
void setUserDataContainer(osg::Object* udc) { _userDataContainer = udc; } void setUserDataContainer(osg::UserDataContainer* udc);
/** get the UserDataContainer attached to this object.*/ /** get the UserDataContainer attached to this object.*/
osg::Object* getUserDataContainer() { return _userDataContainer.get(); } osg::UserDataContainer* getUserDataContainer() { return _userDataContainer; }
/** get the const UserDataContainer attached to this object.*/ /** get the const UserDataContainer attached to this object.*/
const osg::Object* getUserDataContainer() const { return _userDataContainer.get(); } const osg::UserDataContainer* getUserDataContainer() const { return _userDataContainer; }
/** Convinience method that returns the UserDataContainer, and if one doesn't already exist creates and assigns /** Convinience method that returns the UserDataContainer, and if one doesn't already exist creates and assigns
* one to the Object and then return this new UserDataContainer.*/ * a DefaultUserDataContainer to the Object and then return this new UserDataContainer.*/
osg::Object* getOrCreateUserDataContainer(); osg::UserDataContainer* getOrCreateUserDataContainer();
/** /**
@ -148,37 +149,6 @@ class OSG_EXPORT Object : public Referenced
/** Get const user data.*/ /** Get const user data.*/
virtual const Referenced* getUserData() const; virtual const Referenced* getUserData() const;
/** Add user data object. Returns the index position of object added. */
virtual unsigned int addUserObject(Object* obj);
/** Add element to list of user data objects.*/
virtual void setUserObject(unsigned int i, Object* obj);
/** Remove element from the list of user data objects.*/
virtual void removeUserObject(unsigned int i);
/** Get user data object as specified index position. */
virtual Object* getUserObject(unsigned int i);
/** Get const user data object as specified index position. */
virtual const Object* getUserObject(unsigned int i) const;
/** Get number of user objects assigned to this object.*/
virtual unsigned int getNumUserObjects() const;
/** Get the index position of specified user data object.*/
virtual unsigned int getUserObjectIndex(const osg::Object* obj, unsigned int startPos=0) const;
/** Get the index position of first user data object that matches specified name.*/
virtual unsigned int getUserObjectIndex(const std::string& name, unsigned int startPos=0) const;
/** Get first user data object with specified name. */
Object* getUserObject(const std::string& name, unsigned int startPos=0);
/** Get first const user data object with specified name. */
const Object* getUserObject(const std::string& name, unsigned int startPos=0) const;
/** Convinience method that casts the named UserObject to osg::TemplateValueObject<T> and gets the value. /** Convinience method that casts the named UserObject to osg::TemplateValueObject<T> and gets the value.
@ -192,33 +162,6 @@ class OSG_EXPORT Object : public Referenced
template<typename T> template<typename T>
void setUserValue(const std::string& name, const T& value); void setUserValue(const std::string& name, const T& value);
/** A vector of std::string's which are used to describe the object.*/
typedef std::vector<std::string> DescriptionList;
/** Set the list of string descriptions.*/
virtual void setDescriptions(const DescriptionList& descriptions);
/** Get the description list of the node.*/
virtual DescriptionList& getDescriptions();
/** Get the const description list of the const node.*/
virtual const DescriptionList& getDescriptions() const;
/** Get a single const description of the const node.*/
const std::string& getDescription(unsigned int i) const;
/** Get a single description of the node.*/
std::string& getDescription(unsigned int i);
/** Get the number of descriptions of the node.*/
unsigned int getNumDescriptions() const;
/** Add a description string to the node.*/
void addDescription(const std::string& desc);
/** Resize any per context GLObject buffers to specified size. */ /** Resize any per context GLObject buffers to specified size. */
virtual void resizeGLObjectBuffers(unsigned int /*maxSize*/) {} virtual void resizeGLObjectBuffers(unsigned int /*maxSize*/) {}
@ -238,12 +181,12 @@ class OSG_EXPORT Object : public Referenced
Nodes cannot be created on stack i.e Node node will not compile, Nodes cannot be created on stack i.e Node node will not compile,
forcing all nodes to be created on the heap i.e Node* node forcing all nodes to be created on the heap i.e Node* node
= new Node().*/ = new Node().*/
virtual ~Object() {} virtual ~Object();
std::string _name; std::string _name;
DataVariance _dataVariance; DataVariance _dataVariance;
ref_ptr<osg::Object> _userDataContainer; osg::UserDataContainer* _userDataContainer;
private: private:

View File

@ -28,9 +28,95 @@ class OSG_EXPORT UserDataContainer : public osg::Object
UserDataContainer(); UserDataContainer();
UserDataContainer(const UserDataContainer& udc, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); UserDataContainer(const UserDataContainer& udc, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
META_Object(osg, UserDataContainer) virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const UserDataContainer*>(obj)!=0; }
/** return the name of the object's library. Must be defined
by derived classes. The OpenSceneGraph convention is that the
namespace of a library is the same as the library name.*/
virtual const char* libraryName() const { return "osg"; }
/** return the name of the object's class type. Must be defined
by derived classes.*/
virtual const char* className() const { return "UserDataContainer"; }
/**
* Set user data, data must be subclassed from Referenced to allow
* automatic memory handling. If your own data isn't directly
* subclassed from Referenced then create an adapter object
* which points to your own object and handles the memory addressing.
*/
virtual void setUserData(Referenced* obj) = 0;
/** Get user data.*/
virtual Referenced* getUserData() = 0;
/** Get const user data.*/
virtual const Referenced* getUserData() const = 0;
/** Add user data object. Returns the index position of object added. */
virtual unsigned int addUserObject(Object* obj) = 0;
/** Add element to list of user data objects.*/
virtual void setUserObject(unsigned int i, Object* obj) = 0;
/** Remove element from the list of user data objects.*/
virtual void removeUserObject(unsigned int i) = 0;
/** Get user data object as specified index position. */
virtual Object* getUserObject(unsigned int i) = 0;
/** Get const user data object as specified index position. */
virtual const Object* getUserObject(unsigned int i) const = 0;
/** Get number of user objects assigned to this object.*/
virtual unsigned int getNumUserObjects() const = 0;
/** Get the index position of specified user data object.*/
virtual unsigned int getUserObjectIndex(const osg::Object* obj, unsigned int startPos=0) const = 0;
/** Get the index position of first user data object that matches specified name.*/
virtual unsigned int getUserObjectIndex(const std::string& name, unsigned int startPos=0) const = 0;
/** Get first user data object with specified name. */
virtual Object* getUserObject(const std::string& name, unsigned int startPos=0);
/** Get first const user data object with specified name. */
virtual const Object* getUserObject(const std::string& name, unsigned int startPos=0) const;
typedef std::vector<std::string> DescriptionList;
/** Set the list of string descriptions.*/
virtual void setDescriptions(const DescriptionList& descriptions) = 0;
/** Get the description list.*/
virtual DescriptionList& getDescriptions() = 0;
/** Get the const description list.*/
virtual const DescriptionList& getDescriptions() const = 0;
/** Get number of description strings.*/
virtual unsigned int getNumDescriptions() const = 0;
/** Add a description string.*/
virtual void addDescription(const std::string& desc) = 0;
protected:
virtual ~UserDataContainer() {}
};
/** Internal structure for storing all user data.*/
class OSG_EXPORT DefaultUserDataContainer : public osg::UserDataContainer
{
public:
DefaultUserDataContainer();
DefaultUserDataContainer(const DefaultUserDataContainer& udc, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
META_Object(osg, DefaultUserDataContainer)
virtual void setThreadSafeRefUnref(bool threadSafe); virtual void setThreadSafeRefUnref(bool threadSafe);
/** /**
@ -73,18 +159,26 @@ class OSG_EXPORT UserDataContainer : public osg::Object
virtual unsigned int getUserObjectIndex(const std::string& name, unsigned int startPos=0) const; virtual unsigned int getUserObjectIndex(const std::string& name, unsigned int startPos=0) const;
/** Set the list of string descriptions.*/ /** Set the list of string descriptions.*/
virtual void setDescriptions(const DescriptionList& descriptions); virtual void setDescriptions(const DescriptionList& descriptions);
/** Get the description list of the node.*/ /** Get the description list.*/
virtual DescriptionList& getDescriptions(); virtual DescriptionList& getDescriptions();
/** Get the const description list of the const node.*/ /** Get the const description list.*/
virtual const DescriptionList& getDescriptions() const; virtual const DescriptionList& getDescriptions() const;
/** Get number of description strings.*/
virtual unsigned int getNumDescriptions() const;
protected: /** Add a description string.*/
virtual ~UserDataContainer() {} virtual void addDescription(const std::string& desc);
protected:
virtual ~DefaultUserDataContainer() {}
typedef std::vector< osg::ref_ptr<osg::Object> > ObjectList; typedef std::vector< osg::ref_ptr<osg::Object> > ObjectList;
@ -93,7 +187,6 @@ class OSG_EXPORT UserDataContainer : public osg::Object
ObjectList _objectList; ObjectList _objectList;
}; };
} }
#endif #endif

View File

@ -15,6 +15,7 @@
#define OSG_VALUEOBJECT 1 #define OSG_VALUEOBJECT 1
#include <osg/Object> #include <osg/Object>
#include <osg/UserDataContainer>
namespace osg { namespace osg {
@ -171,7 +172,7 @@ template<typename T>
bool osg::Object::getUserValue(const std::string& name, T& value) const bool osg::Object::getUserValue(const std::string& name, T& value) const
{ {
typedef TemplateValueObject<T> UserValueObject; typedef TemplateValueObject<T> UserValueObject;
const UserValueObject* uvo = dynamic_cast<const UserValueObject*>(getUserObject(name)); const UserValueObject* uvo = _userDataContainer ? dynamic_cast<const UserValueObject*>(_userDataContainer->getUserObject(name)) : 0;
if (uvo) if (uvo)
{ {
value = uvo->getValue(); value = uvo->getValue();
@ -189,9 +190,11 @@ void osg::Object::setUserValue(const std::string& name, const T& value)
{ {
typedef TemplateValueObject<T> UserValueObject; typedef TemplateValueObject<T> UserValueObject;
unsigned int i = getUserObjectIndex(name); getOrCreateUserDataContainer();
if (i<getNumUserObjects()) setUserObject(i, new UserValueObject(name,value));
else addUserObject(new UserValueObject(name,value)); unsigned int i = _userDataContainer->getUserObjectIndex(name);
if (i<_userDataContainer->getNumUserObjects()) _userDataContainer->setUserObject(i, new UserValueObject(name,value));
else _userDataContainer->addUserObject(new UserValueObject(name,value));
} }
} }

View File

@ -17,6 +17,7 @@
#include <osg/Notify> #include <osg/Notify>
#include <osg/OccluderNode> #include <osg/OccluderNode>
#include <osg/Transform> #include <osg/Transform>
#include <osg/UserDataContainer>
#include <algorithm> #include <algorithm>
@ -472,6 +473,51 @@ bool Node::containsOccluderNodes() const
return _numChildrenWithOccluderNodes>0 || dynamic_cast<const OccluderNode*>(this); return _numChildrenWithOccluderNodes>0 || dynamic_cast<const OccluderNode*>(this);
} }
void Node::setDescriptions(const DescriptionList& descriptions)
{
getOrCreateUserDataContainer()->setDescriptions(descriptions);
}
Node::DescriptionList& Node::getDescriptions()
{
return getOrCreateUserDataContainer()->getDescriptions();
}
static OpenThreads::Mutex s_mutex_StaticDescriptionList;
static const Node::DescriptionList& getStaticDescriptionList()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_StaticDescriptionList);
static Node::DescriptionList s_descriptionList;
return s_descriptionList;
}
const Node::DescriptionList& Node::getDescriptions() const
{
if (_userDataContainer) return _userDataContainer->getDescriptions();
else return getStaticDescriptionList();
}
std::string& Node::getDescription(unsigned int i)
{
return getOrCreateUserDataContainer()->getDescriptions()[i];
}
const std::string& Node::getDescription(unsigned int i) const
{
if (_userDataContainer) return _userDataContainer->getDescriptions()[i];
else return getStaticDescriptionList()[i];
}
unsigned int Node::getNumDescriptions() const
{
return _userDataContainer ? _userDataContainer->getDescriptions().size() : 0;
}
void Node::addDescription(const std::string& desc)
{
getOrCreateUserDataContainer()->getDescriptions().push_back(desc);
}
BoundingSphere Node::computeBound() const BoundingSphere Node::computeBound() const
{ {
return BoundingSphere(); return BoundingSphere();

View File

@ -23,143 +23,66 @@ namespace osg
Object::Object(const Object& obj,const CopyOp& copyop): Object::Object(const Object& obj,const CopyOp& copyop):
Referenced(), Referenced(),
_name(obj._name), _name(obj._name),
_dataVariance(obj._dataVariance) _dataVariance(obj._dataVariance),
_userDataContainer(0)
{ {
if (obj._userDataContainer.valid()) if (obj._userDataContainer)
{ {
if (copyop.getCopyFlags()&osg::CopyOp::DEEP_COPY_USERDATA) if (copyop.getCopyFlags()&osg::CopyOp::DEEP_COPY_USERDATA)
{ {
_userDataContainer = obj.getUserDataContainer()->clone(copyop); setUserDataContainer(osg::clone(obj._userDataContainer,copyop));
} }
else else
{ {
_userDataContainer = obj._userDataContainer; setUserDataContainer(obj._userDataContainer);
} }
} }
} }
Object::~Object()
{
if (_userDataContainer) _userDataContainer->unref();
}
void Object::setThreadSafeRefUnref(bool threadSafe) void Object::setThreadSafeRefUnref(bool threadSafe)
{ {
Referenced::setThreadSafeRefUnref(threadSafe); Referenced::setThreadSafeRefUnref(threadSafe);
if (_userDataContainer.valid()) _userDataContainer->setThreadSafeRefUnref(threadSafe); if (_userDataContainer) _userDataContainer->setThreadSafeRefUnref(threadSafe);
} }
osg::Object* Object::getOrCreateUserDataContainer() void Object::setUserDataContainer(osg::UserDataContainer* udc)
{ {
if (!_userDataContainer) _userDataContainer = new UserDataContainer(); if (_userDataContainer == udc) return;
return _userDataContainer.get();
if (_userDataContainer) _userDataContainer->unref();
_userDataContainer = udc;
if (_userDataContainer) _userDataContainer->ref();
}
osg::UserDataContainer* Object::getOrCreateUserDataContainer()
{
if (!_userDataContainer) setUserDataContainer(new DefaultUserDataContainer());
return _userDataContainer;
} }
void Object::setUserData(Referenced* obj) void Object::setUserData(Referenced* obj)
{ {
if (getUserData()==obj) return;
getOrCreateUserDataContainer()->setUserData(obj); getOrCreateUserDataContainer()->setUserData(obj);
} }
Referenced* Object::getUserData() Referenced* Object::getUserData()
{ {
return _userDataContainer.valid() ? _userDataContainer->getUserData() : 0; return _userDataContainer ? _userDataContainer->getUserData() : 0;
} }
const Referenced* Object::getUserData() const const Referenced* Object::getUserData() const
{ {
return _userDataContainer.valid() ? _userDataContainer->getUserData() : 0; return _userDataContainer ? _userDataContainer->getUserData() : 0;
}
unsigned int Object::addUserObject(Object* obj)
{
// make sure the UserDataContainer exists
return getOrCreateUserDataContainer()->addUserObject(obj);
}
void Object::removeUserObject(unsigned int i)
{
if (_userDataContainer.valid()) _userDataContainer->removeUserObject(i);
}
void Object::setUserObject(unsigned int i, Object* obj)
{
// make sure the UserDataContainer exists
getOrCreateUserDataContainer()->setUserObject(i,obj);
}
Object* Object::getUserObject(unsigned int i)
{
return _userDataContainer.valid() ? _userDataContainer->getUserObject(i) : 0;
}
const Object* Object::getUserObject(unsigned int i) const
{
return _userDataContainer.valid() ? _userDataContainer->getUserObject(i) : 0;
}
unsigned int Object::getNumUserObjects() const
{
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()->setDescriptions(descriptions);
}
Object::DescriptionList& Object::getDescriptions()
{
return getOrCreateUserDataContainer()->getDescriptions();
}
static OpenThreads::Mutex s_mutex_StaticDescriptionList;
static const Object::DescriptionList& getStaticDescriptionList()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_StaticDescriptionList);
static Object::DescriptionList s_descriptionList;
return s_descriptionList;
}
const Object::DescriptionList& Object::getDescriptions() const
{
if (_userDataContainer.valid()) return _userDataContainer->getDescriptions();
else return getStaticDescriptionList();
}
std::string& Object::getDescription(unsigned int i)
{
return getOrCreateUserDataContainer()->getDescriptions()[i];
}
const std::string& Object::getDescription(unsigned int i) const
{
if (_userDataContainer.valid()) return _userDataContainer->getDescriptions()[i];
else return getStaticDescriptionList()[i];
}
unsigned int Object::getNumDescriptions() const
{
return _userDataContainer.valid() ? _userDataContainer->getDescriptions().size() : 0;
}
void Object::addDescription(const std::string& desc)
{
getOrCreateUserDataContainer()->getDescriptions().push_back(desc);
} }
} // end of namespace osg } // end of namespace osg

View File

@ -26,12 +26,35 @@ UserDataContainer::UserDataContainer():
UserDataContainer::UserDataContainer(const UserDataContainer& udc, const osg::CopyOp& copyop): UserDataContainer::UserDataContainer(const UserDataContainer& udc, const osg::CopyOp& copyop):
Object(udc, copyop) Object(udc, copyop)
{
}
Object* UserDataContainer::getUserObject(const std::string& name, unsigned int startPos)
{
return getUserObject(getUserObjectIndex(name, startPos));
}
const Object* UserDataContainer::getUserObject(const std::string& name, unsigned int startPos) const
{
return getUserObject(getUserObjectIndex(name, startPos));
}
//////////////////////////////////////////////////////////////////////////////////////////////////
//
// DefaultUserDataContainer
//
DefaultUserDataContainer::DefaultUserDataContainer()
{
}
DefaultUserDataContainer::DefaultUserDataContainer(const DefaultUserDataContainer& udc, const osg::CopyOp& copyop):
UserDataContainer(udc, copyop)
{ {
_userData = udc._userData; _userData = udc._userData;
_descriptionList = udc._descriptionList; _descriptionList = udc._descriptionList;
} }
void UserDataContainer::setThreadSafeRefUnref(bool threadSafe) void DefaultUserDataContainer::setThreadSafeRefUnref(bool threadSafe)
{ {
Object::setThreadSafeRefUnref(threadSafe); Object::setThreadSafeRefUnref(threadSafe);
@ -45,22 +68,22 @@ void UserDataContainer::setThreadSafeRefUnref(bool threadSafe)
} }
} }
void UserDataContainer::setUserData(Referenced* obj) void DefaultUserDataContainer::setUserData(Referenced* obj)
{ {
_userData = obj; _userData = obj;
} }
Referenced* UserDataContainer::getUserData() Referenced* DefaultUserDataContainer::getUserData()
{ {
return _userData.get(); return _userData.get();
} }
const Referenced* UserDataContainer::getUserData() const const Referenced* DefaultUserDataContainer::getUserData() const
{ {
return _userData.get(); return _userData.get();
} }
unsigned int UserDataContainer::addUserObject(Object* obj) unsigned int DefaultUserDataContainer::addUserObject(Object* obj)
{ {
// make sure that the object isn't already in the container // make sure that the object isn't already in the container
unsigned int i = getUserObjectIndex(obj); unsigned int i = getUserObjectIndex(obj);
@ -78,7 +101,7 @@ unsigned int UserDataContainer::addUserObject(Object* obj)
return pos; return pos;
} }
void UserDataContainer::removeUserObject(unsigned int i) void DefaultUserDataContainer::removeUserObject(unsigned int i)
{ {
if (i<_objectList.size()) if (i<_objectList.size())
{ {
@ -86,7 +109,7 @@ void UserDataContainer::removeUserObject(unsigned int i)
} }
} }
void UserDataContainer::setUserObject(unsigned int i, Object* obj) void DefaultUserDataContainer::setUserObject(unsigned int i, Object* obj)
{ {
if (i<_objectList.size()) if (i<_objectList.size())
{ {
@ -94,7 +117,7 @@ void UserDataContainer::setUserObject(unsigned int i, Object* obj)
} }
} }
Object* UserDataContainer::getUserObject(unsigned int i) Object* DefaultUserDataContainer::getUserObject(unsigned int i)
{ {
if (i<_objectList.size()) if (i<_objectList.size())
{ {
@ -103,7 +126,7 @@ Object* UserDataContainer::getUserObject(unsigned int i)
return 0; return 0;
} }
const Object* UserDataContainer::getUserObject(unsigned int i) const const Object* DefaultUserDataContainer::getUserObject(unsigned int i) const
{ {
if (i<_objectList.size()) if (i<_objectList.size())
{ {
@ -112,12 +135,12 @@ const Object* UserDataContainer::getUserObject(unsigned int i) const
return 0; return 0;
} }
unsigned int UserDataContainer::getNumUserObjects() const unsigned int DefaultUserDataContainer::getNumUserObjects() const
{ {
return _objectList.size(); return _objectList.size();
} }
unsigned int UserDataContainer::getUserObjectIndex(const osg::Object* obj, unsigned int startPos) const unsigned int DefaultUserDataContainer::getUserObjectIndex(const osg::Object* obj, unsigned int startPos) const
{ {
for(unsigned int i = startPos; i < _objectList.size(); ++i) for(unsigned int i = startPos; i < _objectList.size(); ++i)
{ {
@ -126,7 +149,7 @@ unsigned int UserDataContainer::getUserObjectIndex(const osg::Object* obj, unsig
return _objectList.size(); return _objectList.size();
} }
unsigned int UserDataContainer::getUserObjectIndex(const std::string& name, unsigned int startPos) const unsigned int DefaultUserDataContainer::getUserObjectIndex(const std::string& name, unsigned int startPos) const
{ {
for(unsigned int i = startPos; i < _objectList.size(); ++i) for(unsigned int i = startPos; i < _objectList.size(); ++i)
{ {
@ -136,21 +159,29 @@ unsigned int UserDataContainer::getUserObjectIndex(const std::string& name, unsi
return _objectList.size(); return _objectList.size();
} }
void UserDataContainer::setDescriptions(const DescriptionList& descriptions) void DefaultUserDataContainer::setDescriptions(const DescriptionList& descriptions)
{ {
_descriptionList = descriptions; _descriptionList = descriptions;
} }
Object::DescriptionList& UserDataContainer::getDescriptions() UserDataContainer::DescriptionList& DefaultUserDataContainer::getDescriptions()
{ {
return _descriptionList; return _descriptionList;
} }
const Object::DescriptionList& UserDataContainer::getDescriptions() const const UserDataContainer::DescriptionList& DefaultUserDataContainer::getDescriptions() const
{ {
return _descriptionList; return _descriptionList;
} }
unsigned int DefaultUserDataContainer::getNumDescriptions() const
{
return _descriptionList.size();
}
void DefaultUserDataContainer::addDescription(const std::string& desc)
{
_descriptionList.push_back(desc);
}
} // end of namespace osg } // end of namespace osg

View File

@ -1,4 +1,5 @@
#include <osg/Object> #include <osg/Object>
#include <osg/UserDataContainer>
#include <osgDB/ObjectWrapper> #include <osgDB/ObjectWrapper>
#include <osgDB/InputStream> #include <osgDB/InputStream>
#include <osgDB/OutputStream> #include <osgDB/OutputStream>
@ -45,6 +46,6 @@ REGISTER_OBJECT_WRAPPER( Object,
UPDATE_TO_VERSION( 77 ) UPDATE_TO_VERSION( 77 )
{ {
REMOVE_SERIALIZER( UserData ); REMOVE_SERIALIZER( UserData );
ADD_OBJECT_SERIALIZER( UserDataContainer, osg::Object, NULL ); ADD_OBJECT_SERIALIZER( UserDataContainer, osg::UserDataContainer, NULL );
} }
} }

View File

@ -4,12 +4,12 @@
#include <osgDB/InputStream> #include <osgDB/InputStream>
#include <osgDB/OutputStream> #include <osgDB/OutputStream>
static bool checkUDC_UserData( const osg::UserDataContainer& udc ) static bool checkUDC_UserData( const osg::DefaultUserDataContainer& udc )
{ {
return dynamic_cast<const osg::Object*>(udc.getUserData())!=0; return dynamic_cast<const osg::Object*>(udc.getUserData())!=0;
} }
static bool readUDC_UserData( osgDB::InputStream& is, osg::UserDataContainer& udc ) static bool readUDC_UserData( osgDB::InputStream& is, osg::DefaultUserDataContainer& udc )
{ {
is >> osgDB::BEGIN_BRACKET; is >> osgDB::BEGIN_BRACKET;
osg::Object* object = is.readObject(); osg::Object* object = is.readObject();
@ -18,7 +18,7 @@ static bool readUDC_UserData( osgDB::InputStream& is, osg::UserDataContainer& ud
return true; return true;
} }
static bool writeUDC_UserData( osgDB::OutputStream& os, const osg::UserDataContainer& udc ) static bool writeUDC_UserData( osgDB::OutputStream& os, const osg::DefaultUserDataContainer& udc )
{ {
os << osgDB::BEGIN_BRACKET << std::endl; os << osgDB::BEGIN_BRACKET << std::endl;
os.writeObject(dynamic_cast<const osg::Object*>(udc.getUserData())); os.writeObject(dynamic_cast<const osg::Object*>(udc.getUserData()));
@ -27,12 +27,12 @@ static bool writeUDC_UserData( osgDB::OutputStream& os, const osg::UserDataConta
} }
// _descriptions // _descriptions
static bool checkUDC_Descriptions( const osg::UserDataContainer& udc ) static bool checkUDC_Descriptions( const osg::DefaultUserDataContainer& udc )
{ {
return udc.getNumDescriptions()>0; return udc.getNumDescriptions()>0;
} }
static bool readUDC_Descriptions( osgDB::InputStream& is, osg::UserDataContainer& udc ) static bool readUDC_Descriptions( osgDB::InputStream& is, osg::DefaultUserDataContainer& udc )
{ {
unsigned int size = is.readSize(); is >> osgDB::BEGIN_BRACKET; unsigned int size = is.readSize(); is >> osgDB::BEGIN_BRACKET;
for ( unsigned int i=0; i<size; ++i ) for ( unsigned int i=0; i<size; ++i )
@ -45,11 +45,11 @@ static bool readUDC_Descriptions( osgDB::InputStream& is, osg::UserDataContainer
return true; return true;
} }
static bool writeUDC_Descriptions( osgDB::OutputStream& os, const osg::UserDataContainer& udc ) static bool writeUDC_Descriptions( osgDB::OutputStream& os, const osg::DefaultUserDataContainer& udc )
{ {
const osg::Object::DescriptionList& slist = udc.getDescriptions(); const osg::UserDataContainer::DescriptionList& slist = udc.getDescriptions();
os.writeSize(slist.size()); os << osgDB::BEGIN_BRACKET << std::endl; os.writeSize(slist.size()); os << osgDB::BEGIN_BRACKET << std::endl;
for ( osg::Object::DescriptionList::const_iterator itr=slist.begin(); for ( osg::UserDataContainer::DescriptionList::const_iterator itr=slist.begin();
itr!=slist.end(); ++itr ) itr!=slist.end(); ++itr )
{ {
os.writeWrappedString( *itr ); os.writeWrappedString( *itr );
@ -60,12 +60,12 @@ static bool writeUDC_Descriptions( osgDB::OutputStream& os, const osg::UserDataC
} }
static bool checkUDC_UserObjects( const osg::UserDataContainer& udc ) static bool checkUDC_UserObjects( const osg::DefaultUserDataContainer& udc )
{ {
return udc.getNumUserObjects()>0; return udc.getNumUserObjects()>0;
} }
static bool readUDC_UserObjects( osgDB::InputStream& is, osg::UserDataContainer& udc ) static bool readUDC_UserObjects( osgDB::InputStream& is, osg::DefaultUserDataContainer& udc )
{ {
unsigned int size = is.readSize(); is >> osgDB::BEGIN_BRACKET; unsigned int size = is.readSize(); is >> osgDB::BEGIN_BRACKET;
for( unsigned int i=0; i<size; ++i ) for( unsigned int i=0; i<size; ++i )
@ -77,7 +77,7 @@ static bool readUDC_UserObjects( osgDB::InputStream& is, osg::UserDataContainer&
return true; return true;
} }
static bool writeUDC_UserObjects( osgDB::OutputStream& os, const osg::UserDataContainer& udc ) static bool writeUDC_UserObjects( osgDB::OutputStream& os, const osg::DefaultUserDataContainer& udc )
{ {
unsigned int numObjects = udc.getNumUserObjects(); unsigned int numObjects = udc.getNumUserObjects();
os.writeSize(numObjects); os << osgDB::BEGIN_BRACKET << std::endl; os.writeSize(numObjects); os << osgDB::BEGIN_BRACKET << std::endl;
@ -90,13 +90,25 @@ static bool writeUDC_UserObjects( osgDB::OutputStream& os, const osg::UserDataCo
} }
namespace UserDataContainerNamespace
REGISTER_OBJECT_WRAPPER( UserDataContainer,
new osg::UserDataContainer,
osg::UserDataContainer,
"osg::Object osg::UserDataContainer" )
{ {
ADD_USER_SERIALIZER( UDC_UserData ); // _userData REGISTER_OBJECT_WRAPPER( UserDataContainer,
ADD_USER_SERIALIZER( UDC_Descriptions ); // _descriptions 0,
ADD_USER_SERIALIZER( UDC_UserObjects ); // _userData osg::UserDataContainer,
"osg::Object osg::UserDataContainer" )
{
}
}
namespace DefaultUserDataContainerNamespace
{
REGISTER_OBJECT_WRAPPER( DefaultUserDataContainer,
new osg::DefaultUserDataContainer,
osg::DefaultUserDataContainer,
"osg::Object osg::UserDataContainer osg::DefaultUserDataContainer" )
{
ADD_USER_SERIALIZER( UDC_UserData ); // _userData
ADD_USER_SERIALIZER( UDC_Descriptions ); // _descriptions
ADD_USER_SERIALIZER( UDC_UserObjects ); // _userData
}
} }