diff --git a/src/osgGA/StateSetManipulator.cpp b/src/osgGA/StateSetManipulator.cpp index a4be13f7b..8fcd70209 100644 --- a/src/osgGA/StateSetManipulator.cpp +++ b/src/osgGA/StateSetManipulator.cpp @@ -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 newStateSet = dynamic_cast(_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(object); + if (node) node->setStateSet(newStateSet.get()); + else + { + osg::Drawable* drawable = dynamic_cast(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 // ( _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();