Hi Peter,

On Thu, Jun 9, 2011 at 10:07 PM, Peter Amstutz
<peter.amst...@tseboston.com> wrote:
> I understand the circular reference problem with setting
> _userDataContainer to "this", so overriding get/setUserDataContainer()
> and ignoring _userDataContainer seems like a reasonable solution to me.
> Making _userDataContainer a private (not protected) field of osg::Object
> prevents end-runs around subclasses that overrides getUserDataContainer().


Having UserDataContainer::getUserDataContainer() return this would
still create a
circular reference as any code that chained calls to use data would
end up in an infinite loop.
The osg::Object serializers automatically write out the
UserDataContainer so is one
example of code that would end up in an infinite loop.   One could put
work arounds in
to such code but it's not particularily robust.

Logically I don't think it make sense either, as osg::Object agregates
UserDataContainer, and
UserDataContainer "is a" osg::Object so should logically do the same.

I don't think the UserDataContainer having an active
getUserDataContainer() is a problem,
but osg::Object::set/getUserValue not working how you'd expect in on a
UserDataContainer is
so I would suggest that this template functions implementation be
tweaked to return use this
pointer if it's dynamic_cast<> to UserDataContainer.

I have gone for the following implemetation:

/** provide implementation of osg::Object::getUserValue(..) template*/
template<typename T>
bool osg::Object::getUserValue(const std::string& name, T& value) const
{
    typedef TemplateValueObject<T> UserValueObject;

    const osg::UserDataContainer* udc = dynamic_cast<const
osg::UserDataContainer*>(this);
    if (!udc) udc = _userDataContainer;

    const UserValueObject* uvo = udc ? dynamic_cast<const
UserValueObject*>(udc->getUserObject(name)) : 0;
    if (uvo)
    {
        value = uvo->getValue();
        return true;
    }
    else
    {
        return false;
    }
}

/** provide implementation of osg::Object::setUserValue(..) template.*/
template<typename T>
void osg::Object::setUserValue(const std::string& name, const T& value)
{
    typedef TemplateValueObject<T> UserValueObject;

    osg::UserDataContainer* udc = dynamic_cast<osg::UserDataContainer*>(this);
    if (!udc)
    {
        getOrCreateUserDataContainer();
        udc = _userDataContainer;
    }

    unsigned int i = udc->getUserObjectIndex(name);
    if (i<udc->getNumUserObjects()) udc->setUserObject(i, new
UserValueObject(name,value));
    else udc->addUserObject(new UserValueObject(name,value));
}


Let me know if you spot a problem with this approach.

Cheers,
Robert.

Robert.
_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to