OpenSceneGraph/include/osg/State

1075 lines
37 KiB
Plaintext
Raw Normal View History

2002-07-17 04:07:32 +08:00
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
2001-01-11 00:32:10 +08:00
#ifndef OSG_STATE
#define OSG_STATE 1
#include <osg/Export>
#include <osg/StateSet>
#include <osg/Matrix>
2001-09-22 10:42:08 +08:00
#include <osg/FrameStamp>
#include <osg/DisplaySettings>
#include <osg/Polytope>
2001-09-22 10:42:08 +08:00
#include <vector>
#include <map>
2001-01-11 00:32:10 +08:00
namespace osg {
2002-07-12 02:32:41 +08:00
#ifndef GL_TEXTURE0
#define GL_TEXTURE0 0x84C0
#endif
#ifndef GL_FOG_COORDINATE_ARRAY
#ifdef GL_FOG_COORDINATE_ARRAY_EXT
#define GL_FOG_COORDINATE_ARRAY GL_FOG_COORDINATE_ARRAY_EXT
#else
#define GL_FOG_COORDINATE_ARRAY 0x8457
#endif
#endif
#ifndef GL_SECONDARY_COLOR_ARRAY
#ifdef GL_SECONDARY_COLOR_ARRAY
#define GL_SECONDARY_COLOR_ARRAY GL_SECONDARY_COLOR_ARRAY_EXT
#else
#define GL_SECONDARY_COLOR_ARRAY 0x845E
#endif
#endif
2002-07-12 05:08:02 +08:00
/** macro for use with osg::StateAttrbiute::apply methods for detected and
* reporting OpenGL error messages.*/
#define OSG_GL_DEBUG(message) \
if (state.getFineGrainedErrorDetection()) \
{ \
GLenum errorNo = glGetError(); \
if (errorNo!=GL_NO_ERROR) \
{ \
osg::notify(WARN)<<"Warning: detected OpenGL error '"<<gluErrorString(errorNo)<<" "<<message<<endl; \
}\
}
/** State class for managing a state stack.
* Lazy state updating is used to minimize state changes.
*/
class SG_EXPORT State : public Referenced
2001-01-11 00:32:10 +08:00
{
public :
State();
virtual ~State();
/** push stateset onto state stack.*/
void pushStateSet(const StateSet* dstate);
/** pop drawstate off state stack.*/
void popStateSet();
/** copy the modes and attributes which captures the current state.*/
void captureCurrentState(StateSet& stateset) const;
/** reset the state object to an empty stack.*/
void reset();
inline void applyProjectionMatrix(const osg::Matrix* matrix)
{
if (_projection!=matrix)
{
glMatrixMode( GL_PROJECTION );
if (matrix)
{
_projection=matrix;
glLoadMatrixf(matrix->ptr());
}
else
{
_projection=_identity;
glLoadIdentity();
}
glMatrixMode( GL_MODELVIEW );
}
}
const osg::Matrix& getProjectionMatrix() const
{
return *_projection;
}
inline void applyModelViewMatrix(const osg::Matrix* matrix)
{
if (_modelView!=matrix)
{
if (matrix)
{
_modelView=matrix;
glLoadMatrixf(matrix->ptr());
}
else
{
_modelView=_identity;
glLoadIdentity();
}
}
}
const osg::Matrix& getModelViewMatrix() const
{
return *_modelView;
}
Polytope getViewFrustum() const;
/** Apply stateset.*/
void apply(const StateSet* dstate);
/** Apply the state.*/
void apply();
/** Apply an OpenGL mode if required. */
inline bool applyMode(StateAttribute::GLMode mode,bool enabled)
{
ModeStack& ms = _modeMap[mode];
ms.changed = true;
return applyMode(mode,enabled,ms);
}
inline bool applyTextureMode(unsigned int unit, StateAttribute::GLMode mode,bool enabled)
{
ModeMap& modeMap = getOrCreateTextureModeMap(unit);
ModeStack& ms = modeMap[mode];
ms.changed = true;
return applyMode(mode,enabled,ms);
}
/** Apply an attribute if required. */
inline bool applyAttribute(const StateAttribute* attribute)
{
AttributeStack& as = _attributeMap[attribute->getType()];
as.changed = true;
return applyAttribute(attribute,as);
}
inline bool applyTextureAttribute(unsigned int unit, const StateAttribute* attribute)
{
AttributeMap& attributeMap = getOrCreateTextureAttributeMap(unit);
AttributeStack& as = attributeMap[attribute->getType()];
as.changed = true;
return applyAttribute(attribute,as);
}
/** Mode has been set externally, update state to reflect this setting.*/
void haveAppliedMode(StateAttribute::GLMode mode,StateAttribute::GLModeValue value);
/** Mode has been set externally, therefore dirty the associated mode in osg::State
* so it is applied on next call to osg::State::apply(..)*/
void haveAppliedMode(StateAttribute::GLMode mode);
/** Attribute has been applied externally, update state to reflect this setting.*/
void haveAppliedAttribute(const StateAttribute* attribute);
/** Attribute has been applied externally,
* and therefore this attribute type has been dirtied
* and will need to be re-appplied on next osg::State.apply(..).
* note, if you have an osg::StateAttribute which you have applied externally
* then use the have_applied(attribute) method as this will the osg::State to
* track the current state more accuratly and enable lazy state updating such
* that only changed state will be applied.*/
void haveAppliedAttribute(StateAttribute::Type type);
/** Get whether the current specified mode is enabled (true) or disabled (false).*/
bool getLastAppliedMode(StateAttribute::GLMode mode) const;
/** Get the current specified attribute, return NULL is one has not yet been applied.*/
const StateAttribute* getLastAppliedAttribute(StateAttribute::Type type) const;
/** texture Mode has been set externally, update state to reflect this setting.*/
void haveAppliedTextureMode(unsigned int unit, StateAttribute::GLMode mode,StateAttribute::GLModeValue value);
/** texture Mode has been set externally, therefore dirty the associated mode in osg::State
* so it is applied on next call to osg::State::apply(..)*/
void haveAppliedTextureMode(unsigned int unit, StateAttribute::GLMode mode);
/** texture Attribute has been applied externally, update state to reflect this setting.*/
void haveAppliedTextureAttribute(unsigned int unit, const StateAttribute* attribute);
/** texture Attribute has been applied externally,
* and therefore this attribute type has been dirtied
* and will need to be re-appplied on next osg::State.apply(..).
* note, if you have an osg::StateAttribute which you have applied externally
* then use the have_applied(attribute) method as this will the osg::State to
* track the current state more accuratly and enable lazy state updating such
* that only changed state will be applied.*/
void haveAppliedTextureAttribute(unsigned int unit, StateAttribute::Type type);
/** Get whether the current specified texture mode is enabled (true) or disabled (false).*/
bool getLastAppliedTextureMode(unsigned int unit, StateAttribute::GLMode mode) const;
/** Get the current specified texture attribute, return NULL is one has not yet been applied.*/
const StateAttribute* getLastAppliedTextureAttribute(unsigned int unit, StateAttribute::Type type) const;
/** disable the vertex, normal, color, tex coords, secenday color, fog coord and index arrays.*/
void disableAllVertexArrays();
/** dirty the vertex, normal, color, tex coords, secenday color, fog coord and index arrays.*/
void dirtyAllVertexArrays();
/** wrapper around glEnableClientState(GL_VERTEX_ARRAY);glVertexPointer(..);
* note, only updates values that change.*/
inline void setVertexPointer( GLint size, GLenum type,
GLsizei stride, const GLvoid *ptr )
{
if (!_vertexArray._enabled || _vertexArray._dirty)
{
_vertexArray._enabled = true;
glEnableClientState(GL_VERTEX_ARRAY);
}
if (_vertexArray._pointer!=ptr || _vertexArray._dirty)
{
_vertexArray._pointer=ptr;
glVertexPointer( size, type, stride, ptr );
}
_vertexArray._dirty = false;
}
/** wrapper glDisableClientState(GL_VERTEX_ARRAY).
* note, only updates values that change.*/
inline void disableVertexPointer()
{
if (_vertexArray._enabled || _vertexArray._dirty)
{
_vertexArray._enabled = false;
_vertexArray._dirty = false;
glDisableClientState(GL_VERTEX_ARRAY);
}
}
inline void dirtyVertexPointer()
{
_vertexArray._dirty = true;
}
/** wrapper around glEnableClientState(GL_NORMAL_ARRAY);glNormalPointer(..);
* note, only updates values that change.*/
inline void setNormalPointer( GLenum type, GLsizei stride,
const GLvoid *ptr )
{
if (!_normalArray._enabled || _normalArray._dirty)
{
_normalArray._enabled = true;
glEnableClientState(GL_NORMAL_ARRAY);
}
if (_normalArray._pointer!=ptr || _normalArray._dirty)
{
_normalArray._pointer=ptr;
glNormalPointer( type, stride, ptr );
}
_normalArray._dirty = false;
}
/** wrapper around glDisableClientState(GL_NORMAL_ARRAY);
* note, only updates values that change.*/
inline void disableNormalPointer()
{
if (_normalArray._enabled || _normalArray._dirty)
{
_normalArray._enabled = false;
_normalArray._dirty = false;
glDisableClientState(GL_NORMAL_ARRAY);
}
}
inline void dirtyNormalPointer()
{
_normalArray._dirty = true;
}
/** wrapper around glEnableClientState(GL_COLOR_ARRAY);glColorPointer(..);
* note, only updates values that change.*/
inline void setColorPointer( GLint size, GLenum type,
GLsizei stride, const GLvoid *ptr )
{
if (!_colorArray._enabled || _colorArray._dirty)
{
_colorArray._enabled = true;
glEnableClientState(GL_COLOR_ARRAY);
}
if (_colorArray._pointer!=ptr || _colorArray._dirty)
{
_colorArray._pointer=ptr;
glColorPointer( size, type, stride, ptr );
}
_colorArray._dirty = false;
}
/** wrapper around glDisableClientState(GL_COLOR_ARRAY);
* note, only updates values that change.*/
inline void disableColorPointer()
{
if (_colorArray._enabled || _colorArray._dirty)
{
_colorArray._enabled = false;
_colorArray._dirty = false;
glDisableClientState(GL_COLOR_ARRAY);
}
}
inline void dirtyColorPointer()
{
_colorArray._dirty = true;
}
/** wrapper around glEnableClientState(GL_SECONDARY_COLOR_ARRAY);glSecondayColorPointer(..);
* note, only updates values that change.*/
void setSecondaryColorPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *ptr );
/** wrapper around glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
* note, only updates values that change.*/
inline void disableSecondaryColorPointer()
{
if (_secondaryColorArray._enabled || _secondaryColorArray._dirty)
{
_secondaryColorArray._enabled = false;
_secondaryColorArray._dirty = false;
glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
}
}
inline void dirtySecondaryColorPointer()
{
_secondaryColorArray._dirty = true;
}
/** wrapper around glEnableClientState(GL_INDEX_ARRAY);glIndexPointer(..);
* note, only updates values that change.*/
inline void setIndexPointer( GLenum type, GLsizei stride,
const GLvoid *ptr )
{
if (!_indexArray._enabled || _indexArray._dirty)
{
_indexArray._enabled = true;
glEnableClientState(GL_INDEX_ARRAY);
}
if (_indexArray._pointer!=ptr || _indexArray._dirty)
{
_indexArray._pointer=ptr;
glIndexPointer( type, stride, ptr );
}
_indexArray._dirty = false;
}
/** wrapper around glDisableClientState(GL_INDEX_ARRAY);
* note, only updates values that change.*/
inline void disableIndexPointer()
{
if (_indexArray._enabled || _indexArray._dirty)
{
_indexArray._enabled = false;
_indexArray._dirty = false;
glDisableClientState(GL_INDEX_ARRAY);
}
}
inline void dirtyIndexPointer()
{
_indexArray._dirty = true;
}
/** wrapper around glEnableClientState(GL_FOG_COORDINATE_ARRAY);glFogCoordPointer(..);
* note, only updates values that change.*/
void setFogCoordPointer( GLenum type, GLsizei stride, const GLvoid *ptr );
/** wrapper around glDisableClientState(GL_FOG_COORDINATE_ARRAY);
* note, only updates values that change.*/
inline void disableFogCoordPointer()
{
if (_fogArray._enabled || _fogArray._dirty)
{
_fogArray._enabled = false;
_fogArray._dirty = false;
glDisableClientState(GL_FOG_COORDINATE_ARRAY);
}
}
inline void dirtyFogCoordPointer()
{
_fogArray._dirty = true;
}
/** wrapper around glEnableClientState(GL_TEXTURE_COORD_ARRAY);glTexCoordPointer(..);
* note, only updates values that change.*/
inline void setTexCoordPointer( unsigned int unit,
GLint size, GLenum type,
GLsizei stride, const GLvoid *ptr )
{
if (setClientActiveTextureUnit(unit))
{
if ( unit >= _texCoordArrayList.size()) _texCoordArrayList.resize(unit+1);
EnabledArrayPair& eap = _texCoordArrayList[unit];
if (!eap._enabled || eap._dirty)
{
eap._enabled = true;
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
if (eap._pointer!=ptr || eap._dirty)
{
glTexCoordPointer( size, type, stride, ptr );
eap._pointer = ptr;
}
eap._dirty = false;
}
}
/** wrapper around glDisableClientState(GL_TEXTURE_COORD_ARRAY);
* note, only updates values that change.*/
inline void disableTexCoordPointer( unsigned int unit )
{
if (setClientActiveTextureUnit(unit))
{
if ( unit >= _texCoordArrayList.size()) _texCoordArrayList.resize(unit+1);
EnabledArrayPair& eap = _texCoordArrayList[unit];
if (eap._enabled || eap._dirty)
{
eap._enabled = false;
eap._dirty = false;
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
}
}
inline void dirtyTexCoordPointer( unsigned int unit )
{
if ( unit >= _texCoordArrayList.size()) return; // _texCoordArrayList.resize(unit+1);
EnabledArrayPair& eap = _texCoordArrayList[unit];
eap._dirty = true;
}
inline void disableTexCoordPointersAboveAndIncluding( unsigned int unit )
{
while (unit<_texCoordArrayList.size())
{
EnabledArrayPair& eap = _texCoordArrayList[unit];
if (eap._enabled || eap._dirty)
{
if (setClientActiveTextureUnit(unit))
{
eap._enabled = false;
eap._dirty = false;
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
}
++unit;
}
}
inline void dirtyTexCoordPointersAboveAndIncluding( unsigned int unit )
{
while (unit<_texCoordArrayList.size())
{
EnabledArrayPair& eap = _texCoordArrayList[unit];
eap._dirty = true;
++unit;
}
}
/** set the current tex coord array texture unit, return true if selected, false if selection failed such as when multitexturing is not supported.
* note, only updates values that change.*/
2002-07-12 05:08:02 +08:00
bool setClientActiveTextureUnit( unsigned int unit );
/** set the current texture unit, return true if selected, false if selection failed such as when multitexturing is not supported.
* note, only updates values that change.*/
2002-07-12 05:08:02 +08:00
bool setActiveTextureUnit( unsigned int unit );
/** Set the current OpenGL context uniqueID.
Note, it is the application developers responsibility to
set up unique ID for each OpenGL context. This value is
then used by osg::StateAttribure's and osg::Drawable's to
help manage OpenGL display list and texture binds appropriate
for each context.*/
inline void setContextID(unsigned int contextID) { _contextID=contextID; }
/** Get the current OpenGL context unique ID.*/
inline unsigned int getContextID() const { return _contextID; }
2001-09-22 10:42:08 +08:00
/** Set the frame stamp for the current frame.*/
inline void setFrameStamp(FrameStamp* fs) { _frameStamp = fs; }
/** Set the frame stamp for the current frame.*/
inline const FrameStamp* getFrameStamp() const { return _frameStamp.get(); }
/** Set the DisplaySettings. Note, nothing is applied, the visual settings are just used
* used in the State object to pass the current visual settings to Drawables
* during rendering. */
inline void setDisplaySettings(DisplaySettings* vs) { _displaySettings = vs; }
/** Get the DisplaySettings */
inline const DisplaySettings* getDisplaySettings() const { return _displaySettings.get(); }
typedef std::pair<const StateAttribute*,StateAttribute::OverrideValue> AttributePair;
typedef std::vector<AttributePair> AttributeVec;
typedef std::vector<StateAttribute::GLModeValue> ValueVec;
private:
unsigned int _contextID;
ref_ptr<FrameStamp> _frameStamp;
ref_ptr<const Matrix> _identity;
ref_ptr<const Matrix> _projection;
ref_ptr<const Matrix> _modelView;
ref_ptr<DisplaySettings> _displaySettings;
struct ModeStack
{
ModeStack()
{
changed = false;
last_applied_value = false;
global_default_value = false;
}
bool changed;
bool last_applied_value;
bool global_default_value;
ValueVec valueVec;
};
struct AttributeStack
{
AttributeStack()
{
changed = false;
last_applied_attribute = 0L;
global_default_attribute = 0L;
}
/** apply an attribute if required, passing in attribute and appropriate attribute stack */
bool changed;
const StateAttribute* last_applied_attribute;
ref_ptr<StateAttribute> global_default_attribute;
AttributeVec attributeVec;
};
/** apply an OpenGL mode if required, passing in mode, enable flag and appropriate mode stack */
inline bool applyMode(StateAttribute::GLMode mode,bool enabled,ModeStack& ms)
{
if (ms.last_applied_value != enabled)
{
ms.last_applied_value = enabled;
if (enabled) glEnable(mode);
else glDisable(mode);
return true;
}
else
return false;
}
/** apply an attribute if required, passing in attribute and appropriate attribute stack */
inline bool applyAttribute(const StateAttribute* attribute,AttributeStack& as)
{
if (as.last_applied_attribute != attribute)
{
if (!as.global_default_attribute.valid()) as.global_default_attribute = dynamic_cast<StateAttribute*>(attribute->cloneType());
as.last_applied_attribute = attribute;
attribute->apply(*this);
return true;
}
else
return false;
}
inline bool applyGlobalDefaultAttribute(AttributeStack& as)
{
if (as.last_applied_attribute != as.global_default_attribute.get())
{
as.last_applied_attribute = as.global_default_attribute.get();
if (as.global_default_attribute.valid()) as.global_default_attribute->apply(*this);
return true;
}
else
return false;
}
typedef std::map<StateAttribute::GLMode,ModeStack> ModeMap;
typedef std::vector<ModeMap> TextureModeMapList;
typedef std::map<StateAttribute::Type,AttributeStack> AttributeMap;
typedef std::vector<AttributeMap> TextureAttributeMapList;
typedef std::vector<ref_ptr<const StateSet> > StateSetStack;
typedef std::vector<ref_ptr<const Matrix> > MatrixStack;
ModeMap _modeMap;
AttributeMap _attributeMap;
TextureModeMapList _textureModeMapList;
TextureAttributeMapList _textureAttributeMapList;
StateSetStack _drawStateStack;
struct EnabledArrayPair
{
EnabledArrayPair():_dirty(true),_enabled(false),_pointer(0) {}
EnabledArrayPair(const EnabledArrayPair& eap):_dirty(eap._dirty), _enabled(eap._enabled),_pointer(eap._pointer) {}
EnabledArrayPair& operator = (const EnabledArrayPair& eap) { _dirty=eap._dirty; _enabled=eap._enabled; _pointer=eap._pointer; return *this; }
bool _dirty;
bool _enabled;
const GLvoid* _pointer;
};
typedef std::vector<EnabledArrayPair> EnabledTexCoordArrayList;
EnabledArrayPair _vertexArray;
EnabledArrayPair _normalArray;
EnabledArrayPair _colorArray;
EnabledArrayPair _secondaryColorArray;
EnabledArrayPair _indexArray;
EnabledArrayPair _fogArray;
EnabledTexCoordArrayList _texCoordArrayList;
unsigned int _currentActiveTextureUnit;
unsigned int _currentClientActiveTextureUnit;
2001-09-22 10:42:08 +08:00
inline ModeMap& getOrCreateTextureModeMap(unsigned int unit)
{
if (unit>=_textureModeMapList.size()) _textureModeMapList.resize(unit+1);
return _textureModeMapList[unit];
}
inline AttributeMap& getOrCreateTextureAttributeMap(unsigned int unit)
{
if (unit>=_textureAttributeMapList.size()) _textureAttributeMapList.resize(unit+1);
return _textureAttributeMapList[unit];
}
inline void pushModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
inline void pushAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
inline void popModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
inline void popAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
inline void applyModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
inline void applyAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
inline void applyModeMap(ModeMap& modeMap);
inline void applyAttributeMap(AttributeMap& attributeMap);
void haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode,StateAttribute::GLModeValue value);
void haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode);
void haveAppliedAttribute(AttributeMap& attributeMap,const StateAttribute* attribute);
void haveAppliedAttribute(AttributeMap& attributeMap,StateAttribute::Type type);
bool getLastAppliedMode(const ModeMap& modeMap,StateAttribute::GLMode mode) const;
const StateAttribute* getLastAppliedAttribute(const AttributeMap& attributeMap,StateAttribute::Type type) const;
2001-01-11 00:32:10 +08:00
};
inline void State::pushModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
{
for(StateSet::ModeList::const_iterator mitr=modeList.begin();
mitr!=modeList.end();
++mitr)
{
// get the mode stack for incomming GLmode {mitr->first}.
ModeStack& ms = modeMap[mitr->first];
if (ms.valueVec.empty())
{
// first pair so simply push incomming pair to back.
ms.valueVec.push_back(mitr->second);
}
else if ((ms.valueVec.back() & StateAttribute::OVERRIDE) && !(mitr->second & StateAttribute::PROTECTED)) // check the existing override flag
{
// push existing back since override keeps the previoius value.
ms.valueVec.push_back(ms.valueVec.back());
}
else
{
// no override on so simply push incomming pair to back.
ms.valueVec.push_back(mitr->second);
}
ms.changed = true;
}
}
inline void State::pushAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
{
for(StateSet::AttributeList::const_iterator aitr=attributeList.begin();
aitr!=attributeList.end();
++aitr)
{
// get the attribute stack for incomming type {aitr->first}.
AttributeStack& as = attributeMap[aitr->first];
if (as.attributeVec.empty())
{
// first pair so simply push incomming pair to back.
as.attributeVec.push_back(
AttributePair(aitr->second.first.get(),aitr->second.second));
}
else if ((as.attributeVec.back().second & StateAttribute::OVERRIDE) && !(aitr->second.second & StateAttribute::PROTECTED)) // check the existing override flag
{
// push existing back since override keeps the previoius value.
as.attributeVec.push_back(as.attributeVec.back());
}
else
{
// no override on so simply push incomming pair to back.
as.attributeVec.push_back(
AttributePair(aitr->second.first.get(),aitr->second.second));
}
as.changed = true;
}
}
inline void State::popModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
{
for(StateSet::ModeList::const_iterator mitr=modeList.begin();
mitr!=modeList.end();
++mitr)
{
// get the mode stack for incomming GLmode {mitr->first}.
ModeStack& ms = modeMap[mitr->first];
if (!ms.valueVec.empty())
{
ms.valueVec.pop_back();
}
ms.changed = true;
}
}
inline void State::popAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
{
for(StateSet::AttributeList::const_iterator aitr=attributeList.begin();
aitr!=attributeList.end();
++aitr)
{
// get the attribute stack for incomming type {aitr->first}.
AttributeStack& as = attributeMap[aitr->first];
if (!as.attributeVec.empty())
{
as.attributeVec.pop_back();
}
as.changed = true;
}
}
inline void State::applyModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
{
StateSet::ModeList::const_iterator ds_mitr = modeList.begin();
ModeMap::iterator this_mitr=modeMap.begin();
while (this_mitr!=modeMap.end() && ds_mitr!=modeList.end())
{
if (this_mitr->first<ds_mitr->first)
{
// note GLMode = this_mitr->first
ModeStack& ms = this_mitr->second;
if (ms.changed)
{
ms.changed = false;
if (!ms.valueVec.empty())
{
bool new_value = ms.valueVec.back() & StateAttribute::ON;
applyMode(this_mitr->first,new_value,ms);
}
else
{
// assume default of disabled.
applyMode(this_mitr->first,ms.global_default_value,ms);
}
}
++this_mitr;
}
else if (ds_mitr->first<this_mitr->first)
{
// ds_mitr->first is a new mode, therefore
// need to insert a new mode entry for ds_mistr->first.
ModeStack& ms = modeMap[ds_mitr->first];
bool new_value = ds_mitr->second & StateAttribute::ON;
applyMode(ds_mitr->first,new_value,ms);
// will need to disable this mode on next apply so set it to changed.
ms.changed = true;
++ds_mitr;
}
else
{
// this_mitr & ds_mitr refer to the same mode, check the overide
// if any otherwise just apply the incomming mode.
ModeStack& ms = this_mitr->second;
if (!ms.valueVec.empty() && (ms.valueVec.back() & StateAttribute::OVERRIDE) && !(ds_mitr->second & StateAttribute::PROTECTED))
{
// override is on, there just treat as a normal apply on modes.
if (ms.changed)
{
ms.changed = false;
bool new_value = ms.valueVec.back() & StateAttribute::ON;
applyMode(this_mitr->first,new_value,ms);
}
}
else
{
// no override on or no previous entry, therefore consider incomming mode.
bool new_value = ds_mitr->second & StateAttribute::ON;
if (applyMode(ds_mitr->first,new_value,ms))
{
ms.changed = true;
}
}
++this_mitr;
++ds_mitr;
}
}
// iterator over the remaining state modes to apply any previous changes.
for(;
this_mitr!=modeMap.end();
++this_mitr)
{
// note GLMode = this_mitr->first
ModeStack& ms = this_mitr->second;
if (ms.changed)
{
ms.changed = false;
if (!ms.valueVec.empty())
{
bool new_value = ms.valueVec.back() & StateAttribute::ON;
applyMode(this_mitr->first,new_value,ms);
}
else
{
// assume default of disabled.
applyMode(this_mitr->first,ms.global_default_value,ms);
}
}
}
// iterator over the remaining incomming modes to apply any new mode.
for(;
ds_mitr!=modeList.end();
++ds_mitr)
{
ModeStack& ms = modeMap[ds_mitr->first];
bool new_value = ds_mitr->second & StateAttribute::ON;
applyMode(ds_mitr->first,new_value,ms);
// will need to disable this mode on next apply so set it to changed.
ms.changed = true;
}
}
inline void State::applyAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
{
StateSet::AttributeList::const_iterator ds_aitr=attributeList.begin();
AttributeMap::iterator this_aitr=attributeMap.begin();
while (this_aitr!=attributeMap.end() && ds_aitr!=attributeList.end())
{
if (this_aitr->first<ds_aitr->first)
{
// note attribute type = this_aitr->first
AttributeStack& as = this_aitr->second;
if (as.changed)
{
as.changed = false;
if (!as.attributeVec.empty())
{
const StateAttribute* new_attr = as.attributeVec.back().first;
applyAttribute(new_attr,as);
}
else
{
applyGlobalDefaultAttribute(as);
}
}
++this_aitr;
}
else if (ds_aitr->first<this_aitr->first)
{
// ds_mitr->first is a new attribute, therefore
// need to insert a new attribute entry for ds_aistr->first.
AttributeStack& as = attributeMap[ds_aitr->first];
const StateAttribute* new_attr = ds_aitr->second.first.get();
applyAttribute(new_attr,as);
// will need to disable this mode on next apply so set it to changed.
as.changed = true;
++ds_aitr;
}
else
{
// this_mitr & ds_mitr refer to the same attribute, check the overide
// if any otherwise just apply the incomming attribute
AttributeStack& as = this_aitr->second;
if (!as.attributeVec.empty() && (as.attributeVec.back().second & StateAttribute::OVERRIDE) && !(ds_aitr->second.second & StateAttribute::PROTECTED))
{
// override is on, there just treat as a normal apply on modes.
if (as.changed)
{
as.changed = false;
const StateAttribute* new_attr = as.attributeVec.back().first;
applyAttribute(new_attr,as);
}
}
else
{
// no override on or no previous entry, therefore consider incomming mode.
const StateAttribute* new_attr = ds_aitr->second.first.get();
if (applyAttribute(new_attr,as))
{
as.changed = true;
}
}
++this_aitr;
++ds_aitr;
}
}
// iterator over the remaining state modes to apply any previous changes.
for(;
this_aitr!=attributeMap.end();
++this_aitr)
{
// note attribute type = this_aitr->first
AttributeStack& as = this_aitr->second;
if (as.changed)
{
as.changed = false;
if (!as.attributeVec.empty())
{
const StateAttribute* new_attr = as.attributeVec.back().first;
applyAttribute(new_attr,as);
}
else
{
applyGlobalDefaultAttribute(as);
}
}
}
// iterator over the remaining incomming modes to apply any new mode.
for(;
ds_aitr!=attributeList.end();
++ds_aitr)
{
// ds_mitr->first is a new attribute, therefore
// need to insert a new attribute entry for ds_aistr->first.
AttributeStack& as = attributeMap[ds_aitr->first];
const StateAttribute* new_attr = ds_aitr->second.first.get();
applyAttribute(new_attr,as);
// will need to update this attribute on next apply so set it to changed.
as.changed = true;
}
}
inline void State::applyModeMap(ModeMap& modeMap)
{
for(ModeMap::iterator mitr=modeMap.begin();
mitr!=modeMap.end();
++mitr)
{
// note GLMode = mitr->first
ModeStack& ms = mitr->second;
if (ms.changed)
{
ms.changed = false;
if (!ms.valueVec.empty())
{
bool new_value = ms.valueVec.back() & StateAttribute::ON;
applyMode(mitr->first,new_value,ms);
}
else
{
// assume default of disabled.
applyMode(mitr->first,ms.global_default_value,ms);
}
}
}
}
inline void State::applyAttributeMap(AttributeMap& attributeMap)
{
for(AttributeMap::iterator aitr=attributeMap.begin();
aitr!=attributeMap.end();
++aitr)
{
AttributeStack& as = aitr->second;
if (as.changed)
{
as.changed = false;
if (!as.attributeVec.empty())
{
const StateAttribute* new_attr = as.attributeVec.back().first;
applyAttribute(new_attr,as);
}
else
{
applyGlobalDefaultAttribute(as);
}
}
}
}
}
2001-01-11 00:32:10 +08:00
#endif