diff --git a/VisualStudio/osg/osg.dsp b/VisualStudio/osg/osg.dsp index 3bf1d75cc..fb38d00ca 100755 --- a/VisualStudio/osg/osg.dsp +++ b/VisualStudio/osg/osg.dsp @@ -432,6 +432,10 @@ SOURCE=..\..\src\osg\State.cpp # End Source File # Begin Source File +SOURCE=..\..\src\osg\StateAttribute.cpp +# End Source File +# Begin Source File + SOURCE=..\..\src\osg\StateSet.cpp # End Source File # Begin Source File diff --git a/include/osg/Drawable b/include/osg/Drawable index def1ff5fa..9dec4a7b5 100644 --- a/include/osg/Drawable +++ b/include/osg/Drawable @@ -135,7 +135,7 @@ class OSG_EXPORT Drawable : public Object /** Set the StateSet attached to the Drawable. Previously attached StateSet are automatically unreferenced on assignment of a new drawstate.*/ - inline void setStateSet(StateSet *state) { _stateset = state; } + void setStateSet(StateSet* stateset); /** Get the attached StateSet.*/ inline StateSet* getStateSet() { return _stateset.get();} diff --git a/include/osg/Node b/include/osg/Node index c065e0bf6..04485a895 100644 --- a/include/osg/Node +++ b/include/osg/Node @@ -221,7 +221,7 @@ class OSG_EXPORT Node : public Object /** Set the node's StateSet.*/ - inline void setStateSet(osg::StateSet* dstate) { _stateset = dstate; } + void setStateSet(osg::StateSet* stateset); /** return the node's StateSet, if one does not already exist create it * set the node and return the newly created StateSet. This ensures diff --git a/include/osg/StateAttribute b/include/osg/StateAttribute index 7fc7bad62..810870b99 100644 --- a/include/osg/StateAttribute +++ b/include/osg/StateAttribute @@ -20,6 +20,7 @@ #include #include +#include // define for the GL_EXT_secondary_color extension, GL_COLOR_SUM is OpenGL // mode to be used to enable and disable the second color. @@ -231,7 +232,28 @@ class OSG_EXPORT StateAttribute : public Object bool operator < (const StateAttribute& rhs) const { return compare(rhs)<0; } bool operator == (const StateAttribute& rhs) const { return compare(rhs)==0; } bool operator != (const StateAttribute& rhs) const { return compare(rhs)!=0; } + + /** A vector of osg::StateSet pointers which is used to store the parent(s) of this StateAttribute.*/ + typedef std::vector ParentList; + + /** Get the parent list of this StateAttribute. */ + inline const ParentList& getParents() const { return _parents; } + + inline StateSet* getParent(unsigned int i) { return _parents[i]; } + /** + * Get a single const parent of this StateAttribute. + * @param i index of the parent to get. + * @return the parent i. + */ + inline const StateSet* getParent(unsigned int i) const { return _parents[i]; } + + /** + * Get the number of parents of this StateAttribute. + * @return the number of parents of this StateAttribute. + */ + inline unsigned int getNumParents() const { return _parents.size(); } + struct ModeUsage { @@ -299,6 +321,12 @@ class OSG_EXPORT StateAttribute : public Object virtual ~StateAttribute() {} + void addParent(osg::StateSet* object); + void removeParent(osg::StateSet* object); + + ParentList _parents; + friend class osg::StateSet; + ref_ptr _updateCallback; ref_ptr _eventCallback; }; diff --git a/include/osg/StateSet b/include/osg/StateSet index b2f7e7b7f..bcfd722e3 100644 --- a/include/osg/StateSet +++ b/include/osg/StateSet @@ -66,6 +66,32 @@ class OSG_EXPORT StateSet : public Object bool operator == (const StateSet& rhs) const { return compare(rhs)==0; } bool operator != (const StateSet& rhs) const { return compare(rhs)!=0; } + + /** A vector of osg::Object pointers which is used to store the parent(s) of this Stateset, the parents could be osg::Node or osg::Drawable.*/ + typedef std::vector ParentList; + + /** Get the parent list of this StateSet. */ + inline const ParentList& getParents() const { return _parents; } + + /** Get the a copy of parent list of node. A copy is returned to + * prevent modification of the parent list.*/ + inline ParentList getParents() { return _parents; } + + inline Object* getParent(unsigned int i) { return _parents[i]; } + /** + * Get a single const parent of this StateSet. + * @param i index of the parent to get. + * @return the parent i. + */ + inline const Object* getParent(unsigned int i) const { return _parents[i]; } + + /** + * Get the number of parents of this StateSet. + * @return the number of parents of this StateSet. + */ + inline unsigned int getNumParents() const { return _parents.size(); } + + /** Set all the modes to on or off so that it defines a complete state, typically used for a default global state.*/ void setGlobalDefaults(); @@ -410,6 +436,13 @@ class OSG_EXPORT StateSet : public Object StateSet& operator = (const StateSet&) { return *this; } + void addParent(osg::Object* object); + void removeParent(osg::Object* object); + + ParentList _parents; + friend class osg::Node; + friend class osg::Drawable; + ModeList _modeList; AttributeList _attributeList; diff --git a/include/osg/Uniform b/include/osg/Uniform index 41e992d86..dd52d86f0 100644 --- a/include/osg/Uniform +++ b/include/osg/Uniform @@ -25,6 +25,7 @@ #include #include +#include #ifndef GL_VERSION_2_0 //[ #define GL_VERSION_2_0 1 @@ -159,6 +160,9 @@ class OSG_EXPORT Uniform : public Object META_Object(osg, Uniform); + + + bool setType( Type t ); bool setName( const std::string& name ); @@ -202,6 +206,32 @@ class OSG_EXPORT Uniform : public Object void copyData( const Uniform& rhs ); + + /** A vector of osg::StateSet pointers which is used to store the parent(s) of this Uniform, the parents could be osg::Node or osg::Drawable.*/ + typedef std::vector ParentList; + + /** Get the parent list of this Uniform. */ + inline const ParentList& getParents() const { return _parents; } + + /** Get the a copy of parent list of node. A copy is returned to + * prevent modification of the parent list.*/ + inline ParentList getParents() { return _parents; } + + inline StateSet* getParent(unsigned int i) { return _parents[i]; } + /** + * Get a single const parent of this Uniform. + * @param i index of the parent to get. + * @return the parent i. + */ + inline const StateSet* getParent(unsigned int i) const { return _parents[i]; } + + /** + * Get the number of parents of this Uniform. + * @return the number of parents of this Uniform. + */ + inline unsigned int getNumParents() const { return _parents.size(); } + + /** value assignment */ bool set( float f ); bool set( int i ); @@ -280,6 +310,12 @@ class OSG_EXPORT Uniform : public Object bool isCompatibleType( Type t ) const; + void addParent(osg::StateSet* object); + void removeParent(osg::StateSet* object); + + ParentList _parents; + friend class osg::StateSet; + std::string _name; Type _type; union { diff --git a/src/osg/Drawable.cpp b/src/osg/Drawable.cpp index cf40966a9..4f997d424 100644 --- a/src/osg/Drawable.cpp +++ b/src/osg/Drawable.cpp @@ -306,6 +306,22 @@ void Drawable::removeParent(osg::Node* node) if (pitr!=_parents.end()) _parents.erase(pitr); } + +void Drawable::setStateSet(osg::StateSet* stateset) +{ + // do nothing if nothing changed. + if (_stateset==stateset) return; + + // remove this node from the current statesets parent list + if (_stateset.valid()) _stateset->removeParent(this); + + // set the stateset. + _stateset = stateset; + + // add this node to the new stateset to the parent list. + if (_stateset.valid()) _stateset->addParent(this); +} + osg::StateSet* Drawable::getOrCreateStateSet() { if (!_stateset) _stateset = new StateSet; diff --git a/src/osg/GNUmakefile b/src/osg/GNUmakefile index dfcf4fb65..64e04de31 100644 --- a/src/osg/GNUmakefile +++ b/src/osg/GNUmakefile @@ -86,6 +86,7 @@ CXXFILES =\ Shape.cpp\ ShapeDrawable.cpp\ State.cpp\ + StateAttribute.cpp\ StateSet.cpp\ Stencil.cpp\ Switch.cpp\ diff --git a/src/osg/Node.cpp b/src/osg/Node.cpp index f055e794c..5b5e04011 100644 --- a/src/osg/Node.cpp +++ b/src/osg/Node.cpp @@ -86,6 +86,21 @@ void Node::ascend(NodeVisitor& nv) std::for_each(_parents.begin(),_parents.end(),NodeAcceptOp(nv)); } +void Node::setStateSet(osg::StateSet* stateset) +{ + // do nothing if nothing changed. + if (_stateset==stateset) return; + + // remove this node from the current statesets parent list + if (_stateset.valid()) _stateset->removeParent(this); + + // set the stateset. + _stateset = stateset; + + // add this node to the new stateset to the parent list. + if (_stateset.valid()) _stateset->addParent(this); +} + osg::StateSet* Node::getOrCreateStateSet() { if (!_stateset) _stateset = new StateSet; diff --git a/src/osg/StateAttribute.cpp b/src/osg/StateAttribute.cpp new file mode 100644 index 000000000..109fd6103 --- /dev/null +++ b/src/osg/StateAttribute.cpp @@ -0,0 +1,27 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2005 Robert Osfield + * + * This application is open source and may be redistributed and/or modified + * freely and without restriction, both in commericial and non commericial + * applications, as long as this copyright notice is maintained. + * + * This application 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. +*/ + +#include + +#include + +using namespace osg; + +void StateAttribute::addParent(osg::StateSet* object) +{ + _parents.push_back(object); +} + +void StateAttribute::removeParent(osg::StateSet* object) +{ + ParentList::iterator pitr = std::find(_parents.begin(),_parents.end(),object); + if (pitr!=_parents.end()) _parents.erase(pitr); +} diff --git a/src/osg/StateSet.cpp b/src/osg/StateSet.cpp index 87d618798..79d2b2a46 100644 --- a/src/osg/StateSet.cpp +++ b/src/osg/StateSet.cpp @@ -45,7 +45,7 @@ class TextureGLModeSet _textureModeSet.insert(GL_TEXTURE_3D); _textureModeSet.insert(GL_TEXTURE_CUBE_MAP); - _textureModeSet.insert(GL_TEXTURE_RECTANGLE_NV); + _textureModeSet.insert(GL_TEXTURE_RECTANGLE_NV); _textureModeSet.insert(GL_TEXTURE_GEN_Q); _textureModeSet.insert(GL_TEXTURE_GEN_R); @@ -87,7 +87,11 @@ StateSet::StateSet(const StateSet& rhs,const CopyOp& copyop):Object(rhs,copyop) 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); + if (attr) + { + _attributeList[typemember]=RefAttributePair(attr,rap.second); + attr->addParent(this); + } } // copy texture related modes. @@ -109,7 +113,11 @@ StateSet::StateSet(const StateSet& rhs,const CopyOp& copyop):Object(rhs,copyop) const StateAttribute::TypeMemberPair& typemember = itr->first; const RefAttributePair& rap = itr->second; StateAttribute* attr = copyop(rap.first.get()); - if (attr) lhs_attributeList[typemember]=RefAttributePair(attr,rap.second); + if (attr) + { + lhs_attributeList[typemember]=RefAttributePair(attr,rap.second); + attr->addParent(this); + } } } @@ -118,10 +126,14 @@ StateSet::StateSet(const StateSet& rhs,const CopyOp& copyop):Object(rhs,copyop) 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); + 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; @@ -133,9 +145,18 @@ StateSet::StateSet(const StateSet& rhs,const CopyOp& copyop):Object(rhs,copyop) StateSet::~StateSet() { - // note, all attached state attributes will be automatically - // unreferenced by ref_ptr<> and therefore there is no need to - // delete the memory manually. + clear(); +} + +void StateSet::addParent(osg::Object* object) +{ + _parents.push_back(object); +} + +void StateSet::removeParent(osg::Object* object) +{ + ParentList::iterator pitr = std::find(_parents.begin(),_parents.end(),object); + if (pitr!=_parents.end()) _parents.erase(pitr); } int StateSet::compare(const StateSet& rhs,bool compareAttributeContents) const @@ -402,12 +423,42 @@ void StateSet::clear() 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(); + _textureModeList.clear(); _textureAttributeList.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); + } + } + + + // remove self from uniforms parent + for(UniformList::iterator uitr = _uniformList.begin(); + uitr != _uniformList.end(); + ++uitr) + { + uitr->second.first->removeParent(this); + } + _uniformList.clear(); } @@ -449,13 +500,29 @@ void StateSet::merge(const StateSet& rhs) { // override isn't on in rhs, so overrite it with incomming // value. - lhs_aitr->second = rhs_aitr->second; + 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. - _attributeList.insert(*rhs_aitr); + // 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); } } @@ -508,13 +575,23 @@ void StateSet::merge(const StateSet& rhs) { // override isn't on in rhs, so overrite it with incomming // value. - lhs_aitr->second = rhs_aitr->second; + + 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. - lhs_attributeList.insert(*rhs_aitr); + // entry doesn't exist so insert it and add self as parent + lhs_attributeList.insert(*rhs_aitr).first->second.first->addParent(this); } } } @@ -532,13 +609,24 @@ void StateSet::merge(const StateSet& rhs) { // override isn't on in rhs, so overrite it with incomming // value. - lhs_uitr->second = rhs_uitr->second; + + 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. - _uniformList.insert(*rhs_uitr); + // entry doesn't exist so insert it and add self as parent + _uniformList.insert(*rhs_uitr).first->second.first->addParent(this); } } @@ -649,6 +737,7 @@ void StateSet::removeAttribute(StateAttribute::Type type, unsigned int member) AttributeList::iterator itr = _attributeList.find(StateAttribute::TypeMemberPair(type,member)); if (itr!=_attributeList.end()) { + itr->second.first->removeParent(this); setAssociatedModes(itr->second.first.get(),StateAttribute::INHERIT); _attributeList.erase(itr); } @@ -663,6 +752,8 @@ void StateSet::removeAttribute(StateAttribute* attribute) { if (itr->second.first != attribute) return; + itr->second.first->removeParent(this); + setAssociatedModes(itr->second.first.get(),StateAttribute::INHERIT); _attributeList.erase(itr); } @@ -687,9 +778,31 @@ void StateSet::addUniform(Uniform* uniform, StateAttribute::OverrideValue value) { if (uniform) { - RefUniformPair& up = _uniformList[uniform->getName()]; - up.first = uniform; - up.second = value; + 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); + } + else + { + if (itr->second.first==uniform) + { + // chaning just override + itr->second.second = value&(StateAttribute::OVERRIDE|StateAttribute::PROTECTED); + } + else + { + itr->second.first->removeParent(this); + uniform->addParent(this); + itr->second.first = uniform; + itr->second.second = value&(StateAttribute::OVERRIDE|StateAttribute::PROTECTED); + } + } } } @@ -698,6 +811,7 @@ void StateSet::removeUniform(const std::string& name) UniformList::iterator itr = _uniformList.find(name); if (itr!=_uniformList.end()) { + itr->second.first->removeParent(this); _uniformList.erase(itr); } } @@ -710,6 +824,8 @@ void StateSet::removeUniform(Uniform* uniform) if (itr!=_uniformList.end()) { if (itr->second.first != uniform) return; + + itr->second.first->removeParent(this); _uniformList.erase(itr); } } @@ -844,24 +960,26 @@ void StateSet::removeTextureAttribute(unsigned int unit,StateAttribute::Type typ { setAssociatedTextureModes(unit,itr->second.first.get(),StateAttribute::INHERIT); } + itr->second.first->removeParent(this); attributeList.erase(itr); } } void StateSet::removeTextureAttribute(unsigned int unit, StateAttribute* attribute) { - if (!attribute) return; - if (unit>=_textureAttributeList.size()) return; + 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; + 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); - attributeList.erase(itr); - } + setAssociatedTextureModes(unit,itr->second.first.get(),StateAttribute::INHERIT); + itr->second.first->removeParent(this); + attributeList.erase(itr); + } } StateAttribute* StateSet::getTextureAttribute(unsigned int unit,StateAttribute::Type type) @@ -1040,7 +1158,28 @@ void StateSet::setAttribute(AttributeList& attributeList,StateAttribute *attribu { if (attribute) { - attributeList[attribute->getTypeMemberPair()] = RefAttributePair(attribute,value&(StateAttribute::OVERRIDE|StateAttribute::PROTECTED)); + 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); + } + else + { + if (itr->second.first==attribute) + { + // changing just override + itr->second.second = value&(StateAttribute::OVERRIDE|StateAttribute::PROTECTED); + } + else + { + itr->second.first->removeParent(this); + attribute->addParent(this); + itr->second.first = attribute; + itr->second.second = value&(StateAttribute::OVERRIDE|StateAttribute::PROTECTED); + } + } } } diff --git a/src/osg/Uniform.cpp b/src/osg/Uniform.cpp index 398aad8a6..69db8da81 100644 --- a/src/osg/Uniform.cpp +++ b/src/osg/Uniform.cpp @@ -68,6 +68,17 @@ Uniform::Uniform( const Uniform& rhs, const CopyOp& copyop ) : copyData( rhs ); } +void Uniform::addParent(osg::StateSet* object) +{ + _parents.push_back(object); +} + +void Uniform::removeParent(osg::StateSet* object) +{ + ParentList::iterator pitr = std::find(_parents.begin(),_parents.end(),object); + if (pitr!=_parents.end()) _parents.erase(pitr); +} + bool Uniform::setType( Type t ) { if( _type != UNDEFINED )