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

Revision 9354, 61.2 kB (checked in by robert, 5 years ago)

From Paul Martz, "I'm not sure why this message was added, but it doesn't appear to merit INFO verbosity. Changing this from INFO to DEBUG_FP."

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