root/OpenSceneGraph/trunk/src/osg/StateSet.cpp @ 10671

Revision 10671, 61.4 kB (checked in by robert, 5 years ago)

From Cedric Pinson, "Here a patch to be able to clone stateattribute, in order to do that i
moved the StateAttribute::Callback structure to a file
StateAttributeCallback? with the same behavior as NodeCallback?.
"

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[8455]1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield
[1529]2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
[10]13#include <stdio.h>
14
15#include <osg/StateSet>
16#include <osg/State>
17#include <osg/Notify>
18
19#include <osg/AlphaFunc>
20#include <osg/Material>
21#include <osg/CullFace>
22#include <osg/FrontFace>
23#include <osg/PolygonMode>
[868]24#include <osg/BlendFunc>
[37]25#include <osg/Depth>
[4094]26#include <osg/Drawable>
27#include <osg/Node>
[10]28
[1078]29#include <osg/TextureCubeMap>
[1995]30#include <osg/TextureRectangle>
[7371]31#include <osg/Texture2DArray>
[1078]32
[961]33#include <set>
[4101]34#include <algorithm>
[961]35
[10]36using namespace osg;
37
[961]38// local class to help porting from OSG0.8.x to 0.9.x
39class TextureGLModeSet
40{
41
42    public:
43
44        TextureGLModeSet()
45        {
46
47            _textureModeSet.insert(GL_TEXTURE_1D);
48            _textureModeSet.insert(GL_TEXTURE_2D);
49            _textureModeSet.insert(GL_TEXTURE_3D);
50
51            _textureModeSet.insert(GL_TEXTURE_CUBE_MAP);
[7371]52            _textureModeSet.insert(GL_TEXTURE_RECTANGLE_NV);
53            _textureModeSet.insert(GL_TEXTURE_2D_ARRAY_EXT);
[961]54
55            _textureModeSet.insert(GL_TEXTURE_GEN_Q);
56            _textureModeSet.insert(GL_TEXTURE_GEN_R);
57            _textureModeSet.insert(GL_TEXTURE_GEN_S);
58            _textureModeSet.insert(GL_TEXTURE_GEN_T);
59        }
60       
61        bool isTextureMode(StateAttribute::GLMode mode) const
62        {
63            return _textureModeSet.find(mode)!=_textureModeSet.end();
64        }
65
66    protected:
67
68        std::set<StateAttribute::GLMode> _textureModeSet;
69       
70};
71
[5387]72static TextureGLModeSet& getTextureGLModeSet()
73{
74    static TextureGLModeSet s_textureGLModeSet;
75    return s_textureGLModeSet;
76}
[961]77
[5586]78bool osg::isTextureMode(StateAttribute::GLMode mode)
79{
80    return getTextureGLModeSet().isTextureMode(mode);
81}
82
[7332]83StateSet::StateSet():
[8455]84    Object(true),
85    _nestRenderBins(true)
[10]86{
87    _renderingHint = DEFAULT_BIN;
88   
[4092]89    _numChildrenRequiringUpdateTraversal = 0;
90    _numChildrenRequiringEventTraversal = 0;
91
[1166]92    setRenderBinToInherit();
[10]93}
94
[8455]95StateSet::StateSet(const StateSet& rhs,const CopyOp& copyop):Object(rhs,copyop),
96    _nestRenderBins(rhs._nestRenderBins)
[121]97{
[329]98    _modeList = rhs._modeList;
[327]99
[329]100    for(AttributeList::const_iterator itr=rhs._attributeList.begin();
101        itr!=rhs._attributeList.end();
102        ++itr)
103    {
[3488]104        const StateAttribute::TypeMemberPair& typemember = itr->first;
[329]105        const RefAttributePair& rap = itr->second;
[331]106        StateAttribute* attr = copyop(rap.first.get());
[4091]107        if (attr)
108        {
109            _attributeList[typemember]=RefAttributePair(attr,rap.second);
110            attr->addParent(this);
111        }
[329]112    }
[121]113   
[828]114    // copy texture related modes.
115    _textureModeList = rhs._textureModeList;
116   
117    // set up the size of the texture attribute list.
118    _textureAttributeList.resize(rhs._textureAttributeList.size());
119   
120    // copy the contents across.
121    for(unsigned int i=0;i<rhs._textureAttributeList.size();++i)
122    {
123       
124        AttributeList& lhs_attributeList = _textureAttributeList[i];
125        const AttributeList& rhs_attributeList = rhs._textureAttributeList[i];
126        for(AttributeList::const_iterator itr=rhs_attributeList.begin();
127            itr!=rhs_attributeList.end();
128            ++itr)
129        {
[3488]130            const StateAttribute::TypeMemberPair& typemember = itr->first;
[828]131            const RefAttributePair& rap = itr->second;
132            StateAttribute* attr = copyop(rap.first.get());
[4091]133            if (attr)
134            {
135                lhs_attributeList[typemember]=RefAttributePair(attr,rap.second);
136                attr->addParent(this);
137            }
[828]138        }
139    }
[3948]140
141    // copy uniform values
142    for(UniformList::const_iterator rhs_uitr = rhs._uniformList.begin();
143        rhs_uitr != rhs._uniformList.end();
144        ++rhs_uitr)
145    {
[7953]146        const std::string& name = rhs_uitr->first;
147        const RefUniformPair& rup = rhs_uitr->second;
148        Uniform* uni = copyop(rup.first.get());
149        if (uni)
[4091]150        {
151            _uniformList[name] = RefUniformPair(uni, rup.second);
152            uni->addParent(this);
153        }
[3948]154    }
[828]155   
[121]156    _renderingHint = rhs._renderingHint;
[10]157
[121]158    _binMode = rhs._binMode;
159    _binNum = rhs._binNum;
160    _binName = rhs._binName;
[4092]161
[4100]162    _updateCallback = rhs._updateCallback;
[4092]163    _numChildrenRequiringUpdateTraversal = rhs._numChildrenRequiringUpdateTraversal;
[4100]164
165    _eventCallback = rhs._eventCallback;
[4092]166    _numChildrenRequiringEventTraversal = rhs._numChildrenRequiringEventTraversal;
167
[121]168}
169
[10]170StateSet::~StateSet()
171{
[4091]172    clear();
[10]173}
174
[6180]175void StateSet::computeDataVariance()
176{
177    bool dynamic = false;
178
179    if (_updateCallback.valid() ||
180        _eventCallback.valid())
181    {
182        dynamic = true;
183    }
184
185    // run attribute callbacks
[6184]186
[6180]187    for(AttributeList::iterator itr=_attributeList.begin();
188        itr!=_attributeList.end();
189        ++itr)
190    {
[6184]191        if (itr->second.first->getDataVariance()==UNSPECIFIED &&
192            (itr->second.first->getUpdateCallback() || itr->second.first->getEventCallback()))
[6180]193        {
194            itr->second.first->setDataVariance(DYNAMIC);
195        }
[6184]196
197        if (itr->second.first->getDataVariance()==DYNAMIC) dynamic = true;
[6180]198    }
199
200    // run texture attribute callbacks.
201    for(unsigned int i=0;i<_textureAttributeList.size();++i)
202    {
203        AttributeList& attributeList = _textureAttributeList[i];
204        for(AttributeList::iterator itr=attributeList.begin();
205            itr!=attributeList.end();
206            ++itr)
207        {
[6184]208            if (itr->second.first->getDataVariance()==UNSPECIFIED &&
209                (itr->second.first->getUpdateCallback() || itr->second.first->getEventCallback()))
[6180]210            {
[6184]211                itr->second.first->setDataVariance(DYNAMIC);
[6180]212            }
[6184]213
214            if (itr->second.first->getDataVariance()==DYNAMIC) dynamic = true;
[6180]215        }
216    }
217
218
219    // run uniform callbacks.
220    for(UniformList::iterator uitr = _uniformList.begin();
221        uitr != _uniformList.end();
222        ++uitr)
223    {
[6184]224        if (uitr->second.first->getDataVariance()==UNSPECIFIED &&
225            (uitr->second.first->getUpdateCallback() || uitr->second.first->getEventCallback()))
[6180]226        {
227            uitr->second.first->setDataVariance(DYNAMIC);
228        }
[6184]229
230        if (uitr->second.first->getDataVariance()==DYNAMIC) dynamic = true;
[6180]231    }
232
233#if 0
[6184]234
[6180]235    if (dynamic)
236    {
237        osg::notify(osg::NOTICE)<<"StateSet::computeDataVariance setting to DYNAMIC"<<std::endl;
238    }
239    else
240    {
241        osg::notify(osg::NOTICE)<<"StateSet::computeDataVariance to STATIC"<<std::endl;
242    }
243#endif
244
[6184]245    if (getDataVariance()==UNSPECIFIED)
246    {
247        setDataVariance(dynamic ? DYNAMIC : STATIC);
248    }
[6180]249}
250
251
[4091]252void StateSet::addParent(osg::Object* object)
253{
[9354]254    // osg::notify(osg::DEBUG_FP)<<"Adding parent"<<std::endl;
[9023]255    OpenThreads::ScopedPointerLock<OpenThreads::Mutex> lock(getRefMutex());
[4094]256
[9023]257    _parents.push_back(object);
[4091]258}
259
260void StateSet::removeParent(osg::Object* object)
261{
[9023]262    OpenThreads::ScopedPointerLock<OpenThreads::Mutex> lock(getRefMutex());
[7332]263
[9023]264    ParentList::iterator pitr = std::find(_parents.begin(),_parents.end(),object);
265    if (pitr!=_parents.end()) _parents.erase(pitr);
[4091]266}
267
[152]268int StateSet::compare(const StateSet& rhs,bool compareAttributeContents) const
[41]269{
[10]270
[828]271    if (_textureAttributeList.size()<rhs._textureAttributeList.size()) return -1;
272    if (_textureAttributeList.size()>rhs._textureAttributeList.size()) return 1;
273   
274    for(unsigned int ai=0;ai<_textureAttributeList.size();++ai)
275    {
276        const AttributeList& rhs_attributeList = _textureAttributeList[ai];
277        const AttributeList& lhs_attributeList = rhs._textureAttributeList[ai];
278        if (compareAttributeContents)
279        {
280            // now check to see how the attributes compare.
281            AttributeList::const_iterator lhs_attr_itr = lhs_attributeList.begin();
282            AttributeList::const_iterator rhs_attr_itr = rhs_attributeList.begin();
283            while (lhs_attr_itr!=lhs_attributeList.end() && rhs_attr_itr!=rhs_attributeList.end())
284            {
285                if      (lhs_attr_itr->first<rhs_attr_itr->first) return -1;
286                else if (rhs_attr_itr->first<lhs_attr_itr->first) return 1;
287                if      (*(lhs_attr_itr->second.first)<*(rhs_attr_itr->second.first)) return -1;
288                else if (*(rhs_attr_itr->second.first)<*(lhs_attr_itr->second.first)) return 1;
289                if      (lhs_attr_itr->second.second<rhs_attr_itr->second.second) return -1;
290                else if (rhs_attr_itr->second.second<lhs_attr_itr->second.second) return 1;
291                ++lhs_attr_itr;
292                ++rhs_attr_itr;
293            }
294            if (lhs_attr_itr==lhs_attributeList.end())
295            {
296                if (rhs_attr_itr!=rhs_attributeList.end()) return -1;
297            }
298            else if (rhs_attr_itr == rhs_attributeList.end()) return 1;
299        }
300        else // just compare pointers.
301        {
302            // now check to see how the attributes compare.
303            AttributeList::const_iterator lhs_attr_itr = lhs_attributeList.begin();
304            AttributeList::const_iterator rhs_attr_itr = rhs_attributeList.begin();
305            while (lhs_attr_itr!=lhs_attributeList.end() && rhs_attr_itr!=rhs_attributeList.end())
306            {
307                if      (lhs_attr_itr->first<rhs_attr_itr->first) return -1;
308                else if (rhs_attr_itr->first<lhs_attr_itr->first) return 1;
309                if      (lhs_attr_itr->second.first<rhs_attr_itr->second.first) return -1;
310                else if (rhs_attr_itr->second.first<lhs_attr_itr->second.first) return 1;
311                if      (lhs_attr_itr->second.second<rhs_attr_itr->second.second) return -1;
312                else if (rhs_attr_itr->second.second<lhs_attr_itr->second.second) return 1;
313                ++lhs_attr_itr;
314                ++rhs_attr_itr;
315            }
316            if (lhs_attr_itr==lhs_attributeList.end())
317            {
318                if (rhs_attr_itr!=rhs_attributeList.end()) return -1;
319            }
320            else if (rhs_attr_itr == rhs_attributeList.end()) return 1;
321        }
322    }
323
324   
325    // now check the rest of the non texture attributes
[152]326    if (compareAttributeContents)
[41]327    {
[152]328        // now check to see how the attributes compare.
329        AttributeList::const_iterator lhs_attr_itr = _attributeList.begin();
330        AttributeList::const_iterator rhs_attr_itr = rhs._attributeList.begin();
331        while (lhs_attr_itr!=_attributeList.end() && rhs_attr_itr!=rhs._attributeList.end())
332        {
333            if      (lhs_attr_itr->first<rhs_attr_itr->first) return -1;
334            else if (rhs_attr_itr->first<lhs_attr_itr->first) return 1;
335            if      (*(lhs_attr_itr->second.first)<*(rhs_attr_itr->second.first)) return -1;
336            else if (*(rhs_attr_itr->second.first)<*(lhs_attr_itr->second.first)) return 1;
337            if      (lhs_attr_itr->second.second<rhs_attr_itr->second.second) return -1;
338            else if (rhs_attr_itr->second.second<lhs_attr_itr->second.second) return 1;
339            ++lhs_attr_itr;
340            ++rhs_attr_itr;
341        }
342        if (lhs_attr_itr==_attributeList.end())
343        {
344            if (rhs_attr_itr!=rhs._attributeList.end()) return -1;
345        }
346        else if (rhs_attr_itr == rhs._attributeList.end()) return 1;
[41]347    }
[152]348    else // just compare pointers.
[41]349    {
[152]350        // now check to see how the attributes compare.
351        AttributeList::const_iterator lhs_attr_itr = _attributeList.begin();
352        AttributeList::const_iterator rhs_attr_itr = rhs._attributeList.begin();
353        while (lhs_attr_itr!=_attributeList.end() && rhs_attr_itr!=rhs._attributeList.end())
354        {
355            if      (lhs_attr_itr->first<rhs_attr_itr->first) return -1;
356            else if (rhs_attr_itr->first<lhs_attr_itr->first) return 1;
357            if      (lhs_attr_itr->second.first<rhs_attr_itr->second.first) return -1;
358            else if (rhs_attr_itr->second.first<lhs_attr_itr->second.first) return 1;
359            if      (lhs_attr_itr->second.second<rhs_attr_itr->second.second) return -1;
360            else if (rhs_attr_itr->second.second<lhs_attr_itr->second.second) return 1;
361            ++lhs_attr_itr;
362            ++rhs_attr_itr;
363        }
364        if (lhs_attr_itr==_attributeList.end())
365        {
366            if (rhs_attr_itr!=rhs._attributeList.end()) return -1;
367        }
368        else if (rhs_attr_itr == rhs._attributeList.end()) return 1;
[41]369    }
[152]370   
[50]371    // we've got here so attributes must be equal...   
372
[828]373
374    if (_textureModeList.size()<rhs._textureModeList.size()) return -1;
375    if (_textureModeList.size()>rhs._textureModeList.size()) return 1;
376
[50]377    // check to see how the modes compare.
[828]378    // first check the rest of the texture modes
379    for(unsigned int ti=0;ti<_textureModeList.size();++ti)
380    {
381        const ModeList& lhs_modeList = _textureModeList[ti];
382        const ModeList& rhs_modeList = rhs._textureModeList[ti];
[50]383
[828]384        ModeList::const_iterator lhs_mode_itr = lhs_modeList.begin();
385        ModeList::const_iterator rhs_mode_itr = rhs_modeList.begin();
386        while (lhs_mode_itr!=lhs_modeList.end() && rhs_mode_itr!=rhs_modeList.end())
387        {
388            if      (lhs_mode_itr->first<rhs_mode_itr->first) return -1;
389            else if (rhs_mode_itr->first<lhs_mode_itr->first) return 1;
390            if      (lhs_mode_itr->second<rhs_mode_itr->second) return -1;
391            else if (rhs_mode_itr->second<lhs_mode_itr->second) return 1;
392            ++lhs_mode_itr;
393            ++rhs_mode_itr;
394        }
395        if (lhs_mode_itr==lhs_modeList.end())
396        {
397            if (rhs_mode_itr!=rhs_modeList.end()) return -1;
398        }
399        else if (rhs_mode_itr == rhs_modeList.end()) return 1;
400    }
401
402    // check non texture modes.
[50]403    ModeList::const_iterator lhs_mode_itr = _modeList.begin();
404    ModeList::const_iterator rhs_mode_itr = rhs._modeList.begin();
405    while (lhs_mode_itr!=_modeList.end() && rhs_mode_itr!=rhs._modeList.end())
406    {
407        if      (lhs_mode_itr->first<rhs_mode_itr->first) return -1;
408        else if (rhs_mode_itr->first<lhs_mode_itr->first) return 1;
409        if      (lhs_mode_itr->second<rhs_mode_itr->second) return -1;
410        else if (rhs_mode_itr->second<lhs_mode_itr->second) return 1;
411        ++lhs_mode_itr;
412        ++rhs_mode_itr;
413    }
414    if (lhs_mode_itr==_modeList.end())
415    {
416        if (rhs_mode_itr!=rhs._modeList.end()) return -1;
417    }
418    else if (rhs_mode_itr == rhs._modeList.end()) return 1;
419
[3897]420
421    // check uniforms.
422    UniformList::const_iterator lhs_uniform_itr = _uniformList.begin();
423    UniformList::const_iterator rhs_uniform_itr = rhs._uniformList.begin();
424    while (lhs_uniform_itr!=_uniformList.end() && rhs_uniform_itr!=rhs._uniformList.end())
425    {
426        if      (lhs_uniform_itr->first<rhs_uniform_itr->first) return -1;
427        else if (rhs_uniform_itr->first<lhs_uniform_itr->first) return 1;
[9989]428        if      (*lhs_uniform_itr->second.first<*rhs_uniform_itr->second.first) return -1;
429        else if (*rhs_uniform_itr->second.first<*lhs_uniform_itr->second.first) return 1;
430        if      (lhs_uniform_itr->second.second<rhs_uniform_itr->second.second) return -1;
431        else if (rhs_uniform_itr->second.second<lhs_uniform_itr->second.second) return 1;
[3897]432        ++lhs_uniform_itr;
433        ++rhs_uniform_itr;
434    }
435    if (lhs_uniform_itr==_uniformList.end())
436    {
437        if (rhs_uniform_itr!=rhs._uniformList.end()) return -1;
438    }
[4034]439    else if (rhs_uniform_itr == rhs._uniformList.end()) return 1; 
[3897]440
[5623]441    // check render bin details
442   
443    if ( _binMode < rhs._binMode ) return -1;
444    else if ( _binMode > rhs._binMode ) return 1;
445   
446    if ( _binMode != INHERIT_RENDERBIN_DETAILS )
447    {
448        if ( _binNum < rhs._binNum ) return -1;
449        else if ( _binNum > rhs._binNum ) return 1;
450
451        if ( _binName < rhs._binName ) return -1;
452        else if ( _binName > rhs._binName ) return 1;
453    }
454
[41]455    return 0;
456}
457
[836]458int StateSet::compareModes(const ModeList& lhs,const ModeList& rhs)
459{
460    ModeList::const_iterator lhs_mode_itr = lhs.begin();
461    ModeList::const_iterator rhs_mode_itr = rhs.begin();
462    while (lhs_mode_itr!=lhs.end() && rhs_mode_itr!=rhs.end())
463    {
464        if      (lhs_mode_itr->first<rhs_mode_itr->first) return -1;
465        else if (rhs_mode_itr->first<lhs_mode_itr->first) return 1;
466        if      (lhs_mode_itr->second<rhs_mode_itr->second) return -1;
467        else if (rhs_mode_itr->second<lhs_mode_itr->second) return 1;
468        ++lhs_mode_itr;
469        ++rhs_mode_itr;
470    }
471    if (lhs_mode_itr==lhs.end())
472    {
473        if (rhs_mode_itr!=rhs.end()) return -1;
474    }
475    else if (rhs_mode_itr == rhs.end()) return 1;
476    return 0;
477}
478
479int StateSet::compareAttributePtrs(const AttributeList& lhs,const AttributeList& rhs)
480{
481    AttributeList::const_iterator lhs_attr_itr = lhs.begin();
482    AttributeList::const_iterator rhs_attr_itr = rhs.begin();
483    while (lhs_attr_itr!=lhs.end() && rhs_attr_itr!=rhs.end())
484    {
485        if      (lhs_attr_itr->first<rhs_attr_itr->first) return -1;
486        else if (rhs_attr_itr->first<lhs_attr_itr->first) return 1;
487        if      (lhs_attr_itr->second.first<rhs_attr_itr->second.first) return -1;
488        else if (rhs_attr_itr->second.first<lhs_attr_itr->second.first) return 1;
489        if      (lhs_attr_itr->second.second<rhs_attr_itr->second.second) return -1;
490        else if (rhs_attr_itr->second.second<lhs_attr_itr->second.second) return 1;
491        ++lhs_attr_itr;
492        ++rhs_attr_itr;
493    }
494    if (lhs_attr_itr==lhs.end())
495    {
496        if (rhs_attr_itr!=rhs.end()) return -1;
497    }
498    else if (rhs_attr_itr == rhs.end()) return 1;
499    return 0;
500}
501
502int StateSet::compareAttributeContents(const AttributeList& lhs,const AttributeList& rhs)
503{
504    AttributeList::const_iterator lhs_attr_itr = lhs.begin();
505    AttributeList::const_iterator rhs_attr_itr = rhs.begin();
506    while (lhs_attr_itr!=lhs.end() && rhs_attr_itr!=rhs.end())
507    {
508        if      (lhs_attr_itr->first<rhs_attr_itr->first) return -1;
509        else if (rhs_attr_itr->first<lhs_attr_itr->first) return 1;
510        if      (*(lhs_attr_itr->second.first)<*(rhs_attr_itr->second.first)) return -1;
511        else if (*(rhs_attr_itr->second.first)<*(lhs_attr_itr->second.first)) return 1;
512        if      (lhs_attr_itr->second.second<rhs_attr_itr->second.second) return -1;
513        else if (rhs_attr_itr->second.second<lhs_attr_itr->second.second) return 1;
514        ++lhs_attr_itr;
515        ++rhs_attr_itr;
516    }
517    if (lhs_attr_itr==lhs.end())
518    {
519        if (rhs_attr_itr!=rhs.end()) return -1;
520    }
521    else if (rhs_attr_itr == rhs.end()) return 1;
522    return 0;
523}
524
[10]525void StateSet::setGlobalDefaults()
526{   
527    _renderingHint = DEFAULT_BIN;
528
[1166]529    setRenderBinToInherit();
[10]530
[97]531
[609]532    setMode(GL_DEPTH_TEST,StateAttribute::ON);
[5211]533    // setAttributeAndModes(new AlphaFunc,StateAttribute::OFF);
[1418]534    setAttributeAndModes(new BlendFunc,StateAttribute::OFF);
[97]535
[1418]536    Material *material       = new Material;
[97]537    material->setColorMode(Material::AMBIENT_AND_DIFFUSE);
538    setAttributeAndModes(material,StateAttribute::ON);
[10]539}
540
541
[3480]542void StateSet::clear()
[10]543{
544    _renderingHint = DEFAULT_BIN;
545
[1166]546    setRenderBinToInherit();
[10]547
[4569]548
[4091]549    // remove self from as attributes parent
550    for(AttributeList::iterator itr=_attributeList.begin();
551        itr!=_attributeList.end();
552        ++itr)
553    {
554        itr->second.first->removeParent(this);
555    }
556   
[10]557    _modeList.clear();
558    _attributeList.clear();
[828]559   
[3948]560
[4091]561    // remove self from as texture attributes parent
562    for(unsigned int i=0;i<_textureAttributeList.size();++i)
563    {
564        AttributeList& attributeList = _textureAttributeList[i];
565        for(AttributeList::iterator itr=attributeList.begin();
566            itr!=attributeList.end();
567            ++itr)
568        {
569            itr->second.first->removeParent(this);
570        }
571    }
572
[4569]573    _textureModeList.clear();
574    _textureAttributeList.clear();
[4091]575
[4569]576
[4091]577    // remove self from uniforms parent
578    for(UniformList::iterator uitr = _uniformList.begin();
579        uitr != _uniformList.end();
580        ++uitr)
581    {
582        uitr->second.first->removeParent(this);
583    }
584
[3948]585    _uniformList.clear();
[10]586}
587
[88]588void StateSet::merge(const StateSet& rhs)
589{
590    // merge the modes of rhs into this,
591    // this overrides rhs if OVERRIDE defined in this.
592    for(ModeList::const_iterator rhs_mitr = rhs._modeList.begin();
[183]593        rhs_mitr != rhs._modeList.end();
[88]594        ++rhs_mitr)
595    {
596        ModeList::iterator lhs_mitr = _modeList.find(rhs_mitr->first);
597        if (lhs_mitr!=_modeList.end())
598        {
[7630]599            // take the rhs mode unless the lhs is override and the rhs is not protected
600            if (!(lhs_mitr->second & StateAttribute::OVERRIDE ) ||
601                 (rhs_mitr->second & StateAttribute::PROTECTED))
[88]602            {
[7648]603                // override isn't on in rhs, so override it with incoming
[88]604                // value.
605                lhs_mitr->second = rhs_mitr->second;
606            }
607        }
608        else
609        {
610            // entry doesn't exist so insert it.
611            _modeList.insert(*rhs_mitr);
612        }
613    }
614
615    // merge the attributes of rhs into this,
616    // this overrides rhs if OVERRIDE defined in this.
617    for(AttributeList::const_iterator rhs_aitr = rhs._attributeList.begin();
[183]618        rhs_aitr != rhs._attributeList.end();
[88]619        ++rhs_aitr)
620    {
621        AttributeList::iterator lhs_aitr = _attributeList.find(rhs_aitr->first);
622        if (lhs_aitr!=_attributeList.end())
623        {
[7630]624            // take the rhs attribute unless the lhs is override and the rhs is not protected
625            if (!(lhs_aitr->second.second & StateAttribute::OVERRIDE) ||
626                 (rhs_aitr->second.second & StateAttribute::PROTECTED))
[88]627            {
[7648]628                // override isn't on in rhs, so override it with incoming
[88]629                // value.
[4091]630                if (lhs_aitr->second.first!=rhs_aitr->second.first)
631                {
632                    // new attribute so need to remove self from outgoing attribute
633                    lhs_aitr->second.first->removeParent(this);
634
[7648]635                    // override isn't on in rhs, so override it with incoming
[4091]636                    // value.
637                    lhs_aitr->second = rhs_aitr->second;
638                    lhs_aitr->second.first->addParent(this);
639
640                }
641                else
642                {
643                    // same attribute but with override to set.
644                    lhs_aitr->second = rhs_aitr->second;
645                }
646
[88]647            }
648        }
649        else
650        {
[4091]651            // entry doesn't exist so insert it, and then tell it about self by adding self as parent.
652            _attributeList.insert(*rhs_aitr).first->second.first->addParent(this);
[88]653        }
654    }
[183]655
[828]656
657    if (_textureModeList.size()<rhs._textureModeList.size()) _textureModeList.resize(rhs._textureModeList.size());
658    for(unsigned int mi=0;mi<rhs._textureModeList.size();++mi)
659    {
660        ModeList& lhs_modeList = _textureModeList[mi];
661        const ModeList& rhs_modeList = rhs._textureModeList[mi];
662        // merge the modes of rhs into this,
663        // this overrides rhs if OVERRIDE defined in this.
664        for(ModeList::const_iterator rhs_mitr = rhs_modeList.begin();
665            rhs_mitr != rhs_modeList.end();
666            ++rhs_mitr)
667        {
668            ModeList::iterator lhs_mitr = lhs_modeList.find(rhs_mitr->first);
669            if (lhs_mitr!=lhs_modeList.end())
670            {
[7630]671                // take the rhs mode unless the lhs is override and the rhs is not protected
672                if (!(lhs_mitr->second & StateAttribute::OVERRIDE) ||
673                     (rhs_mitr->second & StateAttribute::PROTECTED))
[828]674                {
[7648]675                    // override isn't on in rhs, so override it with incoming
[828]676                    // value.
677                    lhs_mitr->second = rhs_mitr->second;
678                }
679            }
680            else
681            {
682                // entry doesn't exist so insert it.
683                lhs_modeList.insert(*rhs_mitr);
684            }
685        }
686    }
687   
688    if (_textureAttributeList.size()<rhs._textureAttributeList.size()) _textureAttributeList.resize(rhs._textureAttributeList.size());
689    for(unsigned int ai=0;ai<rhs._textureAttributeList.size();++ai)
690    {
691        AttributeList& lhs_attributeList = _textureAttributeList[ai];
692        const AttributeList& rhs_attributeList = rhs._textureAttributeList[ai];
693       
694        // merge the attributes of rhs into this,
695        // this overrides rhs if OVERRIDE defined in this.
696        for(AttributeList::const_iterator rhs_aitr = rhs_attributeList.begin();
697            rhs_aitr != rhs_attributeList.end();
698            ++rhs_aitr)
699        {
700            AttributeList::iterator lhs_aitr = lhs_attributeList.find(rhs_aitr->first);
701            if (lhs_aitr!=lhs_attributeList.end())
702            {
[7630]703                // take the rhs attribute unless the lhs is override and the rhs is not protected
704                if (!(lhs_aitr->second.second & StateAttribute::OVERRIDE) ||
705                     (rhs_aitr->second.second & StateAttribute::PROTECTED))
[828]706                {
[7648]707                    // override isn't on in rhs, so override it with incoming
[828]708                    // value.
[4091]709                   
710                    if (lhs_aitr->second.first!=rhs_aitr->second.first)
711                    {
712                        lhs_aitr->second.first->removeParent(this);
713                        lhs_aitr->second = rhs_aitr->second;
714                        lhs_aitr->second.first->addParent(this);
715                    }
716                    else
717                    {
718                        lhs_aitr->second = rhs_aitr->second;
719                    }
[828]720                }
721            }
722            else
723            {
[4091]724                // entry doesn't exist so insert it and add self as parent
725                lhs_attributeList.insert(*rhs_aitr).first->second.first->addParent(this);
[828]726            }
727        }
728    }
729
[3948]730    // merge the uniforms of rhs into this,
731    // this overrides rhs if OVERRIDE defined in this.
732    for(UniformList::const_iterator rhs_uitr = rhs._uniformList.begin();
733        rhs_uitr != rhs._uniformList.end();
734        ++rhs_uitr)
735    {
736        UniformList::iterator lhs_uitr = _uniformList.find(rhs_uitr->first);
737        if (lhs_uitr!=_uniformList.end())
738        {
[7630]739            // take the rhs uniform unless the lhs is override and the rhs is not protected
740            if (!(lhs_uitr->second.second & StateAttribute::OVERRIDE) ||
741                 (rhs_uitr->second.second & StateAttribute::PROTECTED))
[3948]742            {
[7648]743                // override isn't on in rhs, so override it with incoming
[3948]744                // value.
[4091]745
746                if (lhs_uitr->second.first!=rhs_uitr->second.first)
747                {
748                    lhs_uitr->second.first->removeParent(this);
749                    lhs_uitr->second = rhs_uitr->second;
750                    lhs_uitr->second.first->addParent(this);
751                }
752                else
753                {
754                    lhs_uitr->second = rhs_uitr->second;
755                }
756
[3948]757            }
758        }
759        else
760        {
[4091]761            // entry doesn't exist so insert it and add self as parent
762            _uniformList.insert(*rhs_uitr).first->second.first->addParent(this);
[3948]763        }
764    }
765
[8354]766    // Merge RenderBin state from rhs into this.
767    // Only do so if this's RenderBinMode is INHERIT.
768    if (getRenderBinMode() == INHERIT_RENDERBIN_DETAILS)
769    {
770        setRenderingHint( rhs.getRenderingHint() );
771        setRenderBinMode( rhs.getRenderBinMode() );
772        setBinNumber( rhs.getBinNumber() );
773        setBinName( rhs.getBinName() );
774    }
[88]775}
776
777
[1133]778void StateSet::setMode(StateAttribute::GLMode mode, StateAttribute::GLModeValue value)
[10]779{
[8905]780    if (getTextureGLModeSet().isTextureMode(mode))
[961]781    {
782        notify(NOTICE)<<"Warning: texture mode '"<<mode<<"'passed to setMode(mode,value), "<<std::endl;
783        notify(NOTICE)<<"         assuming setTextureMode(unit=0,mode,value) instead."<<std::endl;
784        notify(NOTICE)<<"         please change calling code to use appropriate call."<<std::endl;
785
786        setTextureMode(0,mode,value);
787    }
[8905]788    else if (mode == GL_COLOR_MATERIAL)
789    {
790        notify(NOTICE)<<"Error: Setting mode 'GL_COLOR_MATERIAL' via osg::StateSet::setMode(mode,value) ignored.\n";
791        notify(NOTICE)<<"       The mode 'GL_COLOR_MATERIAL' is set by the osg::Material StateAttribute.\n";
792        notify(NOTICE)<<"       Setting this as a mode fools osg's State tracking."<<std::endl;
793    }
794    else
795    {
796        setMode(_modeList,mode,value);
797    }
[10]798}
799
[3480]800void StateSet::removeMode(StateAttribute::GLMode mode)
[10]801{
[8905]802    if (getTextureGLModeSet().isTextureMode(mode))
[961]803    {
804        notify(NOTICE)<<"Warning: texture mode '"<<mode<<"'passed to setModeToInherit(mode), "<<std::endl;
805        notify(NOTICE)<<"         assuming setTextureModeToInherit(unit=0,mode) instead."<<std::endl;
806        notify(NOTICE)<<"         please change calling code to use appropriate call."<<std::endl;
807
[3480]808        removeTextureMode(0,mode);
[961]809    }
[8905]810    else if (mode == GL_COLOR_MATERIAL)
811    {
812        notify(NOTICE)<<"Error: Setting mode 'GL_COLOR_MATERIAL' via osg::StateSet::removeMode(mode) ignored.\n";
813        notify(NOTICE)<<"       The mode 'GL_COLOR_MATERIAL' is set by the osg::Material StateAttribute.\n";
814        notify(NOTICE)<<"       Setting this as a mode fools osg's State tracking."<<std::endl;
815    }
816    else
817    {
818        setModeToInherit(_modeList,mode);
819    }
[961]820
[10]821}
822
[1133]823StateAttribute::GLModeValue StateSet::getMode(StateAttribute::GLMode mode) const
[10]824{
[5387]825    if (!getTextureGLModeSet().isTextureMode(mode))
[961]826    {
827        return getMode(_modeList,mode);
828    }
829    else
830    {
831        notify(NOTICE)<<"Warning: texture mode '"<<mode<<"'passed to getMode(mode), "<<std::endl;
832        notify(NOTICE)<<"         assuming getTextureMode(unit=0,mode) instead."<<std::endl;
833        notify(NOTICE)<<"         please change calling code to use appropriate call."<<std::endl;
834
835        return getTextureMode(0,mode);
836    }
[10]837}
838
[1133]839void StateSet::setAttribute(StateAttribute *attribute, StateAttribute::OverrideValue value)
[10]840{
841    if (attribute)
842    {
[836]843        if (!attribute->isTextureAttribute())
844        {
845            setAttribute(_attributeList,attribute,value);
846        }
847        else
848        {
849            notify(NOTICE)<<"Warning: texture attribute '"<<attribute->className()<<"'passed to setAttribute(attr,value), "<<std::endl;
850            notify(NOTICE)<<"         assuming setTextureAttribute(unit=0,attr,value) instead."<<std::endl;
851            notify(NOTICE)<<"         please change calling code to use appropriate call."<<std::endl;
[961]852
[836]853            setTextureAttribute(0,attribute,value);
854        }
855    }       
[10]856}
857
[1133]858void StateSet::setAttributeAndModes(StateAttribute *attribute, StateAttribute::GLModeValue value)
[10]859{
860    if (attribute)
861    {
[836]862        if (!attribute->isTextureAttribute())
863        {
864            if (value&StateAttribute::INHERIT)
865            {
[3480]866                removeAttribute(attribute->getType());
[836]867            }   
868            else
869            {
870                setAttribute(_attributeList,attribute,value);
[2773]871                setAssociatedModes(attribute,value);
[836]872            }
873        }
874        else
875        {
876            notify(NOTICE)<<"Warning: texture attribute '"<<attribute->className()<<"' passed to setAttributeAndModes(attr,value), "<<std::endl;
877            notify(NOTICE)<<"         assuming setTextureAttributeAndModes(unit=0,attr,value) instead."<<std::endl;
878            notify(NOTICE)<<"         please change calling code to use appropriate call."<<std::endl;
[961]879
[836]880            setTextureAttributeAndModes(0,attribute,value);
881        }
[10]882    }
883}
884
[3488]885void StateSet::removeAttribute(StateAttribute::Type type, unsigned int member)
[10]886{
[3488]887    AttributeList::iterator itr = _attributeList.find(StateAttribute::TypeMemberPair(type,member));
[10]888    if (itr!=_attributeList.end())
889    {
[4094]890        if (itr->second.first->getUpdateCallback())
891        {
892            setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()-1);
893        }
894
895        if (itr->second.first->getEventCallback())
896        {
897            setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()-1);
898        }
899
[4091]900        itr->second.first->removeParent(this);
[2773]901        setAssociatedModes(itr->second.first.get(),StateAttribute::INHERIT);
[10]902        _attributeList.erase(itr);
903    }
904}
905
[3480]906void StateSet::removeAttribute(StateAttribute* attribute)
907{
908    if (!attribute) return;
909   
[3488]910    AttributeList::iterator itr = _attributeList.find(attribute->getTypeMemberPair());
[3480]911    if (itr!=_attributeList.end())
912    {
913        if (itr->second.first != attribute) return;
914       
[4094]915        if (itr->second.first->getUpdateCallback())
916        {
917            setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()-1);
918        }
919
920        if (itr->second.first->getEventCallback())
921        {
922            setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()-1);
923        }
924
[4091]925        itr->second.first->removeParent(this);
926
[3480]927        setAssociatedModes(itr->second.first.get(),StateAttribute::INHERIT);
928        _attributeList.erase(itr);
929    }
930}
931
[3488]932StateAttribute* StateSet::getAttribute(StateAttribute::Type type, unsigned int member)
[32]933{
[3488]934    return getAttribute(_attributeList,type,member);
[32]935}
936
[3488]937const StateAttribute* StateSet::getAttribute(StateAttribute::Type type, unsigned int member) const
[10]938{
[3488]939    return getAttribute(_attributeList,type,member);
[10]940}
941
[3488]942const StateSet::RefAttributePair* StateSet::getAttributePair(StateAttribute::Type type, unsigned int member) const
[10]943{
[3488]944    return getAttributePair(_attributeList,type,member);
[10]945}
946
[3948]947void StateSet::addUniform(Uniform* uniform, StateAttribute::OverrideValue value)
[3897]948{
949    if (uniform)
950    {
[4094]951        int delta_update = 0;
952        int delta_event = 0;
953       
[4091]954        UniformList::iterator itr=_uniformList.find(uniform->getName());
955        if (itr==_uniformList.end())
956        {
957            // new entry.
958            RefUniformPair& up = _uniformList[uniform->getName()];
959            up.first = uniform;
960            up.second = value&(StateAttribute::OVERRIDE|StateAttribute::PROTECTED);
961           
962            uniform->addParent(this);
[4094]963           
964            if (uniform->getUpdateCallback())
965            {
966                delta_update = 1;
967            }
968
969            if (uniform->getEventCallback())
970            {
971                delta_event = 1;
972            }
[4091]973        }
974        else
975        {
976            if (itr->second.first==uniform)
977            {
978                // chaning just override
979                itr->second.second = value&(StateAttribute::OVERRIDE|StateAttribute::PROTECTED);
980            }
981            else
982            {
983                itr->second.first->removeParent(this);
[4094]984                if (itr->second.first->getUpdateCallback()) --delta_update;
985                if (itr->second.first->getEventCallback()) --delta_event;
986               
[4091]987                uniform->addParent(this);
988                itr->second.first = uniform;
[4094]989                if (itr->second.first->getUpdateCallback()) ++delta_update;
990                if (itr->second.first->getEventCallback()) ++delta_event;
991
[4091]992                itr->second.second = value&(StateAttribute::OVERRIDE|StateAttribute::PROTECTED);
993            }
994        }
[4094]995
996        if (delta_update!=0)
997        {
998            setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+delta_update);
999        }
1000
1001        if (delta_event!=0)
1002        {
1003            setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()+delta_event);
1004        }
1005
[3897]1006    }
1007}
1008
1009void StateSet::removeUniform(const std::string& name)
1010{
1011    UniformList::iterator itr = _uniformList.find(name);
1012    if (itr!=_uniformList.end())
1013    {
[4094]1014        if (itr->second.first->getUpdateCallback())
1015        {
1016            setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()-1);
1017        }
1018
1019        if (itr->second.first->getEventCallback())
1020        {
1021            setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()-1);
1022        }
1023
[4091]1024        itr->second.first->removeParent(this);
[4094]1025
[3897]1026        _uniformList.erase(itr);
1027    }
1028}
1029
1030void StateSet::removeUniform(Uniform* uniform)
1031{
1032    if (!uniform) return;
1033   
1034    UniformList::iterator itr = _uniformList.find(uniform->getName());
1035    if (itr!=_uniformList.end())
1036    {
1037        if (itr->second.first != uniform) return;
[4091]1038
[4094]1039        if (itr->second.first->getUpdateCallback())
1040        {
1041            setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()-1);
1042        }
1043
1044        if (itr->second.first->getEventCallback())
1045        {
1046            setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()-1);
1047        }
1048
[4091]1049        itr->second.first->removeParent(this);
[3897]1050        _uniformList.erase(itr);
1051    }
1052}
1053
1054Uniform* StateSet::getUniform(const std::string& name)
1055{
1056    UniformList::iterator itr = _uniformList.find(name);
1057    if (itr!=_uniformList.end()) return itr->second.first.get();
1058    else return 0;
1059}
1060
[5150]1061Uniform* StateSet::getOrCreateUniform(const std::string& name, Uniform::Type type, unsigned int numElements)
[4157]1062{
1063    // for look for an appropriate uniform.
1064    UniformList::iterator itr = _uniformList.find(name);
1065    if (itr!=_uniformList.end() &&
1066        itr->second.first->getType()==type)
1067    {
1068        return itr->second.first.get();
1069    }
1070
1071    // no uniform found matching name so create it..
1072   
[5146]1073    Uniform* uniform = new Uniform(type,name,numElements);
[4157]1074    addUniform(uniform);
1075   
1076    return uniform;
1077}
1078
1079
[3897]1080const Uniform* StateSet::getUniform(const std::string& name) const
1081{
1082    UniformList::const_iterator itr = _uniformList.find(name);
1083    if (itr!=_uniformList.end()) return itr->second.first.get();
1084    else return 0;
1085}
1086
1087const StateSet::RefUniformPair* StateSet::getUniformPair(const std::string& name) const
1088{
1089    UniformList::const_iterator itr = _uniformList.find(name);
1090    if (itr!=_uniformList.end()) return &(itr->second);
1091    else return 0;
1092}
1093
[1133]1094void StateSet::setTextureMode(unsigned int unit,StateAttribute::GLMode mode, StateAttribute::GLModeValue value)
[828]1095{
[5387]1096    if (getTextureGLModeSet().isTextureMode(mode))
[961]1097    {
1098        setMode(getOrCreateTextureModeList(unit),mode,value);
1099    }
1100    else
1101    {
1102        notify(NOTICE)<<"Warning: non-texture mode '"<<mode<<"'passed to setTextureMode(unit,mode,value), "<<std::endl;
1103        notify(NOTICE)<<"         assuming setMode(mode,value) instead."<<std::endl;
1104        notify(NOTICE)<<"         please change calling code to use appropriate call."<<std::endl;
1105
1106        setMode(mode,value);
1107    }
[828]1108}
1109
[3480]1110void StateSet::removeTextureMode(unsigned int unit,StateAttribute::GLMode mode)
[828]1111{
[5387]1112    if (getTextureGLModeSet().isTextureMode(mode))
[961]1113    {
1114        if (unit>=_textureModeList.size()) return;
1115        setModeToInherit(_textureModeList[unit],mode);
1116    }
1117    else
1118    {
1119        notify(NOTICE)<<"Warning: non-texture mode '"<<mode<<"'passed to setTextureModeToInherit(unit,mode), "<<std::endl;
1120        notify(NOTICE)<<"         assuming setModeToInherit(unit=0,mode) instead."<<std::endl;
1121        notify(NOTICE)<<"         please change calling code to use appropriate call."<<std::endl;
1122
[3480]1123        removeMode(mode);
[961]1124    }
[828]1125}
1126
1127
[1133]1128StateAttribute::GLModeValue StateSet::getTextureMode(unsigned int unit,StateAttribute::GLMode mode) const
[828]1129{
[5387]1130    if (getTextureGLModeSet().isTextureMode(mode))
[961]1131    {
1132        if (unit>=_textureModeList.size()) return StateAttribute::INHERIT;
1133        return getMode(_textureModeList[unit],mode);
1134    }
1135    else
1136    {
1137        notify(NOTICE)<<"Warning: non-texture mode '"<<mode<<"'passed to geTexturetMode(unit,mode), "<<std::endl;
1138        notify(NOTICE)<<"         assuming getMode(mode) instead."<<std::endl;
1139        notify(NOTICE)<<"         please change calling code to use appropriate call."<<std::endl;
1140
1141        return getMode(mode);
1142    }
[828]1143}
1144
[831]1145void StateSet::setTextureAttribute(unsigned int unit,StateAttribute *attribute, const StateAttribute::OverrideValue value)
[828]1146{
1147    if (attribute)
1148    {
[836]1149        if (attribute->isTextureAttribute())
1150        {
1151            setAttribute(getOrCreateTextureAttributeList(unit),attribute,value);
1152        }
1153        else
1154        {
1155            notify(NOTICE)<<"Warning: texture attribute '"<<attribute->className()<<"' passed to setTextureAttribute(unit,attr,value), "<<std::endl;
1156            notify(NOTICE)<<"         assuming setAttribute(attr,value) instead."<<std::endl;
1157            notify(NOTICE)<<"         please change calling code to use appropriate call."<<std::endl;
1158            setAttribute(attribute,value);
1159        }
[828]1160    }
1161}
1162
1163
[1133]1164void StateSet::setTextureAttributeAndModes(unsigned int unit,StateAttribute *attribute, StateAttribute::GLModeValue value)
[828]1165{
1166    if (attribute)
1167    {
[836]1168   
1169        if (attribute->isTextureAttribute())
1170        {
1171            if (value&StateAttribute::INHERIT)
1172            {
[3480]1173                removeTextureAttribute(unit,attribute->getType());
[836]1174            }
1175            else
1176            {
1177                setAttribute(getOrCreateTextureAttributeList(unit),attribute,value);
[2773]1178                setAssociatedTextureModes(unit,attribute,value);
[836]1179            }
1180        }
1181        else
1182        {
1183            notify(NOTICE)<<"Warning: non texture attribute '"<<attribute->className()<<"' passed to setTextureAttributeAndModes(unit,attr,value), "<<std::endl;
1184            notify(NOTICE)<<"         assuming setAttributeAndModes(attr,value) instead."<<std::endl;
1185            notify(NOTICE)<<"         please change calling code to use appropriate call."<<std::endl;
1186            setAttribute(attribute,value);
1187        }
[828]1188    }
1189}
1190
1191
[3480]1192void StateSet::removeTextureAttribute(unsigned int unit,StateAttribute::Type type)
[828]1193{
1194    if (unit>=_textureAttributeList.size()) return;
1195    AttributeList& attributeList = _textureAttributeList[unit];
[3488]1196    AttributeList::iterator itr = attributeList.find(StateAttribute::TypeMemberPair(type,0));
[828]1197    if (itr!=attributeList.end())
1198    {
[836]1199        if (unit<_textureModeList.size())
1200        {
[2773]1201            setAssociatedTextureModes(unit,itr->second.first.get(),StateAttribute::INHERIT);
[836]1202        }
[4094]1203
1204        if (itr->second.first->getUpdateCallback())
1205        {
1206            setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()-1);
1207        }
1208
1209        if (itr->second.first->getEventCallback())
1210        {
1211            setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()-1);
1212        }
1213
1214
[4091]1215        itr->second.first->removeParent(this);
[828]1216        attributeList.erase(itr);
1217    }
1218}
1219
[3535]1220void StateSet::removeTextureAttribute(unsigned int unit, StateAttribute* attribute)
1221{
[4091]1222    if (!attribute) return;
1223    if (unit>=_textureAttributeList.size()) return;
[828]1224
[4091]1225    AttributeList& attributeList = _textureAttributeList[unit];
1226    AttributeList::iterator itr = attributeList.find(attribute->getTypeMemberPair());
1227    if (itr!=attributeList.end())
1228    {
1229        if (itr->second.first != attribute) return;
[3535]1230
[4091]1231        setAssociatedTextureModes(unit,itr->second.first.get(),StateAttribute::INHERIT);
[4094]1232
1233        if (itr->second.first->getUpdateCallback())
1234        {
1235            setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()-1);
1236        }
1237
1238        if (itr->second.first->getEventCallback())
1239        {
1240            setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()-1);
1241        }
1242
[4091]1243        itr->second.first->removeParent(this);
1244        attributeList.erase(itr);
1245    }
[3535]1246}
1247
[1133]1248StateAttribute* StateSet::getTextureAttribute(unsigned int unit,StateAttribute::Type type)
[828]1249{
1250    if (unit>=_textureAttributeList.size()) return 0;
[3488]1251    return getAttribute(_textureAttributeList[unit],type,0);
[828]1252}
1253
1254
[1133]1255const StateAttribute* StateSet::getTextureAttribute(unsigned int unit,StateAttribute::Type type) const
[828]1256{
1257    if (unit>=_textureAttributeList.size()) return 0;
[3488]1258    return getAttribute(_textureAttributeList[unit],type,0);
[828]1259}
1260
1261
[1133]1262const StateSet::RefAttributePair* StateSet::getTextureAttributePair(unsigned int unit,StateAttribute::Type type) const
[828]1263{
1264    if (unit>=_textureAttributeList.size()) return 0;
[3488]1265    return getAttributePair(_textureAttributeList[unit],type,0);
[828]1266}
1267
[5004]1268bool StateSet::checkValidityOfAssociatedModes(osg::State& state) const
[5001]1269{
[828]1270
[5001]1271
1272    bool modesValid = true;
1273    for(AttributeList::const_iterator itr = _attributeList.begin();
1274        itr!=_attributeList.end();
1275        ++itr)
1276    {
[5004]1277        if (!itr->second.first->checkValidityOfAssociatedModes(state)) modesValid = false;
[5001]1278    }
1279
1280    for(TextureAttributeList::const_iterator taitr=_textureAttributeList.begin();
1281        taitr!=_textureAttributeList.end();
1282        ++taitr)
1283    {
1284        for(AttributeList::const_iterator itr = taitr->begin();
1285            itr!=taitr->end();
1286            ++itr)
1287        {
[5004]1288            if (!itr->second.first->checkValidityOfAssociatedModes(state)) modesValid = false;
[5001]1289        }
1290    }
1291
1292    return modesValid;
1293}
1294
[5885]1295void StateSet::setThreadSafeRefUnref(bool threadSafe)
1296{
1297    Object::setThreadSafeRefUnref(threadSafe);
1298
1299    for(AttributeList::const_iterator itr = _attributeList.begin();
1300        itr!=_attributeList.end();
1301        ++itr)
1302    {
1303        itr->second.first->setThreadSafeRefUnref(threadSafe);
1304    }
1305
1306    for(TextureAttributeList::const_iterator taitr=_textureAttributeList.begin();
1307        taitr!=_textureAttributeList.end();
1308        ++taitr)
1309    {
1310        for(AttributeList::const_iterator itr = taitr->begin();
1311            itr!=taitr->end();
1312            ++itr)
1313        {
1314            itr->second.first->setThreadSafeRefUnref(threadSafe);
1315        }
1316    }
1317}
1318
[3159]1319void StateSet::compileGLObjects(State& state) const
[10]1320{
1321    for(AttributeList::const_iterator itr = _attributeList.begin();
1322        itr!=_attributeList.end();
1323        ++itr)
1324    {
[3159]1325        itr->second.first->compileGLObjects(state);
[10]1326    }
[828]1327
1328    for(TextureAttributeList::const_iterator taitr=_textureAttributeList.begin();
1329        taitr!=_textureAttributeList.end();
1330        ++taitr)
1331    {
1332        for(AttributeList::const_iterator itr = taitr->begin();
1333            itr!=taitr->end();
1334            ++itr)
1335        {
[3159]1336            itr->second.first->compileGLObjects(state);
[828]1337        }
1338    }
[10]1339}
1340
[5882]1341void StateSet::resizeGLObjectBuffers(unsigned int maxSize)
1342{
1343    for(AttributeList::const_iterator itr = _attributeList.begin();
1344        itr!=_attributeList.end();
1345        ++itr)
1346    {
1347        itr->second.first->resizeGLObjectBuffers(maxSize);
1348    }
1349
1350    for(TextureAttributeList::const_iterator taitr=_textureAttributeList.begin();
1351        taitr!=_textureAttributeList.end();
1352        ++taitr)
1353    {
1354        for(AttributeList::const_iterator itr = taitr->begin();
1355            itr!=taitr->end();
1356            ++itr)
1357        {
1358            itr->second.first->resizeGLObjectBuffers(maxSize);
1359        }
1360    }
1361}
1362
[3159]1363void StateSet::releaseGLObjects(State* state) const
1364{
1365    for(AttributeList::const_iterator itr = _attributeList.begin();
1366        itr!=_attributeList.end();
1367        ++itr)
1368    {
1369        itr->second.first->releaseGLObjects(state);
1370    }
1371
1372    for(TextureAttributeList::const_iterator taitr=_textureAttributeList.begin();
1373        taitr!=_textureAttributeList.end();
1374        ++taitr)
1375    {
1376        for(AttributeList::const_iterator itr = taitr->begin();
1377            itr!=taitr->end();
1378            ++itr)
1379        {
1380            itr->second.first->releaseGLObjects(state);
1381        }
1382    }
1383}
1384
[1200]1385void StateSet::setRenderingHint(int hint)
[10]1386{
1387    _renderingHint = hint;
1388    // temporary hack to get new render bins working.
[1166]1389    switch(_renderingHint)
[10]1390    {
[1166]1391        case(TRANSPARENT_BIN):
1392        {
1393            _binMode = USE_RENDERBIN_DETAILS;
[1772]1394            _binNum = 10;
[1166]1395            _binName = "DepthSortedBin";
1396            break;
1397        }
1398        case(OPAQUE_BIN):
1399        {
1400            _binMode = USE_RENDERBIN_DETAILS;
1401            _binNum = 0;
1402            _binName = "RenderBin";
1403            break;
1404        }
1405        default: // DEFAULT_BIN
1406        {
1407            setRenderBinToInherit();
1408            break;
1409        }
[10]1410    }
1411}
1412
[1200]1413void StateSet::setRenderBinDetails(int binNum,const std::string& binName,RenderBinMode mode)
[10]1414{
1415    _binMode = mode;
1416    _binNum = binNum;
1417    _binName = binName;
1418}
1419
[1166]1420void StateSet::setRenderBinToInherit()
[10]1421{
1422    _binMode = INHERIT_RENDERBIN_DETAILS;
1423    _binNum = 0;
1424    _binName = "";
1425}
[828]1426
[1133]1427void StateSet::setMode(ModeList& modeList,StateAttribute::GLMode mode, StateAttribute::GLModeValue value)
[836]1428{
1429    if ((value&StateAttribute::INHERIT)) setModeToInherit(modeList,mode);
1430    else modeList[mode] = value;
1431}
[828]1432
[1133]1433void StateSet::setModeToInherit(ModeList& modeList,StateAttribute::GLMode mode)
[836]1434{
1435    ModeList::iterator itr = modeList.find(mode);
1436    if (itr!=modeList.end())
1437    {
1438        modeList.erase(itr);
1439    }
1440}
[828]1441
[1133]1442StateAttribute::GLModeValue StateSet::getMode(const ModeList& modeList,StateAttribute::GLMode mode) const
[836]1443{
1444    ModeList::const_iterator itr = modeList.find(mode);
1445    if (itr!=modeList.end())
1446    {
1447        return itr->second;
1448    }
1449    else
1450        return StateAttribute::INHERIT;
1451}
[828]1452
[2773]1453class SetAssociateModesHelper : public StateAttribute::ModeUsage
[836]1454{
[2773]1455    public:
1456        SetAssociateModesHelper(StateSet* stateset, StateAttribute::GLModeValue value,unsigned int unit=0):
1457            _stateset(stateset),
1458            _value(value),
1459            _unit(unit) {}
1460           
1461        virtual ~SetAssociateModesHelper() {}
1462       
1463        virtual void usesMode(StateAttribute::GLMode mode)
1464        {
1465            _stateset->setMode(mode,_value);
1466        }
1467       
1468        virtual void usesTextureMode(StateAttribute::GLMode mode)
1469        {
1470            _stateset->setTextureMode(_unit,mode,_value);
1471        }
1472       
1473       
1474       
1475        StateSet*                   _stateset;
1476        StateAttribute::GLModeValue _value;
1477        unsigned int                _unit;
1478};
[828]1479
[7659]1480class RemoveAssociateModesHelper : public StateAttribute::ModeUsage
1481{
1482    public:
1483        RemoveAssociateModesHelper(StateSet* stateset, unsigned int unit=0):
1484            _stateset(stateset),
1485            _unit(unit) {}
1486           
1487        virtual ~RemoveAssociateModesHelper() {}
1488       
1489        virtual void usesMode(StateAttribute::GLMode mode)
1490        {
1491            _stateset->removeMode(mode);
1492        }
1493       
1494        virtual void usesTextureMode(StateAttribute::GLMode mode)
1495        {
1496           _stateset->removeTextureMode(_unit, mode);
1497        }
1498       
1499       
1500       
1501        StateSet*                   _stateset;
1502        unsigned int                _unit;
1503};
1504
[2773]1505void StateSet::setAssociatedModes(const StateAttribute* attribute, StateAttribute::GLModeValue value)
1506{
1507    SetAssociateModesHelper helper(this,value);
1508    attribute->getModeUsage(helper);
[836]1509}
[828]1510
[7659]1511void StateSet::removeAssociatedModes(const StateAttribute* attribute)
1512{
1513    RemoveAssociateModesHelper helper(this);
1514    attribute->getModeUsage(helper);
1515}
1516
[2773]1517void StateSet::setAssociatedTextureModes(unsigned int unit,const StateAttribute* attribute, StateAttribute::GLModeValue value)
1518{
1519    SetAssociateModesHelper helper(this,value,unit);
1520    attribute->getModeUsage(helper);
1521}
1522
[7659]1523void StateSet::removeAssociatedTextureModes(unsigned int unit,const StateAttribute* attribute)
1524{
1525    RemoveAssociateModesHelper helper(this,unit);
1526    attribute->getModeUsage(helper);
1527}
1528
[836]1529void StateSet::setAttribute(AttributeList& attributeList,StateAttribute *attribute, const StateAttribute::OverrideValue value)
1530{
1531    if (attribute)
1532    {
[4094]1533        int delta_update = 0;
1534        int delta_event = 0;
1535       
[4091]1536        AttributeList::iterator itr=attributeList.find(attribute->getTypeMemberPair());
1537        if (itr==attributeList.end())
1538        {
1539            // new entry.
1540            attributeList[attribute->getTypeMemberPair()] = RefAttributePair(attribute,value&(StateAttribute::OVERRIDE|StateAttribute::PROTECTED));
1541            attribute->addParent(this);
[4094]1542           
1543            if (attribute->getUpdateCallback())
1544            {
1545                delta_update = 1;
1546            }
1547
1548            if (attribute->getEventCallback())
1549            {
1550                delta_event = 1;
1551            }
[4091]1552        }
1553        else
1554        {
1555            if (itr->second.first==attribute)
1556            {
1557                // changing just override
1558                itr->second.second = value&(StateAttribute::OVERRIDE|StateAttribute::PROTECTED);
1559            }
1560            else
1561            {
1562                itr->second.first->removeParent(this);
[4094]1563                if (itr->second.first->getUpdateCallback()) --delta_update;
1564                if (itr->second.first->getEventCallback()) --delta_event;
1565
[4091]1566                attribute->addParent(this);
1567                itr->second.first = attribute;
[4094]1568                if (itr->second.first->getUpdateCallback()) ++delta_update;
1569                if (itr->second.first->getEventCallback()) ++delta_event;
1570
1571               itr->second.second = value&(StateAttribute::OVERRIDE|StateAttribute::PROTECTED);
[4091]1572            }
1573        }
[4094]1574
1575        if (delta_update!=0)
1576        {
1577            setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+delta_update);
1578        }
1579
1580        if (delta_event!=0)
1581        {
1582            setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()+delta_event);
1583        }
[836]1584    }
1585}
1586
1587
[3488]1588StateAttribute* StateSet::getAttribute(AttributeList& attributeList,StateAttribute::Type type, unsigned int member)
[836]1589{
[3488]1590    AttributeList::iterator itr = attributeList.find(StateAttribute::TypeMemberPair(type,member));
[836]1591    if (itr!=attributeList.end())
1592    {
1593        return itr->second.first.get();
1594    }
1595    else
1596        return NULL;
1597}
1598
[3488]1599const StateAttribute* StateSet::getAttribute(const AttributeList& attributeList,StateAttribute::Type type, unsigned int member) const
[836]1600{
[3488]1601    AttributeList::const_iterator itr = attributeList.find(StateAttribute::TypeMemberPair(type,member));
[836]1602    if (itr!=attributeList.end())
1603    {
1604        return itr->second.first.get();
1605    }
1606    else
1607        return NULL;
1608}
1609
[3488]1610const StateSet::RefAttributePair* StateSet::getAttributePair(const AttributeList& attributeList,StateAttribute::Type type, unsigned int member) const
[836]1611{
[3488]1612    AttributeList::const_iterator itr = attributeList.find(StateAttribute::TypeMemberPair(type,member));
[836]1613    if (itr!=attributeList.end())
1614    {
1615        return &(itr->second);
1616    }
1617    else
1618        return NULL;
1619}
1620
1621
1622
1623
[4086]1624void StateSet::setUpdateCallback(Callback* ac)
1625{
[4125]1626    //osg::notify(osg::INFO)<<"Setting StateSet callbacks"<<std::endl;
[4094]1627
[4086]1628    if (_updateCallback==ac) return;
1629   
1630    int delta = 0;
1631    if (_updateCallback.valid()) --delta;
1632    if (ac) ++delta;
1633
1634    _updateCallback = ac;
1635   
[4094]1636    if (delta!=0 && _numChildrenRequiringUpdateTraversal==0)
[4086]1637    {
[4125]1638        //osg::notify(osg::INFO)<<"Going to set StateSet parents"<<std::endl;
[4094]1639
[4086]1640        for(ParentList::iterator itr=_parents.begin();
1641            itr!=_parents.end();
1642            ++itr)
1643        {
[4125]1644            //osg::notify(osg::INFO)<<"Setting StateSet parent"<<std::endl;
[4094]1645
1646            osg::Drawable* drawable = dynamic_cast<osg::Drawable*>(*itr);
1647            if (drawable)
1648            {
1649                //drawable->setNumChildrenRequiringUpdateTraversal(drawable->getNumChildrenRequiringUpdateTraversal()+delta);
1650            }
1651            else 
1652            {
1653                osg::Node* node = dynamic_cast<osg::Node*>(*itr);
1654                if (node)
1655                {
1656                    node->setNumChildrenRequiringUpdateTraversal(node->getNumChildrenRequiringUpdateTraversal()+delta);
1657                }
1658            }
[4086]1659        }
1660    }
1661}
1662
[4092]1663void StateSet::runUpdateCallbacks(osg::NodeVisitor* nv)
1664{
[4125]1665    //osg::notify(osg::INFO)<<"Running StateSet callbacks"<<std::endl;
[4094]1666
[4092]1667    if (_updateCallback.valid()) (*_updateCallback)(this,nv);
1668
1669    if (_numChildrenRequiringUpdateTraversal!=0)
1670    {
1671        // run attribute callbacks
1672        for(AttributeList::iterator itr=_attributeList.begin();
1673            itr!=_attributeList.end();
1674            ++itr)
1675        {
[10671]1676            StateAttributeCallback* callback = itr->second.first->getUpdateCallback();
[4092]1677            if (callback) (*callback)(itr->second.first.get(),nv);
1678        }
1679
1680
1681        // run texture attribute callbacks.
1682        for(unsigned int i=0;i<_textureAttributeList.size();++i)
1683        {
1684            AttributeList& attributeList = _textureAttributeList[i];
1685            for(AttributeList::iterator itr=attributeList.begin();
1686                itr!=attributeList.end();
1687                ++itr)
1688            {
[10671]1689                StateAttributeCallback* callback = itr->second.first->getUpdateCallback();
[4092]1690                if (callback) (*callback)(itr->second.first.get(),nv);
1691            }
1692        }
1693
1694
1695        // run uniform callbacks.
1696        for(UniformList::iterator uitr = _uniformList.begin();
1697            uitr != _uniformList.end();
1698            ++uitr)
1699        {
1700            Uniform::Callback* callback = uitr->second.first->getUpdateCallback();
1701            if (callback) (*callback)(uitr->second.first.get(),nv);
1702        }
1703    }
1704}
1705
[4086]1706void StateSet::setEventCallback(Callback* ac)
1707{
1708    if (_eventCallback==ac) return;
1709   
1710    int delta = 0;
1711    if (_eventCallback.valid()) --delta;
1712    if (ac) ++delta;
1713
1714    _eventCallback = ac;
1715   
[4094]1716    if (delta!=0 && _numChildrenRequiringEventTraversal==0)
[4086]1717    {
1718        for(ParentList::iterator itr=_parents.begin();
1719            itr!=_parents.end();
1720            ++itr)
1721        {
[4094]1722            osg::Drawable* drawable = dynamic_cast<osg::Drawable*>(*itr);
1723            if (drawable)
1724            {
1725                //drawable->setNumChildrenRequiringUpdateTraversal(drawable->getNumChildrenRequiringUpdateTraversal()+delta);
1726            }
1727            else 
1728            {
1729                osg::Node* node = dynamic_cast<osg::Node*>(*itr);
1730                if (node)
1731                {
1732                    node->setNumChildrenRequiringEventTraversal(node->getNumChildrenRequiringEventTraversal()+delta);
1733                }
1734            }
[4086]1735        }
1736    }
1737}
[4092]1738
1739void StateSet::runEventCallbacks(osg::NodeVisitor* nv)
1740{
1741    if (_eventCallback.valid()) (*_eventCallback)(this,nv);
1742
1743    if (_numChildrenRequiringEventTraversal!=0)
1744    {
1745        // run attribute callbacks
1746        for(AttributeList::iterator itr=_attributeList.begin();
1747            itr!=_attributeList.end();
1748            ++itr)
1749        {
[10671]1750            StateAttributeCallback* callback = itr->second.first->getEventCallback();
[4092]1751            if (callback) (*callback)(itr->second.first.get(),nv);
1752        }
1753
1754
1755        // run texture attribute callbacks.
1756        for(unsigned int i=0;i<_textureAttributeList.size();++i)
1757        {
1758            AttributeList& attributeList = _textureAttributeList[i];
1759            for(AttributeList::iterator itr=attributeList.begin();
1760                itr!=attributeList.end();
1761                ++itr)
1762            {
[10671]1763                StateAttributeCallback* callback = itr->second.first->getEventCallback();
[4092]1764                if (callback) (*callback)(itr->second.first.get(),nv);
1765            }
1766        }
1767
1768
1769        // run uniform callbacks.
1770        for(UniformList::iterator uitr = _uniformList.begin();
1771            uitr != _uniformList.end();
1772            ++uitr)
1773        {
1774            Uniform::Callback* callback = uitr->second.first->getEventCallback();
1775            if (callback) (*callback)(uitr->second.first.get(),nv);
1776        }
1777    }
1778}
[4094]1779
1780void StateSet::setNumChildrenRequiringUpdateTraversal(unsigned int num)
1781{
1782    // if no changes just return.
1783    if (_numChildrenRequiringUpdateTraversal==num) return;
1784
1785    // note, if _updateCallback is set then the
1786    // parents won't be affected by any changes to
1787    // _numChildrenRequiringUpdateTraversal so no need to inform them.
1788    if (!_updateCallback && !_parents.empty())
1789    {
1790   
1791        // need to pass on changes to parents.       
1792        int delta = 0;
1793        if (_numChildrenRequiringUpdateTraversal>0) --delta;
1794        if (num>0) ++delta;
1795        if (delta!=0)
1796        {
1797            // the number of callbacks has changed, need to pass this
1798            // on to parents so they know whether app traversal is
[7648]1799            // required on this subgraph.
[4094]1800            for(ParentList::iterator itr =_parents.begin();
1801                itr != _parents.end();
1802                ++itr)
1803            {   
1804                osg::Drawable* drawable = dynamic_cast<osg::Drawable*>(*itr);
1805                if (drawable)
1806                {
[4100]1807                    drawable->setNumChildrenRequiringUpdateTraversal(drawable->getNumChildrenRequiringUpdateTraversal()+delta);
[4094]1808                }
1809                else 
1810                {
1811                    osg::Node* node = dynamic_cast<osg::Node*>(*itr);
1812                    if (node)
1813                    {
1814                        node->setNumChildrenRequiringUpdateTraversal(node->getNumChildrenRequiringUpdateTraversal()+delta);
1815                    }
1816                }
1817            }
1818        }
1819    }
1820   
1821    // finally update this objects value.
1822    _numChildrenRequiringUpdateTraversal=num;
1823}
1824
1825void StateSet::setNumChildrenRequiringEventTraversal(unsigned int num)
1826{
1827    // if no changes just return.
1828    if (_numChildrenRequiringEventTraversal==num) return;
1829
1830    // note, if _EventCallback is set then the
1831    // parents won't be affected by any changes to
1832    // _numChildrenRequiringEventTraversal so no need to inform them.
1833    if (!_eventCallback && !_parents.empty())
1834    {
1835   
1836        // need to pass on changes to parents.       
1837        int delta = 0;
1838        if (_numChildrenRequiringEventTraversal>0) --delta;
1839        if (num>0) ++delta;
1840        if (delta!=0)
1841        {
1842            // the number of callbacks has changed, need to pass this
1843            // on to parents so they know whether app traversal is
[7648]1844            // required on this subgraph.
[4094]1845            for(ParentList::iterator itr =_parents.begin();
1846                itr != _parents.end();
1847                ++itr)
1848            {   
1849                osg::Drawable* drawable = dynamic_cast<osg::Drawable*>(*itr);
1850                if (drawable)
1851                {
[4100]1852                    drawable->setNumChildrenRequiringEventTraversal(drawable->getNumChildrenRequiringEventTraversal()+delta);
[4094]1853                }
1854                else 
1855                {
1856                    osg::Node* node = dynamic_cast<osg::Node*>(*itr);
1857                    if (node)
1858                    {
1859                        node->setNumChildrenRequiringEventTraversal(node->getNumChildrenRequiringEventTraversal()+delta);
1860                    }
1861                }
1862            }
1863        }
1864    }
1865   
1866    // finally Event this objects value.
1867    _numChildrenRequiringEventTraversal=num;
1868}
Note: See TracBrowser for help on using the browser.