/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace osg; // local class to help porting from OSG0.8.x to 0.9.x class TextureGLModeSet { public: TextureGLModeSet() { _textureModeSet.insert(GL_TEXTURE_1D); _textureModeSet.insert(GL_TEXTURE_2D); _textureModeSet.insert(GL_TEXTURE_3D); _textureModeSet.insert(GL_TEXTURE_CUBE_MAP); _textureModeSet.insert(GL_TEXTURE_RECTANGLE_NV); _textureModeSet.insert(GL_TEXTURE_GEN_Q); _textureModeSet.insert(GL_TEXTURE_GEN_R); _textureModeSet.insert(GL_TEXTURE_GEN_S); _textureModeSet.insert(GL_TEXTURE_GEN_T); } bool isTextureMode(StateAttribute::GLMode mode) const { return _textureModeSet.find(mode)!=_textureModeSet.end(); } protected: std::set _textureModeSet; }; static TextureGLModeSet& getTextureGLModeSet() { static TextureGLModeSet s_textureGLModeSet; return s_textureGLModeSet; } StateSet::StateSet() { setDataVariance(osg::StateAttribute::STATIC); _renderingHint = DEFAULT_BIN; _numChildrenRequiringUpdateTraversal = 0; _numChildrenRequiringEventTraversal = 0; setRenderBinToInherit(); } StateSet::StateSet(const StateSet& rhs,const CopyOp& copyop):Object(rhs,copyop) { _modeList = rhs._modeList; for(AttributeList::const_iterator itr=rhs._attributeList.begin(); itr!=rhs._attributeList.end(); ++itr) { const StateAttribute::TypeMemberPair& typemember = itr->first; const RefAttributePair& rap = itr->second; StateAttribute* attr = copyop(rap.first.get()); if (attr) { _attributeList[typemember]=RefAttributePair(attr,rap.second); attr->addParent(this); } } // copy texture related modes. _textureModeList = rhs._textureModeList; // set up the size of the texture attribute list. _textureAttributeList.resize(rhs._textureAttributeList.size()); // copy the contents across. for(unsigned int i=0;ifirst; const RefAttributePair& rap = itr->second; StateAttribute* attr = copyop(rap.first.get()); if (attr) { lhs_attributeList[typemember]=RefAttributePair(attr,rap.second); attr->addParent(this); } } } // copy uniform values for(UniformList::const_iterator rhs_uitr = rhs._uniformList.begin(); rhs_uitr != rhs._uniformList.end(); ++rhs_uitr) { const std::string& name = rhs_uitr->first; const RefUniformPair& rup = rhs_uitr->second; Uniform* uni = copyop(rup.first.get()); if (uni) { _uniformList[name] = RefUniformPair(uni, rup.second); uni->addParent(this); } } _renderingHint = rhs._renderingHint; _binMode = rhs._binMode; _binNum = rhs._binNum; _binName = rhs._binName; _updateCallback = rhs._updateCallback; _numChildrenRequiringUpdateTraversal = rhs._numChildrenRequiringUpdateTraversal; _eventCallback = rhs._eventCallback; _numChildrenRequiringEventTraversal = rhs._numChildrenRequiringEventTraversal; } StateSet::~StateSet() { clear(); } void StateSet::addParent(osg::Object* object) { // osg::notify(osg::INFO)<<"Adding parent"<rhs._textureAttributeList.size()) return 1; for(unsigned int ai=0;ai<_textureAttributeList.size();++ai) { const AttributeList& rhs_attributeList = _textureAttributeList[ai]; const AttributeList& lhs_attributeList = rhs._textureAttributeList[ai]; if (compareAttributeContents) { // now check to see how the attributes compare. AttributeList::const_iterator lhs_attr_itr = lhs_attributeList.begin(); AttributeList::const_iterator rhs_attr_itr = rhs_attributeList.begin(); while (lhs_attr_itr!=lhs_attributeList.end() && rhs_attr_itr!=rhs_attributeList.end()) { if (lhs_attr_itr->firstfirst) return -1; else if (rhs_attr_itr->firstfirst) return 1; if (*(lhs_attr_itr->second.first)<*(rhs_attr_itr->second.first)) return -1; else if (*(rhs_attr_itr->second.first)<*(lhs_attr_itr->second.first)) return 1; if (lhs_attr_itr->second.secondsecond.second) return -1; else if (rhs_attr_itr->second.secondsecond.second) return 1; ++lhs_attr_itr; ++rhs_attr_itr; } if (lhs_attr_itr==lhs_attributeList.end()) { if (rhs_attr_itr!=rhs_attributeList.end()) return -1; } else if (rhs_attr_itr == rhs_attributeList.end()) return 1; } else // just compare pointers. { // now check to see how the attributes compare. AttributeList::const_iterator lhs_attr_itr = lhs_attributeList.begin(); AttributeList::const_iterator rhs_attr_itr = rhs_attributeList.begin(); while (lhs_attr_itr!=lhs_attributeList.end() && rhs_attr_itr!=rhs_attributeList.end()) { if (lhs_attr_itr->firstfirst) return -1; else if (rhs_attr_itr->firstfirst) return 1; if (lhs_attr_itr->second.firstsecond.first) return -1; else if (rhs_attr_itr->second.firstsecond.first) return 1; if (lhs_attr_itr->second.secondsecond.second) return -1; else if (rhs_attr_itr->second.secondsecond.second) return 1; ++lhs_attr_itr; ++rhs_attr_itr; } if (lhs_attr_itr==lhs_attributeList.end()) { if (rhs_attr_itr!=rhs_attributeList.end()) return -1; } else if (rhs_attr_itr == rhs_attributeList.end()) return 1; } } // now check the rest of the non texture attributes if (compareAttributeContents) { // now check to see how the attributes compare. AttributeList::const_iterator lhs_attr_itr = _attributeList.begin(); AttributeList::const_iterator rhs_attr_itr = rhs._attributeList.begin(); while (lhs_attr_itr!=_attributeList.end() && rhs_attr_itr!=rhs._attributeList.end()) { if (lhs_attr_itr->firstfirst) return -1; else if (rhs_attr_itr->firstfirst) return 1; if (*(lhs_attr_itr->second.first)<*(rhs_attr_itr->second.first)) return -1; else if (*(rhs_attr_itr->second.first)<*(lhs_attr_itr->second.first)) return 1; if (lhs_attr_itr->second.secondsecond.second) return -1; else if (rhs_attr_itr->second.secondsecond.second) return 1; ++lhs_attr_itr; ++rhs_attr_itr; } if (lhs_attr_itr==_attributeList.end()) { if (rhs_attr_itr!=rhs._attributeList.end()) return -1; } else if (rhs_attr_itr == rhs._attributeList.end()) return 1; } else // just compare pointers. { // now check to see how the attributes compare. AttributeList::const_iterator lhs_attr_itr = _attributeList.begin(); AttributeList::const_iterator rhs_attr_itr = rhs._attributeList.begin(); while (lhs_attr_itr!=_attributeList.end() && rhs_attr_itr!=rhs._attributeList.end()) { if (lhs_attr_itr->firstfirst) return -1; else if (rhs_attr_itr->firstfirst) return 1; if (lhs_attr_itr->second.firstsecond.first) return -1; else if (rhs_attr_itr->second.firstsecond.first) return 1; if (lhs_attr_itr->second.secondsecond.second) return -1; else if (rhs_attr_itr->second.secondsecond.second) return 1; ++lhs_attr_itr; ++rhs_attr_itr; } if (lhs_attr_itr==_attributeList.end()) { if (rhs_attr_itr!=rhs._attributeList.end()) return -1; } else if (rhs_attr_itr == rhs._attributeList.end()) return 1; } // we've got here so attributes must be equal... if (_textureModeList.size()rhs._textureModeList.size()) return 1; // check to see how the modes compare. // first check the rest of the texture modes for(unsigned int ti=0;ti<_textureModeList.size();++ti) { const ModeList& lhs_modeList = _textureModeList[ti]; const ModeList& rhs_modeList = rhs._textureModeList[ti]; ModeList::const_iterator lhs_mode_itr = lhs_modeList.begin(); ModeList::const_iterator rhs_mode_itr = rhs_modeList.begin(); while (lhs_mode_itr!=lhs_modeList.end() && rhs_mode_itr!=rhs_modeList.end()) { if (lhs_mode_itr->firstfirst) return -1; else if (rhs_mode_itr->firstfirst) return 1; if (lhs_mode_itr->secondsecond) return -1; else if (rhs_mode_itr->secondsecond) return 1; ++lhs_mode_itr; ++rhs_mode_itr; } if (lhs_mode_itr==lhs_modeList.end()) { if (rhs_mode_itr!=rhs_modeList.end()) return -1; } else if (rhs_mode_itr == rhs_modeList.end()) return 1; } // check non texture modes. ModeList::const_iterator lhs_mode_itr = _modeList.begin(); ModeList::const_iterator rhs_mode_itr = rhs._modeList.begin(); while (lhs_mode_itr!=_modeList.end() && rhs_mode_itr!=rhs._modeList.end()) { if (lhs_mode_itr->firstfirst) return -1; else if (rhs_mode_itr->firstfirst) return 1; if (lhs_mode_itr->secondsecond) return -1; else if (rhs_mode_itr->secondsecond) return 1; ++lhs_mode_itr; ++rhs_mode_itr; } if (lhs_mode_itr==_modeList.end()) { if (rhs_mode_itr!=rhs._modeList.end()) return -1; } else if (rhs_mode_itr == rhs._modeList.end()) return 1; // check uniforms. UniformList::const_iterator lhs_uniform_itr = _uniformList.begin(); UniformList::const_iterator rhs_uniform_itr = rhs._uniformList.begin(); while (lhs_uniform_itr!=_uniformList.end() && rhs_uniform_itr!=rhs._uniformList.end()) { if (lhs_uniform_itr->firstfirst) return -1; else if (rhs_uniform_itr->firstfirst) return 1; if (lhs_uniform_itr->secondsecond) return -1; else if (rhs_uniform_itr->secondsecond) return 1; ++lhs_uniform_itr; ++rhs_uniform_itr; } if (lhs_uniform_itr==_uniformList.end()) { if (rhs_uniform_itr!=rhs._uniformList.end()) return -1; } else if (rhs_uniform_itr == rhs._uniformList.end()) return 1; return 0; } int StateSet::compareModes(const ModeList& lhs,const ModeList& rhs) { ModeList::const_iterator lhs_mode_itr = lhs.begin(); ModeList::const_iterator rhs_mode_itr = rhs.begin(); while (lhs_mode_itr!=lhs.end() && rhs_mode_itr!=rhs.end()) { if (lhs_mode_itr->firstfirst) return -1; else if (rhs_mode_itr->firstfirst) return 1; if (lhs_mode_itr->secondsecond) return -1; else if (rhs_mode_itr->secondsecond) return 1; ++lhs_mode_itr; ++rhs_mode_itr; } if (lhs_mode_itr==lhs.end()) { if (rhs_mode_itr!=rhs.end()) return -1; } else if (rhs_mode_itr == rhs.end()) return 1; return 0; } int StateSet::compareAttributePtrs(const AttributeList& lhs,const AttributeList& rhs) { AttributeList::const_iterator lhs_attr_itr = lhs.begin(); AttributeList::const_iterator rhs_attr_itr = rhs.begin(); while (lhs_attr_itr!=lhs.end() && rhs_attr_itr!=rhs.end()) { if (lhs_attr_itr->firstfirst) return -1; else if (rhs_attr_itr->firstfirst) return 1; if (lhs_attr_itr->second.firstsecond.first) return -1; else if (rhs_attr_itr->second.firstsecond.first) return 1; if (lhs_attr_itr->second.secondsecond.second) return -1; else if (rhs_attr_itr->second.secondsecond.second) return 1; ++lhs_attr_itr; ++rhs_attr_itr; } if (lhs_attr_itr==lhs.end()) { if (rhs_attr_itr!=rhs.end()) return -1; } else if (rhs_attr_itr == rhs.end()) return 1; return 0; } int StateSet::compareAttributeContents(const AttributeList& lhs,const AttributeList& rhs) { AttributeList::const_iterator lhs_attr_itr = lhs.begin(); AttributeList::const_iterator rhs_attr_itr = rhs.begin(); while (lhs_attr_itr!=lhs.end() && rhs_attr_itr!=rhs.end()) { if (lhs_attr_itr->firstfirst) return -1; else if (rhs_attr_itr->firstfirst) return 1; if (*(lhs_attr_itr->second.first)<*(rhs_attr_itr->second.first)) return -1; else if (*(rhs_attr_itr->second.first)<*(lhs_attr_itr->second.first)) return 1; if (lhs_attr_itr->second.secondsecond.second) return -1; else if (rhs_attr_itr->second.secondsecond.second) return 1; ++lhs_attr_itr; ++rhs_attr_itr; } if (lhs_attr_itr==lhs.end()) { if (rhs_attr_itr!=rhs.end()) return -1; } else if (rhs_attr_itr == rhs.end()) return 1; return 0; } void StateSet::setGlobalDefaults() { _renderingHint = DEFAULT_BIN; setRenderBinToInherit(); setMode(GL_DEPTH_TEST,StateAttribute::ON); // setAttributeAndModes(new AlphaFunc,StateAttribute::OFF); setAttributeAndModes(new BlendFunc,StateAttribute::OFF); Material *material = new Material; material->setColorMode(Material::AMBIENT_AND_DIFFUSE); setAttributeAndModes(material,StateAttribute::ON); } void StateSet::clear() { _renderingHint = DEFAULT_BIN; setRenderBinToInherit(); // remove self from as attributes parent for(AttributeList::iterator itr=_attributeList.begin(); itr!=_attributeList.end(); ++itr) { itr->second.first->removeParent(this); } _modeList.clear(); _attributeList.clear(); // remove self from as texture attributes parent for(unsigned int i=0;i<_textureAttributeList.size();++i) { AttributeList& attributeList = _textureAttributeList[i]; for(AttributeList::iterator itr=attributeList.begin(); itr!=attributeList.end(); ++itr) { itr->second.first->removeParent(this); } } _textureModeList.clear(); _textureAttributeList.clear(); // remove self from uniforms parent for(UniformList::iterator uitr = _uniformList.begin(); uitr != _uniformList.end(); ++uitr) { uitr->second.first->removeParent(this); } _uniformList.clear(); } void StateSet::merge(const StateSet& rhs) { // merge the modes of rhs into this, // this overrides rhs if OVERRIDE defined in this. for(ModeList::const_iterator rhs_mitr = rhs._modeList.begin(); rhs_mitr != rhs._modeList.end(); ++rhs_mitr) { ModeList::iterator lhs_mitr = _modeList.find(rhs_mitr->first); if (lhs_mitr!=_modeList.end()) { if (!(lhs_mitr->second & StateAttribute::OVERRIDE)) { // override isn't on in rhs, so overrite it with incomming // value. lhs_mitr->second = rhs_mitr->second; } } else { // entry doesn't exist so insert it. _modeList.insert(*rhs_mitr); } } // merge the attributes of rhs into this, // this overrides rhs if OVERRIDE defined in this. for(AttributeList::const_iterator rhs_aitr = rhs._attributeList.begin(); rhs_aitr != rhs._attributeList.end(); ++rhs_aitr) { AttributeList::iterator lhs_aitr = _attributeList.find(rhs_aitr->first); if (lhs_aitr!=_attributeList.end()) { if (!(lhs_aitr->second.second & StateAttribute::OVERRIDE)) { // override isn't on in rhs, so overrite it with incomming // value. if (lhs_aitr->second.first!=rhs_aitr->second.first) { // new attribute so need to remove self from outgoing attribute lhs_aitr->second.first->removeParent(this); // override isn't on in rhs, so overrite it with incomming // value. lhs_aitr->second = rhs_aitr->second; lhs_aitr->second.first->addParent(this); } else { // same attribute but with override to set. lhs_aitr->second = rhs_aitr->second; } } } else { // entry doesn't exist so insert it, and then tell it about self by adding self as parent. _attributeList.insert(*rhs_aitr).first->second.first->addParent(this); } } if (_textureModeList.size()first); if (lhs_mitr!=lhs_modeList.end()) { if (!(lhs_mitr->second & StateAttribute::OVERRIDE)) { // override isn't on in rhs, so overrite it with incomming // value. lhs_mitr->second = rhs_mitr->second; } } else { // entry doesn't exist so insert it. lhs_modeList.insert(*rhs_mitr); } } } if (_textureAttributeList.size()first); if (lhs_aitr!=lhs_attributeList.end()) { if (!(lhs_aitr->second.second & StateAttribute::OVERRIDE)) { // override isn't on in rhs, so overrite it with incomming // value. if (lhs_aitr->second.first!=rhs_aitr->second.first) { lhs_aitr->second.first->removeParent(this); lhs_aitr->second = rhs_aitr->second; lhs_aitr->second.first->addParent(this); } else { lhs_aitr->second = rhs_aitr->second; } } } else { // entry doesn't exist so insert it and add self as parent lhs_attributeList.insert(*rhs_aitr).first->second.first->addParent(this); } } } // merge the uniforms of rhs into this, // this overrides rhs if OVERRIDE defined in this. for(UniformList::const_iterator rhs_uitr = rhs._uniformList.begin(); rhs_uitr != rhs._uniformList.end(); ++rhs_uitr) { UniformList::iterator lhs_uitr = _uniformList.find(rhs_uitr->first); if (lhs_uitr!=_uniformList.end()) { if (!(lhs_uitr->second.second & StateAttribute::OVERRIDE)) { // override isn't on in rhs, so overrite it with incomming // value. if (lhs_uitr->second.first!=rhs_uitr->second.first) { lhs_uitr->second.first->removeParent(this); lhs_uitr->second = rhs_uitr->second; lhs_uitr->second.first->addParent(this); } else { lhs_uitr->second = rhs_uitr->second; } } } else { // entry doesn't exist so insert it and add self as parent _uniformList.insert(*rhs_uitr).first->second.first->addParent(this); } } // need to merge rendering hints // but will need to think how best to do this first // RO, Nov. 2001. } void StateSet::setMode(StateAttribute::GLMode mode, StateAttribute::GLModeValue value) { if (!getTextureGLModeSet().isTextureMode(mode)) { setMode(_modeList,mode,value); } else { notify(NOTICE)<<"Warning: texture mode '"<isTextureAttribute()) { setAttribute(_attributeList,attribute,value); } else { notify(NOTICE)<<"Warning: texture attribute '"<className()<<"'passed to setAttribute(attr,value), "<isTextureAttribute()) { if (value&StateAttribute::INHERIT) { removeAttribute(attribute->getType()); } else { setAttribute(_attributeList,attribute,value); setAssociatedModes(attribute,value); } } else { notify(NOTICE)<<"Warning: texture attribute '"<className()<<"' passed to setAttributeAndModes(attr,value), "<second.first->getUpdateCallback()) { setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()-1); } if (itr->second.first->getEventCallback()) { setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()-1); } itr->second.first->removeParent(this); setAssociatedModes(itr->second.first.get(),StateAttribute::INHERIT); _attributeList.erase(itr); } } void StateSet::removeAttribute(StateAttribute* attribute) { if (!attribute) return; AttributeList::iterator itr = _attributeList.find(attribute->getTypeMemberPair()); if (itr!=_attributeList.end()) { if (itr->second.first != attribute) return; if (itr->second.first->getUpdateCallback()) { setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()-1); } if (itr->second.first->getEventCallback()) { setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()-1); } itr->second.first->removeParent(this); setAssociatedModes(itr->second.first.get(),StateAttribute::INHERIT); _attributeList.erase(itr); } } StateAttribute* StateSet::getAttribute(StateAttribute::Type type, unsigned int member) { return getAttribute(_attributeList,type,member); } const StateAttribute* StateSet::getAttribute(StateAttribute::Type type, unsigned int member) const { return getAttribute(_attributeList,type,member); } const StateSet::RefAttributePair* StateSet::getAttributePair(StateAttribute::Type type, unsigned int member) const { return getAttributePair(_attributeList,type,member); } void StateSet::addUniform(Uniform* uniform, StateAttribute::OverrideValue value) { if (uniform) { int delta_update = 0; int delta_event = 0; UniformList::iterator itr=_uniformList.find(uniform->getName()); if (itr==_uniformList.end()) { // new entry. RefUniformPair& up = _uniformList[uniform->getName()]; up.first = uniform; up.second = value&(StateAttribute::OVERRIDE|StateAttribute::PROTECTED); uniform->addParent(this); if (uniform->getUpdateCallback()) { delta_update = 1; } if (uniform->getEventCallback()) { delta_event = 1; } } else { if (itr->second.first==uniform) { // chaning just override itr->second.second = value&(StateAttribute::OVERRIDE|StateAttribute::PROTECTED); } else { itr->second.first->removeParent(this); if (itr->second.first->getUpdateCallback()) --delta_update; if (itr->second.first->getEventCallback()) --delta_event; uniform->addParent(this); itr->second.first = uniform; if (itr->second.first->getUpdateCallback()) ++delta_update; if (itr->second.first->getEventCallback()) ++delta_event; itr->second.second = value&(StateAttribute::OVERRIDE|StateAttribute::PROTECTED); } } if (delta_update!=0) { setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+delta_update); } if (delta_event!=0) { setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()+delta_event); } } } void StateSet::removeUniform(const std::string& name) { UniformList::iterator itr = _uniformList.find(name); if (itr!=_uniformList.end()) { if (itr->second.first->getUpdateCallback()) { setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()-1); } if (itr->second.first->getEventCallback()) { setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()-1); } itr->second.first->removeParent(this); _uniformList.erase(itr); } } void StateSet::removeUniform(Uniform* uniform) { if (!uniform) return; UniformList::iterator itr = _uniformList.find(uniform->getName()); if (itr!=_uniformList.end()) { if (itr->second.first != uniform) return; if (itr->second.first->getUpdateCallback()) { setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()-1); } if (itr->second.first->getEventCallback()) { setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()-1); } itr->second.first->removeParent(this); _uniformList.erase(itr); } } Uniform* StateSet::getUniform(const std::string& name) { UniformList::iterator itr = _uniformList.find(name); if (itr!=_uniformList.end()) return itr->second.first.get(); else return 0; } Uniform* StateSet::getOrCreateUniform(const std::string& name, Uniform::Type type, unsigned int numElements) { // for look for an appropriate uniform. UniformList::iterator itr = _uniformList.find(name); if (itr!=_uniformList.end() && itr->second.first->getType()==type) { return itr->second.first.get(); } // no uniform found matching name so create it.. Uniform* uniform = new Uniform(type,name,numElements); addUniform(uniform); return uniform; } const Uniform* StateSet::getUniform(const std::string& name) const { UniformList::const_iterator itr = _uniformList.find(name); if (itr!=_uniformList.end()) return itr->second.first.get(); else return 0; } const StateSet::RefUniformPair* StateSet::getUniformPair(const std::string& name) const { UniformList::const_iterator itr = _uniformList.find(name); if (itr!=_uniformList.end()) return &(itr->second); else return 0; } void StateSet::setTextureMode(unsigned int unit,StateAttribute::GLMode mode, StateAttribute::GLModeValue value) { if (getTextureGLModeSet().isTextureMode(mode)) { setMode(getOrCreateTextureModeList(unit),mode,value); } else { notify(NOTICE)<<"Warning: non-texture mode '"<=_textureModeList.size()) return; setModeToInherit(_textureModeList[unit],mode); } else { notify(NOTICE)<<"Warning: non-texture mode '"<=_textureModeList.size()) return StateAttribute::INHERIT; return getMode(_textureModeList[unit],mode); } else { notify(NOTICE)<<"Warning: non-texture mode '"<isTextureAttribute()) { setAttribute(getOrCreateTextureAttributeList(unit),attribute,value); } else { notify(NOTICE)<<"Warning: texture attribute '"<className()<<"' passed to setTextureAttribute(unit,attr,value), "<isTextureAttribute()) { if (value&StateAttribute::INHERIT) { removeTextureAttribute(unit,attribute->getType()); } else { setAttribute(getOrCreateTextureAttributeList(unit),attribute,value); setAssociatedTextureModes(unit,attribute,value); } } else { notify(NOTICE)<<"Warning: non texture attribute '"<className()<<"' passed to setTextureAttributeAndModes(unit,attr,value), "<=_textureAttributeList.size()) return; AttributeList& attributeList = _textureAttributeList[unit]; AttributeList::iterator itr = attributeList.find(StateAttribute::TypeMemberPair(type,0)); if (itr!=attributeList.end()) { if (unit<_textureModeList.size()) { setAssociatedTextureModes(unit,itr->second.first.get(),StateAttribute::INHERIT); } if (itr->second.first->getUpdateCallback()) { setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()-1); } if (itr->second.first->getEventCallback()) { setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()-1); } itr->second.first->removeParent(this); attributeList.erase(itr); } } void StateSet::removeTextureAttribute(unsigned int unit, StateAttribute* attribute) { if (!attribute) return; if (unit>=_textureAttributeList.size()) return; AttributeList& attributeList = _textureAttributeList[unit]; AttributeList::iterator itr = attributeList.find(attribute->getTypeMemberPair()); if (itr!=attributeList.end()) { if (itr->second.first != attribute) return; setAssociatedTextureModes(unit,itr->second.first.get(),StateAttribute::INHERIT); if (itr->second.first->getUpdateCallback()) { setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()-1); } if (itr->second.first->getEventCallback()) { setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()-1); } itr->second.first->removeParent(this); attributeList.erase(itr); } } StateAttribute* StateSet::getTextureAttribute(unsigned int unit,StateAttribute::Type type) { if (unit>=_textureAttributeList.size()) return 0; return getAttribute(_textureAttributeList[unit],type,0); } const StateAttribute* StateSet::getTextureAttribute(unsigned int unit,StateAttribute::Type type) const { if (unit>=_textureAttributeList.size()) return 0; return getAttribute(_textureAttributeList[unit],type,0); } const StateSet::RefAttributePair* StateSet::getTextureAttributePair(unsigned int unit,StateAttribute::Type type) const { if (unit>=_textureAttributeList.size()) return 0; return getAttributePair(_textureAttributeList[unit],type,0); } bool StateSet::checkValidityOfAssociatedModes(osg::State& state) const { bool modesValid = true; for(AttributeList::const_iterator itr = _attributeList.begin(); itr!=_attributeList.end(); ++itr) { if (!itr->second.first->checkValidityOfAssociatedModes(state)) modesValid = false; } for(TextureAttributeList::const_iterator taitr=_textureAttributeList.begin(); taitr!=_textureAttributeList.end(); ++taitr) { for(AttributeList::const_iterator itr = taitr->begin(); itr!=taitr->end(); ++itr) { if (!itr->second.first->checkValidityOfAssociatedModes(state)) modesValid = false; } } return modesValid; } void StateSet::compileGLObjects(State& state) const { for(AttributeList::const_iterator itr = _attributeList.begin(); itr!=_attributeList.end(); ++itr) { itr->second.first->compileGLObjects(state); } for(TextureAttributeList::const_iterator taitr=_textureAttributeList.begin(); taitr!=_textureAttributeList.end(); ++taitr) { for(AttributeList::const_iterator itr = taitr->begin(); itr!=taitr->end(); ++itr) { itr->second.first->compileGLObjects(state); } } } void StateSet::releaseGLObjects(State* state) const { for(AttributeList::const_iterator itr = _attributeList.begin(); itr!=_attributeList.end(); ++itr) { itr->second.first->releaseGLObjects(state); } for(TextureAttributeList::const_iterator taitr=_textureAttributeList.begin(); taitr!=_textureAttributeList.end(); ++taitr) { for(AttributeList::const_iterator itr = taitr->begin(); itr!=taitr->end(); ++itr) { itr->second.first->releaseGLObjects(state); } } } void StateSet::setRenderingHint(int hint) { _renderingHint = hint; // temporary hack to get new render bins working. switch(_renderingHint) { case(TRANSPARENT_BIN): { _binMode = USE_RENDERBIN_DETAILS; _binNum = 10; _binName = "DepthSortedBin"; break; } case(OPAQUE_BIN): { _binMode = USE_RENDERBIN_DETAILS; _binNum = 0; _binName = "RenderBin"; break; } default: // DEFAULT_BIN { setRenderBinToInherit(); break; } } } void StateSet::setRenderBinDetails(int binNum,const std::string& binName,RenderBinMode mode) { _binMode = mode; _binNum = binNum; _binName = binName; } void StateSet::setRenderBinToInherit() { _binMode = INHERIT_RENDERBIN_DETAILS; _binNum = 0; _binName = ""; } void StateSet::setMode(ModeList& modeList,StateAttribute::GLMode mode, StateAttribute::GLModeValue value) { if ((value&StateAttribute::INHERIT)) setModeToInherit(modeList,mode); else modeList[mode] = value; } void StateSet::setModeToInherit(ModeList& modeList,StateAttribute::GLMode mode) { ModeList::iterator itr = modeList.find(mode); if (itr!=modeList.end()) { modeList.erase(itr); } } StateAttribute::GLModeValue StateSet::getMode(const ModeList& modeList,StateAttribute::GLMode mode) const { ModeList::const_iterator itr = modeList.find(mode); if (itr!=modeList.end()) { return itr->second; } else return StateAttribute::INHERIT; } class SetAssociateModesHelper : public StateAttribute::ModeUsage { public: SetAssociateModesHelper(StateSet* stateset, StateAttribute::GLModeValue value,unsigned int unit=0): _stateset(stateset), _value(value), _unit(unit) {} virtual ~SetAssociateModesHelper() {} virtual void usesMode(StateAttribute::GLMode mode) { _stateset->setMode(mode,_value); } virtual void usesTextureMode(StateAttribute::GLMode mode) { _stateset->setTextureMode(_unit,mode,_value); } StateSet* _stateset; StateAttribute::GLModeValue _value; unsigned int _unit; }; void StateSet::setAssociatedModes(const StateAttribute* attribute, StateAttribute::GLModeValue value) { SetAssociateModesHelper helper(this,value); attribute->getModeUsage(helper); } void StateSet::setAssociatedTextureModes(unsigned int unit,const StateAttribute* attribute, StateAttribute::GLModeValue value) { SetAssociateModesHelper helper(this,value,unit); attribute->getModeUsage(helper); } void StateSet::setAttribute(AttributeList& attributeList,StateAttribute *attribute, const StateAttribute::OverrideValue value) { if (attribute) { int delta_update = 0; int delta_event = 0; AttributeList::iterator itr=attributeList.find(attribute->getTypeMemberPair()); if (itr==attributeList.end()) { // new entry. attributeList[attribute->getTypeMemberPair()] = RefAttributePair(attribute,value&(StateAttribute::OVERRIDE|StateAttribute::PROTECTED)); attribute->addParent(this); if (attribute->getUpdateCallback()) { delta_update = 1; } if (attribute->getEventCallback()) { delta_event = 1; } } else { if (itr->second.first==attribute) { // changing just override itr->second.second = value&(StateAttribute::OVERRIDE|StateAttribute::PROTECTED); } else { itr->second.first->removeParent(this); if (itr->second.first->getUpdateCallback()) --delta_update; if (itr->second.first->getEventCallback()) --delta_event; attribute->addParent(this); itr->second.first = attribute; if (itr->second.first->getUpdateCallback()) ++delta_update; if (itr->second.first->getEventCallback()) ++delta_event; itr->second.second = value&(StateAttribute::OVERRIDE|StateAttribute::PROTECTED); } } if (delta_update!=0) { setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+delta_update); } if (delta_event!=0) { setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()+delta_event); } } } StateAttribute* StateSet::getAttribute(AttributeList& attributeList,StateAttribute::Type type, unsigned int member) { AttributeList::iterator itr = attributeList.find(StateAttribute::TypeMemberPair(type,member)); if (itr!=attributeList.end()) { return itr->second.first.get(); } else return NULL; } const StateAttribute* StateSet::getAttribute(const AttributeList& attributeList,StateAttribute::Type type, unsigned int member) const { AttributeList::const_iterator itr = attributeList.find(StateAttribute::TypeMemberPair(type,member)); if (itr!=attributeList.end()) { return itr->second.first.get(); } else return NULL; } const StateSet::RefAttributePair* StateSet::getAttributePair(const AttributeList& attributeList,StateAttribute::Type type, unsigned int member) const { AttributeList::const_iterator itr = attributeList.find(StateAttribute::TypeMemberPair(type,member)); if (itr!=attributeList.end()) { return &(itr->second); } else return NULL; } void StateSet::setUpdateCallback(Callback* ac) { //osg::notify(osg::INFO)<<"Setting StateSet callbacks"<(*itr); if (drawable) { //drawable->setNumChildrenRequiringUpdateTraversal(drawable->getNumChildrenRequiringUpdateTraversal()+delta); } else { osg::Node* node = dynamic_cast(*itr); if (node) { node->setNumChildrenRequiringUpdateTraversal(node->getNumChildrenRequiringUpdateTraversal()+delta); } } } } } void StateSet::runUpdateCallbacks(osg::NodeVisitor* nv) { //osg::notify(osg::INFO)<<"Running StateSet callbacks"<second.first->getUpdateCallback(); if (callback) (*callback)(itr->second.first.get(),nv); } // run texture attribute callbacks. for(unsigned int i=0;i<_textureAttributeList.size();++i) { AttributeList& attributeList = _textureAttributeList[i]; for(AttributeList::iterator itr=attributeList.begin(); itr!=attributeList.end(); ++itr) { StateAttribute::Callback* callback = itr->second.first->getUpdateCallback(); if (callback) (*callback)(itr->second.first.get(),nv); } } // run uniform callbacks. for(UniformList::iterator uitr = _uniformList.begin(); uitr != _uniformList.end(); ++uitr) { Uniform::Callback* callback = uitr->second.first->getUpdateCallback(); if (callback) (*callback)(uitr->second.first.get(),nv); } } } void StateSet::setEventCallback(Callback* ac) { if (_eventCallback==ac) return; int delta = 0; if (_eventCallback.valid()) --delta; if (ac) ++delta; _eventCallback = ac; if (delta!=0 && _numChildrenRequiringEventTraversal==0) { for(ParentList::iterator itr=_parents.begin(); itr!=_parents.end(); ++itr) { osg::Drawable* drawable = dynamic_cast(*itr); if (drawable) { //drawable->setNumChildrenRequiringUpdateTraversal(drawable->getNumChildrenRequiringUpdateTraversal()+delta); } else { osg::Node* node = dynamic_cast(*itr); if (node) { node->setNumChildrenRequiringEventTraversal(node->getNumChildrenRequiringEventTraversal()+delta); } } } } } void StateSet::runEventCallbacks(osg::NodeVisitor* nv) { if (_eventCallback.valid()) (*_eventCallback)(this,nv); if (_numChildrenRequiringEventTraversal!=0) { // run attribute callbacks for(AttributeList::iterator itr=_attributeList.begin(); itr!=_attributeList.end(); ++itr) { StateAttribute::Callback* callback = itr->second.first->getEventCallback(); if (callback) (*callback)(itr->second.first.get(),nv); } // run texture attribute callbacks. for(unsigned int i=0;i<_textureAttributeList.size();++i) { AttributeList& attributeList = _textureAttributeList[i]; for(AttributeList::iterator itr=attributeList.begin(); itr!=attributeList.end(); ++itr) { StateAttribute::Callback* callback = itr->second.first->getEventCallback(); if (callback) (*callback)(itr->second.first.get(),nv); } } // run uniform callbacks. for(UniformList::iterator uitr = _uniformList.begin(); uitr != _uniformList.end(); ++uitr) { Uniform::Callback* callback = uitr->second.first->getEventCallback(); if (callback) (*callback)(uitr->second.first.get(),nv); } } } void StateSet::setNumChildrenRequiringUpdateTraversal(unsigned int num) { // if no changes just return. if (_numChildrenRequiringUpdateTraversal==num) return; // note, if _updateCallback is set then the // parents won't be affected by any changes to // _numChildrenRequiringUpdateTraversal so no need to inform them. if (!_updateCallback && !_parents.empty()) { // need to pass on changes to parents. int delta = 0; if (_numChildrenRequiringUpdateTraversal>0) --delta; if (num>0) ++delta; if (delta!=0) { // the number of callbacks has changed, need to pass this // on to parents so they know whether app traversal is // reqired on this subgraph. for(ParentList::iterator itr =_parents.begin(); itr != _parents.end(); ++itr) { osg::Drawable* drawable = dynamic_cast(*itr); if (drawable) { drawable->setNumChildrenRequiringUpdateTraversal(drawable->getNumChildrenRequiringUpdateTraversal()+delta); } else { osg::Node* node = dynamic_cast(*itr); if (node) { node->setNumChildrenRequiringUpdateTraversal(node->getNumChildrenRequiringUpdateTraversal()+delta); } } } } } // finally update this objects value. _numChildrenRequiringUpdateTraversal=num; } void StateSet::setNumChildrenRequiringEventTraversal(unsigned int num) { // if no changes just return. if (_numChildrenRequiringEventTraversal==num) return; // note, if _EventCallback is set then the // parents won't be affected by any changes to // _numChildrenRequiringEventTraversal so no need to inform them. if (!_eventCallback && !_parents.empty()) { // need to pass on changes to parents. int delta = 0; if (_numChildrenRequiringEventTraversal>0) --delta; if (num>0) ++delta; if (delta!=0) { // the number of callbacks has changed, need to pass this // on to parents so they know whether app traversal is // reqired on this subgraph. for(ParentList::iterator itr =_parents.begin(); itr != _parents.end(); ++itr) { osg::Drawable* drawable = dynamic_cast(*itr); if (drawable) { drawable->setNumChildrenRequiringEventTraversal(drawable->getNumChildrenRequiringEventTraversal()+delta); } else { osg::Node* node = dynamic_cast(*itr); if (node) { node->setNumChildrenRequiringEventTraversal(node->getNumChildrenRequiringEventTraversal()+delta); } } } } } // finally Event this objects value. _numChildrenRequiringEventTraversal=num; }