2001-10-04 23:12:57 +08:00
|
|
|
//C++ header - Open Scene Graph - Copyright (C) 1998-2001 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>
|
2001-09-20 05:08:56 +08:00
|
|
|
#include <osg/StateSet>
|
|
|
|
#include <osg/Matrix>
|
|
|
|
|
2001-09-22 10:42:08 +08:00
|
|
|
#include <osg/FrameStamp>
|
2001-12-22 06:48:19 +08:00
|
|
|
#include <osg/DisplaySettings>
|
2002-06-03 23:39:41 +08:00
|
|
|
#include <osg/Polytope>
|
2001-09-22 10:42:08 +08:00
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
#include <vector>
|
|
|
|
#include <map>
|
2001-01-11 00:32:10 +08:00
|
|
|
|
|
|
|
namespace osg {
|
|
|
|
|
2001-09-20 05:08:56 +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.
|
2001-10-01 19:15:55 +08:00
|
|
|
* Lazy state updating is used to minimize state changes.
|
2001-09-20 05:08:56 +08:00
|
|
|
*/
|
|
|
|
class SG_EXPORT State : public Referenced
|
2001-01-11 00:32:10 +08:00
|
|
|
{
|
|
|
|
public :
|
2001-09-20 05:08:56 +08:00
|
|
|
|
|
|
|
State();
|
|
|
|
|
|
|
|
virtual ~State();
|
|
|
|
|
|
|
|
/** push stateset onto state stack.*/
|
|
|
|
void pushStateSet(const StateSet* dstate);
|
|
|
|
|
|
|
|
/** pop drawstate off state stack.*/
|
|
|
|
void popStateSet();
|
|
|
|
|
2001-10-23 06:02:47 +08:00
|
|
|
/** copy the modes and attributes which captures the current state.*/
|
|
|
|
void captureCurrentState(StateSet& stateset) const;
|
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
/** reset the state object to an empty stack.*/
|
|
|
|
void reset();
|
|
|
|
|
2002-03-30 01:26:40 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-06-03 23:39:41 +08:00
|
|
|
Polytope getViewFrustum() const;
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2002-05-21 16:59:26 +08:00
|
|
|
|
|
|
|
/** Apply stateset.*/
|
2001-09-20 05:08:56 +08:00
|
|
|
void apply(const StateSet* dstate);
|
|
|
|
|
2002-05-21 16:59:26 +08:00
|
|
|
/** Apply the state.*/
|
2001-09-20 05:08:56 +08:00
|
|
|
void apply();
|
2002-05-21 16:59:26 +08:00
|
|
|
|
|
|
|
|
|
|
|
/** Apply an OpenGL mode if required. */
|
|
|
|
inline const bool applyMode(const StateAttribute::GLMode mode,const bool enabled)
|
|
|
|
{
|
2002-05-22 18:04:28 +08:00
|
|
|
ModeStack& ms = _modeMap[mode];
|
|
|
|
ms.changed = true;
|
|
|
|
return applyMode(mode,enabled,ms);
|
2002-05-21 16:59:26 +08:00
|
|
|
}
|
|
|
|
|
2002-07-07 22:40:41 +08:00
|
|
|
inline const bool applyTextureMode(unsigned int unit, const StateAttribute::GLMode mode,const bool enabled)
|
|
|
|
{
|
2002-07-09 17:35:42 +08:00
|
|
|
ModeMap& modeMap = getOrCreateTextureModeMap(unit);
|
2002-07-07 22:40:41 +08:00
|
|
|
ModeStack& ms = modeMap[mode];
|
2002-07-09 17:35:42 +08:00
|
|
|
ms.changed = true;
|
2002-07-07 22:40:41 +08:00
|
|
|
return applyMode(mode,enabled,ms);
|
|
|
|
}
|
2002-05-21 16:59:26 +08:00
|
|
|
|
|
|
|
/** Apply an attribute if required. */
|
|
|
|
inline const bool applyAttribute(const StateAttribute* attribute)
|
|
|
|
{
|
2002-05-22 18:04:28 +08:00
|
|
|
AttributeStack& as = _attributeMap[attribute->getType()];
|
|
|
|
as.changed = true;
|
|
|
|
return applyAttribute(attribute,as);
|
2002-05-21 16:59:26 +08:00
|
|
|
}
|
|
|
|
|
2002-07-07 22:40:41 +08:00
|
|
|
inline const bool applyTextureAttribute(unsigned int unit, const StateAttribute* attribute)
|
|
|
|
{
|
2002-07-09 17:35:42 +08:00
|
|
|
AttributeMap& attributeMap = getOrCreateTextureAttributeMap(unit);
|
2002-07-07 22:40:41 +08:00
|
|
|
AttributeStack& as = attributeMap[attribute->getType()];
|
|
|
|
as.changed = true;
|
|
|
|
return applyAttribute(attribute,as);
|
|
|
|
}
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2002-05-21 16:59:26 +08:00
|
|
|
/** Mode has been set externally, update state to reflect this setting.*/
|
2002-03-21 20:36:05 +08:00
|
|
|
void haveAppliedMode(const StateAttribute::GLMode mode,const StateAttribute::GLModeValue value);
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2002-05-21 16:59:26 +08:00
|
|
|
/** Mode has been set externally, therefore dirty the associated mode in osg::State
|
2002-03-21 20:00:10 +08:00
|
|
|
* so it is applied on next call to osg::State::apply(..)*/
|
2002-03-21 20:36:05 +08:00
|
|
|
void haveAppliedMode(const StateAttribute::GLMode mode);
|
2002-03-21 20:00:10 +08:00
|
|
|
|
2002-05-21 16:59:26 +08:00
|
|
|
/** Attribute has been applied externally, update state to reflect this setting.*/
|
2002-03-21 20:36:05 +08:00
|
|
|
void haveAppliedAttribute(const StateAttribute* attribute);
|
2002-03-21 20:00:10 +08:00
|
|
|
|
2002-05-21 16:59:26 +08:00
|
|
|
/** Attribute has been applied externally,
|
2002-03-21 20:00:10 +08:00
|
|
|
* 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.*/
|
2002-03-21 20:36:05 +08:00
|
|
|
void haveAppliedAttribute(const StateAttribute::Type type);
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2002-05-21 16:59:26 +08:00
|
|
|
/** Get whether the current specified mode is enabled (true) or disabled (false).*/
|
2002-05-21 17:16:31 +08:00
|
|
|
const bool getLastAppliedMode(const StateAttribute::GLMode mode) const;
|
2002-05-21 16:59:26 +08:00
|
|
|
|
|
|
|
/** Get the current specified attribute, return NULL is one has not yet been applied.*/
|
2002-05-21 17:16:31 +08:00
|
|
|
const StateAttribute* getLastAppliedAttribute(const StateAttribute::Type type) const;
|
2002-07-07 22:40:41 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** texture Mode has been set externally, update state to reflect this setting.*/
|
|
|
|
void haveAppliedTextureMode(unsigned int unit, const StateAttribute::GLMode mode,const 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, const 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, const StateAttribute::Type type);
|
|
|
|
|
|
|
|
/** Get whether the current specified texture mode is enabled (true) or disabled (false).*/
|
|
|
|
const bool getLastAppliedTextureMode(unsigned int unit, const 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, const StateAttribute::Type type) const;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** 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._enabled = true;
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
}
|
|
|
|
if (_vertexArray._pointer!=ptr)
|
|
|
|
{
|
|
|
|
_vertexArray._pointer=ptr;
|
|
|
|
glVertexPointer( size, type, stride, ptr );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** wrapper glDisableClientState(GL_VERTEX_ARRAY).
|
|
|
|
* note, only updates values that change.*/
|
|
|
|
inline void disableVertexPointer()
|
|
|
|
{
|
|
|
|
if (_vertexArray._enabled)
|
|
|
|
{
|
|
|
|
_vertexArray._enabled = false;
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** 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._enabled = true;
|
|
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
|
|
}
|
|
|
|
if (_normalArray._pointer!=ptr)
|
|
|
|
{
|
|
|
|
_normalArray._pointer=ptr;
|
|
|
|
glNormalPointer( type, stride, ptr );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** wrapper around glDisableClientState(GL_NORMAL_ARRAY);
|
|
|
|
* note, only updates values that change.*/
|
|
|
|
inline void disableNormalPointer()
|
|
|
|
{
|
|
|
|
if (_normalArray._enabled)
|
|
|
|
{
|
|
|
|
_normalArray._enabled = false;
|
|
|
|
glDisableClientState(GL_NORMAL_ARRAY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** 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._enabled = true;
|
|
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
|
|
|
}
|
|
|
|
if (_colorArray._pointer!=ptr)
|
|
|
|
{
|
|
|
|
_colorArray._pointer=ptr;
|
|
|
|
glColorPointer( size, type, stride, ptr );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** wrapper around glDisableClientState(GL_COLOR_ARRAY);
|
|
|
|
* note, only updates values that change.*/
|
|
|
|
inline void disableColorPointer()
|
|
|
|
{
|
|
|
|
if (_colorArray._enabled)
|
|
|
|
{
|
|
|
|
_colorArray._enabled = false;
|
|
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** 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._enabled = true;
|
|
|
|
glEnableClientState(GL_INDEX_ARRAY);
|
|
|
|
}
|
|
|
|
if (_indexArray._pointer!=ptr)
|
|
|
|
{
|
|
|
|
_indexArray._pointer=ptr;
|
|
|
|
glIndexPointer( type, stride, ptr );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** wrapper around glDisableClientState(GL_INDEX_ARRAY);
|
|
|
|
* note, only updates values that change.*/
|
|
|
|
inline void disableIndexPointer()
|
|
|
|
{
|
|
|
|
//if (_indexArray._enabled)
|
|
|
|
{
|
|
|
|
_indexArray._enabled = false;
|
|
|
|
glDisableClientState(GL_INDEX_ARRAY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** 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._enabled = true;
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
}
|
|
|
|
if (eap._pointer!=ptr)
|
|
|
|
{
|
|
|
|
glTexCoordPointer( size, type, stride, ptr );
|
|
|
|
eap._pointer = ptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** wrapper around glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
* note, only updates values that change.*/
|
|
|
|
inline void disableTexCoordPointer( unsigned int unit )
|
|
|
|
{
|
|
|
|
if (setClientActiveTextureUnit(unit))
|
|
|
|
{
|
2002-07-11 19:33:06 +08:00
|
|
|
if ( unit >= _texCoordArrayList.size()) _texCoordArrayList.resize(unit+1);
|
2002-07-07 22:40:41 +08:00
|
|
|
EnabledArrayPair& eap = _texCoordArrayList[unit];
|
|
|
|
|
|
|
|
if (eap._enabled)
|
|
|
|
{
|
|
|
|
eap._enabled = false;
|
|
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 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.*/
|
|
|
|
inline bool setClientActiveTextureUnit( unsigned int unit )
|
|
|
|
{
|
|
|
|
return unit==0;
|
|
|
|
// will need to check for extensions etc.
|
|
|
|
// if (unit!=_currentClientActiveTextureUnit)
|
|
|
|
// {
|
|
|
|
// glClientActiveTextureARB(GL_TEXTURE0_ARB+unit);
|
|
|
|
// _currentClientActiveTextureUnit = unit;
|
|
|
|
// }
|
|
|
|
// return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 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.*/
|
|
|
|
inline bool setActiveTextureUnit( unsigned int unit )
|
|
|
|
{
|
|
|
|
return unit==0;
|
|
|
|
//
|
|
|
|
// if (unit!=_currentActiveTextureUnit)
|
|
|
|
// {
|
|
|
|
// glActiveTextureARB(GL_TEXTURE0_ARB+unit);
|
|
|
|
// _currentActiveTextureUnit = unit;
|
|
|
|
// }
|
|
|
|
// return true;
|
|
|
|
}
|
|
|
|
|
2002-05-21 16:59:26 +08:00
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
|
|
|
|
/** Set the current OpenGL context uniqueID.
|
2001-10-01 19:15:55 +08:00
|
|
|
Note, it is the application developers responsibility to
|
2001-09-20 05:08:56 +08:00
|
|
|
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 const 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(); }
|
|
|
|
|
2002-03-30 01:26:40 +08:00
|
|
|
|
2001-12-22 06:48:19 +08:00
|
|
|
/** Set the DisplaySettings. Note, nothing is applied, the visual settings are just used
|
2001-12-19 08:38:23 +08:00
|
|
|
* used in the State object to pass the current visual settings to Drawables
|
|
|
|
* during rendering. */
|
2001-12-22 06:48:19 +08:00
|
|
|
inline void setDisplaySettings(DisplaySettings* vs) { _displaySettings = vs; }
|
2001-12-19 08:38:23 +08:00
|
|
|
|
2001-12-22 06:48:19 +08:00
|
|
|
/** Get the DisplaySettings */
|
|
|
|
inline const DisplaySettings* getDisplaySettings() const { return _displaySettings.get(); }
|
2001-12-19 08:38:23 +08:00
|
|
|
|
2002-03-19 05:56:00 +08:00
|
|
|
typedef std::pair<const StateAttribute*,StateAttribute::OverrideValue> AttributePair;
|
|
|
|
typedef std::vector<AttributePair> AttributeVec;
|
|
|
|
typedef std::vector<StateAttribute::GLModeValue> ValueVec;
|
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
private:
|
2002-03-19 05:56:00 +08:00
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2001-12-19 08:38:23 +08:00
|
|
|
unsigned int _contextID;
|
|
|
|
ref_ptr<FrameStamp> _frameStamp;
|
2002-03-30 01:26:40 +08:00
|
|
|
|
|
|
|
ref_ptr<const Matrix> _identity;
|
|
|
|
ref_ptr<const Matrix> _projection;
|
|
|
|
ref_ptr<const Matrix> _modelView;
|
|
|
|
|
2001-12-22 06:48:19 +08:00
|
|
|
ref_ptr<DisplaySettings> _displaySettings;
|
2001-09-20 05:08:56 +08:00
|
|
|
|
|
|
|
|
|
|
|
struct ModeStack
|
|
|
|
{
|
|
|
|
ModeStack()
|
|
|
|
{
|
|
|
|
changed = false;
|
|
|
|
last_applied_value = false;
|
2001-10-15 22:07:54 +08:00
|
|
|
global_default_value = false;
|
2001-09-20 05:08:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool changed;
|
|
|
|
bool last_applied_value;
|
2001-10-15 22:07:54 +08:00
|
|
|
bool global_default_value;
|
2001-09-20 05:08:56 +08:00
|
|
|
ValueVec valueVec;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct AttributeStack
|
|
|
|
{
|
|
|
|
AttributeStack()
|
|
|
|
{
|
|
|
|
changed = false;
|
|
|
|
last_applied_attribute = 0L;
|
2001-10-15 22:07:54 +08:00
|
|
|
global_default_attribute = 0L;
|
2001-09-20 05:08:56 +08:00
|
|
|
}
|
|
|
|
|
2001-10-15 22:07:54 +08:00
|
|
|
/** apply an attribute if required, passing in attribute and appropriate attribute stack */
|
2001-09-20 05:08:56 +08:00
|
|
|
bool changed;
|
|
|
|
const StateAttribute* last_applied_attribute;
|
2001-10-15 22:29:40 +08:00
|
|
|
ref_ptr<StateAttribute> global_default_attribute;
|
2001-09-20 05:08:56 +08:00
|
|
|
AttributeVec attributeVec;
|
|
|
|
};
|
|
|
|
|
|
|
|
/** apply an OpenGL mode if required, passing in mode, enable flag and appropriate mode stack */
|
2002-03-21 20:36:05 +08:00
|
|
|
inline const bool applyMode(const StateAttribute::GLMode mode,const bool enabled,ModeStack& ms)
|
2001-09-20 05:08:56 +08:00
|
|
|
{
|
|
|
|
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 */
|
2002-03-21 20:36:05 +08:00
|
|
|
inline const bool applyAttribute(const StateAttribute* attribute,AttributeStack& as)
|
2001-09-20 05:08:56 +08:00
|
|
|
{
|
|
|
|
if (as.last_applied_attribute != attribute)
|
|
|
|
{
|
Added support for shallow and deep copy of nodes, drawables and state, via a
copy constructor which takes an optional Cloner object, and the old
osg::Object::clone() has changed so that it now requires a Cloner as paramter.
This is passed on to the copy constructor to help control the shallow vs
deep copying. The old functionality of clone() which was clone of type has
been renamed to cloneType().
Updated all of the OSG to work with these new conventions, implemention all
the required copy constructors etc. A couple of areas will do shallow
copies by design, a couple of other still need to be updated to do either
shallow or deep.
Neither of the shallow or deep copy operations have been tested yet, only
the old functionality of the OSG has been checked so far, such running the
viewer on various demo datasets.
Also fixed a problem in osg::Optimize::RemoveRendundentNodesVisitor which
was not checking that Group didn't have have any attached StateSet's, Callbacks
or UserData. These checks have now been added, which fixes a bug which was
revealled by the new osgscribe demo, this related to removal of group acting
as state decorator.
method
2002-01-29 05:17:01 +08:00
|
|
|
if (!as.global_default_attribute.valid()) as.global_default_attribute = dynamic_cast<StateAttribute*>(attribute->cloneType());
|
2001-10-15 22:07:54 +08:00
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
as.last_applied_attribute = attribute;
|
|
|
|
attribute->apply(*this);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2002-03-21 20:36:05 +08:00
|
|
|
inline const bool applyGlobalDefaultAttribute(AttributeStack& as)
|
2001-10-15 22:07:54 +08:00
|
|
|
{
|
2001-10-15 22:29:40 +08:00
|
|
|
if (as.last_applied_attribute != as.global_default_attribute.get())
|
2001-10-15 22:07:54 +08:00
|
|
|
{
|
2001-10-15 22:29:40 +08:00
|
|
|
as.last_applied_attribute = as.global_default_attribute.get();
|
|
|
|
if (as.global_default_attribute.valid()) as.global_default_attribute->apply(*this);
|
2001-10-15 22:07:54 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2002-07-09 17:35:42 +08:00
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
typedef std::map<StateAttribute::GLMode,ModeStack> ModeMap;
|
2002-07-07 22:40:41 +08:00
|
|
|
typedef std::vector<ModeMap> TextureModeMapList;
|
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
typedef std::map<StateAttribute::Type,AttributeStack> AttributeMap;
|
2002-07-07 22:40:41 +08:00
|
|
|
typedef std::vector<AttributeMap> TextureAttributeMapList;
|
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
typedef std::vector<ref_ptr<const StateSet> > StateSetStack;
|
|
|
|
typedef std::vector<ref_ptr<const Matrix> > MatrixStack;
|
|
|
|
|
2002-07-07 22:40:41 +08:00
|
|
|
ModeMap _modeMap;
|
|
|
|
AttributeMap _attributeMap;
|
2002-07-09 17:35:42 +08:00
|
|
|
|
2002-07-07 22:40:41 +08:00
|
|
|
TextureModeMapList _textureModeMapList;
|
|
|
|
TextureAttributeMapList _textureAttributeMapList;
|
2002-07-09 17:35:42 +08:00
|
|
|
|
2002-07-07 22:40:41 +08:00
|
|
|
StateSetStack _drawStateStack;
|
|
|
|
|
|
|
|
struct EnabledArrayPair
|
|
|
|
{
|
|
|
|
EnabledArrayPair():_enabled(false),_pointer(0) {}
|
|
|
|
EnabledArrayPair(const EnabledArrayPair& eap):_enabled(eap._enabled),_pointer(eap._pointer) {}
|
|
|
|
EnabledArrayPair& operator = (const EnabledArrayPair& eap) { _enabled=eap._enabled; _pointer=eap._pointer; return *this; }
|
|
|
|
|
|
|
|
bool _enabled;
|
|
|
|
const GLvoid* _pointer;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<EnabledArrayPair> EnabledTexCoordArrayList;
|
|
|
|
|
|
|
|
EnabledArrayPair _vertexArray;
|
|
|
|
EnabledArrayPair _colorArray;
|
|
|
|
EnabledArrayPair _indexArray;
|
|
|
|
EnabledArrayPair _normalArray;
|
|
|
|
EnabledTexCoordArrayList _texCoordArrayList;
|
|
|
|
|
|
|
|
unsigned int _currentActiveTextureUnit;
|
|
|
|
unsigned int _currentClientActiveTextureUnit;
|
2001-09-22 10:42:08 +08:00
|
|
|
|
2002-07-09 17:35:42 +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,const StateAttribute::GLMode mode,const StateAttribute::GLModeValue value);
|
|
|
|
void haveAppliedMode(ModeMap& modeMap,const StateAttribute::GLMode mode);
|
|
|
|
void haveAppliedAttribute(AttributeMap& attributeMap,const StateAttribute* attribute);
|
|
|
|
void haveAppliedAttribute(AttributeMap& attributeMap,const StateAttribute::Type type);
|
|
|
|
const bool getLastAppliedMode(const ModeMap& modeMap,const StateAttribute::GLMode mode) const;
|
|
|
|
const StateAttribute* getLastAppliedAttribute(const AttributeMap& attributeMap,const StateAttribute::Type type) const;
|
|
|
|
|
2001-01-11 00:32:10 +08:00
|
|
|
};
|
|
|
|
|
2002-07-09 17:35:42 +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) // 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) // 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)
|
|
|
|
{
|
|
|
|
// 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 mode, check the overide
|
|
|
|
// if any otherwise just apply the incomming mode.
|
|
|
|
|
|
|
|
AttributeStack& as = this_aitr->second;
|
|
|
|
|
|
|
|
if (!as.attributeVec.empty() && as.attributeVec.back().second)
|
|
|
|
{
|
|
|
|
// override is os, 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-02-03 20:33:41 +08:00
|
|
|
}
|
2001-01-11 00:32:10 +08:00
|
|
|
|
|
|
|
#endif
|