ac975bf79a
to avoid threading problems when using atomic ref counting.
1867 lines
61 KiB
C++
1867 lines
61 KiB
C++
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 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 <stdio.h>
|
|
|
|
#include <osg/StateSet>
|
|
#include <osg/State>
|
|
#include <osg/Notify>
|
|
|
|
#include <osg/AlphaFunc>
|
|
#include <osg/Material>
|
|
#include <osg/CullFace>
|
|
#include <osg/FrontFace>
|
|
#include <osg/PolygonMode>
|
|
#include <osg/BlendFunc>
|
|
#include <osg/Depth>
|
|
#include <osg/Drawable>
|
|
#include <osg/Node>
|
|
|
|
#include <osg/TextureCubeMap>
|
|
#include <osg/TextureRectangle>
|
|
#include <osg/Texture2DArray>
|
|
|
|
#include <set>
|
|
#include <algorithm>
|
|
|
|
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_2D_ARRAY_EXT);
|
|
|
|
_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<StateAttribute::GLMode> _textureModeSet;
|
|
|
|
};
|
|
|
|
static TextureGLModeSet& getTextureGLModeSet()
|
|
{
|
|
static TextureGLModeSet s_textureGLModeSet;
|
|
return s_textureGLModeSet;
|
|
}
|
|
|
|
bool osg::isTextureMode(StateAttribute::GLMode mode)
|
|
{
|
|
return getTextureGLModeSet().isTextureMode(mode);
|
|
}
|
|
|
|
StateSet::StateSet():
|
|
Object(true),
|
|
_nestRenderBins(true)
|
|
{
|
|
_renderingHint = DEFAULT_BIN;
|
|
|
|
_numChildrenRequiringUpdateTraversal = 0;
|
|
_numChildrenRequiringEventTraversal = 0;
|
|
|
|
setRenderBinToInherit();
|
|
}
|
|
|
|
StateSet::StateSet(const StateSet& rhs,const CopyOp& copyop):Object(rhs,copyop),
|
|
_nestRenderBins(rhs._nestRenderBins)
|
|
{
|
|
_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;i<rhs._textureAttributeList.size();++i)
|
|
{
|
|
|
|
AttributeList& lhs_attributeList = _textureAttributeList[i];
|
|
const AttributeList& rhs_attributeList = rhs._textureAttributeList[i];
|
|
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)
|
|
{
|
|
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::computeDataVariance()
|
|
{
|
|
bool dynamic = false;
|
|
|
|
if (_updateCallback.valid() ||
|
|
_eventCallback.valid())
|
|
{
|
|
dynamic = true;
|
|
}
|
|
|
|
// run attribute callbacks
|
|
|
|
for(AttributeList::iterator itr=_attributeList.begin();
|
|
itr!=_attributeList.end();
|
|
++itr)
|
|
{
|
|
if (itr->second.first->getDataVariance()==UNSPECIFIED &&
|
|
(itr->second.first->getUpdateCallback() || itr->second.first->getEventCallback()))
|
|
{
|
|
itr->second.first->setDataVariance(DYNAMIC);
|
|
}
|
|
|
|
if (itr->second.first->getDataVariance()==DYNAMIC) dynamic = true;
|
|
}
|
|
|
|
// 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)
|
|
{
|
|
if (itr->second.first->getDataVariance()==UNSPECIFIED &&
|
|
(itr->second.first->getUpdateCallback() || itr->second.first->getEventCallback()))
|
|
{
|
|
itr->second.first->setDataVariance(DYNAMIC);
|
|
}
|
|
|
|
if (itr->second.first->getDataVariance()==DYNAMIC) dynamic = true;
|
|
}
|
|
}
|
|
|
|
|
|
// run uniform callbacks.
|
|
for(UniformList::iterator uitr = _uniformList.begin();
|
|
uitr != _uniformList.end();
|
|
++uitr)
|
|
{
|
|
if (uitr->second.first->getDataVariance()==UNSPECIFIED &&
|
|
(uitr->second.first->getUpdateCallback() || uitr->second.first->getEventCallback()))
|
|
{
|
|
uitr->second.first->setDataVariance(DYNAMIC);
|
|
}
|
|
|
|
if (uitr->second.first->getDataVariance()==DYNAMIC) dynamic = true;
|
|
}
|
|
|
|
#if 0
|
|
|
|
if (dynamic)
|
|
{
|
|
osg::notify(osg::NOTICE)<<"StateSet::computeDataVariance setting to DYNAMIC"<<std::endl;
|
|
}
|
|
else
|
|
{
|
|
osg::notify(osg::NOTICE)<<"StateSet::computeDataVariance to STATIC"<<std::endl;
|
|
}
|
|
#endif
|
|
|
|
if (getDataVariance()==UNSPECIFIED)
|
|
{
|
|
setDataVariance(dynamic ? DYNAMIC : STATIC);
|
|
}
|
|
}
|
|
|
|
|
|
void StateSet::addParent(osg::Object* object)
|
|
{
|
|
// osg::notify(osg::INFO)<<"Adding parent"<<std::endl;
|
|
OpenThreads::ScopedPointerLock<OpenThreads::Mutex> lock(getRefMutex());
|
|
|
|
_parents.push_back(object);
|
|
}
|
|
|
|
void StateSet::removeParent(osg::Object* object)
|
|
{
|
|
OpenThreads::ScopedPointerLock<OpenThreads::Mutex> lock(getRefMutex());
|
|
|
|
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
|
|
{
|
|
|
|
if (_textureAttributeList.size()<rhs._textureAttributeList.size()) return -1;
|
|
if (_textureAttributeList.size()>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->first<rhs_attr_itr->first) return -1;
|
|
else if (rhs_attr_itr->first<lhs_attr_itr->first) 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.second<rhs_attr_itr->second.second) return -1;
|
|
else if (rhs_attr_itr->second.second<lhs_attr_itr->second.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->first<rhs_attr_itr->first) return -1;
|
|
else if (rhs_attr_itr->first<lhs_attr_itr->first) 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.second<rhs_attr_itr->second.second) return -1;
|
|
else if (rhs_attr_itr->second.second<lhs_attr_itr->second.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->first<rhs_attr_itr->first) return -1;
|
|
else if (rhs_attr_itr->first<lhs_attr_itr->first) 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.second<rhs_attr_itr->second.second) return -1;
|
|
else if (rhs_attr_itr->second.second<lhs_attr_itr->second.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->first<rhs_attr_itr->first) return -1;
|
|
else if (rhs_attr_itr->first<lhs_attr_itr->first) 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.second<rhs_attr_itr->second.second) return -1;
|
|
else if (rhs_attr_itr->second.second<lhs_attr_itr->second.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;
|
|
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->first<rhs_mode_itr->first) return -1;
|
|
else if (rhs_mode_itr->first<lhs_mode_itr->first) return 1;
|
|
if (lhs_mode_itr->second<rhs_mode_itr->second) return -1;
|
|
else if (rhs_mode_itr->second<lhs_mode_itr->second) 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->first<rhs_mode_itr->first) return -1;
|
|
else if (rhs_mode_itr->first<lhs_mode_itr->first) return 1;
|
|
if (lhs_mode_itr->second<rhs_mode_itr->second) return -1;
|
|
else if (rhs_mode_itr->second<lhs_mode_itr->second) 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->first<rhs_uniform_itr->first) return -1;
|
|
else if (rhs_uniform_itr->first<lhs_uniform_itr->first) return 1;
|
|
if (lhs_uniform_itr->second<rhs_uniform_itr->second) return -1;
|
|
else if (rhs_uniform_itr->second<lhs_uniform_itr->second) 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;
|
|
|
|
// check render bin details
|
|
|
|
if ( _binMode < rhs._binMode ) return -1;
|
|
else if ( _binMode > rhs._binMode ) return 1;
|
|
|
|
if ( _binMode != INHERIT_RENDERBIN_DETAILS )
|
|
{
|
|
if ( _binNum < rhs._binNum ) return -1;
|
|
else if ( _binNum > rhs._binNum ) return 1;
|
|
|
|
if ( _binName < rhs._binName ) return -1;
|
|
else if ( _binName > rhs._binName ) 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->first<rhs_mode_itr->first) return -1;
|
|
else if (rhs_mode_itr->first<lhs_mode_itr->first) return 1;
|
|
if (lhs_mode_itr->second<rhs_mode_itr->second) return -1;
|
|
else if (rhs_mode_itr->second<lhs_mode_itr->second) 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->first<rhs_attr_itr->first) return -1;
|
|
else if (rhs_attr_itr->first<lhs_attr_itr->first) 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.second<rhs_attr_itr->second.second) return -1;
|
|
else if (rhs_attr_itr->second.second<lhs_attr_itr->second.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->first<rhs_attr_itr->first) return -1;
|
|
else if (rhs_attr_itr->first<lhs_attr_itr->first) 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.second<rhs_attr_itr->second.second) return -1;
|
|
else if (rhs_attr_itr->second.second<lhs_attr_itr->second.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())
|
|
{
|
|
// take the rhs mode unless the lhs is override and the rhs is not protected
|
|
if (!(lhs_mitr->second & StateAttribute::OVERRIDE ) ||
|
|
(rhs_mitr->second & StateAttribute::PROTECTED))
|
|
{
|
|
// override isn't on in rhs, so override it with incoming
|
|
// 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())
|
|
{
|
|
// take the rhs attribute unless the lhs is override and the rhs is not protected
|
|
if (!(lhs_aitr->second.second & StateAttribute::OVERRIDE) ||
|
|
(rhs_aitr->second.second & StateAttribute::PROTECTED))
|
|
{
|
|
// override isn't on in rhs, so override it with incoming
|
|
// 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 override it with incoming
|
|
// 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()<rhs._textureModeList.size()) _textureModeList.resize(rhs._textureModeList.size());
|
|
for(unsigned int mi=0;mi<rhs._textureModeList.size();++mi)
|
|
{
|
|
ModeList& lhs_modeList = _textureModeList[mi];
|
|
const ModeList& rhs_modeList = rhs._textureModeList[mi];
|
|
// 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 = lhs_modeList.find(rhs_mitr->first);
|
|
if (lhs_mitr!=lhs_modeList.end())
|
|
{
|
|
// take the rhs mode unless the lhs is override and the rhs is not protected
|
|
if (!(lhs_mitr->second & StateAttribute::OVERRIDE) ||
|
|
(rhs_mitr->second & StateAttribute::PROTECTED))
|
|
{
|
|
// override isn't on in rhs, so override it with incoming
|
|
// value.
|
|
lhs_mitr->second = rhs_mitr->second;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// entry doesn't exist so insert it.
|
|
lhs_modeList.insert(*rhs_mitr);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_textureAttributeList.size()<rhs._textureAttributeList.size()) _textureAttributeList.resize(rhs._textureAttributeList.size());
|
|
for(unsigned int ai=0;ai<rhs._textureAttributeList.size();++ai)
|
|
{
|
|
AttributeList& lhs_attributeList = _textureAttributeList[ai];
|
|
const AttributeList& rhs_attributeList = rhs._textureAttributeList[ai];
|
|
|
|
// 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 = lhs_attributeList.find(rhs_aitr->first);
|
|
if (lhs_aitr!=lhs_attributeList.end())
|
|
{
|
|
// take the rhs attribute unless the lhs is override and the rhs is not protected
|
|
if (!(lhs_aitr->second.second & StateAttribute::OVERRIDE) ||
|
|
(rhs_aitr->second.second & StateAttribute::PROTECTED))
|
|
{
|
|
// override isn't on in rhs, so override it with incoming
|
|
// 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())
|
|
{
|
|
// take the rhs uniform unless the lhs is override and the rhs is not protected
|
|
if (!(lhs_uitr->second.second & StateAttribute::OVERRIDE) ||
|
|
(rhs_uitr->second.second & StateAttribute::PROTECTED))
|
|
{
|
|
// override isn't on in rhs, so override it with incoming
|
|
// 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);
|
|
}
|
|
}
|
|
|
|
// Merge RenderBin state from rhs into this.
|
|
// Only do so if this's RenderBinMode is INHERIT.
|
|
if (getRenderBinMode() == INHERIT_RENDERBIN_DETAILS)
|
|
{
|
|
setRenderingHint( rhs.getRenderingHint() );
|
|
setRenderBinMode( rhs.getRenderBinMode() );
|
|
setBinNumber( rhs.getBinNumber() );
|
|
setBinName( rhs.getBinName() );
|
|
}
|
|
}
|
|
|
|
|
|
void StateSet::setMode(StateAttribute::GLMode mode, StateAttribute::GLModeValue value)
|
|
{
|
|
if (getTextureGLModeSet().isTextureMode(mode))
|
|
{
|
|
notify(NOTICE)<<"Warning: texture mode '"<<mode<<"'passed to setMode(mode,value), "<<std::endl;
|
|
notify(NOTICE)<<" assuming setTextureMode(unit=0,mode,value) instead."<<std::endl;
|
|
notify(NOTICE)<<" please change calling code to use appropriate call."<<std::endl;
|
|
|
|
setTextureMode(0,mode,value);
|
|
}
|
|
else if (mode == GL_COLOR_MATERIAL)
|
|
{
|
|
notify(NOTICE)<<"Error: Setting mode 'GL_COLOR_MATERIAL' via osg::StateSet::setMode(mode,value) ignored.\n";
|
|
notify(NOTICE)<<" The mode 'GL_COLOR_MATERIAL' is set by the osg::Material StateAttribute.\n";
|
|
notify(NOTICE)<<" Setting this as a mode fools osg's State tracking."<<std::endl;
|
|
}
|
|
else
|
|
{
|
|
setMode(_modeList,mode,value);
|
|
}
|
|
}
|
|
|
|
void StateSet::removeMode(StateAttribute::GLMode mode)
|
|
{
|
|
if (getTextureGLModeSet().isTextureMode(mode))
|
|
{
|
|
notify(NOTICE)<<"Warning: texture mode '"<<mode<<"'passed to setModeToInherit(mode), "<<std::endl;
|
|
notify(NOTICE)<<" assuming setTextureModeToInherit(unit=0,mode) instead."<<std::endl;
|
|
notify(NOTICE)<<" please change calling code to use appropriate call."<<std::endl;
|
|
|
|
removeTextureMode(0,mode);
|
|
}
|
|
else if (mode == GL_COLOR_MATERIAL)
|
|
{
|
|
notify(NOTICE)<<"Error: Setting mode 'GL_COLOR_MATERIAL' via osg::StateSet::removeMode(mode) ignored.\n";
|
|
notify(NOTICE)<<" The mode 'GL_COLOR_MATERIAL' is set by the osg::Material StateAttribute.\n";
|
|
notify(NOTICE)<<" Setting this as a mode fools osg's State tracking."<<std::endl;
|
|
}
|
|
else
|
|
{
|
|
setModeToInherit(_modeList,mode);
|
|
}
|
|
|
|
}
|
|
|
|
StateAttribute::GLModeValue StateSet::getMode(StateAttribute::GLMode mode) const
|
|
{
|
|
if (!getTextureGLModeSet().isTextureMode(mode))
|
|
{
|
|
return getMode(_modeList,mode);
|
|
}
|
|
else
|
|
{
|
|
notify(NOTICE)<<"Warning: texture mode '"<<mode<<"'passed to getMode(mode), "<<std::endl;
|
|
notify(NOTICE)<<" assuming getTextureMode(unit=0,mode) instead."<<std::endl;
|
|
notify(NOTICE)<<" please change calling code to use appropriate call."<<std::endl;
|
|
|
|
return getTextureMode(0,mode);
|
|
}
|
|
}
|
|
|
|
void StateSet::setAttribute(StateAttribute *attribute, StateAttribute::OverrideValue value)
|
|
{
|
|
if (attribute)
|
|
{
|
|
if (!attribute->isTextureAttribute())
|
|
{
|
|
setAttribute(_attributeList,attribute,value);
|
|
}
|
|
else
|
|
{
|
|
notify(NOTICE)<<"Warning: texture attribute '"<<attribute->className()<<"'passed to setAttribute(attr,value), "<<std::endl;
|
|
notify(NOTICE)<<" assuming setTextureAttribute(unit=0,attr,value) instead."<<std::endl;
|
|
notify(NOTICE)<<" please change calling code to use appropriate call."<<std::endl;
|
|
|
|
setTextureAttribute(0,attribute,value);
|
|
}
|
|
}
|
|
}
|
|
|
|
void StateSet::setAttributeAndModes(StateAttribute *attribute, StateAttribute::GLModeValue value)
|
|
{
|
|
if (attribute)
|
|
{
|
|
if (!attribute->isTextureAttribute())
|
|
{
|
|
if (value&StateAttribute::INHERIT)
|
|
{
|
|
removeAttribute(attribute->getType());
|
|
}
|
|
else
|
|
{
|
|
setAttribute(_attributeList,attribute,value);
|
|
setAssociatedModes(attribute,value);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
notify(NOTICE)<<"Warning: texture attribute '"<<attribute->className()<<"' passed to setAttributeAndModes(attr,value), "<<std::endl;
|
|
notify(NOTICE)<<" assuming setTextureAttributeAndModes(unit=0,attr,value) instead."<<std::endl;
|
|
notify(NOTICE)<<" please change calling code to use appropriate call."<<std::endl;
|
|
|
|
setTextureAttributeAndModes(0,attribute,value);
|
|
}
|
|
}
|
|
}
|
|
|
|
void StateSet::removeAttribute(StateAttribute::Type type, unsigned int member)
|
|
{
|
|
AttributeList::iterator itr = _attributeList.find(StateAttribute::TypeMemberPair(type,member));
|
|
if (itr!=_attributeList.end())
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
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 '"<<mode<<"'passed to setTextureMode(unit,mode,value), "<<std::endl;
|
|
notify(NOTICE)<<" assuming setMode(mode,value) instead."<<std::endl;
|
|
notify(NOTICE)<<" please change calling code to use appropriate call."<<std::endl;
|
|
|
|
setMode(mode,value);
|
|
}
|
|
}
|
|
|
|
void StateSet::removeTextureMode(unsigned int unit,StateAttribute::GLMode mode)
|
|
{
|
|
if (getTextureGLModeSet().isTextureMode(mode))
|
|
{
|
|
if (unit>=_textureModeList.size()) return;
|
|
setModeToInherit(_textureModeList[unit],mode);
|
|
}
|
|
else
|
|
{
|
|
notify(NOTICE)<<"Warning: non-texture mode '"<<mode<<"'passed to setTextureModeToInherit(unit,mode), "<<std::endl;
|
|
notify(NOTICE)<<" assuming setModeToInherit(unit=0,mode) instead."<<std::endl;
|
|
notify(NOTICE)<<" please change calling code to use appropriate call."<<std::endl;
|
|
|
|
removeMode(mode);
|
|
}
|
|
}
|
|
|
|
|
|
StateAttribute::GLModeValue StateSet::getTextureMode(unsigned int unit,StateAttribute::GLMode mode) const
|
|
{
|
|
if (getTextureGLModeSet().isTextureMode(mode))
|
|
{
|
|
if (unit>=_textureModeList.size()) return StateAttribute::INHERIT;
|
|
return getMode(_textureModeList[unit],mode);
|
|
}
|
|
else
|
|
{
|
|
notify(NOTICE)<<"Warning: non-texture mode '"<<mode<<"'passed to geTexturetMode(unit,mode), "<<std::endl;
|
|
notify(NOTICE)<<" assuming getMode(mode) instead."<<std::endl;
|
|
notify(NOTICE)<<" please change calling code to use appropriate call."<<std::endl;
|
|
|
|
return getMode(mode);
|
|
}
|
|
}
|
|
|
|
void StateSet::setTextureAttribute(unsigned int unit,StateAttribute *attribute, const StateAttribute::OverrideValue value)
|
|
{
|
|
if (attribute)
|
|
{
|
|
if (attribute->isTextureAttribute())
|
|
{
|
|
setAttribute(getOrCreateTextureAttributeList(unit),attribute,value);
|
|
}
|
|
else
|
|
{
|
|
notify(NOTICE)<<"Warning: texture attribute '"<<attribute->className()<<"' passed to setTextureAttribute(unit,attr,value), "<<std::endl;
|
|
notify(NOTICE)<<" assuming setAttribute(attr,value) instead."<<std::endl;
|
|
notify(NOTICE)<<" please change calling code to use appropriate call."<<std::endl;
|
|
setAttribute(attribute,value);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void StateSet::setTextureAttributeAndModes(unsigned int unit,StateAttribute *attribute, StateAttribute::GLModeValue value)
|
|
{
|
|
if (attribute)
|
|
{
|
|
|
|
if (attribute->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 '"<<attribute->className()<<"' passed to setTextureAttributeAndModes(unit,attr,value), "<<std::endl;
|
|
notify(NOTICE)<<" assuming setAttributeAndModes(attr,value) instead."<<std::endl;
|
|
notify(NOTICE)<<" please change calling code to use appropriate call."<<std::endl;
|
|
setAttribute(attribute,value);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void StateSet::removeTextureAttribute(unsigned int unit,StateAttribute::Type type)
|
|
{
|
|
if (unit>=_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::setThreadSafeRefUnref(bool threadSafe)
|
|
{
|
|
Object::setThreadSafeRefUnref(threadSafe);
|
|
|
|
for(AttributeList::const_iterator itr = _attributeList.begin();
|
|
itr!=_attributeList.end();
|
|
++itr)
|
|
{
|
|
itr->second.first->setThreadSafeRefUnref(threadSafe);
|
|
}
|
|
|
|
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->setThreadSafeRefUnref(threadSafe);
|
|
}
|
|
}
|
|
}
|
|
|
|
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::resizeGLObjectBuffers(unsigned int maxSize)
|
|
{
|
|
for(AttributeList::const_iterator itr = _attributeList.begin();
|
|
itr!=_attributeList.end();
|
|
++itr)
|
|
{
|
|
itr->second.first->resizeGLObjectBuffers(maxSize);
|
|
}
|
|
|
|
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->resizeGLObjectBuffers(maxSize);
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
};
|
|
|
|
class RemoveAssociateModesHelper : public StateAttribute::ModeUsage
|
|
{
|
|
public:
|
|
RemoveAssociateModesHelper(StateSet* stateset, unsigned int unit=0):
|
|
_stateset(stateset),
|
|
_unit(unit) {}
|
|
|
|
virtual ~RemoveAssociateModesHelper() {}
|
|
|
|
virtual void usesMode(StateAttribute::GLMode mode)
|
|
{
|
|
_stateset->removeMode(mode);
|
|
}
|
|
|
|
virtual void usesTextureMode(StateAttribute::GLMode mode)
|
|
{
|
|
_stateset->removeTextureMode(_unit, mode);
|
|
}
|
|
|
|
|
|
|
|
StateSet* _stateset;
|
|
unsigned int _unit;
|
|
};
|
|
|
|
void StateSet::setAssociatedModes(const StateAttribute* attribute, StateAttribute::GLModeValue value)
|
|
{
|
|
SetAssociateModesHelper helper(this,value);
|
|
attribute->getModeUsage(helper);
|
|
}
|
|
|
|
void StateSet::removeAssociatedModes(const StateAttribute* attribute)
|
|
{
|
|
RemoveAssociateModesHelper helper(this);
|
|
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::removeAssociatedTextureModes(unsigned int unit,const StateAttribute* attribute)
|
|
{
|
|
RemoveAssociateModesHelper helper(this,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"<<std::endl;
|
|
|
|
if (_updateCallback==ac) return;
|
|
|
|
int delta = 0;
|
|
if (_updateCallback.valid()) --delta;
|
|
if (ac) ++delta;
|
|
|
|
_updateCallback = ac;
|
|
|
|
if (delta!=0 && _numChildrenRequiringUpdateTraversal==0)
|
|
{
|
|
//osg::notify(osg::INFO)<<"Going to set StateSet parents"<<std::endl;
|
|
|
|
for(ParentList::iterator itr=_parents.begin();
|
|
itr!=_parents.end();
|
|
++itr)
|
|
{
|
|
//osg::notify(osg::INFO)<<"Setting StateSet parent"<<std::endl;
|
|
|
|
osg::Drawable* drawable = dynamic_cast<osg::Drawable*>(*itr);
|
|
if (drawable)
|
|
{
|
|
//drawable->setNumChildrenRequiringUpdateTraversal(drawable->getNumChildrenRequiringUpdateTraversal()+delta);
|
|
}
|
|
else
|
|
{
|
|
osg::Node* node = dynamic_cast<osg::Node*>(*itr);
|
|
if (node)
|
|
{
|
|
node->setNumChildrenRequiringUpdateTraversal(node->getNumChildrenRequiringUpdateTraversal()+delta);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void StateSet::runUpdateCallbacks(osg::NodeVisitor* nv)
|
|
{
|
|
//osg::notify(osg::INFO)<<"Running StateSet callbacks"<<std::endl;
|
|
|
|
if (_updateCallback.valid()) (*_updateCallback)(this,nv);
|
|
|
|
if (_numChildrenRequiringUpdateTraversal!=0)
|
|
{
|
|
// run attribute callbacks
|
|
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 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<osg::Drawable*>(*itr);
|
|
if (drawable)
|
|
{
|
|
//drawable->setNumChildrenRequiringUpdateTraversal(drawable->getNumChildrenRequiringUpdateTraversal()+delta);
|
|
}
|
|
else
|
|
{
|
|
osg::Node* node = dynamic_cast<osg::Node*>(*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
|
|
// required on this subgraph.
|
|
for(ParentList::iterator itr =_parents.begin();
|
|
itr != _parents.end();
|
|
++itr)
|
|
{
|
|
osg::Drawable* drawable = dynamic_cast<osg::Drawable*>(*itr);
|
|
if (drawable)
|
|
{
|
|
drawable->setNumChildrenRequiringUpdateTraversal(drawable->getNumChildrenRequiringUpdateTraversal()+delta);
|
|
}
|
|
else
|
|
{
|
|
osg::Node* node = dynamic_cast<osg::Node*>(*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
|
|
// required on this subgraph.
|
|
for(ParentList::iterator itr =_parents.begin();
|
|
itr != _parents.end();
|
|
++itr)
|
|
{
|
|
osg::Drawable* drawable = dynamic_cast<osg::Drawable*>(*itr);
|
|
if (drawable)
|
|
{
|
|
drawable->setNumChildrenRequiringEventTraversal(drawable->getNumChildrenRequiringEventTraversal()+delta);
|
|
}
|
|
else
|
|
{
|
|
osg::Node* node = dynamic_cast<osg::Node*>(*itr);
|
|
if (node)
|
|
{
|
|
node->setNumChildrenRequiringEventTraversal(node->getNumChildrenRequiringEventTraversal()+delta);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// finally Event this objects value.
|
|
_numChildrenRequiringEventTraversal=num;
|
|
}
|