source: OGRE/trunk/ogrenew/OgreMain/src/OgrePass.cpp @ 692

Revision 692, 47.8 KB checked in by mattausch, 18 years ago (diff)

adding ogre 1.2 and dependencies

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://ogre.sourceforge.net/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#include "OgreStableHeaders.h"
26
27#include "OgrePass.h"
28#include "OgreTechnique.h"
29#include "OgreException.h"
30#include "OgreGpuProgramUsage.h"
31#include "OgreTextureUnitState.h"
32#include "OgreStringConverter.h"
33
34namespace Ogre {
35       
36    //-----------------------------------------------------------------------------
37        Pass::PassSet Pass::msDirtyHashList;
38    Pass::PassSet Pass::msPassGraveyard;
39    //-----------------------------------------------------------------------------
40        Pass::Pass(Technique* parent, unsigned short index)
41        : mParent(parent), mIndex(index), mPassIterationCount(0)
42    {
43        // Default to white ambient & diffuse, no specular / emissive
44            mAmbient = mDiffuse = ColourValue::White;
45            mSpecular = mEmissive = ColourValue::Black;
46            mShininess = 0;
47        mPointSize = 1.0f;
48                mPointMinSize = 0.0f;
49                mPointMaxSize = 0.0f;
50                mPointSpritesEnabled = false;
51                mPointAttenuationEnabled = false;
52                mPointAttenuationCoeffs[0] = 1.0f;
53                mPointAttenuationCoeffs[1] = mPointAttenuationCoeffs[2] = 0.0f;
54        mTracking = TVC_NONE;
55        mHash = 0;
56
57        // By default, don't override the scene's fog settings
58        mFogOverride = false;
59        mFogMode = FOG_NONE;
60        mFogColour = ColourValue::White;
61        mFogStart = 0.0;
62        mFogEnd = 1.0;
63        mFogDensity = 0.001;
64
65            // Default blending (overwrite)
66            mSourceBlendFactor = SBF_ONE;
67            mDestBlendFactor = SBF_ZERO;
68
69            mDepthCheck = true;
70            mDepthWrite = true;
71        mColourWrite = true;
72            mDepthFunc = CMPF_LESS_EQUAL;
73        mDepthBias = 0;
74                mAlphaRejectFunc = CMPF_ALWAYS_PASS;
75                mAlphaRejectVal = 0;
76            mCullMode = CULL_CLOCKWISE;
77            mManualCullMode = MANUAL_CULL_BACK;
78            mLightingEnabled = true;
79        mMaxSimultaneousLights = OGRE_MAX_SIMULTANEOUS_LIGHTS;
80                mIteratePerLight = false;
81        mRunOnlyForOneLightType = true;
82        mOnlyLightType = Light::LT_POINT;
83            mShadeOptions = SO_GOURAUD;
84                mPolygonMode = PM_SOLID;
85
86                mVertexProgramUsage = NULL;
87        mShadowCasterVertexProgramUsage = NULL;
88        mShadowReceiverVertexProgramUsage = NULL;
89                mShadowReceiverFragmentProgramUsage = NULL;
90                mFragmentProgramUsage = NULL;
91
92        mQueuedForDeletion = false;
93
94        // default name to index
95        mName = StringConverter::toString(mIndex);
96
97        _dirtyHash();
98   }
99       
100    //-----------------------------------------------------------------------------
101        Pass::Pass(Technique *parent, unsigned short index, const Pass& oth)
102        :mParent(parent), mIndex(index), mQueuedForDeletion(false), mPassIterationCount(0)
103    {
104        *this = oth;
105        mParent = parent;
106        mIndex = index;
107        mQueuedForDeletion = false;
108        _dirtyHash();
109    }
110    //-----------------------------------------------------------------------------
111    Pass::~Pass()
112    {
113
114    }
115    //-----------------------------------------------------------------------------
116    Pass& Pass::operator=(const Pass& oth)
117    {
118        mName = oth.mName;
119            mAmbient = oth.mAmbient;
120        mDiffuse = oth.mDiffuse;
121            mSpecular = oth.mSpecular;
122        mEmissive = oth.mEmissive;
123            mShininess = oth.mShininess;
124        mTracking = oth.mTracking;
125
126        // Copy fog parameters
127        mFogOverride = oth.mFogOverride;
128        mFogMode = oth.mFogMode;
129        mFogColour = oth.mFogColour;
130        mFogStart = oth.mFogStart;
131        mFogEnd = oth.mFogEnd;
132        mFogDensity = oth.mFogDensity;
133
134            // Default blending (overwrite)
135            mSourceBlendFactor = oth.mSourceBlendFactor;
136            mDestBlendFactor = oth.mDestBlendFactor;
137
138            mDepthCheck = oth.mDepthCheck;
139            mDepthWrite = oth.mDepthWrite;
140                mAlphaRejectFunc = oth.mAlphaRejectFunc;
141                mAlphaRejectVal = oth.mAlphaRejectVal;
142        mColourWrite = oth.mColourWrite;
143            mDepthFunc = oth.mDepthFunc;
144        mDepthBias = oth.mDepthBias;
145            mCullMode = oth.mCullMode;
146            mManualCullMode = oth.mManualCullMode;
147            mLightingEnabled = oth.mLightingEnabled;
148        mMaxSimultaneousLights = oth.mMaxSimultaneousLights;
149                mIteratePerLight = oth.mIteratePerLight;
150        mRunOnlyForOneLightType = oth.mRunOnlyForOneLightType;
151        mOnlyLightType = oth.mOnlyLightType;
152            mShadeOptions = oth.mShadeOptions;
153                mPolygonMode = oth.mPolygonMode;
154        mPassIterationCount = oth.mPassIterationCount;
155                mPointSize = oth.mPointSize;
156                mPointMinSize = oth.mPointMinSize;
157                mPointMaxSize = oth.mPointMaxSize;
158                mPointSpritesEnabled = oth.mPointSpritesEnabled;
159                mPointAttenuationEnabled = oth.mPointAttenuationEnabled;
160                memcpy(mPointAttenuationCoeffs, oth.mPointAttenuationCoeffs, sizeof(Real)*3);
161
162
163                if (oth.mVertexProgramUsage)
164                {
165                        mVertexProgramUsage = new GpuProgramUsage(*(oth.mVertexProgramUsage));
166                }
167                else
168                {
169                    mVertexProgramUsage = NULL;
170                }
171        if (oth.mShadowCasterVertexProgramUsage)
172        {
173            mShadowCasterVertexProgramUsage = new GpuProgramUsage(*(oth.mShadowCasterVertexProgramUsage));
174        }
175        else
176        {
177            mShadowCasterVertexProgramUsage = NULL;
178        }
179        if (oth.mShadowReceiverVertexProgramUsage)
180        {
181            mShadowReceiverVertexProgramUsage = new GpuProgramUsage(*(oth.mShadowReceiverVertexProgramUsage));
182        }
183        else
184        {
185            mShadowReceiverVertexProgramUsage = NULL;
186        }
187                if (oth.mFragmentProgramUsage)
188                {
189                    mFragmentProgramUsage = new GpuProgramUsage(*(oth.mFragmentProgramUsage));
190        }
191        else
192        {
193                    mFragmentProgramUsage = NULL;
194        }
195                if (oth.mShadowReceiverFragmentProgramUsage)
196                {
197                        mShadowReceiverFragmentProgramUsage = new GpuProgramUsage(*(oth.mShadowReceiverFragmentProgramUsage));
198                }
199                else
200                {
201                        mShadowReceiverFragmentProgramUsage = NULL;
202                }
203
204                TextureUnitStates::const_iterator i, iend;
205
206        // Clear texture units but doesn't notify need recompilation in the case
207        // we are cloning, The parent material will take care of this.
208        iend = mTextureUnitStates.end();
209        for (i = mTextureUnitStates.begin(); i != iend; ++i)
210        {
211            delete *i;
212        }
213
214        mTextureUnitStates.clear();
215
216                // Copy texture units
217                iend = oth.mTextureUnitStates.end();
218                for (i = oth.mTextureUnitStates.begin(); i != iend; ++i)
219                {
220                        TextureUnitState* t = new TextureUnitState(this, *(*i));
221                        mTextureUnitStates.push_back(t);
222                }
223
224        _dirtyHash();
225
226                return *this;
227    }
228    //-----------------------------------------------------------------------
229    void Pass::setName(const String& name)
230    {
231        mName = name;
232    }
233    //-----------------------------------------------------------------------
234    void Pass::setPointSize(Real ps)
235    {
236            mPointSize = ps;
237    }
238    //-----------------------------------------------------------------------
239        void Pass::setPointSpritesEnabled(bool enabled)
240        {
241                mPointSpritesEnabled = enabled;
242        }
243    //-----------------------------------------------------------------------
244        bool Pass::getPointSpritesEnabled(void) const
245        {
246                return mPointSpritesEnabled;
247        }
248    //-----------------------------------------------------------------------
249        void Pass::setPointAttenuation(bool enabled,
250                Real constant, Real linear, Real quadratic)
251        {
252                mPointAttenuationEnabled = enabled;
253                mPointAttenuationCoeffs[0] = constant;
254                mPointAttenuationCoeffs[1] = linear;
255                mPointAttenuationCoeffs[2] = quadratic;
256        }
257    //-----------------------------------------------------------------------
258        bool Pass::isPointAttenuationEnabled(void) const
259        {
260                return mPointAttenuationEnabled;
261        }
262    //-----------------------------------------------------------------------
263        Real Pass::getPointAttenuationConstant(void) const
264        {
265                return mPointAttenuationCoeffs[0];
266        }
267    //-----------------------------------------------------------------------
268        Real Pass::getPointAttenuationLinear(void) const
269        {
270                return mPointAttenuationCoeffs[1];
271        }
272    //-----------------------------------------------------------------------
273        Real Pass::getPointAttenuationQuadratic(void) const
274        {
275                return mPointAttenuationCoeffs[2];
276        }
277    //-----------------------------------------------------------------------
278        void Pass::setPointMinSize(Real min)
279        {
280                mPointMinSize = min;
281        }
282    //-----------------------------------------------------------------------
283        Real Pass::getPointMinSize(void) const
284        {
285                return mPointMinSize;
286        }
287    //-----------------------------------------------------------------------
288        void Pass::setPointMaxSize(Real max)
289        {
290                mPointMaxSize = max;
291        }
292    //-----------------------------------------------------------------------
293        Real Pass::getPointMaxSize(void) const
294        {
295                return mPointMaxSize;
296        }
297    //-----------------------------------------------------------------------
298    void Pass::setAmbient(Real red, Real green, Real blue)
299    {
300            mAmbient.r = red;
301            mAmbient.g = green;
302            mAmbient.b = blue;
303
304    }
305    //-----------------------------------------------------------------------
306    void Pass::setAmbient(const ColourValue& ambient)
307    {
308            mAmbient = ambient;
309    }
310    //-----------------------------------------------------------------------
311    void Pass::setDiffuse(Real red, Real green, Real blue, Real alpha)
312    {
313            mDiffuse.r = red;
314            mDiffuse.g = green;
315            mDiffuse.b = blue;
316                mDiffuse.a = alpha;
317    }
318    //-----------------------------------------------------------------------
319    void Pass::setDiffuse(const ColourValue& diffuse)
320    {
321            mDiffuse = diffuse;
322    }
323    //-----------------------------------------------------------------------
324    void Pass::setSpecular(Real red, Real green, Real blue, Real alpha)
325    {
326            mSpecular.r = red;
327            mSpecular.g = green;
328            mSpecular.b = blue;
329                mSpecular.a = alpha;
330    }
331    //-----------------------------------------------------------------------
332    void Pass::setSpecular(const ColourValue& specular)
333    {
334            mSpecular = specular;
335    }
336    //-----------------------------------------------------------------------
337    void Pass::setShininess(Real val)
338    {
339            mShininess = val;
340    }
341    //-----------------------------------------------------------------------
342    void Pass::setSelfIllumination(Real red, Real green, Real blue)
343    {
344            mEmissive.r = red;
345            mEmissive.g = green;
346            mEmissive.b = blue;
347
348    }
349    //-----------------------------------------------------------------------
350    void Pass::setSelfIllumination(const ColourValue& selfIllum)
351    {
352            mEmissive = selfIllum;
353    }
354    //-----------------------------------------------------------------------
355    void Pass::setVertexColourTracking(TrackVertexColourType tracking)
356    {
357        mTracking = tracking;
358    }
359    //-----------------------------------------------------------------------
360    Real Pass::getPointSize(void) const
361    {
362            return mPointSize;
363    }
364    //-----------------------------------------------------------------------
365    const ColourValue& Pass::getAmbient(void) const
366    {
367            return mAmbient;
368    }
369    //-----------------------------------------------------------------------
370    const ColourValue& Pass::getDiffuse(void) const
371    {
372            return mDiffuse;
373    }
374    //-----------------------------------------------------------------------
375    const ColourValue& Pass::getSpecular(void) const
376    {
377            return mSpecular;
378    }
379    //-----------------------------------------------------------------------
380    const ColourValue& Pass::getSelfIllumination(void) const
381    {
382            return mEmissive;
383    }
384    //-----------------------------------------------------------------------
385    Real Pass::getShininess(void) const
386    {
387            return mShininess;
388    }
389    //-----------------------------------------------------------------------
390    TrackVertexColourType Pass::getVertexColourTracking(void) const
391    {
392        return mTracking;
393    }
394    //-----------------------------------------------------------------------
395    TextureUnitState* Pass::createTextureUnitState(void)
396    {
397        TextureUnitState *t = new TextureUnitState(this);
398        addTextureUnitState(t);
399            return t;
400    }
401    //-----------------------------------------------------------------------
402    TextureUnitState* Pass::createTextureUnitState(
403        const String& textureName, unsigned short texCoordSet)
404    {
405        TextureUnitState *t = new TextureUnitState(this);
406            t->setTextureName(textureName);
407            t->setTextureCoordSet(texCoordSet);
408        addTextureUnitState(t);
409            return t;
410    }
411    //-----------------------------------------------------------------------
412        void Pass::addTextureUnitState(TextureUnitState* state)
413        {
414        assert(state && "state is 0 in Pass::addTextureUnitState()");
415        if (state)
416        {
417            // only attach TUS to pass if TUS does not belong to another pass
418            if ((state->getParent() == 0) || (state->getParent() == this))
419            {
420                        mTextureUnitStates.push_back(state);
421                                // Notify state
422                                state->_notifyParent(this);
423                // if texture unit state name is empty then give it a default name based on its index
424                if (state->getName().empty())
425                {
426                    // its the last entry in the container so its index is size - 1
427                    size_t idx = mTextureUnitStates.size() - 1;
428                    state->setName( StringConverter::toString(idx) );
429                }
430                // Needs recompilation
431                mParent->_notifyNeedsRecompile();
432                _dirtyHash();
433            }
434            else
435            {
436                            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "TextureUnitState already attached to another pass",
437                                    "Pass:addTextureUnitState");
438
439            }
440        }
441        }
442    //-----------------------------------------------------------------------
443    TextureUnitState* Pass::getTextureUnitState(unsigned short index)
444    {
445        assert (index < mTextureUnitStates.size() && "Index out of bounds");
446            return mTextureUnitStates[index];
447    }
448    //-----------------------------------------------------------------------------
449    TextureUnitState* Pass::getTextureUnitState(const String& name)
450    {
451        TextureUnitStates::iterator i    = mTextureUnitStates.begin();
452        TextureUnitStates::iterator iend = mTextureUnitStates.end();
453        TextureUnitState* foundTUS = 0;
454
455        // iterate through TUS Container to find a match
456        while (i != iend)
457        {
458            if ( (*i)->getName() == name )
459            {
460                foundTUS = (*i);
461                break;
462            }
463
464            ++i;
465        }
466
467        return foundTUS;
468    }
469        //-----------------------------------------------------------------------
470        const TextureUnitState* Pass::getTextureUnitState(unsigned short index) const
471        {
472                assert (index < mTextureUnitStates.size() && "Index out of bounds");
473                return mTextureUnitStates[index];
474        }
475        //-----------------------------------------------------------------------------
476        const TextureUnitState* Pass::getTextureUnitState(const String& name) const
477        {
478                TextureUnitStates::const_iterator i    = mTextureUnitStates.begin();
479                TextureUnitStates::const_iterator iend = mTextureUnitStates.end();
480                const TextureUnitState* foundTUS = 0;
481
482                // iterate through TUS Container to find a match
483                while (i != iend)
484                {
485                        if ( (*i)->getName() == name )
486                        {
487                                foundTUS = (*i);
488                                break;
489                        }
490
491                        ++i;
492                }
493
494                return foundTUS;
495        }
496
497    //-----------------------------------------------------------------------
498    unsigned short Pass::getTextureUnitStateIndex(const TextureUnitState* state)
499    {
500        assert(state && "state is 0 in Pass::addTextureUnitState()");
501        unsigned short idx = 0;
502
503        // only find index for state attached to this pass
504        if (state->getParent() == this)
505        {
506            // iterate through TUS container and find matching pointer to state
507            TextureUnitStates::iterator i    = mTextureUnitStates.begin();
508            TextureUnitStates::iterator iend = mTextureUnitStates.end();
509            while (i != iend)
510            {
511                if ( (*i) == state )
512                {
513                    // calculate index
514                    idx = static_cast<unsigned short>(i - mTextureUnitStates.begin());
515                    break;
516                }
517
518                ++i;
519            }
520        }
521        else
522        {
523                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "TextureUnitState is not attached to this pass",
524                                "Pass:getTextureUnitStateIndex");
525        }
526
527        return idx;
528    }
529
530    //-----------------------------------------------------------------------
531    Pass::TextureUnitStateIterator
532        Pass::getTextureUnitStateIterator(void)
533    {
534        return TextureUnitStateIterator(mTextureUnitStates.begin(), mTextureUnitStates.end());
535    }
536        //-----------------------------------------------------------------------
537        Pass::ConstTextureUnitStateIterator
538                Pass::getTextureUnitStateIterator(void) const
539        {
540                return ConstTextureUnitStateIterator(mTextureUnitStates.begin(), mTextureUnitStates.end());
541        }
542    //-----------------------------------------------------------------------
543    void Pass::removeTextureUnitState(unsigned short index)
544    {
545        assert (index < mTextureUnitStates.size() && "Index out of bounds");
546
547        TextureUnitStates::iterator i = mTextureUnitStates.begin() + index;
548        delete *i;
549            mTextureUnitStates.erase(i);
550        if (!mQueuedForDeletion)
551        {
552            // Needs recompilation
553            mParent->_notifyNeedsRecompile();
554        }
555        _dirtyHash();
556    }
557    //-----------------------------------------------------------------------
558    void Pass::removeAllTextureUnitStates(void)
559    {
560        TextureUnitStates::iterator i, iend;
561        iend = mTextureUnitStates.end();
562        for (i = mTextureUnitStates.begin(); i != iend; ++i)
563        {
564            delete *i;
565        }
566        mTextureUnitStates.clear();
567        if (!mQueuedForDeletion)
568        {       
569            // Needs recompilation
570            mParent->_notifyNeedsRecompile();
571        }
572        _dirtyHash();
573    }
574    //-----------------------------------------------------------------------
575    void Pass::setSceneBlending(SceneBlendType sbt)
576    {
577            // Turn predefined type into blending factors
578            switch (sbt)
579            {
580            case SBT_TRANSPARENT_ALPHA:
581                    setSceneBlending(SBF_SOURCE_ALPHA, SBF_ONE_MINUS_SOURCE_ALPHA);
582                    break;
583            case SBT_TRANSPARENT_COLOUR:
584                    setSceneBlending(SBF_SOURCE_COLOUR, SBF_ONE_MINUS_SOURCE_COLOUR);
585                    break;
586                case SBT_MODULATE:
587                        setSceneBlending(SBF_DEST_COLOUR, SBF_ZERO);
588                        break;
589            case SBT_ADD:
590                    setSceneBlending(SBF_ONE, SBF_ONE);
591                    break;
592        case SBT_REPLACE:
593            setSceneBlending(SBF_ONE, SBF_ZERO);
594            break;
595            // TODO: more
596            }
597
598    }
599    //-----------------------------------------------------------------------
600    void Pass::setSceneBlending(SceneBlendFactor sourceFactor, SceneBlendFactor destFactor)
601    {
602            mSourceBlendFactor = sourceFactor;
603            mDestBlendFactor = destFactor;
604    }
605    //-----------------------------------------------------------------------
606    SceneBlendFactor Pass::getSourceBlendFactor(void) const
607    {
608            return mSourceBlendFactor;
609    }
610    //-----------------------------------------------------------------------
611    SceneBlendFactor Pass::getDestBlendFactor(void) const
612    {
613            return mDestBlendFactor;
614    }
615    //-----------------------------------------------------------------------
616    bool Pass::isTransparent(void) const
617    {
618                // Transparent if any of the destination colour is taken into account
619                if (mDestBlendFactor == SBF_ZERO &&
620                        mSourceBlendFactor != SBF_DEST_COLOUR &&
621                        mSourceBlendFactor != SBF_ONE_MINUS_DEST_COLOUR &&
622                        mSourceBlendFactor != SBF_DEST_ALPHA &&
623                        mSourceBlendFactor != SBF_ONE_MINUS_DEST_ALPHA)
624                {
625                    return false;
626                }
627            else
628                {
629                    return true;
630                }
631    }
632    //-----------------------------------------------------------------------
633    void Pass::setDepthCheckEnabled(bool enabled)
634    {
635            mDepthCheck = enabled;
636    }
637    //-----------------------------------------------------------------------
638    bool Pass::getDepthCheckEnabled(void) const
639    {
640            return mDepthCheck;
641    }
642    //-----------------------------------------------------------------------
643    void Pass::setDepthWriteEnabled(bool enabled)
644    {
645            mDepthWrite = enabled;
646    }
647    //-----------------------------------------------------------------------
648    bool Pass::getDepthWriteEnabled(void) const
649    {
650            return mDepthWrite;
651    }
652    //-----------------------------------------------------------------------
653    void Pass::setDepthFunction( CompareFunction func)
654    {
655            mDepthFunc = func;
656    }
657    //-----------------------------------------------------------------------
658    CompareFunction Pass::getDepthFunction(void) const
659    {
660            return mDepthFunc;
661    }
662        //-----------------------------------------------------------------------
663        void Pass::setAlphaRejectSettings(CompareFunction func, unsigned char value)
664        {
665                mAlphaRejectFunc = func;
666                mAlphaRejectVal = value;
667        }
668        //-----------------------------------------------------------------------
669        void Pass::setAlphaRejectFunction(CompareFunction func)
670        {
671                mAlphaRejectFunc = func;
672        }
673        //-----------------------------------------------------------------------
674        void Pass::setAlphaRejectValue(unsigned char val)
675        {
676                mAlphaRejectVal = val;
677        }
678    //-----------------------------------------------------------------------
679        void Pass::setColourWriteEnabled(bool enabled)
680        {
681                mColourWrite = enabled;
682        }
683    //-----------------------------------------------------------------------
684        bool Pass::getColourWriteEnabled(void) const
685        {
686                return mColourWrite;
687        }
688    //-----------------------------------------------------------------------
689    void Pass::setCullingMode( CullingMode mode)
690    {
691            mCullMode = mode;
692    }
693    //-----------------------------------------------------------------------
694    CullingMode Pass::getCullingMode(void) const
695    {
696            return mCullMode;
697    }
698    //-----------------------------------------------------------------------
699    void Pass::setLightingEnabled(bool enabled)
700    {
701            mLightingEnabled = enabled;
702    }
703    //-----------------------------------------------------------------------
704    bool Pass::getLightingEnabled(void) const
705    {
706            return mLightingEnabled;
707    }
708    //-----------------------------------------------------------------------
709    void Pass::setMaxSimultaneousLights(unsigned short maxLights)
710    {
711        mMaxSimultaneousLights = maxLights;
712    }
713    //-----------------------------------------------------------------------
714    unsigned short Pass::getMaxSimultaneousLights(void) const
715    {
716        return mMaxSimultaneousLights;
717    }
718    //-----------------------------------------------------------------------
719    void Pass::setIteratePerLight(bool enabled,
720            bool onlyForOneLightType, Light::LightTypes lightType)
721    {
722        mIteratePerLight = enabled;
723        mRunOnlyForOneLightType = onlyForOneLightType;
724        mOnlyLightType = lightType;
725    }
726    //-----------------------------------------------------------------------
727    void Pass::setShadingMode(ShadeOptions mode)
728    {
729            mShadeOptions = mode;
730    }
731    //-----------------------------------------------------------------------
732    ShadeOptions Pass::getShadingMode(void) const
733    {
734            return mShadeOptions;
735    }
736        //-----------------------------------------------------------------------
737        void Pass::setPolygonMode(PolygonMode mode)
738        {
739                mPolygonMode = mode;
740        }
741        //-----------------------------------------------------------------------
742        PolygonMode Pass::getPolygonMode(void) const
743        {
744                return mPolygonMode;
745        }
746    //-----------------------------------------------------------------------
747    void Pass::setManualCullingMode(ManualCullingMode mode)
748    {
749            mManualCullMode = mode;
750    }
751    //-----------------------------------------------------------------------
752    ManualCullingMode Pass::getManualCullingMode(void) const
753    {
754            return mManualCullMode;
755    }
756    //-----------------------------------------------------------------------
757    void Pass::setFog(bool overrideScene, FogMode mode, const ColourValue& colour, Real density, Real start, Real end)
758    {
759            mFogOverride = overrideScene;
760            if (overrideScene)
761            {
762                    mFogMode = mode;
763                    mFogColour = colour;
764                    mFogStart = start;
765                    mFogEnd = end;
766                    mFogDensity = density;
767            }
768    }
769    //-----------------------------------------------------------------------
770    bool Pass::getFogOverride(void) const
771    {
772            return mFogOverride;
773    }
774    //-----------------------------------------------------------------------
775    FogMode Pass::getFogMode(void) const
776    {
777            return mFogMode;
778    }
779    //-----------------------------------------------------------------------
780    const ColourValue& Pass::getFogColour(void) const
781    {
782            return mFogColour;
783    }
784    //-----------------------------------------------------------------------
785    Real Pass::getFogStart(void) const
786    {
787            return mFogStart;
788    }
789    //-----------------------------------------------------------------------
790    Real Pass::getFogEnd(void) const
791    {
792            return mFogEnd;
793    }
794    //-----------------------------------------------------------------------
795    Real Pass::getFogDensity(void) const
796    {
797            return mFogDensity;
798    }
799    //-----------------------------------------------------------------------
800    void Pass::setDepthBias(ushort bias)
801    {
802        assert(bias <= 16 && "Depth bias must be between 0 and 16");
803        mDepthBias = bias;
804    }
805    //-----------------------------------------------------------------------
806    ushort Pass::getDepthBias(void) const
807    {
808        return mDepthBias;
809    }
810    //-----------------------------------------------------------------------
811        Pass* Pass::_split(unsigned short numUnits)
812        {
813                if (mVertexProgramUsage || mFragmentProgramUsage)
814                {
815                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Programmable passes cannot be "
816                                "automatically split, define a fallback technique instead.",
817                                "Pass:_split");
818                }
819
820                if (mTextureUnitStates.size() > numUnits)
821                {
822                        size_t start = mTextureUnitStates.size() - numUnits;
823                       
824                        Pass* newPass = mParent->createPass();
825
826                        TextureUnitStates::iterator istart, i, iend;
827                        iend = mTextureUnitStates.end();
828                        i = istart = mTextureUnitStates.begin() + start;
829                        // Set the new pass to fallback using scene blend
830                        newPass->setSceneBlending(
831                                (*i)->getColourBlendFallbackSrc(), (*i)->getColourBlendFallbackDest());
832                        // Fixup the texture unit 0   of new pass   blending method   to replace
833                        // all colour and alpha   with texture without adjustment, because we
834                        // assume it's detail texture.
835                        (*i)->setColourOperationEx(LBX_SOURCE1,   LBS_TEXTURE, LBS_CURRENT);
836                        (*i)->setAlphaOperation(LBX_SOURCE1, LBS_TEXTURE, LBS_CURRENT);
837
838                        // Add all the other texture unit states
839                        for (; i != iend; ++i)
840                        {
841                                // detach from parent first
842                                (*i)->_notifyParent(0);
843                                newPass->addTextureUnitState(*i);
844                        }
845                        // Now remove texture units from this Pass, we don't need to delete since they've
846                        // been transferred
847                        mTextureUnitStates.erase(istart, iend);
848                        _dirtyHash();
849                        return newPass;
850                }
851                return NULL;
852        }
853        //-----------------------------------------------------------------------------
854        void Pass::_notifyIndex(unsigned short index)
855        {
856                if (mIndex != index)
857                {
858                        mIndex = index;
859                        _dirtyHash();
860                }
861        }
862    //-----------------------------------------------------------------------
863        void Pass::_load(void)
864        {
865                // We assume the Technique only calls this when the material is being
866                // loaded
867
868                // Load each TextureUnitState
869                TextureUnitStates::iterator i, iend;
870                iend = mTextureUnitStates.end();
871                for (i = mTextureUnitStates.begin(); i != iend; ++i)
872                {
873                        (*i)->_load();
874                }
875
876                // Load programs
877                if (mVertexProgramUsage)
878                {
879                        // Load vertex program
880            mVertexProgramUsage->_load();
881        }
882        if (mShadowCasterVertexProgramUsage)
883        {
884            // Load vertex program
885            mShadowCasterVertexProgramUsage->_load();
886        }
887        if (mShadowReceiverVertexProgramUsage)
888        {
889            // Load vertex program
890            mShadowReceiverVertexProgramUsage->_load();
891        }
892
893        if (mFragmentProgramUsage)
894        {
895                        // Load fragment program
896            mFragmentProgramUsage->_load();
897                }
898                if (mShadowReceiverFragmentProgramUsage)
899                {
900                        // Load Fragment program
901                        mShadowReceiverFragmentProgramUsage->_load();
902                }
903
904        // Recalculate hash
905        _dirtyHash();
906               
907        }
908    //-----------------------------------------------------------------------
909        void Pass::_unload(void)
910        {
911                // Unload each TextureUnitState
912                TextureUnitStates::iterator i, iend;
913                iend = mTextureUnitStates.end();
914                for (i = mTextureUnitStates.begin(); i != iend; ++i)
915                {
916                        (*i)->_unload();
917                }
918
919                // Unload programs
920                if (mVertexProgramUsage)
921                {
922                        // TODO
923                }
924        if (mFragmentProgramUsage)
925        {
926            // TODO
927        }
928        }
929    //-----------------------------------------------------------------------
930        void Pass::setVertexProgram(const String& name, bool resetParams)
931        {
932        // Turn off vertex program if name blank
933        if (name.empty())
934        {
935            if (mVertexProgramUsage) delete mVertexProgramUsage;
936            mVertexProgramUsage = NULL;
937        }
938        else
939        {
940            if (!mVertexProgramUsage)
941            {
942                mVertexProgramUsage = new GpuProgramUsage(GPT_VERTEX_PROGRAM);
943            }
944                    mVertexProgramUsage->setProgramName(name, resetParams);
945        }
946        // Needs recompilation
947        mParent->_notifyNeedsRecompile();
948        }
949    //-----------------------------------------------------------------------
950        void Pass::setVertexProgramParameters(GpuProgramParametersSharedPtr params)
951        {
952                if (!mVertexProgramUsage)
953        {
954            OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
955                "This pass does not have a vertex program assigned!",
956                "Pass::setVertexProgramParameters");
957        }
958                mVertexProgramUsage->setParameters(params);
959        }
960    //-----------------------------------------------------------------------
961        void Pass::setFragmentProgram(const String& name, bool resetParams)
962        {
963        // Turn off fragment program if name blank
964        if (name.empty())
965        {
966            if (mFragmentProgramUsage) delete mFragmentProgramUsage;
967            mFragmentProgramUsage = NULL;
968        }
969        else
970        {
971            if (!mFragmentProgramUsage)
972            {
973                mFragmentProgramUsage = new GpuProgramUsage(GPT_FRAGMENT_PROGRAM);
974            }
975                    mFragmentProgramUsage->setProgramName(name, resetParams);
976        }
977        // Needs recompilation
978        mParent->_notifyNeedsRecompile();
979        }
980    //-----------------------------------------------------------------------
981        void Pass::setFragmentProgramParameters(GpuProgramParametersSharedPtr params)
982        {
983                if (!mFragmentProgramUsage)
984        {
985            OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
986                "This pass does not have a fragment program assigned!",
987                "Pass::setFragmentProgramParameters");
988        }
989                mFragmentProgramUsage->setParameters(params);
990        }
991        //-----------------------------------------------------------------------
992        const String& Pass::getVertexProgramName(void) const
993        {
994        if (!mVertexProgramUsage)
995            return StringUtil::BLANK;
996        else
997                    return mVertexProgramUsage->getProgramName();
998        }
999        //-----------------------------------------------------------------------
1000        GpuProgramParametersSharedPtr Pass::getVertexProgramParameters(void) const
1001        {
1002                if (!mVertexProgramUsage)
1003        {
1004            OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1005                "This pass does not have a vertex program assigned!",
1006                "Pass::getVertexProgramParameters");
1007        }
1008                return mVertexProgramUsage->getParameters();
1009        }
1010        //-----------------------------------------------------------------------
1011        const GpuProgramPtr& Pass::getVertexProgram(void) const
1012        {
1013                return mVertexProgramUsage->getProgram();
1014        }
1015        //-----------------------------------------------------------------------
1016        const String& Pass::getFragmentProgramName(void) const
1017        {
1018        if (!mFragmentProgramUsage)
1019            return StringUtil::BLANK;
1020        else
1021                return mFragmentProgramUsage->getProgramName();
1022        }
1023        //-----------------------------------------------------------------------
1024        GpuProgramParametersSharedPtr Pass::getFragmentProgramParameters(void) const
1025        {
1026                return mFragmentProgramUsage->getParameters();
1027        }
1028        //-----------------------------------------------------------------------
1029        const GpuProgramPtr& Pass::getFragmentProgram(void) const
1030        {
1031                return mFragmentProgramUsage->getProgram();
1032        }
1033        //-----------------------------------------------------------------------
1034    bool Pass::isLoaded(void) const
1035    {
1036        return mParent->isLoaded();
1037    }
1038        //-----------------------------------------------------------------------
1039    uint32 Pass::getHash(void) const
1040    {
1041        return mHash;
1042    }
1043        //-----------------------------------------------------------------------
1044    void Pass::_recalculateHash(void)
1045    {
1046        /* Hash format is 32-bit, divided as follows (high to low bits)
1047           bits   purpose
1048            4     Pass index (i.e. max 16 passes!)
1049           14     Hashed texture name from unit 0
1050           14     Hashed texture name from unit 1
1051
1052           Note that at the moment we don't sort on the 3rd texture unit plus
1053           on the assumption that these are less frequently used; sorting on
1054           the first 2 gives us the most benefit for now.
1055       */
1056        _StringHash H;
1057        mHash = (mIndex << 28);
1058        size_t c = getNumTextureUnitStates();
1059
1060        if (c && !mTextureUnitStates[0]->isBlank())
1061            mHash += (H(mTextureUnitStates[0]->getTextureName()) % (1 << 14)) << 14;
1062        if (c > 1 && !mTextureUnitStates[1]->isBlank())
1063            mHash += (H(mTextureUnitStates[1]->getTextureName()) % (1 << 14));
1064    }
1065    //-----------------------------------------------------------------------
1066        void Pass::_dirtyHash(void)
1067        {
1068                // Mark this hash as for follow up
1069                msDirtyHashList.insert(this);
1070        }
1071    //-----------------------------------------------------------------------
1072    void Pass::_notifyNeedsRecompile(void)
1073    {
1074        mParent->_notifyNeedsRecompile();
1075    }
1076    //-----------------------------------------------------------------------
1077    void Pass::setTextureFiltering(TextureFilterOptions filterType)
1078    {
1079        TextureUnitStates::iterator i, iend;
1080        iend = mTextureUnitStates.end();
1081        for (i = mTextureUnitStates.begin(); i != iend; ++i)
1082        {
1083            (*i)->setTextureFiltering(filterType);
1084        }
1085    }
1086    // --------------------------------------------------------------------
1087    void Pass::setTextureAnisotropy(unsigned int maxAniso)
1088    {
1089        TextureUnitStates::iterator i, iend;
1090        iend = mTextureUnitStates.end();
1091        for (i = mTextureUnitStates.begin(); i != iend; ++i)
1092        {
1093            (*i)->setTextureAnisotropy(maxAniso);
1094        }
1095    }
1096    //-----------------------------------------------------------------------
1097    void Pass::_updateAutoParamsNoLights(const AutoParamDataSource& source) const
1098    {
1099        if (hasVertexProgram())
1100        {
1101            // Update vertex program auto params
1102            mVertexProgramUsage->getParameters()->_updateAutoParamsNoLights(source);
1103        }
1104
1105        if (hasFragmentProgram())
1106        {
1107            // Update fragment program auto params
1108            mFragmentProgramUsage->getParameters()->_updateAutoParamsNoLights(source);
1109        }
1110    }
1111    //-----------------------------------------------------------------------
1112    void Pass::_updateAutoParamsLightsOnly(const AutoParamDataSource& source) const
1113    {
1114        if (hasVertexProgram())
1115        {
1116            // Update vertex program auto params
1117            mVertexProgramUsage->getParameters()->_updateAutoParamsLightsOnly(source);
1118        }
1119
1120        if (hasFragmentProgram())
1121        {
1122            // Update fragment program auto params
1123            mFragmentProgramUsage->getParameters()->_updateAutoParamsLightsOnly(source);
1124        }
1125    }
1126    //-----------------------------------------------------------------------
1127    void Pass::processPendingPassUpdates(void)
1128    {
1129        // Delete items in the graveyard
1130        PassSet::iterator i, iend;
1131        iend = msPassGraveyard.end();
1132        for (i = msPassGraveyard.begin(); i != iend; ++i)
1133        {
1134            delete *i;
1135        }
1136        msPassGraveyard.clear();
1137
1138        // The dirty ones will have been removed from the groups above using the old hash now
1139        iend = msDirtyHashList.end();
1140        for (i = msDirtyHashList.begin(); i != iend; ++i)
1141        {
1142            Pass* p = *i;
1143            p->_recalculateHash();
1144        }
1145        // Clear the dirty list
1146        msDirtyHashList.clear();
1147    }
1148    //-----------------------------------------------------------------------
1149    void Pass::queueForDeletion(void)
1150    {
1151        mQueuedForDeletion = true;
1152
1153        removeAllTextureUnitStates();
1154        if (mVertexProgramUsage)
1155        {
1156            delete mVertexProgramUsage;
1157            mVertexProgramUsage = 0;
1158        }
1159        if (mShadowCasterVertexProgramUsage)
1160        {
1161            delete mShadowCasterVertexProgramUsage;
1162            mShadowCasterVertexProgramUsage = 0;
1163        }
1164        if (mShadowReceiverVertexProgramUsage)
1165        {
1166            delete mShadowReceiverVertexProgramUsage;
1167            mShadowReceiverVertexProgramUsage = 0;
1168        }
1169        if (mFragmentProgramUsage)
1170        {
1171            delete mFragmentProgramUsage;
1172            mFragmentProgramUsage = 0;
1173        }
1174                if (mShadowReceiverFragmentProgramUsage)
1175                {
1176                        delete mShadowReceiverFragmentProgramUsage;
1177                        mShadowReceiverFragmentProgramUsage = 0;
1178                }
1179        // remove from dirty list, if there
1180        msDirtyHashList.erase(this);
1181
1182        msPassGraveyard.insert(this);
1183    }
1184    //-----------------------------------------------------------------------
1185    bool Pass::isAmbientOnly(void) const
1186    {
1187        // treat as ambient if lighting is off, or colour write is off,
1188        // or all non-ambient (& emissive) colours are black
1189        // NB a vertex program could override this, but passes using vertex
1190        // programs are expected to indicate they are ambient only by
1191        // setting the state so it matches one of the conditions above, even
1192        // though this state is not used in rendering.
1193        return (!mLightingEnabled || !mColourWrite ||
1194            (mDiffuse == ColourValue::Black &&
1195             mSpecular == ColourValue::Black));
1196    }
1197    //-----------------------------------------------------------------------
1198    void Pass::setShadowCasterVertexProgram(const String& name)
1199    {
1200        // Turn off vertex program if name blank
1201        if (name.empty())
1202        {
1203            if (mShadowCasterVertexProgramUsage) delete mShadowCasterVertexProgramUsage;
1204            mShadowCasterVertexProgramUsage = NULL;
1205        }
1206        else
1207        {
1208            if (!mShadowCasterVertexProgramUsage)
1209            {
1210                mShadowCasterVertexProgramUsage = new GpuProgramUsage(GPT_VERTEX_PROGRAM);
1211            }
1212            mShadowCasterVertexProgramUsage->setProgramName(name);
1213        }
1214        // Needs recompilation
1215        mParent->_notifyNeedsRecompile();
1216    }
1217    //-----------------------------------------------------------------------
1218    void Pass::setShadowCasterVertexProgramParameters(GpuProgramParametersSharedPtr params)
1219    {
1220        if (!mShadowCasterVertexProgramUsage)
1221        {
1222            OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1223                "This pass does not have a shadow caster vertex program assigned!",
1224                "Pass::setShadowCasterVertexProgramParameters");
1225        }
1226        mShadowCasterVertexProgramUsage->setParameters(params);
1227    }
1228    //-----------------------------------------------------------------------
1229    const String& Pass::getShadowCasterVertexProgramName(void) const
1230    {
1231        if (!mShadowCasterVertexProgramUsage)
1232            return StringUtil::BLANK;
1233        else
1234            return mShadowCasterVertexProgramUsage->getProgramName();
1235    }
1236    //-----------------------------------------------------------------------
1237    GpuProgramParametersSharedPtr Pass::getShadowCasterVertexProgramParameters(void) const
1238    {
1239        if (!mShadowCasterVertexProgramUsage)
1240        {
1241            OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1242                "This pass does not have a shadow caster vertex program assigned!",
1243                "Pass::getShadowCasterVertexProgramParameters");
1244        }
1245        return mShadowCasterVertexProgramUsage->getParameters();
1246    }
1247    //-----------------------------------------------------------------------
1248    const GpuProgramPtr& Pass::getShadowCasterVertexProgram(void) const
1249    {
1250        return mShadowCasterVertexProgramUsage->getProgram();
1251    }
1252    //-----------------------------------------------------------------------
1253    void Pass::setShadowReceiverVertexProgram(const String& name)
1254    {
1255        // Turn off vertex program if name blank
1256        if (name.empty())
1257        {
1258            if (mShadowReceiverVertexProgramUsage) delete mShadowReceiverVertexProgramUsage;
1259            mShadowReceiverVertexProgramUsage = NULL;
1260        }
1261        else
1262        {
1263            if (!mShadowReceiverVertexProgramUsage)
1264            {
1265                mShadowReceiverVertexProgramUsage = new GpuProgramUsage(GPT_VERTEX_PROGRAM);
1266            }
1267            mShadowReceiverVertexProgramUsage->setProgramName(name);
1268        }
1269        // Needs recompilation
1270        mParent->_notifyNeedsRecompile();
1271    }
1272    //-----------------------------------------------------------------------
1273    void Pass::setShadowReceiverVertexProgramParameters(GpuProgramParametersSharedPtr params)
1274    {
1275        if (!mShadowReceiverVertexProgramUsage)
1276        {
1277            OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1278                "This pass does not have a shadow receiver vertex program assigned!",
1279                "Pass::setShadowReceiverVertexProgramParameters");
1280        }
1281        mShadowReceiverVertexProgramUsage->setParameters(params);
1282    }
1283    //-----------------------------------------------------------------------
1284    const String& Pass::getShadowReceiverVertexProgramName(void) const
1285    {
1286        if (!mShadowReceiverVertexProgramUsage)
1287            return StringUtil::BLANK;
1288        else
1289            return mShadowReceiverVertexProgramUsage->getProgramName();
1290    }
1291    //-----------------------------------------------------------------------
1292    GpuProgramParametersSharedPtr Pass::getShadowReceiverVertexProgramParameters(void) const
1293    {
1294        if (!mShadowReceiverVertexProgramUsage)
1295        {
1296            OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1297                "This pass does not have a shadow receiver vertex program assigned!",
1298                "Pass::getShadowReceiverVertexProgramParameters");
1299        }
1300        return mShadowReceiverVertexProgramUsage->getParameters();
1301    }
1302    //-----------------------------------------------------------------------
1303    const GpuProgramPtr& Pass::getShadowReceiverVertexProgram(void) const
1304    {
1305        return mShadowReceiverVertexProgramUsage->getProgram();
1306    }
1307        //-----------------------------------------------------------------------
1308        void Pass::setShadowReceiverFragmentProgram(const String& name)
1309        {
1310                // Turn off Fragment program if name blank
1311                if (name.empty())
1312                {
1313                        if (mShadowReceiverFragmentProgramUsage) delete mShadowReceiverFragmentProgramUsage;
1314                        mShadowReceiverFragmentProgramUsage = NULL;
1315                }
1316                else
1317                {
1318                        if (!mShadowReceiverFragmentProgramUsage)
1319                        {
1320                                mShadowReceiverFragmentProgramUsage = new GpuProgramUsage(GPT_FRAGMENT_PROGRAM);
1321                        }
1322                        mShadowReceiverFragmentProgramUsage->setProgramName(name);
1323                }
1324                // Needs recompilation
1325                mParent->_notifyNeedsRecompile();
1326        }
1327        //-----------------------------------------------------------------------
1328        void Pass::setShadowReceiverFragmentProgramParameters(GpuProgramParametersSharedPtr params)
1329        {
1330                if (!mShadowReceiverFragmentProgramUsage)
1331                {
1332                        OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1333                                "This pass does not have a shadow receiver fragment program assigned!",
1334                                "Pass::setShadowReceiverFragmentProgramParameters");
1335                }
1336                mShadowReceiverFragmentProgramUsage->setParameters(params);
1337        }
1338        //-----------------------------------------------------------------------
1339        const String& Pass::getShadowReceiverFragmentProgramName(void) const
1340        {
1341                if (!mShadowReceiverFragmentProgramUsage)
1342                        return StringUtil::BLANK;
1343                else
1344                        return mShadowReceiverFragmentProgramUsage->getProgramName();
1345        }
1346        //-----------------------------------------------------------------------
1347        GpuProgramParametersSharedPtr Pass::getShadowReceiverFragmentProgramParameters(void) const
1348        {
1349                if (!mShadowReceiverFragmentProgramUsage)
1350                {
1351                        OGRE_EXCEPT (Exception::ERR_INVALIDPARAMS,
1352                                "This pass does not have a shadow receiver fragment program assigned!",
1353                                "Pass::getShadowReceiverFragmentProgramParameters");
1354                }
1355                return mShadowReceiverFragmentProgramUsage->getParameters();
1356        }
1357        //-----------------------------------------------------------------------
1358        const GpuProgramPtr& Pass::getShadowReceiverFragmentProgram(void) const
1359        {
1360                return mShadowReceiverFragmentProgramUsage->getProgram();
1361        }
1362    //-----------------------------------------------------------------------
1363        const String& Pass::getResourceGroup(void) const
1364        {
1365                return mParent->getResourceGroup();
1366        }
1367
1368    //-----------------------------------------------------------------------
1369    bool Pass::applyTextureAliases(const AliasTextureNamePairList& aliasList, const bool apply) const
1370    {
1371        // iterate through each texture unit state and apply the texture alias if it applies
1372        TextureUnitStates::const_iterator i, iend;
1373        iend = mTextureUnitStates.end();
1374        bool testResult = false;
1375
1376        for (i = mTextureUnitStates.begin(); i != iend; ++i)
1377        {
1378            if ((*i)->applyTextureAliases(aliasList, apply))
1379                testResult = true;
1380        }
1381
1382        return testResult;
1383
1384    }
1385
1386
1387}
Note: See TracBrowser for help on using the repository browser.