Added cloning of the StateSet before modification to work around threading issue
relating to the StateSet being modified by the event/update thread and read from the draw thread at the same time.
This commit is contained in:
@@ -56,6 +56,35 @@ const StateSet *StateSetManipulator::getStateSet() const
|
||||
return _stateset.get();
|
||||
}
|
||||
|
||||
void StateSetManipulator::clone()
|
||||
{
|
||||
if (!_stateset) return;
|
||||
|
||||
// we clone the StateSet so that any draw traversals that might be running at the time of the
|
||||
// event traversal won't change the same StateSet that is being read. One could just set the
|
||||
// DataVariance to DYNAMIC to avoid this overlap, but this would introduce a performance penalty.
|
||||
|
||||
StateSet::ParentList parents = _stateset->getParents();
|
||||
osg::ref_ptr<osg::StateSet> newStateSet = dynamic_cast<osg::StateSet*>(_stateset->clone(osg::CopyOp::SHALLOW_COPY));
|
||||
|
||||
// change the parents of the original StateSet to point to the new stateset
|
||||
for(StateSet::ParentList::iterator itr = parents.begin();
|
||||
itr != parents.end();
|
||||
++itr)
|
||||
{
|
||||
osg::Object* object = *itr;
|
||||
osg::Node* node = dynamic_cast<osg::Node*>(object);
|
||||
if (node) node->setStateSet(newStateSet.get());
|
||||
else
|
||||
{
|
||||
osg::Drawable* drawable = dynamic_cast<osg::Drawable*>(object);
|
||||
if (drawable) drawable->setStateSet(newStateSet.get());
|
||||
}
|
||||
}
|
||||
|
||||
_stateset = newStateSet;
|
||||
}
|
||||
|
||||
bool StateSetManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& aa)
|
||||
{
|
||||
if(!_stateset.valid()) return false;
|
||||
@@ -119,6 +148,10 @@ void StateSetManipulator::getUsage(osg::ApplicationUsage& usage) const
|
||||
|
||||
void StateSetManipulator::setBackfaceEnabled(bool newbackface)
|
||||
{
|
||||
if (_backface == newbackface) return;
|
||||
|
||||
clone();
|
||||
|
||||
_backface = newbackface;
|
||||
if( _backface ) _stateset->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
|
||||
else _stateset->setMode(GL_CULL_FACE,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
|
||||
@@ -126,6 +159,10 @@ void StateSetManipulator::setBackfaceEnabled(bool newbackface)
|
||||
|
||||
void StateSetManipulator::setLightingEnabled(bool newlighting)
|
||||
{
|
||||
if (_lighting == newlighting) return;
|
||||
|
||||
clone();
|
||||
|
||||
_lighting = newlighting;
|
||||
if( _lighting ) _stateset->setMode(GL_LIGHTING,osg::StateAttribute::ON);
|
||||
else _stateset->setMode(GL_LIGHTING,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
|
||||
@@ -133,6 +170,10 @@ void StateSetManipulator::setLightingEnabled(bool newlighting)
|
||||
|
||||
void StateSetManipulator::setTextureEnabled(bool newtexture)
|
||||
{
|
||||
if (_texture==newtexture) return;
|
||||
|
||||
clone();
|
||||
|
||||
_texture = newtexture;
|
||||
// osg::ref_ptr< osg::Texture > tex = dynamic_cast<osg::Texture*>
|
||||
// ( _stateset->getAttribute( osg::StateAttribute::TEXTURE ) );
|
||||
@@ -152,6 +193,8 @@ void StateSetManipulator::setTextureEnabled(bool newtexture)
|
||||
|
||||
void StateSetManipulator::setPolygonMode(osg::PolygonMode::Mode newpolygonmode)
|
||||
{
|
||||
clone();
|
||||
|
||||
osg::PolygonMode* polyModeObj = getOrCreatePolygonMode();
|
||||
|
||||
polyModeObj->setMode(osg::PolygonMode::FRONT_AND_BACK,newpolygonmode);
|
||||
@@ -159,6 +202,8 @@ void StateSetManipulator::setPolygonMode(osg::PolygonMode::Mode newpolygonmode)
|
||||
|
||||
void StateSetManipulator::cyclePolygonMode()
|
||||
{
|
||||
clone();
|
||||
|
||||
osg::PolygonMode* polyModeObj = getOrCreatePolygonMode();
|
||||
|
||||
osg::PolygonMode::Mode currentMode = getPolygonMode();
|
||||
|
||||
Reference in New Issue
Block a user