Hi Julien,

I haven't come up with a thread safe solution  to the issue of
changing StateAttirbute Member values but what I have done is
refactored the workaround to this problem that was being applied
separately to classes like Light and ClipPlane etc.

What I have done is added a helper class into the protected scope of
StateAttribute:


        /** Helper class that make is easy to handle changes in a
member value.*/
        struct ReassignToParents
        {
            /** Constructor caches and then removes attribute for all
of it's parents.*/
            ReassignToParents(osg::StateAttribute* att);

            /** Destructor then reassigns the attribute to all of the parents.*/
            ~ReassignToParents();

            ref_ptr<StateAttribute> attribute;
            ParentList              parents;
        };


This is then used in StateAttribute subclasses that change the value
that maps the getMember() value, for example I've modified the
BufferIndexBinding to now support the setIndex() thus:

void BufferIndexBinding::setIndex(unsigned int index)
{
    if (_index==index) return;

    ReassignToParents needToReassingToParentsWhenMemberValueChanges(this);

    _index = index;
}


Here I'm using the C++ constructor/destructor to cache and then
restore the StateAttribute to the parent StateSets.  The
implementation looks like:


StateAttribute::ReassignToParents::ReassignToParents(osg::StateAttribute* attr)
{
    if (!attr->isTextureAttribute() && !attr->getParents().empty())
    {
        // take a reference to this clip plane to prevent it from
going out of scope
        // when we remove it temporarily from its parents.
        attribute = attr;

        // copy the parents as they _parents list will be changed by
the subsequent removeAttributes.
        parents = attr->getParents();

        // remove this attribute from its parents as its position is
being changed
        // and would no longer be valid.
        for(ParentList::iterator itr = parents.begin();
            itr != parents.end();
            ++itr)
        {
            osg::StateSet* stateset = *itr;
            stateset->removeAttribute(attr);

            OSG_NOTICE<<"  Removed from parent "<<stateset<<std::endl;
        }
    }
}

StateAttribute::ReassignToParents::~ReassignToParents()
{
    // add attribute back into its original parents with its new position
    for(ParentList::iterator itr = parents.begin();
        itr != parents.end();
        ++itr)
    {
        osg::StateSet* stateset = *itr;
        stateset->setAttribute(attribute.get());
        OSG_NOTICE<<"   Added back to parent "<<stateset<<std::endl;
    }
}

Robert.
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Reply via email to