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