diff --git a/include/osg/Object b/include/osg/Object index 4f8597c83..3ff78a374 100644 --- a/include/osg/Object +++ b/include/osg/Object @@ -141,7 +141,7 @@ class OSG_EXPORT Object : public Referenced /** Convert 'this' into a Camera pointer if Node is a Camera, otherwise return 0. * Equivalent to dynamic_cast(this).*/ virtual Camera* asCamera() { return 0; } - + /** convert 'const this' into a const Camera pointer if Node is a Camera, otherwise return 0. * Equivalent to dynamic_cast(this).*/ virtual const Camera* asCamera() const { return 0; } @@ -170,6 +170,14 @@ class OSG_EXPORT Object : public Referenced * Equivalent to dynamic_cast(this).*/ virtual const CallbackObject* asCallbackObject() const { return 0; } + /** Convert 'this' into a UserDataContainer pointer if Object is a UserDataContainer, otherwise return 0. + * Equivalent to dynamic_cast(this).*/ + virtual UserDataContainer* asUserDataContainer() { return 0; } + + /** convert 'const this' into a const UserDataContainer pointer if Object is a UserDataContainer, otherwise return 0. + * Equivalent to dynamic_cast(this).*/ + virtual const UserDataContainer* asUserDataContainer() const { return 0; } + /** Set whether to use a mutex to ensure ref() and unref() are thread safe.*/ virtual void setThreadSafeRefUnref(bool threadSafe); @@ -366,7 +374,6 @@ protected: }; - } #endif diff --git a/include/osg/UserDataContainer b/include/osg/UserDataContainer index 98b2406e4..ab63aaf20 100644 --- a/include/osg/UserDataContainer +++ b/include/osg/UserDataContainer @@ -39,6 +39,14 @@ class OSG_EXPORT UserDataContainer : public osg::Object by derived classes.*/ virtual const char* className() const { return "UserDataContainer"; } + /** Convert 'this' into a UserDataContainer pointer if Object is a UserDataContainer, otherwise return 0. + * Equivalent to dynamic_cast(this).*/ + virtual UserDataContainer* asUserDataContainer() { return this; } + + /** convert 'const this' into a const UserDataContainer pointer if Object is a UserDataContainer, otherwise return 0. + * Equivalent to dynamic_cast(this).*/ + virtual const UserDataContainer* asUserDataContainer() const { return this; } + /** * Set user data, data must be subclassed from Referenced to allow * automatic memory handling. If your own data isn't directly @@ -209,7 +217,6 @@ inline const Object* getUserObject(const osg::Object* object, const std::string& return udc ? udc->getUserObject(name) : 0; } - } #endif diff --git a/include/osg/ValueObject b/include/osg/ValueObject index 539deb55a..dfce305ab 100644 --- a/include/osg/ValueObject +++ b/include/osg/ValueObject @@ -19,6 +19,8 @@ #include #include +#include + namespace osg { // forward declare core OSG math classes @@ -126,6 +128,10 @@ class TemplateValueObject : public ValueObject ValueObject(), _value() {} + TemplateValueObject(const T& value) : + ValueObject(), + _value(value) {} + TemplateValueObject(const std::string& name, const T& value) : ValueObject(name), _value(value) {} @@ -189,12 +195,15 @@ bool osg::Object::getUserValue(const std::string& name, T& value) const { typedef TemplateValueObject UserValueObject; - const osg::UserDataContainer* udc = dynamic_cast(this); + const osg::UserDataContainer* udc = asUserDataContainer(); if (!udc) udc = _userDataContainer; - const UserValueObject* uvo = udc ? dynamic_cast(udc->getUserObject(name)) : 0; - if (uvo) + if (!udc) return false; + + const Object* obj = udc->getUserObject(name); + if (obj && typeid(*obj)==typeid(UserValueObject)) { + const UserValueObject* uvo = static_cast(obj); value = uvo->getValue(); return true; } @@ -210,7 +219,7 @@ void osg::Object::setUserValue(const std::string& name, const T& value) { typedef TemplateValueObject UserValueObject; - osg::UserDataContainer* udc = dynamic_cast(this); + osg::UserDataContainer* udc = asUserDataContainer(); if (!udc) { getOrCreateUserDataContainer(); @@ -218,11 +227,62 @@ void osg::Object::setUserValue(const std::string& name, const T& value) } unsigned int i = udc->getUserObjectIndex(name); - if (igetNumUserObjects()) udc->setUserObject(i, new UserValueObject(name,value)); - else udc->addUserObject(new UserValueObject(name,value)); + if (igetNumUserObjects()) + { + Object* obj = udc->getUserObject(i); + if (typeid(*obj)==typeid(UserValueObject)) + { + UserValueObject* uvo = static_cast(obj); + uvo->setValue(value); + } + else + { + udc->setUserObject(i, new UserValueObject(name, value)); + } + } + else + { + udc->addUserObject(new UserValueObject(name,value)); + } } +template +T* getOrCreateUserObjectOfType(P* parent) +{ + T* object=0; + const char* name = typeid(T).name(); + osg::UserDataContainer* udc = parent->getOrCreateUserDataContainer(); + unsigned int index = udc->getUserObjectIndex(name); + if (indexgetNumUserObjects()) + { + osg::Object* userObject = udc->getUserObject(index); + if (typeid(*userObject)==typeid(T)) + { + object = static_cast(userObject); + // OSG_NOTICE<<"Reusing "<className()<setName(name); + udc->setUserObject(index, object); + } + } + else + { + object = new T; + object->setName(name); + udc->addUserObject(object); + // OSG_NOTICE<<"Creating new "<