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

Revision 13041, 61.4 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

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