source: OGRE/trunk/ogrenew/OgreMain/src/OgreMaterialSerializer.cpp @ 657

Revision 657, 130.6 KB checked in by mattausch, 19 years ago (diff)

added ogre dependencies and patched ogre sources

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 "OgreMaterialSerializer.h"
28#include "OgreStringConverter.h"
29#include "OgreLogManager.h"
30#include "OgreException.h"
31#include "OgreTechnique.h"
32#include "OgrePass.h"
33#include "OgreTextureUnitState.h"
34#include "OgreMaterialManager.h"
35#include "OgreGpuProgramManager.h"
36#include "OgreHighLevelGpuProgramManager.h"
37#include "OgreExternalTextureSourceManager.h"
38
39namespace Ogre
40{
41
42    //-----------------------------------------------------------------------
43    // Internal parser methods
44    //-----------------------------------------------------------------------
45    void logParseError(const String& error, const MaterialScriptContext& context)
46    {
47        // log material name only if filename not specified
48        if (context.filename.empty() && !context.material.isNull())
49        {
50            LogManager::getSingleton().logMessage(
51                "Error in material " + context.material->getName() +
52                " : " + error);
53        }
54        else
55        {
56            if (!context.material.isNull())
57            {
58                LogManager::getSingleton().logMessage(
59                    "Error in material " + context.material->getName() +
60                    " at line " + StringConverter::toString(context.lineNo) +
61                    " of " + context.filename + ": " + error);
62            }
63            else
64            {
65                LogManager::getSingleton().logMessage(
66                    "Error at line " + StringConverter::toString(context.lineNo) +
67                    " of " + context.filename + ": " + error);
68            }
69        }
70    }
71    //-----------------------------------------------------------------------
72    ColourValue _parseColourValue(StringVector& vecparams)
73    {
74        return ColourValue(
75            StringConverter::parseReal(vecparams[0]) ,
76            StringConverter::parseReal(vecparams[1]) ,
77            StringConverter::parseReal(vecparams[2]) ,
78            (vecparams.size()==4) ? StringConverter::parseReal(vecparams[3]) : 1.0f ) ;
79    }
80    //-----------------------------------------------------------------------
81    FilterOptions convertFiltering(const String& s)
82    {
83        if (s == "none")
84        {
85            return FO_NONE;
86        }
87        else if (s == "point")
88        {
89            return FO_POINT;
90        }
91        else if (s == "linear")
92        {
93            return FO_LINEAR;
94        }
95        else if (s == "anisotropic")
96        {
97            return FO_ANISOTROPIC;
98        }
99
100        return FO_POINT;
101    }
102    //-----------------------------------------------------------------------
103    bool parseAmbient(String& params, MaterialScriptContext& context)
104    {
105        StringVector vecparams = StringUtil::split(params, " \t");
106        // Must be 1, 3 or 4 parameters
107        if (vecparams.size() == 1) {
108            if(vecparams[0] == "vertexcolour") {
109               context.pass->setVertexColourTracking(context.pass->getVertexColourTracking() | TVC_AMBIENT);
110            } else {
111                logParseError(
112                    "Bad ambient attribute, single parameter flag must be 'vertexcolour'",
113                    context);
114            }
115        }
116        else if (vecparams.size() == 3 || vecparams.size() == 4)
117        {
118            context.pass->setAmbient( _parseColourValue(vecparams) );
119            context.pass->setVertexColourTracking(context.pass->getVertexColourTracking() & ~TVC_AMBIENT);
120        }
121        else
122        {
123            logParseError(
124                "Bad ambient attribute, wrong number of parameters (expected 1, 3 or 4)",
125                context);
126        }
127        return false;
128    }
129   //-----------------------------------------------------------------------
130    bool parseDiffuse(String& params, MaterialScriptContext& context)
131    {
132        StringVector vecparams = StringUtil::split(params, " \t");
133        // Must be 1, 3 or 4 parameters
134        if (vecparams.size() == 1) {
135            if(vecparams[0] == "vertexcolour") {
136               context.pass->setVertexColourTracking(context.pass->getVertexColourTracking() | TVC_DIFFUSE);
137            } else {
138                logParseError(
139                    "Bad diffuse attribute, single parameter flag must be 'vertexcolour'",
140                    context);
141            }
142        }
143        else if (vecparams.size() == 3 || vecparams.size() == 4)
144        {
145            context.pass->setDiffuse( _parseColourValue(vecparams) );
146            context.pass->setVertexColourTracking(context.pass->getVertexColourTracking() & ~TVC_DIFFUSE);
147        }
148        else
149        {
150            logParseError(
151                "Bad diffuse attribute, wrong number of parameters (expected 1, 3 or 4)",
152                context);
153        }        return false;
154    }
155    //-----------------------------------------------------------------------
156    bool parseSpecular(String& params, MaterialScriptContext& context)
157    {
158        StringVector vecparams = StringUtil::split(params, " \t");
159        // Must be 2, 4 or 5 parameters
160        if(vecparams.size() == 2)
161        {   
162            if(vecparams[0] == "vertexcolour") {
163                context.pass->setVertexColourTracking(context.pass->getVertexColourTracking() | TVC_SPECULAR);
164                context.pass->setShininess(StringConverter::parseReal(vecparams[1]) );
165            }
166            else
167            {
168                logParseError(
169                    "Bad specular attribute, double parameter statement must be 'vertexcolour <shininess>'",
170                    context);
171            }
172        }
173        else if(vecparams.size() == 4 || vecparams.size() == 5)
174        {
175            context.pass->setSpecular(
176                StringConverter::parseReal(vecparams[0]),
177                StringConverter::parseReal(vecparams[1]),
178                StringConverter::parseReal(vecparams[2]),
179                vecparams.size() == 5?
180                    StringConverter::parseReal(vecparams[3]) : 1.0f);
181            context.pass->setVertexColourTracking(context.pass->getVertexColourTracking() & ~TVC_SPECULAR);
182            context.pass->setShininess(
183                StringConverter::parseReal(vecparams[vecparams.size() - 1]) );
184        }
185        else
186        {
187            logParseError(
188                "Bad specular attribute, wrong number of parameters (expected 2, 4 or 5)",
189                context);
190        }
191        return false;
192    }
193    //-----------------------------------------------------------------------
194    bool parseEmissive(String& params, MaterialScriptContext& context)
195    {
196        StringVector vecparams = StringUtil::split(params, " \t");
197        // Must be 1, 3 or 4 parameters
198        if (vecparams.size() == 1) {
199            if(vecparams[0] == "vertexcolour") {
200               context.pass->setVertexColourTracking(context.pass->getVertexColourTracking() | TVC_EMISSIVE);
201            } else {
202                logParseError(
203                    "Bad emissive attribute, single parameter flag must be 'vertexcolour'",
204                    context);
205            }
206        }
207        else if (vecparams.size() == 3 || vecparams.size() == 4)
208        {
209            context.pass->setSelfIllumination( _parseColourValue(vecparams) );
210            context.pass->setVertexColourTracking(context.pass->getVertexColourTracking() & ~TVC_EMISSIVE);
211        }
212        else
213        {
214            logParseError(
215                "Bad emissive attribute, wrong number of parameters (expected 1, 3 or 4)",
216                context);
217        }
218        return false;
219    }
220    //-----------------------------------------------------------------------
221    SceneBlendFactor convertBlendFactor(const String& param)
222    {
223        if (param == "one")
224            return SBF_ONE;
225        else if (param == "zero")
226            return SBF_ZERO;
227        else if (param == "dest_colour")
228            return SBF_DEST_COLOUR;
229        else if (param == "src_colour")
230            return SBF_SOURCE_COLOUR;
231        else if (param == "one_minus_dest_colour")
232            return SBF_ONE_MINUS_DEST_COLOUR;
233        else if (param == "one_minus_src_colour")
234            return SBF_ONE_MINUS_SOURCE_COLOUR;
235        else if (param == "dest_alpha")
236            return SBF_DEST_ALPHA;
237        else if (param == "src_alpha")
238            return SBF_SOURCE_ALPHA;
239        else if (param == "one_minus_dest_alpha")
240            return SBF_ONE_MINUS_DEST_ALPHA;
241        else if (param == "one_minus_src_alpha")
242            return SBF_ONE_MINUS_SOURCE_ALPHA;
243        else
244        {
245            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Invalid blend factor.", "convertBlendFactor");
246        }
247
248
249    }
250    //-----------------------------------------------------------------------
251    bool parseSceneBlend(String& params, MaterialScriptContext& context)
252    {
253        StringUtil::toLowerCase(params);
254        StringVector vecparams = StringUtil::split(params, " \t");
255        // Should be 1 or 2 params
256        if (vecparams.size() == 1)
257        {
258            //simple
259            SceneBlendType stype;
260            if (vecparams[0] == "add")
261                stype = SBT_ADD;
262            else if (vecparams[0] == "modulate")
263                stype = SBT_MODULATE;
264                        else if (vecparams[0] == "colour_blend")
265                                stype = SBT_TRANSPARENT_COLOUR;
266            else if (vecparams[0] == "alpha_blend")
267                stype = SBT_TRANSPARENT_ALPHA;
268            else
269            {
270                logParseError(
271                    "Bad scene_blend attribute, unrecognised parameter '" + vecparams[0] + "'",
272                    context);
273                return false;
274            }
275            context.pass->setSceneBlending(stype);
276
277        }
278        else if (vecparams.size() == 2)
279        {
280            //src/dest
281            SceneBlendFactor src, dest;
282
283            try {
284                src = convertBlendFactor(vecparams[0]);
285                dest = convertBlendFactor(vecparams[1]);
286                context.pass->setSceneBlending(src,dest);
287            }
288            catch (Exception& e)
289            {
290                logParseError("Bad scene_blend attribute, " + e.getFullDescription(), context);
291            }
292
293        }
294        else
295        {
296            logParseError(
297                "Bad scene_blend attribute, wrong number of parameters (expected 1 or 2)",
298                context);
299        }
300
301        return false;
302
303    }
304    //-----------------------------------------------------------------------
305    CompareFunction convertCompareFunction(const String& param)
306    {
307        if (param == "always_fail")
308            return CMPF_ALWAYS_FAIL;
309        else if (param == "always_pass")
310            return CMPF_ALWAYS_PASS;
311        else if (param == "less")
312            return CMPF_LESS;
313        else if (param == "less_equal")
314            return CMPF_LESS_EQUAL;
315        else if (param == "equal")
316            return CMPF_EQUAL;
317        else if (param == "not_equal")
318            return CMPF_NOT_EQUAL;
319        else if (param == "greater_equal")
320            return CMPF_GREATER_EQUAL;
321        else if (param == "greater")
322            return CMPF_GREATER;
323        else
324            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Invalid compare function", "convertCompareFunction");
325
326    }
327    //-----------------------------------------------------------------------
328    bool parseDepthCheck(String& params, MaterialScriptContext& context)
329    {
330        StringUtil::toLowerCase(params);
331        if (params == "on")
332            context.pass->setDepthCheckEnabled(true);
333        else if (params == "off")
334            context.pass->setDepthCheckEnabled(false);
335        else
336            logParseError(
337            "Bad depth_check attribute, valid parameters are 'on' or 'off'.",
338            context);
339
340        return false;
341    }
342    //-----------------------------------------------------------------------
343    bool parseDepthWrite(String& params, MaterialScriptContext& context)
344    {
345        StringUtil::toLowerCase(params);
346        if (params == "on")
347            context.pass->setDepthWriteEnabled(true);
348        else if (params == "off")
349            context.pass->setDepthWriteEnabled(false);
350        else
351            logParseError(
352                "Bad depth_write attribute, valid parameters are 'on' or 'off'.",
353                context);
354        return false;
355    }
356
357    //-----------------------------------------------------------------------
358    bool parseDepthFunc(String& params, MaterialScriptContext& context)
359    {
360        StringUtil::toLowerCase(params);
361        try {
362            CompareFunction func = convertCompareFunction(params);
363            context.pass->setDepthFunction(func);
364        }
365        catch (...)
366        {
367            logParseError("Bad depth_func attribute, invalid function parameter.", context);
368        }
369
370        return false;
371    }
372    //-----------------------------------------------------------------------
373    bool parseColourWrite(String& params, MaterialScriptContext& context)
374    {
375        StringUtil::toLowerCase(params);
376        if (params == "on")
377            context.pass->setColourWriteEnabled(true);
378        else if (params == "off")
379            context.pass->setColourWriteEnabled(false);
380        else
381            logParseError(
382                "Bad colour_write attribute, valid parameters are 'on' or 'off'.",
383                context);
384        return false;
385    }
386
387    //-----------------------------------------------------------------------
388    bool parseCullHardware(String& params, MaterialScriptContext& context)
389    {
390        StringUtil::toLowerCase(params);
391        if (params=="none")
392            context.pass->setCullingMode(CULL_NONE);
393        else if (params=="anticlockwise")
394            context.pass->setCullingMode(CULL_ANTICLOCKWISE);
395        else if (params=="clockwise")
396            context.pass->setCullingMode(CULL_CLOCKWISE);
397        else
398            logParseError(
399                "Bad cull_hardware attribute, valid parameters are "
400                "'none', 'clockwise' or 'anticlockwise'.", context);
401        return false;
402    }
403    //-----------------------------------------------------------------------
404    bool parseCullSoftware(String& params, MaterialScriptContext& context)
405    {
406        StringUtil::toLowerCase(params);
407        if (params=="none")
408            context.pass->setManualCullingMode(MANUAL_CULL_NONE);
409        else if (params=="back")
410            context.pass->setManualCullingMode(MANUAL_CULL_BACK);
411        else if (params=="front")
412            context.pass->setManualCullingMode(MANUAL_CULL_FRONT);
413        else
414            logParseError(
415                "Bad cull_software attribute, valid parameters are 'none', "
416                "'front' or 'back'.", context);
417        return false;
418    }
419    //-----------------------------------------------------------------------
420    bool parseLighting(String& params, MaterialScriptContext& context)
421    {
422        StringUtil::toLowerCase(params);
423        if (params=="on")
424            context.pass->setLightingEnabled(true);
425        else if (params=="off")
426            context.pass->setLightingEnabled(false);
427        else
428            logParseError(
429                "Bad lighting attribute, valid parameters are 'on' or 'off'.", context);
430        return false;
431    }
432    //-----------------------------------------------------------------------
433    bool parseMaxLights(String& params, MaterialScriptContext& context)
434    {
435                context.pass->setMaxSimultaneousLights(StringConverter::parseInt(params));
436        return false;
437    }
438    //-----------------------------------------------------------------------
439    bool parseIteration(String& params, MaterialScriptContext& context)
440    {
441        StringUtil::toLowerCase(params);
442        StringVector vecparams = StringUtil::split(params, " \t");
443        if (vecparams.size() != 1 && vecparams.size() != 2)
444        {
445            logParseError("Bad iteration attribute, expected 1 or 2 parameters.", context);
446            return false;
447        }
448
449        if (vecparams[0]=="once")
450            context.pass->setRunOncePerLight(false);
451        else if (vecparams[0]=="once_per_light")
452        {
453            if (vecparams.size() == 2)
454            {
455                // Parse light type
456                if (vecparams[1] == "directional")
457                {
458                    context.pass->setRunOncePerLight(true, true, Light::LT_DIRECTIONAL);
459                }
460                else if (vecparams[1] == "point")
461                {
462                    context.pass->setRunOncePerLight(true, true, Light::LT_POINT);
463                }
464                else if (vecparams[1] == "spot")
465                {
466                    context.pass->setRunOncePerLight(true, true, Light::LT_SPOTLIGHT);
467                }
468                else
469                {
470                    logParseError("Bad iteration attribute, valid values for second parameter "
471                        "are 'point' or 'directional' or 'spot'.", context);
472                }
473            }
474            else
475            {
476                context.pass->setRunOncePerLight(true, false);
477            }
478
479        }
480        else
481            logParseError(
482                "Bad iteration attribute, valid parameters are 'once' or 'once_per_light'.", context);
483        return false;
484    }
485    //-----------------------------------------------------------------------
486    bool parseFogging(String& params, MaterialScriptContext& context)
487    {
488        StringUtil::toLowerCase(params);
489        StringVector vecparams = StringUtil::split(params, " \t");
490        if (vecparams[0]=="true")
491        {
492            // if true, we need to see if they supplied all arguments, or just the 1... if just the one,
493            // Assume they want to disable the default fog from effecting this material.
494            if( vecparams.size() == 8 )
495            {
496                FogMode mFogtype;
497                if( vecparams[1] == "none" )
498                    mFogtype = FOG_NONE;
499                else if( vecparams[1] == "linear" )
500                    mFogtype = FOG_LINEAR;
501                else if( vecparams[1] == "exp" )
502                    mFogtype = FOG_EXP;
503                else if( vecparams[1] == "exp2" )
504                    mFogtype = FOG_EXP2;
505                else
506                {
507                    logParseError(
508                        "Bad fogging attribute, valid parameters are "
509                        "'none', 'linear', 'exp', or 'exp2'.", context);
510                    return false;
511                }
512
513                context.pass->setFog(
514                    true,
515                    mFogtype,
516                    ColourValue(
517                    StringConverter::parseReal(vecparams[2]),
518                    StringConverter::parseReal(vecparams[3]),
519                    StringConverter::parseReal(vecparams[4])),
520                    StringConverter::parseReal(vecparams[5]),
521                    StringConverter::parseReal(vecparams[6]),
522                    StringConverter::parseReal(vecparams[7])
523                    );
524            }
525            else
526            {
527                context.pass->setFog(true);
528            }
529        }
530        else if (vecparams[0]=="false")
531            context.pass->setFog(false);
532        else
533            logParseError(
534                "Bad fog_override attribute, valid parameters are 'true' or 'false'.",
535                context);
536
537        return false;
538    }
539    //-----------------------------------------------------------------------
540    bool parseShading(String& params, MaterialScriptContext& context)
541    {
542        StringUtil::toLowerCase(params);
543        if (params=="flat")
544            context.pass->setShadingMode(SO_FLAT);
545        else if (params=="gouraud")
546            context.pass->setShadingMode(SO_GOURAUD);
547        else if (params=="phong")
548            context.pass->setShadingMode(SO_PHONG);
549        else
550            logParseError("Bad shading attribute, valid parameters are 'flat', "
551                "'gouraud' or 'phong'.", context);
552
553        return false;
554    }
555    //-----------------------------------------------------------------------
556    bool parseFiltering(String& params, MaterialScriptContext& context)
557    {
558        StringUtil::toLowerCase(params);
559        StringVector vecparams = StringUtil::split(params, " \t");
560        // Must be 1 or 3 parameters
561        if (vecparams.size() == 1)
562        {
563            // Simple format
564            if (vecparams[0]=="none")
565                context.textureUnit->setTextureFiltering(TFO_NONE);
566            else if (vecparams[0]=="bilinear")
567                context.textureUnit->setTextureFiltering(TFO_BILINEAR);
568            else if (vecparams[0]=="trilinear")
569                context.textureUnit->setTextureFiltering(TFO_TRILINEAR);
570            else if (vecparams[0]=="anisotropic")
571                context.textureUnit->setTextureFiltering(TFO_ANISOTROPIC);
572            else
573            {
574                logParseError("Bad filtering attribute, valid parameters for simple format are "
575                    "'none', 'bilinear', 'trilinear' or 'anisotropic'.", context);
576                return false;
577            }
578        }
579        else if (vecparams.size() == 3)
580        {
581            // Complex format
582            context.textureUnit->setTextureFiltering(
583                convertFiltering(vecparams[0]),
584                convertFiltering(vecparams[1]),
585                convertFiltering(vecparams[2]));
586
587
588        }
589        else
590        {
591            logParseError(
592                "Bad filtering attribute, wrong number of parameters (expected 1 or 3)",
593                context);
594        }
595
596        return false;
597    }
598    //-----------------------------------------------------------------------
599    // Texture layer attributes
600    bool parseTexture(String& params, MaterialScriptContext& context)
601    {
602        StringVector vecparams = StringUtil::split(params, " \t");
603        if (vecparams.size() > 3)
604        {
605            logParseError("Invalid texture attribute - expected only 1, 2 or 3 parameters.",
606                context);
607        }
608        TextureType tt = TEX_TYPE_2D;
609                int mips = -1; // When passed to TextureManager::load, this means default to default number of mipmaps
610        if (vecparams.size() >= 2)
611        {
612            StringUtil::toLowerCase(vecparams[1]);
613            if (vecparams[1] == "1d")
614            {
615                tt = TEX_TYPE_1D;
616            }
617            else if (vecparams[1] == "2d")
618            {
619                tt = TEX_TYPE_2D;
620            }
621            else if (vecparams[1] == "3d")
622            {
623                tt = TEX_TYPE_3D;
624            }
625            else if (vecparams[1] == "cubic")
626            {
627                tt = TEX_TYPE_CUBE_MAP;
628            } 
629                        else
630                        {
631                                logParseError("Invalid texture type - "+vecparams[1]+".",
632                context);
633                        }
634        }
635                if (vecparams.size() >= 3)
636                {
637                        StringUtil::toLowerCase(vecparams[2]);
638                        if (vecparams[2] == "unlimited")
639            {
640                                mips = MIP_UNLIMITED;
641            }
642                        else
643                        {
644                                mips = StringConverter::parseInt(vecparams[2]);
645                        }
646                }
647        context.textureUnit->setTextureName(vecparams[0], tt, mips);
648        return false;
649    }
650    //-----------------------------------------------------------------------
651    bool parseAnimTexture(String& params, MaterialScriptContext& context)
652    {
653        StringVector vecparams = StringUtil::split(params, " \t");
654        size_t numParams = vecparams.size();
655        // Determine which form it is
656        // Must have at least 3 params though
657        if (numParams < 3)
658        {
659            logParseError("Bad anim_texture attribute, wrong number of parameters "
660                "(expected at least 3)", context);
661            return false;
662        }
663        if (numParams == 3 && StringConverter::parseInt(vecparams[1]) != 0 )
664        {
665            // First form using base name & number of frames
666            context.textureUnit->setAnimatedTextureName(
667                vecparams[0],
668                StringConverter::parseInt(vecparams[1]),
669                StringConverter::parseReal(vecparams[2]));
670        }
671        else
672        {
673            // Second form using individual names
674            context.textureUnit->setAnimatedTextureName(
675                (String*)&vecparams[0],
676                numParams-1,
677                StringConverter::parseReal(vecparams[numParams-1]));
678        }
679        return false;
680
681    }
682    //-----------------------------------------------------------------------
683    bool parseCubicTexture(String& params, MaterialScriptContext& context)
684    {
685
686        StringVector vecparams = StringUtil::split(params, " \t");
687        size_t numParams = vecparams.size();
688
689        // Get final param
690        bool useUVW;
691        String& uvOpt = vecparams[numParams-1];
692                StringUtil::toLowerCase(uvOpt);
693        if (uvOpt == "combineduvw")
694            useUVW = true;
695        else if (uvOpt == "separateuv")
696            useUVW = false;
697        else
698        {
699            logParseError("Bad cubic_texture attribute, final parameter must be "
700                "'combinedUVW' or 'separateUV'.", context);
701            return false;
702        }
703        // Determine which form it is
704        if (numParams == 2)
705        {
706            // First form using base name
707            context.textureUnit->setCubicTextureName(vecparams[0], useUVW);
708        }
709        else if (numParams == 7)
710        {
711            // Second form using individual names
712            // Can use vecparams[0] as array start point
713            context.textureUnit->setCubicTextureName((String*)&vecparams[0], useUVW);
714        }
715        else
716        {
717            logParseError(
718                "Bad cubic_texture attribute, wrong number of parameters (expected 2 or 7)",
719                context);
720            return false;
721        }
722
723        return false;
724    }
725    //-----------------------------------------------------------------------
726    bool parseTexCoord(String& params, MaterialScriptContext& context)
727    {
728        context.textureUnit->setTextureCoordSet(
729            StringConverter::parseInt(params));
730
731        return false;
732    }
733    //-----------------------------------------------------------------------
734    bool parseTexAddressMode(String& params, MaterialScriptContext& context)
735    {
736        StringUtil::toLowerCase(params);
737        if (params=="wrap")
738            context.textureUnit->setTextureAddressingMode(TextureUnitState::TAM_WRAP);
739        else if (params=="mirror")
740            context.textureUnit->setTextureAddressingMode(TextureUnitState::TAM_MIRROR);
741        else if (params=="clamp")
742            context.textureUnit->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
743        else
744            logParseError("Bad tex_address_mode attribute, valid parameters are "
745                "'wrap', 'clamp' or 'mirror'.", context);
746
747        return false;
748    }
749    //-----------------------------------------------------------------------
750    bool parseColourOp(String& params, MaterialScriptContext& context)
751    {
752        StringUtil::toLowerCase(params);
753        if (params=="replace")
754            context.textureUnit->setColourOperation(LBO_REPLACE);
755        else if (params=="add")
756            context.textureUnit->setColourOperation(LBO_ADD);
757        else if (params=="modulate")
758            context.textureUnit->setColourOperation(LBO_MODULATE);
759        else if (params=="alpha_blend")
760            context.textureUnit->setColourOperation(LBO_ALPHA_BLEND);
761        else
762            logParseError("Bad colour_op attribute, valid parameters are "
763                "'replace', 'add', 'modulate' or 'alpha_blend'.", context);
764
765        return false;
766    }
767    //-----------------------------------------------------------------------
768    bool parseAlphaRejection(String& params, MaterialScriptContext& context)
769    {
770        StringUtil::toLowerCase(params);
771        StringVector vecparams = StringUtil::split(params, " \t");
772        if (vecparams.size() != 2)
773        {
774            logParseError(
775                "Bad alpha_rejection attribute, wrong number of parameters (expected 2)",
776                context);
777            return false;
778        }
779
780        CompareFunction cmp;
781        try {
782            cmp = convertCompareFunction(vecparams[0]);
783        }
784        catch (...)
785        {
786            logParseError("Bad alpha_rejection attribute, invalid compare function.", context);
787            return false;
788        }
789
790        context.pass->setAlphaRejectSettings(cmp, StringConverter::parseInt(vecparams[1]));
791
792        return false;
793    }
794    //-----------------------------------------------------------------------
795    LayerBlendOperationEx convertBlendOpEx(const String& param)
796    {
797        if (param == "source1")
798            return LBX_SOURCE1;
799        else if (param == "source2")
800            return LBX_SOURCE2;
801        else if (param == "modulate")
802            return LBX_MODULATE;
803        else if (param == "modulate_x2")
804            return LBX_MODULATE_X2;
805        else if (param == "modulate_x4")
806            return LBX_MODULATE_X4;
807        else if (param == "add")
808            return LBX_ADD;
809        else if (param == "add_signed")
810            return LBX_ADD_SIGNED;
811        else if (param == "add_smooth")
812            return LBX_ADD_SMOOTH;
813        else if (param == "subtract")
814            return LBX_SUBTRACT;
815        else if (param == "blend_diffuse_alpha")
816            return LBX_BLEND_DIFFUSE_ALPHA;
817        else if (param == "blend_texture_alpha")
818            return LBX_BLEND_TEXTURE_ALPHA;
819        else if (param == "blend_current_alpha")
820            return LBX_BLEND_CURRENT_ALPHA;
821        else if (param == "blend_manual")
822            return LBX_BLEND_MANUAL;
823        else if (param == "dotproduct")
824            return LBX_DOTPRODUCT;
825        else
826            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Invalid blend function", "convertBlendOpEx");
827    }
828    //-----------------------------------------------------------------------
829    LayerBlendSource convertBlendSource(const String& param)
830    {
831        if (param == "src_current")
832            return LBS_CURRENT;
833        else if (param == "src_texture")
834            return LBS_TEXTURE;
835        else if (param == "src_diffuse")
836            return LBS_DIFFUSE;
837        else if (param == "src_specular")
838            return LBS_SPECULAR;
839        else if (param == "src_manual")
840            return LBS_MANUAL;
841        else
842            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Invalid blend source", "convertBlendSource");
843    }
844    //-----------------------------------------------------------------------
845    bool parseColourOpEx(String& params, MaterialScriptContext& context)
846    {
847        StringUtil::toLowerCase(params);
848        StringVector vecparams = StringUtil::split(params, " \t");
849        size_t numParams = vecparams.size();
850
851        if (numParams < 3 || numParams > 10)
852        {
853            logParseError(
854                "Bad colour_op_ex attribute, wrong number of parameters (expected 3 to 10)",
855                context);
856            return false;
857        }
858        LayerBlendOperationEx op;
859        LayerBlendSource src1, src2;
860        Real manual = 0.0;
861        ColourValue colSrc1 = ColourValue::White;
862        ColourValue colSrc2 = ColourValue::White;
863
864        try {
865            op = convertBlendOpEx(vecparams[0]);
866            src1 = convertBlendSource(vecparams[1]);
867            src2 = convertBlendSource(vecparams[2]);
868
869            if (op == LBX_BLEND_MANUAL)
870            {
871                if (numParams < 4)
872                {
873                    logParseError("Bad colour_op_ex attribute, wrong number of parameters "
874                        "(expected 4 for manual blend)", context);
875                    return false;
876                }
877                manual = StringConverter::parseReal(vecparams[3]);
878            }
879
880            if (src1 == LBS_MANUAL)
881            {
882                unsigned int parIndex = 3;
883                if (op == LBX_BLEND_MANUAL)
884                    parIndex++;
885
886                if (numParams < parIndex + 3)
887                {
888                    logParseError("Bad colour_op_ex attribute, wrong number of parameters "
889                        "(expected " + StringConverter::toString(parIndex + 3) + ")", context);
890                    return false;
891                }
892
893                colSrc1.r = StringConverter::parseReal(vecparams[parIndex++]);
894                colSrc1.g = StringConverter::parseReal(vecparams[parIndex++]);
895                colSrc1.b = StringConverter::parseReal(vecparams[parIndex++]);
896                if (numParams > parIndex)
897                {
898                    colSrc1.a = StringConverter::parseReal(vecparams[parIndex]);
899                }
900                else
901                {
902                    colSrc1.a = 1.0f;
903                }
904            }
905
906            if (src2 == LBS_MANUAL)
907            {
908                unsigned int parIndex = 3;
909                if (op == LBX_BLEND_MANUAL)
910                    parIndex++;
911                if (src1 == LBS_MANUAL)
912                    parIndex += 3;
913
914                if (numParams < parIndex + 3)
915                {
916                    logParseError("Bad colour_op_ex attribute, wrong number of parameters "
917                        "(expected " + StringConverter::toString(parIndex + 3) + ")", context);
918                    return false;
919                }
920
921                colSrc2.r = StringConverter::parseReal(vecparams[parIndex++]);
922                colSrc2.g = StringConverter::parseReal(vecparams[parIndex++]);
923                colSrc2.b = StringConverter::parseReal(vecparams[parIndex++]);
924                if (numParams > parIndex)
925                {
926                    colSrc2.a = StringConverter::parseReal(vecparams[parIndex]);
927                }
928                else
929                {
930                    colSrc2.a = 1.0f;
931                }
932            }
933        }
934        catch (Exception& e)
935        {
936            logParseError("Bad colour_op_ex attribute, " + e.getFullDescription(), context);
937            return false;
938        }
939
940        context.textureUnit->setColourOperationEx(op, src1, src2, colSrc1, colSrc2, manual);
941        return false;
942    }
943    //-----------------------------------------------------------------------
944    bool parseColourOpFallback(String& params, MaterialScriptContext& context)
945    {
946        StringUtil::toLowerCase(params);
947        StringVector vecparams = StringUtil::split(params, " \t");
948        if (vecparams.size() != 2)
949        {
950            logParseError("Bad colour_op_multipass_fallback attribute, wrong number "
951                "of parameters (expected 2)", context);
952            return false;
953        }
954
955        //src/dest
956        SceneBlendFactor src, dest;
957
958        try {
959            src = convertBlendFactor(vecparams[0]);
960            dest = convertBlendFactor(vecparams[1]);
961            context.textureUnit->setColourOpMultipassFallback(src,dest);
962        }
963        catch (Exception& e)
964        {
965            logParseError("Bad colour_op_multipass_fallback attribute, "
966                + e.getFullDescription(), context);
967        }
968        return false;
969    }
970    //-----------------------------------------------------------------------
971    bool parseAlphaOpEx(String& params, MaterialScriptContext& context)
972    {
973        StringUtil::toLowerCase(params);
974        StringVector vecparams = StringUtil::split(params, " \t");
975        size_t numParams = vecparams.size();
976        if (numParams < 3 || numParams > 6)
977        {
978            logParseError("Bad alpha_op_ex attribute, wrong number of parameters "
979                "(expected 3 to 6)", context);
980            return false;
981        }
982        LayerBlendOperationEx op;
983        LayerBlendSource src1, src2;
984        Real manual = 0.0;
985        Real arg1 = 1.0, arg2 = 1.0;
986
987        try {
988            op = convertBlendOpEx(vecparams[0]);
989            src1 = convertBlendSource(vecparams[1]);
990            src2 = convertBlendSource(vecparams[2]);
991            if (op == LBX_BLEND_MANUAL)
992            {
993                if (numParams != 4)
994                {
995                    logParseError("Bad alpha_op_ex attribute, wrong number of parameters "
996                        "(expected 4 for manual blend)", context);
997                    return false;
998                }
999                manual = StringConverter::parseReal(vecparams[3]);
1000            }
1001            if (src1 == LBS_MANUAL)
1002            {
1003                unsigned int parIndex = 3;
1004                if (op == LBX_BLEND_MANUAL)
1005                    parIndex++;
1006
1007                if (numParams < parIndex)
1008                {
1009                    logParseError(
1010                        "Bad alpha_op_ex attribute, wrong number of parameters (expected " +
1011                        StringConverter::toString(parIndex - 1) + ")", context);
1012                    return false;
1013                }
1014
1015                arg1 = StringConverter::parseReal(vecparams[parIndex]);
1016            }
1017
1018            if (src2 == LBS_MANUAL)
1019            {
1020                unsigned int parIndex = 3;
1021                if (op == LBX_BLEND_MANUAL)
1022                    parIndex++;
1023                if (src1 == LBS_MANUAL)
1024                    parIndex++;
1025
1026                if (numParams < parIndex)
1027                {
1028                    logParseError(
1029                        "Bad alpha_op_ex attribute, wrong number of parameters "
1030                        "(expected " + StringConverter::toString(parIndex - 1) + ")", context);
1031                    return false;
1032                }
1033
1034                arg2 = StringConverter::parseReal(vecparams[parIndex]);
1035            }
1036        }
1037        catch (Exception& e)
1038        {
1039            logParseError("Bad alpha_op_ex attribute, " + e.getFullDescription(), context);
1040            return false;
1041        }
1042
1043        context.textureUnit->setAlphaOperation(op, src1, src2, arg1, arg2, manual);
1044        return false;
1045    }
1046    //-----------------------------------------------------------------------
1047    bool parseEnvMap(String& params, MaterialScriptContext& context)
1048    {
1049        StringUtil::toLowerCase(params);
1050        if (params=="off")
1051            context.textureUnit->setEnvironmentMap(false);
1052        else if (params=="spherical")
1053            context.textureUnit->setEnvironmentMap(true, TextureUnitState::ENV_CURVED);
1054        else if (params=="planar")
1055            context.textureUnit->setEnvironmentMap(true, TextureUnitState::ENV_PLANAR);
1056        else if (params=="cubic_reflection")
1057            context.textureUnit->setEnvironmentMap(true, TextureUnitState::ENV_REFLECTION);
1058        else if (params=="cubic_normal")
1059            context.textureUnit->setEnvironmentMap(true, TextureUnitState::ENV_NORMAL);
1060        else
1061            logParseError("Bad env_map attribute, valid parameters are 'off', "
1062                "'spherical', 'planar', 'cubic_reflection' and 'cubic_normal'.", context);
1063
1064        return false;
1065    }
1066    //-----------------------------------------------------------------------
1067    bool parseScroll(String& params, MaterialScriptContext& context)
1068    {
1069        StringVector vecparams = StringUtil::split(params, " \t");
1070        if (vecparams.size() != 2)
1071        {
1072            logParseError("Bad scroll attribute, wrong number of parameters (expected 2)", context);
1073            return false;
1074        }
1075        context.textureUnit->setTextureScroll(
1076            StringConverter::parseReal(vecparams[0]),
1077            StringConverter::parseReal(vecparams[1]));
1078
1079   
1080        return false;
1081    }
1082    //-----------------------------------------------------------------------
1083    bool parseScrollAnim(String& params, MaterialScriptContext& context)
1084    {
1085        StringVector vecparams = StringUtil::split(params, " \t");
1086        if (vecparams.size() != 2)
1087        {
1088            logParseError("Bad scroll_anim attribute, wrong number of "
1089                "parameters (expected 2)", context);
1090            return false;
1091        }
1092        context.textureUnit->setScrollAnimation(
1093            StringConverter::parseReal(vecparams[0]),
1094            StringConverter::parseReal(vecparams[1]));
1095
1096        return false;
1097    }
1098    //-----------------------------------------------------------------------
1099    bool parseRotate(String& params, MaterialScriptContext& context)
1100    {
1101        context.textureUnit->setTextureRotate(
1102            StringConverter::parseAngle(params));
1103
1104        return false;
1105    }
1106    //-----------------------------------------------------------------------
1107    bool parseRotateAnim(String& params, MaterialScriptContext& context)
1108    {
1109        context.textureUnit->setRotateAnimation(
1110            StringConverter::parseReal(params));
1111
1112        return false;
1113    }
1114    //-----------------------------------------------------------------------
1115    bool parseScale(String& params, MaterialScriptContext& context)
1116    {
1117        StringVector vecparams = StringUtil::split(params, " \t");
1118        if (vecparams.size() != 2)
1119        {
1120            logParseError("Bad scale attribute, wrong number of parameters (expected 2)", context);
1121            return false;
1122        }
1123        context.textureUnit->setTextureScale(
1124            StringConverter::parseReal(vecparams[0]),
1125            StringConverter::parseReal(vecparams[1]));
1126
1127        return false;
1128    }
1129    //-----------------------------------------------------------------------
1130    bool parseWaveXform(String& params, MaterialScriptContext& context)
1131    {
1132        StringUtil::toLowerCase(params);
1133        StringVector vecparams = StringUtil::split(params, " \t");
1134
1135        if (vecparams.size() != 6)
1136        {
1137            logParseError("Bad wave_xform attribute, wrong number of parameters "
1138                "(expected 6)", context);
1139            return false;
1140        }
1141        TextureUnitState::TextureTransformType ttype;
1142        WaveformType waveType;
1143        // Check transform type
1144        if (vecparams[0]=="scroll_x")
1145            ttype = TextureUnitState::TT_TRANSLATE_U;
1146        else if (vecparams[0]=="scroll_y")
1147            ttype = TextureUnitState::TT_TRANSLATE_V;
1148        else if (vecparams[0]=="rotate")
1149            ttype = TextureUnitState::TT_ROTATE;
1150        else if (vecparams[0]=="scale_x")
1151            ttype = TextureUnitState::TT_SCALE_U;
1152        else if (vecparams[0]=="scale_y")
1153            ttype = TextureUnitState::TT_SCALE_V;
1154        else
1155        {
1156            logParseError("Bad wave_xform attribute, parameter 1 must be 'scroll_x', "
1157                "'scroll_y', 'rotate', 'scale_x' or 'scale_y'", context);
1158            return false;
1159        }
1160        // Check wave type
1161        if (vecparams[1]=="sine")
1162            waveType = WFT_SINE;
1163        else if (vecparams[1]=="triangle")
1164            waveType = WFT_TRIANGLE;
1165        else if (vecparams[1]=="square")
1166            waveType = WFT_SQUARE;
1167        else if (vecparams[1]=="sawtooth")
1168            waveType = WFT_SAWTOOTH;
1169        else if (vecparams[1]=="inverse_sawtooth")
1170            waveType = WFT_INVERSE_SAWTOOTH;
1171        else
1172        {
1173            logParseError("Bad wave_xform attribute, parameter 2 must be 'sine', "
1174                "'triangle', 'square', 'sawtooth' or 'inverse_sawtooth'", context);
1175            return false;
1176        }
1177
1178        context.textureUnit->setTransformAnimation(
1179            ttype,
1180            waveType,
1181            StringConverter::parseReal(vecparams[2]),
1182            StringConverter::parseReal(vecparams[3]),
1183            StringConverter::parseReal(vecparams[4]),
1184            StringConverter::parseReal(vecparams[5]) );
1185
1186        return false;
1187    }
1188        //-----------------------------------------------------------------------
1189        bool parseTransform(String& params, MaterialScriptContext& context)
1190        {
1191                StringVector vecparams = StringUtil::split(params, " \t");
1192                if (vecparams.size() != 16)
1193                {
1194                        logParseError("Bad transform attribute, wrong number of parameters (expected 16)", context);
1195                        return false;
1196                }
1197                Matrix4 xform(
1198                        StringConverter::parseReal(vecparams[0]),
1199                        StringConverter::parseReal(vecparams[1]),
1200                        StringConverter::parseReal(vecparams[2]),
1201                        StringConverter::parseReal(vecparams[3]),
1202                        StringConverter::parseReal(vecparams[4]),
1203                        StringConverter::parseReal(vecparams[5]),
1204                        StringConverter::parseReal(vecparams[6]),
1205                        StringConverter::parseReal(vecparams[7]),
1206                        StringConverter::parseReal(vecparams[8]),
1207                        StringConverter::parseReal(vecparams[9]),
1208                        StringConverter::parseReal(vecparams[10]),
1209                        StringConverter::parseReal(vecparams[11]),
1210                        StringConverter::parseReal(vecparams[12]),
1211                        StringConverter::parseReal(vecparams[13]),
1212                        StringConverter::parseReal(vecparams[14]),
1213                        StringConverter::parseReal(vecparams[15]) );
1214                context.textureUnit->setTextureTransform(xform);
1215
1216
1217                return false;
1218        }
1219    //-----------------------------------------------------------------------
1220    bool parseDepthBias(String& params, MaterialScriptContext& context)
1221    {
1222        context.pass->setDepthBias(
1223            StringConverter::parseReal(params));
1224
1225        return false;
1226    }
1227    //-----------------------------------------------------------------------
1228    bool parseAnisotropy(String& params, MaterialScriptContext& context)
1229    {
1230        context.textureUnit->setTextureAnisotropy(
1231            StringConverter::parseInt(params));
1232
1233        return false;
1234    }
1235    //-----------------------------------------------------------------------
1236    bool parseLodDistances(String& params, MaterialScriptContext& context)
1237    {
1238        StringVector vecparams = StringUtil::split(params, " \t");
1239
1240        // iterate over the parameters and parse distances out of them
1241        Material::LodDistanceList lodList;
1242        StringVector::iterator i, iend;
1243        iend = vecparams.end();
1244        for (i = vecparams.begin(); i != iend; ++i)
1245        {
1246            lodList.push_back(StringConverter::parseReal(*i));
1247        }
1248
1249        context.material->setLodLevels(lodList);
1250
1251        return false;
1252    }
1253    //-----------------------------------------------------------------------
1254    bool parseLodIndex(String& params, MaterialScriptContext& context)
1255    {
1256        context.technique->setLodIndex(StringConverter::parseInt(params));
1257        return false;
1258    }
1259    //-----------------------------------------------------------------------
1260    void processManualProgramParam(size_t index, const String& commandname,
1261        StringVector& vecparams, MaterialScriptContext& context)
1262    {
1263        // NB we assume that the first element of vecparams is taken up with either
1264        // the index or the parameter name, which we ignore
1265
1266        // Determine type
1267        size_t start, dims, roundedDims, i;
1268        bool isReal;
1269
1270        StringUtil::toLowerCase(vecparams[1]);
1271
1272        if (vecparams[1] == "matrix4x4")
1273        {
1274            dims = 16;
1275            isReal = true;
1276        }
1277        else if ((start = vecparams[1].find("float")) != String::npos)
1278        {
1279            // find the dimensionality
1280            start = vecparams[1].find_first_not_of("float");
1281            // Assume 1 if not specified
1282            if (start == String::npos)
1283            {
1284                dims = 1;
1285            }
1286            else
1287            {
1288                dims = StringConverter::parseInt(vecparams[1].substr(start));
1289            }
1290            isReal = true;
1291        }
1292        else if ((start = vecparams[1].find("int")) != String::npos)
1293        {
1294            // find the dimensionality
1295            start = vecparams[1].find_first_not_of("int");
1296            // Assume 1 if not specified
1297            if (start == String::npos)
1298            {
1299                dims = 1;
1300            }
1301            else
1302            {
1303                dims = StringConverter::parseInt(vecparams[1].substr(start));
1304            }
1305            isReal = false;
1306        }
1307        else
1308        {
1309            logParseError("Invalid " + commandname + " attribute - unrecognised "
1310                "parameter type " + vecparams[1], context);
1311            return;
1312        }
1313
1314        if (vecparams.size() != 2 + dims)
1315        {
1316            logParseError("Invalid " + commandname + " attribute - you need " +
1317                StringConverter::toString(2 + dims) + " parameters for a parameter of "
1318                "type " + vecparams[1], context);
1319        }
1320
1321        // Round dims to multiple of 4
1322        if (dims %4 != 0)
1323        {
1324            roundedDims = dims + 4 - (dims % 4);
1325        }
1326        else
1327        {
1328            roundedDims = dims;
1329        }
1330
1331        // Now parse all the values
1332        if (isReal)
1333        {
1334            Real* realBuffer = new Real[roundedDims];
1335            // Do specified values
1336            for (i = 0; i < dims; ++i)
1337            {
1338                realBuffer[i] = StringConverter::parseReal(vecparams[i+2]);
1339            }
1340            // Fill up to multiple of 4 with zero
1341            for (; i < roundedDims; ++i)
1342            {
1343                realBuffer[i] = 0.0f;
1344            }
1345            // Set
1346            context.programParams->setConstant(index, realBuffer, roundedDims * 0.25);
1347            delete [] realBuffer;
1348        }
1349        else
1350        {
1351            int* intBuffer = new int[roundedDims];
1352            // Do specified values
1353            for (i = 0; i < dims; ++i)
1354            {
1355                intBuffer[i] = StringConverter::parseInt(vecparams[i+2]);
1356            }
1357            // Fill to multiple of 4 with 0
1358            for (; i < roundedDims; ++i)
1359            {
1360                intBuffer[i] = 0;
1361            }
1362            // Set
1363            context.programParams->setConstant(index, intBuffer, roundedDims * 0.25);
1364            delete [] intBuffer;
1365        }
1366    }
1367    //-----------------------------------------------------------------------
1368    void processAutoProgramParam(size_t index, const String& commandname,
1369        StringVector& vecparams, MaterialScriptContext& context)
1370    {
1371        // NB we assume that the first element of vecparams is taken up with either
1372        // the index or the parameter name, which we ignore
1373
1374        bool extras = false;
1375                bool float_extras = false;
1376        GpuProgramParameters::AutoConstantType acType;
1377
1378        StringUtil::toLowerCase(vecparams[1]);
1379
1380        if (vecparams[1] == "world_matrix")
1381        {
1382            acType = GpuProgramParameters::ACT_WORLD_MATRIX;
1383        }
1384        else if (vecparams[1] == "world_matrix_array")
1385        {
1386            acType = GpuProgramParameters::ACT_WORLD_MATRIX_ARRAY;
1387        }
1388        else if (vecparams[1] == "world_matrix_array_3x4")
1389        {
1390            acType = GpuProgramParameters::ACT_WORLD_MATRIX_ARRAY_3x4;
1391        }
1392        else if (vecparams[1] == "view_matrix")
1393        {
1394            acType = GpuProgramParameters::ACT_VIEW_MATRIX;
1395        }
1396                else if (vecparams[1] == "projection_matrix")
1397                {
1398                        acType = GpuProgramParameters::ACT_PROJECTION_MATRIX;
1399                }
1400        else if (vecparams[1] == "viewproj_matrix")
1401        {
1402            acType = GpuProgramParameters::ACT_VIEWPROJ_MATRIX;
1403        }
1404        else if (vecparams[1] == "worldview_matrix")
1405        {
1406            acType = GpuProgramParameters::ACT_WORLDVIEW_MATRIX;
1407        }
1408        else if (vecparams[1] == "worldviewproj_matrix")
1409        {
1410            acType = GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX;
1411        }
1412        else if (vecparams[1] == "inverse_world_matrix")
1413        {
1414            acType = GpuProgramParameters::ACT_INVERSE_WORLD_MATRIX;
1415        }
1416                else if (vecparams[1] == "inverse_view_matrix")
1417                {
1418                        acType = GpuProgramParameters::ACT_INVERSE_VIEW_MATRIX;
1419                }
1420        else if (vecparams[1] == "inverse_worldview_matrix")
1421        {
1422            acType = GpuProgramParameters::ACT_INVERSE_WORLDVIEW_MATRIX;
1423        }
1424        else if (vecparams[1] == "inverse_transpose_world_matrix")
1425        {
1426            acType = GpuProgramParameters::ACT_INVERSETRANSPOSE_WORLD_MATRIX;
1427        }
1428        else if (vecparams[1] == "inverse_transpose_worldview_matrix")
1429        {
1430            acType = GpuProgramParameters::ACT_INVERSETRANSPOSE_WORLDVIEW_MATRIX;
1431        }
1432                else if (vecparams[1] == "time_0_x")
1433                {
1434                        acType = GpuProgramParameters::ACT_TIME_0_X;
1435                        float_extras = true;
1436                }
1437                else if (vecparams[1] == "costime_0_x")
1438                {
1439                        acType = GpuProgramParameters::ACT_COSTIME_0_X;
1440                        float_extras = true;
1441                }
1442                else if (vecparams[1] == "sintime_0_x")
1443                {
1444                        acType = GpuProgramParameters::ACT_SINTIME_0_X;
1445                        float_extras = true;
1446                }
1447                else if (vecparams[1] == "tantime_0_x")
1448                {
1449                        acType = GpuProgramParameters::ACT_TANTIME_0_X;
1450                        float_extras = true;
1451                }
1452                else if (vecparams[1] == "time_0_x_packed")
1453                {
1454                        acType = GpuProgramParameters::ACT_TIME_0_X_PACKED;
1455                        float_extras = true;
1456                }
1457                else if (vecparams[1] == "time_0_1")
1458                {
1459                        acType = GpuProgramParameters::ACT_TIME_0_1;
1460                        float_extras = true;
1461                }
1462                else if (vecparams[1] == "costime_0_1")
1463                {
1464                        acType = GpuProgramParameters::ACT_COSTIME_0_1;
1465                        float_extras = true;
1466                }
1467                else if (vecparams[1] == "sintime_0_1")
1468                {
1469                        acType = GpuProgramParameters::ACT_SINTIME_0_1;
1470                        float_extras = true;
1471                }
1472                else if (vecparams[1] == "tantime_0_1")
1473                {
1474                        acType = GpuProgramParameters::ACT_TANTIME_0_1;
1475                        float_extras = true;
1476                }
1477                else if (vecparams[1] == "time_0_1_packed")
1478                {
1479                        acType = GpuProgramParameters::ACT_TIME_0_1_PACKED;
1480                        float_extras = true;
1481                }
1482                else if (vecparams[1] == "time_0_2pi")
1483                {
1484                        acType = GpuProgramParameters::ACT_TIME_0_2PI;
1485                        float_extras = true;
1486                }
1487                else if (vecparams[1] == "costime_0_2pi")
1488                {
1489                        acType = GpuProgramParameters::ACT_COSTIME_0_2PI;
1490                        float_extras = true;
1491                }
1492                else if (vecparams[1] == "sintime_0_2pi")
1493                {
1494                        acType = GpuProgramParameters::ACT_SINTIME_0_2PI;
1495                        float_extras = true;
1496                }
1497                else if (vecparams[1] == "tantime_0_2pi")
1498                {
1499                        acType = GpuProgramParameters::ACT_TANTIME_0_2PI;
1500                        float_extras = true;
1501                }
1502                else if (vecparams[1] == "time_0_2pi_packed")
1503                {
1504                        acType = GpuProgramParameters::ACT_TIME_0_2PI_PACKED;
1505                        float_extras = true;
1506                }
1507                else if (vecparams[1] == "fps")
1508                {
1509                        acType = GpuProgramParameters::ACT_FPS;
1510                }
1511                else if (vecparams[1] == "viewport_width")
1512                {
1513                        acType = GpuProgramParameters::ACT_VIEWPORT_WIDTH;
1514                }
1515                else if (vecparams[1] == "viewport_height")
1516                {
1517                        acType = GpuProgramParameters::ACT_VIEWPORT_HEIGHT;
1518                }
1519                else if (vecparams[1] == "inverse_viewport_width")
1520                {
1521                        acType = GpuProgramParameters::ACT_INVERSE_VIEWPORT_WIDTH;
1522                }
1523                else if (vecparams[1] == "inverse_viewport_height")
1524                {
1525                        acType = GpuProgramParameters::ACT_INVERSE_VIEWPORT_HEIGHT;
1526                }
1527                else if (vecparams[1] == "view_direction")
1528                {
1529                        acType = GpuProgramParameters::ACT_VIEW_DIRECTION;
1530                }
1531                else if (vecparams[1] == "view_side_vector")
1532                {
1533                        acType = GpuProgramParameters::ACT_VIEW_SIDE_VECTOR;
1534                }
1535                else if (vecparams[1] == "view_up_vector")
1536                {
1537                        acType = GpuProgramParameters::ACT_VIEW_UP_VECTOR;
1538                }
1539                else if (vecparams[1] == "fov")
1540                {
1541                        acType = GpuProgramParameters::ACT_FOV;
1542                }
1543                else if (vecparams[1] == "near_clip_distance")
1544                {
1545                        acType = GpuProgramParameters::ACT_NEAR_CLIP_DISTANCE;
1546                }
1547                else if (vecparams[1] == "far_clip_distance")
1548                {
1549                        acType = GpuProgramParameters::ACT_FAR_CLIP_DISTANCE;
1550                }
1551                else if (vecparams[1] == "inverse_viewproj_matrix")
1552                {
1553                        acType = GpuProgramParameters::ACT_INVERSE_VIEWPROJ_MATRIX;
1554                }
1555                else if (vecparams[1] == "inverse_transpose_viewproj_matrix")
1556                {
1557                        acType = GpuProgramParameters::ACT_INVERSETRANSPOSE_VIEWPROJ_MATRIX;
1558                }
1559                else if (vecparams[1] == "transpose_viewproj_matrix")
1560                {
1561                        acType = GpuProgramParameters::ACT_TRANSPOSE_VIEWPROJ_MATRIX;
1562                }
1563                else if (vecparams[1] == "transpose_view_matrix")
1564                {
1565                        acType = GpuProgramParameters::ACT_TRANSPOSE_VIEW_MATRIX;
1566                }
1567                else if (vecparams[1] == "inverse_transpose_view_matrix")
1568                {
1569                        acType = GpuProgramParameters::ACT_INVERSETRANSPOSE_VIEW_MATRIX;
1570                }
1571                else if (vecparams[1] == "projection_matrix")
1572                {
1573                        acType = GpuProgramParameters::ACT_PROJECTION_MATRIX;
1574                }
1575                else if (vecparams[1] == "transpose_projection_matrix")
1576                {
1577                        acType = GpuProgramParameters::ACT_TRANSPOSE_PROJECTION_MATRIX;
1578                }
1579                else if (vecparams[1] == "inverse_projection_matrix")
1580                {
1581                        acType = GpuProgramParameters::ACT_INVERSE_PROJECTION_MATRIX;
1582                }
1583                else if (vecparams[1] == "inverse_transpose_projection_matrix")
1584                {
1585                        acType = GpuProgramParameters::ACT_INVERSETRANSPOSE_PROJECTION_MATRIX;
1586                }
1587                else if (vecparams[1] == "transpose_worldviewproj_matrix")
1588                {
1589                        acType = GpuProgramParameters::ACT_TRANSPOSE_WORLDVIEWPROJ_MATRIX;
1590                }
1591                else if (vecparams[1] == "inverse_worldviewproj_matrix")
1592                {
1593                        acType = GpuProgramParameters::ACT_INVERSE_WORLDVIEWPROJ_MATRIX;
1594                }
1595                else if (vecparams[1] == "inverse_transpose_worldviewproj_matrix")
1596                {
1597                        acType = GpuProgramParameters::ACT_INVERSETRANSPOSE_WORLDVIEWPROJ_MATRIX;
1598                }
1599                else if (vecparams[1] == "transpose_worldview_matrix")
1600                {
1601                        acType = GpuProgramParameters::ACT_TRANSPOSE_WORLDVIEW_MATRIX;
1602                }
1603                else if (vecparams[1] == "inverse_transpose_worldview_matrix")
1604                {
1605                        acType = GpuProgramParameters::ACT_INVERSE_TRANSPOSE_WORLDVIEW_MATRIX;
1606                }
1607                else if (vecparams[1] == "transpose_world_matrix")
1608                {
1609                        acType = GpuProgramParameters::ACT_TRANSPOSE_WORLD_MATRIX;
1610                }
1611                else if (vecparams[1] == "inverse_transpose_world_matrix")
1612                {
1613                        acType = GpuProgramParameters::ACT_INVERSE_TRANSPOSE_WORLD_MATRIX;
1614                }
1615        else if (vecparams[1] == "light_diffuse_colour")
1616        {
1617            acType = GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR;
1618            extras = true;
1619        }
1620        else if (vecparams[1] == "light_specular_colour")
1621        {
1622            acType = GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR;
1623            extras = true;
1624        }
1625        else if (vecparams[1] == "light_attenuation")
1626        {
1627            acType = GpuProgramParameters::ACT_LIGHT_ATTENUATION;
1628            extras = true;
1629        }
1630        else if (vecparams[1] == "light_position")
1631        {
1632            acType = GpuProgramParameters::ACT_LIGHT_POSITION;
1633            extras = true;
1634        }
1635        else if (vecparams[1] == "light_direction")
1636        {
1637            acType = GpuProgramParameters::ACT_LIGHT_DIRECTION;
1638            extras = true;
1639        }
1640        else if (vecparams[1] == "light_position_object_space")
1641        {
1642            acType = GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE;
1643            extras = true;
1644        }
1645        else if (vecparams[1] == "light_direction_object_space")
1646        {
1647            acType = GpuProgramParameters::ACT_LIGHT_DIRECTION_OBJECT_SPACE;
1648            extras = true;
1649        }
1650        else if (vecparams[1] == "ambient_light_colour")
1651        {
1652            acType = GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR;
1653        }
1654        else if (vecparams[1] == "camera_position")
1655        {
1656            acType = GpuProgramParameters::ACT_CAMERA_POSITION;
1657        }
1658        else if (vecparams[1] == "camera_position_object_space")
1659        {
1660            acType = GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE;
1661        }
1662        else if (vecparams[1] == "texture_viewproj_matrix")
1663        {
1664            acType = GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX;
1665        }
1666        else if (vecparams[1] == "time")
1667        {
1668            // Special case!
1669            Real factor = 1.0f;
1670            if (vecparams.size() == 3)
1671            {
1672                factor = StringConverter::parseReal(vecparams[2]);
1673            }
1674           
1675            context.programParams->setConstantFromTime(index, factor);
1676            return;
1677        }
1678        else if (vecparams[1] == "custom")
1679        {
1680            acType = GpuProgramParameters::ACT_CUSTOM;
1681            extras = true;
1682        }
1683                else
1684                {
1685                        logParseError("Invalid " + commandname + " attribute - "
1686                                + vecparams[1], context);
1687                        return;
1688
1689                }
1690
1691        // Do we need any extra parameters?
1692        size_t extraParam = 0;
1693        if (extras)
1694        {
1695            if (vecparams.size() != 3)
1696            {
1697                logParseError("Invalid " + commandname + " attribute - "
1698                    "expected 3 parameters.", context);
1699                return;
1700            }
1701            extraParam = StringConverter::parseInt(vecparams[2]);
1702        }
1703               
1704               
1705                if (float_extras) {
1706                        Real rData = StringConverter::parseReal(vecparams[2]);
1707                        context.programParams->setAutoConstantReal(index, acType, rData);
1708                }
1709                else {
1710                        context.programParams->setAutoConstant(index, acType, extraParam);
1711                }
1712
1713    }
1714    //-----------------------------------------------------------------------
1715    bool parseParamIndexed(String& params, MaterialScriptContext& context)
1716    {
1717        // NB skip this if the program is not supported or could not be found
1718        if (context.program.isNull() || !context.program->isSupported())
1719        {
1720            return false;
1721        }
1722
1723        StringUtil::toLowerCase(params);
1724        StringVector vecparams = StringUtil::split(params, " \t");
1725        if (vecparams.size() < 3)
1726        {
1727            logParseError("Invalid param_indexed attribute - expected at least 3 parameters.",
1728                context);
1729            return false;
1730        }
1731
1732        // Get start index
1733        size_t index = StringConverter::parseInt(vecparams[0]);
1734
1735        processManualProgramParam(index, "param_indexed", vecparams, context);
1736
1737        return false;
1738    }
1739    //-----------------------------------------------------------------------
1740    bool parseParamIndexedAuto(String& params, MaterialScriptContext& context)
1741    {
1742        // NB skip this if the program is not supported or could not be found
1743        if (context.program.isNull() || !context.program->isSupported())
1744        {
1745            return false;
1746        }
1747
1748        StringUtil::toLowerCase(params);
1749        StringVector vecparams = StringUtil::split(params, " \t");
1750        if (vecparams.size() != 2 && vecparams.size() != 3)
1751        {
1752            logParseError("Invalid param_indexed_auto attribute - expected 2 or 3 parameters.",
1753                context);
1754            return false;
1755        }
1756
1757        // Get start index
1758        size_t index = StringConverter::parseInt(vecparams[0]);
1759
1760        processAutoProgramParam(index, "param_indexed_auto", vecparams, context);
1761
1762        return false;
1763    }
1764    //-----------------------------------------------------------------------
1765    bool parseParamNamed(String& params, MaterialScriptContext& context)
1766    {
1767        // NB skip this if the program is not supported or could not be found
1768        if (context.program.isNull() || !context.program->isSupported())
1769        {
1770            return false;
1771        }
1772
1773        StringVector vecparams = StringUtil::split(params, " \t");
1774        if (vecparams.size() < 3)
1775        {
1776            logParseError("Invalid param_named attribute - expected at least 3 parameters.",
1777                context);
1778            return false;
1779        }
1780
1781        // Get start index from name
1782        size_t index;
1783        try {
1784            index = context.programParams->getParamIndex(vecparams[0]);
1785        }
1786        catch (Exception& e)
1787        {
1788            logParseError("Invalid param_named attribute - " + e.getFullDescription(), context);
1789            return false;
1790        }
1791
1792        // TEST
1793        /*
1794        LogManager::getSingleton().logMessage("SETTING PARAMETER " + vecparams[0] + " as index " +
1795            StringConverter::toString(index));
1796        */
1797        processManualProgramParam(index, "param_named", vecparams, context);
1798
1799        return false;
1800    }
1801    //-----------------------------------------------------------------------
1802    bool parseParamNamedAuto(String& params, MaterialScriptContext& context)
1803    {
1804        // NB skip this if the program is not supported or could not be found
1805        if (context.program.isNull() || !context.program->isSupported())
1806        {
1807            return false;
1808        }
1809
1810        StringVector vecparams = StringUtil::split(params, " \t");
1811        if (vecparams.size() != 2 && vecparams.size() != 3)
1812        {
1813            logParseError("Invalid param_indexed_auto attribute - expected 2 or 3 parameters.",
1814                context);
1815            return false;
1816        }
1817
1818        // Get start index from name
1819        size_t index;
1820        try {
1821            index = context.programParams->getParamIndex(vecparams[0]);
1822        }
1823        catch (Exception& e)
1824        {
1825            logParseError("Invalid param_named_auto attribute - " + e.getFullDescription(), context);
1826            return false;
1827        }
1828
1829        processAutoProgramParam(index, "param_named_auto", vecparams, context);
1830
1831        return false;
1832    }
1833    //-----------------------------------------------------------------------
1834    bool parseMaterial(String& params, MaterialScriptContext& context)
1835    {
1836        // Create a brand new material
1837        context.material =
1838                        MaterialManager::getSingleton().create(params, context.groupName);
1839                context.material->_notifyOrigin(context.filename);
1840        // Remove pre-created technique from defaults
1841        context.material->removeAllTechniques();
1842
1843        // update section
1844        context.section = MSS_MATERIAL;
1845
1846        // Return TRUE because this must be followed by a {
1847        return true;
1848    }
1849    //-----------------------------------------------------------------------
1850    bool parseTechnique(String& params, MaterialScriptContext& context)
1851    {
1852        // Create a new technique
1853        context.technique = context.material->createTechnique();
1854
1855        // update section
1856        context.section = MSS_TECHNIQUE;
1857
1858                //Increase technique level depth
1859                context.techLev += 1;
1860
1861        // Return TRUE because this must be followed by a {
1862        return true;
1863    }
1864    //-----------------------------------------------------------------------
1865    bool parsePass(String& params, MaterialScriptContext& context)
1866    {
1867        // Create a new pass
1868        context.pass = context.technique->createPass();
1869
1870        // update section
1871        context.section = MSS_PASS;
1872
1873                //Increase pass level depth
1874                context.passLev += 1;
1875
1876        // Return TRUE because this must be followed by a {
1877        return true;
1878    }
1879    //-----------------------------------------------------------------------
1880    bool parseTextureUnit(String& params, MaterialScriptContext& context)
1881    {
1882        // Create a new texture unit
1883        context.textureUnit = context.pass->createTextureUnitState();
1884
1885        // update section
1886        context.section = MSS_TEXTUREUNIT;
1887
1888                // Increase texture unit depth
1889                context.stateLev += 1;
1890
1891        // Return TRUE because this must be followed by a {
1892        return true;
1893    }
1894    //-----------------------------------------------------------------------
1895    bool parseVertexProgramRef(String& params, MaterialScriptContext& context)
1896    {
1897        // update section
1898        context.section = MSS_PROGRAM_REF;
1899
1900        context.program = GpuProgramManager::getSingleton().getByName(params);
1901        if (context.program.isNull())
1902        {
1903            // Unknown program
1904            logParseError("Invalid vertex_program_ref entry - vertex program "
1905                + params + " has not been defined.", context);
1906            return true;
1907        }
1908
1909        context.isProgramShadowCaster = false;
1910        context.isProgramShadowReceiver = false;
1911       
1912        // Set the vertex program for this pass
1913        context.pass->setVertexProgram(params);
1914
1915        // Create params? Skip this if program is not supported
1916        if (context.program->isSupported())
1917        {
1918            context.programParams = context.pass->getVertexProgramParameters();
1919        }
1920
1921        // Return TRUE because this must be followed by a {
1922        return true;
1923    }
1924    //-----------------------------------------------------------------------
1925    bool parseShadowCasterVertexProgramRef(String& params, MaterialScriptContext& context)
1926    {
1927        // update section
1928        context.section = MSS_PROGRAM_REF;
1929
1930        context.program = GpuProgramManager::getSingleton().getByName(params);
1931        if (context.program.isNull())
1932        {
1933            // Unknown program
1934            logParseError("Invalid vertex_program_ref entry - vertex program "
1935                + params + " has not been defined.", context);
1936            return true;
1937        }
1938
1939        context.isProgramShadowCaster = true;
1940        context.isProgramShadowReceiver = false;
1941
1942        // Set the vertex program for this pass
1943        context.pass->setShadowCasterVertexProgram(params);
1944
1945        // Create params? Skip this if program is not supported
1946        if (context.program->isSupported())
1947        {
1948            context.programParams = context.pass->getShadowCasterVertexProgramParameters();
1949        }
1950
1951        // Return TRUE because this must be followed by a {
1952        return true;
1953    }
1954    //-----------------------------------------------------------------------
1955    bool parseShadowReceiverVertexProgramRef(String& params, MaterialScriptContext& context)
1956    {
1957        // update section
1958        context.section = MSS_PROGRAM_REF;
1959
1960        context.program = GpuProgramManager::getSingleton().getByName(params);
1961        if (context.program.isNull())
1962        {
1963            // Unknown program
1964            logParseError("Invalid vertex_program_ref entry - vertex program "
1965                + params + " has not been defined.", context);
1966            return true;
1967        }
1968
1969        context.isProgramShadowCaster = false;
1970        context.isProgramShadowReceiver = true;
1971
1972        // Set the vertex program for this pass
1973        context.pass->setShadowReceiverVertexProgram(params);
1974
1975        // Create params? Skip this if program is not supported
1976        if (context.program->isSupported())
1977        {
1978            context.programParams = context.pass->getShadowReceiverVertexProgramParameters();
1979        }
1980
1981        // Return TRUE because this must be followed by a {
1982        return true;
1983    }
1984    //-----------------------------------------------------------------------
1985    bool parseFragmentProgramRef(String& params, MaterialScriptContext& context)
1986    {
1987        // update section
1988        context.section = MSS_PROGRAM_REF;
1989
1990        context.program = GpuProgramManager::getSingleton().getByName(params);
1991        if (context.program.isNull())
1992        {
1993            // Unknown program
1994            logParseError("Invalid fragment_program_ref entry - fragment program "
1995                + params + " has not been defined.", context);
1996            return true;
1997        }
1998       
1999        // Set the vertex program for this pass
2000        context.pass->setFragmentProgram(params);
2001
2002        // Create params? Skip this if program is not supported
2003        if (context.program->isSupported())
2004        {
2005            context.programParams = context.pass->getFragmentProgramParameters();
2006        }
2007
2008        // Return TRUE because this must be followed by a {
2009        return true;
2010    }
2011    //-----------------------------------------------------------------------
2012    bool parseVertexProgram(String& params, MaterialScriptContext& context)
2013    {
2014        // update section
2015        context.section = MSS_PROGRAM;
2016
2017                // Create new program definition-in-progress
2018                context.programDef = new MaterialScriptProgramDefinition();
2019                context.programDef->progType = GPT_VERTEX_PROGRAM;
2020        context.programDef->supportsSkeletalAnimation = false;
2021
2022                // Get name and language code
2023                StringVector vecparams = StringUtil::split(params, " \t");
2024                if (vecparams.size() != 2)
2025                {
2026            logParseError("Invalid vertex_program entry - expected "
2027                                "2 parameters.", context);
2028            return true;
2029                }
2030                // Name, preserve case
2031                context.programDef->name = vecparams[0];
2032                // language code, make lower case
2033                context.programDef->language = vecparams[1];
2034                StringUtil::toLowerCase(context.programDef->language);
2035
2036        // Return TRUE because this must be followed by a {
2037        return true;
2038        }
2039    //-----------------------------------------------------------------------
2040    bool parseFragmentProgram(String& params, MaterialScriptContext& context)
2041    {
2042        // update section
2043        context.section = MSS_PROGRAM;
2044
2045                // Create new program definition-in-progress
2046                context.programDef = new MaterialScriptProgramDefinition();
2047                context.programDef->progType = GPT_FRAGMENT_PROGRAM;
2048                context.programDef->supportsSkeletalAnimation = false;
2049
2050                // Get name and language code
2051                StringVector vecparams = StringUtil::split(params, " \t");
2052                if (vecparams.size() != 2)
2053                {
2054            logParseError("Invalid fragment_program entry - expected "
2055                                "2 parameters.", context);
2056            return true;
2057                }
2058                // Name, preserve case
2059                context.programDef->name = vecparams[0];
2060                // language code, make lower case
2061                context.programDef->language = vecparams[1];
2062                StringUtil::toLowerCase(context.programDef->language);
2063
2064                // Return TRUE because this must be followed by a {
2065        return true;
2066       
2067        }
2068    //-----------------------------------------------------------------------
2069    bool parseProgramSource(String& params, MaterialScriptContext& context)
2070    {
2071                // Source filename, preserve case
2072                context.programDef->source = params;
2073
2074                return false;
2075        }
2076    //-----------------------------------------------------------------------
2077    bool parseProgramSkeletalAnimation(String& params, MaterialScriptContext& context)
2078    {
2079        // Source filename, preserve case
2080        context.programDef->supportsSkeletalAnimation
2081            = StringConverter::parseBool(params);
2082
2083        return false;
2084    }
2085    //-----------------------------------------------------------------------
2086    bool parseProgramSyntax(String& params, MaterialScriptContext& context)
2087    {
2088                // Syntax code, make lower case
2089        StringUtil::toLowerCase(params);
2090                context.programDef->syntax = params;
2091
2092                return false;
2093        }
2094    //-----------------------------------------------------------------------
2095    bool parseProgramCustomParameter(String& params, MaterialScriptContext& context)
2096    {
2097                // This params object does not have the command stripped
2098                // Lower case the command, but not the value incase it's relevant
2099                // Split only up to first delimiter, program deals with the rest
2100                StringVector vecparams = StringUtil::split(params, " \t", 1);
2101                if (vecparams.size() != 2)
2102                {
2103            logParseError("Invalid custom program parameter entry; "
2104                                "there must be a parameter name and at least one value.",
2105                                context);
2106            return false;
2107                }
2108
2109                context.programDef->customParameters[vecparams[0]] = vecparams[1];
2110
2111                return false;
2112        }
2113
2114        //-----------------------------------------------------------------------
2115    bool parseTextureSource(String& params, MaterialScriptContext& context)
2116    {
2117                StringUtil::toLowerCase(params);
2118        StringVector vecparams = StringUtil::split(params, " \t");
2119        if (vecparams.size() != 1)
2120                        logParseError("Invalid texture source attribute - expected 1 parameter.",                 context);
2121        //The only param should identify which ExternalTextureSource is needed
2122                ExternalTextureSourceManager::getSingleton().setCurrentPlugIn( vecparams[0] );
2123
2124                if(     ExternalTextureSourceManager::getSingleton().getCurrentPlugIn() != 0 )
2125                {
2126                        String tps;
2127                        tps = StringConverter::toString( context.techLev ) + " "
2128                                + StringConverter::toString( context.passLev ) + " "
2129                                + StringConverter::toString( context.stateLev);
2130
2131                        ExternalTextureSourceManager::getSingleton().getCurrentPlugIn()->setParameter( "set_T_P_S", tps );
2132                }
2133                       
2134        // update section
2135        context.section = MSS_TEXTURESOURCE;
2136        // Return TRUE because this must be followed by a {
2137        return true;
2138    }
2139
2140    //-----------------------------------------------------------------------
2141    bool parseTextureCustomParameter(String& params, MaterialScriptContext& context)
2142    {
2143                // This params object does not have the command stripped
2144                // Split only up to first delimiter, program deals with the rest
2145                StringVector vecparams = StringUtil::split(params, " \t", 1);
2146                if (vecparams.size() != 2)
2147                {
2148            logParseError("Invalid texture parameter entry; "
2149                                "there must be a parameter name and at least one value.",
2150                                context);
2151            return false;
2152                }
2153               
2154                if(     ExternalTextureSourceManager::getSingleton().getCurrentPlugIn() != 0 )
2155                        ////First is command, next could be a string with one or more values
2156                        ExternalTextureSourceManager::getSingleton().getCurrentPlugIn()->setParameter( vecparams[0], vecparams[1] );
2157               
2158                return false;
2159        }
2160    //-----------------------------------------------------------------------
2161    bool parseReceiveShadows(String& params, MaterialScriptContext& context)
2162    {
2163        StringUtil::toLowerCase(params);
2164        if (params == "on")
2165            context.material->setReceiveShadows(true);
2166        else if (params == "off")
2167            context.material->setReceiveShadows(false);
2168        else
2169            logParseError(
2170            "Bad receive_shadows attribute, valid parameters are 'on' or 'off'.",
2171            context);
2172
2173        return false;
2174
2175    }
2176    //-----------------------------------------------------------------------
2177    bool parseDefaultParams(String& params, MaterialScriptContext& context)
2178    {
2179        context.section = MSS_DEFAULT_PARAMETERS;
2180        // Should be a brace next
2181        return true;
2182    }
2183
2184        //-----------------------------------------------------------------------
2185        bool parseTransparencyCastsShadows(String& params, MaterialScriptContext& context)
2186        {
2187        StringUtil::toLowerCase(params);
2188                if (params == "on")
2189                        context.material->setTransparencyCastsShadows(true);
2190                else if (params == "off")
2191                        context.material->setTransparencyCastsShadows(false);
2192                else
2193                        logParseError(
2194                        "Bad transparency_casts_shadows attribute, valid parameters are 'on' or 'off'.",
2195                        context);
2196
2197                return false;
2198
2199        }
2200        //-----------------------------------------------------------------------
2201    //-----------------------------------------------------------------------
2202    MaterialSerializer::MaterialSerializer()
2203    {
2204        // Set up root attribute parsers
2205        mRootAttribParsers.insert(AttribParserList::value_type("material", (ATTRIBUTE_PARSER)parseMaterial));
2206        mRootAttribParsers.insert(AttribParserList::value_type("vertex_program", (ATTRIBUTE_PARSER)parseVertexProgram));
2207        mRootAttribParsers.insert(AttribParserList::value_type("fragment_program", (ATTRIBUTE_PARSER)parseFragmentProgram));
2208        // Set up material attribute parsers
2209        mMaterialAttribParsers.insert(AttribParserList::value_type("lod_distances", (ATTRIBUTE_PARSER)parseLodDistances));
2210        mMaterialAttribParsers.insert(AttribParserList::value_type("receive_shadows", (ATTRIBUTE_PARSER)parseReceiveShadows));
2211                mMaterialAttribParsers.insert(AttribParserList::value_type("transparency_casts_shadows", (ATTRIBUTE_PARSER)parseTransparencyCastsShadows));
2212        mMaterialAttribParsers.insert(AttribParserList::value_type("technique", (ATTRIBUTE_PARSER)parseTechnique));
2213        // Set up technique attribute parsers
2214        mTechniqueAttribParsers.insert(AttribParserList::value_type("lod_index", (ATTRIBUTE_PARSER)parseLodIndex));
2215        mTechniqueAttribParsers.insert(AttribParserList::value_type("pass", (ATTRIBUTE_PARSER)parsePass));
2216        // Set up pass attribute parsers
2217        mPassAttribParsers.insert(AttribParserList::value_type("ambient", (ATTRIBUTE_PARSER)parseAmbient));
2218        mPassAttribParsers.insert(AttribParserList::value_type("diffuse", (ATTRIBUTE_PARSER)parseDiffuse));
2219        mPassAttribParsers.insert(AttribParserList::value_type("specular", (ATTRIBUTE_PARSER)parseSpecular));
2220        mPassAttribParsers.insert(AttribParserList::value_type("emissive", (ATTRIBUTE_PARSER)parseEmissive));
2221        mPassAttribParsers.insert(AttribParserList::value_type("scene_blend", (ATTRIBUTE_PARSER)parseSceneBlend));
2222        mPassAttribParsers.insert(AttribParserList::value_type("depth_check", (ATTRIBUTE_PARSER)parseDepthCheck));
2223        mPassAttribParsers.insert(AttribParserList::value_type("depth_write", (ATTRIBUTE_PARSER)parseDepthWrite));
2224        mPassAttribParsers.insert(AttribParserList::value_type("depth_func", (ATTRIBUTE_PARSER)parseDepthFunc));
2225                mPassAttribParsers.insert(AttribParserList::value_type("alpha_rejection", (ATTRIBUTE_PARSER)parseAlphaRejection));
2226        mPassAttribParsers.insert(AttribParserList::value_type("colour_write", (ATTRIBUTE_PARSER)parseColourWrite));
2227        mPassAttribParsers.insert(AttribParserList::value_type("cull_hardware", (ATTRIBUTE_PARSER)parseCullHardware));
2228        mPassAttribParsers.insert(AttribParserList::value_type("cull_software", (ATTRIBUTE_PARSER)parseCullSoftware));
2229        mPassAttribParsers.insert(AttribParserList::value_type("lighting", (ATTRIBUTE_PARSER)parseLighting));
2230        mPassAttribParsers.insert(AttribParserList::value_type("fog_override", (ATTRIBUTE_PARSER)parseFogging));
2231        mPassAttribParsers.insert(AttribParserList::value_type("shading", (ATTRIBUTE_PARSER)parseShading));
2232        mPassAttribParsers.insert(AttribParserList::value_type("depth_bias", (ATTRIBUTE_PARSER)parseDepthBias));
2233        mPassAttribParsers.insert(AttribParserList::value_type("texture_unit", (ATTRIBUTE_PARSER)parseTextureUnit));
2234        mPassAttribParsers.insert(AttribParserList::value_type("vertex_program_ref", (ATTRIBUTE_PARSER)parseVertexProgramRef));
2235        mPassAttribParsers.insert(AttribParserList::value_type("shadow_caster_vertex_program_ref", (ATTRIBUTE_PARSER)parseShadowCasterVertexProgramRef));
2236        mPassAttribParsers.insert(AttribParserList::value_type("shadow_receiver_vertex_program_ref", (ATTRIBUTE_PARSER)parseShadowReceiverVertexProgramRef));
2237        mPassAttribParsers.insert(AttribParserList::value_type("fragment_program_ref", (ATTRIBUTE_PARSER)parseFragmentProgramRef));
2238        mPassAttribParsers.insert(AttribParserList::value_type("max_lights", (ATTRIBUTE_PARSER)parseMaxLights));
2239        mPassAttribParsers.insert(AttribParserList::value_type("iteration", (ATTRIBUTE_PARSER)parseIteration));
2240                mTextureUnitAttribParsers.insert(AttribParserList::value_type("texture_source", (ATTRIBUTE_PARSER)parseTextureSource));
2241
2242        // Set up texture unit attribute parsers
2243        mTextureUnitAttribParsers.insert(AttribParserList::value_type("texture", (ATTRIBUTE_PARSER)parseTexture));
2244        mTextureUnitAttribParsers.insert(AttribParserList::value_type("anim_texture", (ATTRIBUTE_PARSER)parseAnimTexture));
2245        mTextureUnitAttribParsers.insert(AttribParserList::value_type("cubic_texture", (ATTRIBUTE_PARSER)parseCubicTexture));
2246        mTextureUnitAttribParsers.insert(AttribParserList::value_type("tex_coord_set", (ATTRIBUTE_PARSER)parseTexCoord));
2247        mTextureUnitAttribParsers.insert(AttribParserList::value_type("tex_address_mode", (ATTRIBUTE_PARSER)parseTexAddressMode));
2248        mTextureUnitAttribParsers.insert(AttribParserList::value_type("colour_op", (ATTRIBUTE_PARSER)parseColourOp));
2249        mTextureUnitAttribParsers.insert(AttribParserList::value_type("colour_op_ex", (ATTRIBUTE_PARSER)parseColourOpEx));
2250        mTextureUnitAttribParsers.insert(AttribParserList::value_type("colour_op_multipass_fallback", (ATTRIBUTE_PARSER)parseColourOpFallback));
2251        mTextureUnitAttribParsers.insert(AttribParserList::value_type("alpha_op_ex", (ATTRIBUTE_PARSER)parseAlphaOpEx));
2252        mTextureUnitAttribParsers.insert(AttribParserList::value_type("env_map", (ATTRIBUTE_PARSER)parseEnvMap));
2253        mTextureUnitAttribParsers.insert(AttribParserList::value_type("scroll", (ATTRIBUTE_PARSER)parseScroll));
2254        mTextureUnitAttribParsers.insert(AttribParserList::value_type("scroll_anim", (ATTRIBUTE_PARSER)parseScrollAnim));
2255        mTextureUnitAttribParsers.insert(AttribParserList::value_type("rotate", (ATTRIBUTE_PARSER)parseRotate));
2256        mTextureUnitAttribParsers.insert(AttribParserList::value_type("rotate_anim", (ATTRIBUTE_PARSER)parseRotateAnim));
2257        mTextureUnitAttribParsers.insert(AttribParserList::value_type("scale", (ATTRIBUTE_PARSER)parseScale));
2258        mTextureUnitAttribParsers.insert(AttribParserList::value_type("wave_xform", (ATTRIBUTE_PARSER)parseWaveXform));
2259                mTextureUnitAttribParsers.insert(AttribParserList::value_type("transform", (ATTRIBUTE_PARSER)parseTransform));
2260        mTextureUnitAttribParsers.insert(AttribParserList::value_type("filtering", (ATTRIBUTE_PARSER)parseFiltering));
2261        mTextureUnitAttribParsers.insert(AttribParserList::value_type("max_anisotropy", (ATTRIBUTE_PARSER)parseAnisotropy));
2262
2263        // Set up program reference attribute parsers
2264        mProgramRefAttribParsers.insert(AttribParserList::value_type("param_indexed", (ATTRIBUTE_PARSER)parseParamIndexed));
2265        mProgramRefAttribParsers.insert(AttribParserList::value_type("param_indexed_auto", (ATTRIBUTE_PARSER)parseParamIndexedAuto));
2266        mProgramRefAttribParsers.insert(AttribParserList::value_type("param_named", (ATTRIBUTE_PARSER)parseParamNamed));
2267        mProgramRefAttribParsers.insert(AttribParserList::value_type("param_named_auto", (ATTRIBUTE_PARSER)parseParamNamedAuto));
2268
2269        // Set up program definition attribute parsers
2270        mProgramAttribParsers.insert(AttribParserList::value_type("source", (ATTRIBUTE_PARSER)parseProgramSource));
2271        mProgramAttribParsers.insert(AttribParserList::value_type("syntax", (ATTRIBUTE_PARSER)parseProgramSyntax));
2272        mProgramAttribParsers.insert(AttribParserList::value_type("includes_skeletal_animation", (ATTRIBUTE_PARSER)parseProgramSkeletalAnimation));
2273        mProgramAttribParsers.insert(AttribParserList::value_type("default_params", (ATTRIBUTE_PARSER)parseDefaultParams));
2274               
2275        // Set up program default param attribute parsers
2276        mProgramDefaultParamAttribParsers.insert(AttribParserList::value_type("param_indexed", (ATTRIBUTE_PARSER)parseParamIndexed));
2277        mProgramDefaultParamAttribParsers.insert(AttribParserList::value_type("param_indexed_auto", (ATTRIBUTE_PARSER)parseParamIndexedAuto));
2278        mProgramDefaultParamAttribParsers.insert(AttribParserList::value_type("param_named", (ATTRIBUTE_PARSER)parseParamNamed));
2279        mProgramDefaultParamAttribParsers.insert(AttribParserList::value_type("param_named_auto", (ATTRIBUTE_PARSER)parseParamNamedAuto));
2280
2281        mScriptContext.section = MSS_NONE;
2282        mScriptContext.material.setNull();
2283        mScriptContext.technique = 0;
2284        mScriptContext.pass = 0;
2285        mScriptContext.textureUnit = 0;
2286        mScriptContext.program.setNull();
2287        mScriptContext.lineNo = 0;
2288        mScriptContext.filename = "";
2289                mScriptContext.techLev = -1;
2290                mScriptContext.passLev = -1;
2291                mScriptContext.stateLev = -1;
2292
2293        mBuffer = "";
2294    }
2295
2296    //-----------------------------------------------------------------------
2297    void MaterialSerializer::parseScript(DataStreamPtr& stream, const String& groupName)
2298    {
2299        String line;
2300        bool nextIsOpenBrace = false;
2301
2302        mScriptContext.section = MSS_NONE;
2303        mScriptContext.material.setNull();
2304        mScriptContext.technique = 0;
2305        mScriptContext.pass = 0;
2306        mScriptContext.textureUnit = 0;
2307        mScriptContext.program.setNull();
2308        mScriptContext.lineNo = 0;
2309                mScriptContext.techLev = -1;
2310                mScriptContext.passLev = -1;
2311                mScriptContext.stateLev = -1;
2312        mScriptContext.filename = stream->getName();
2313                mScriptContext.groupName = groupName;
2314        while(!stream->eof())
2315        {
2316            line = stream->getLine();
2317            mScriptContext.lineNo++;
2318           
2319            // DEBUG LINE
2320            // LogManager::getSingleton().logMessage("About to attempt line(#" +
2321            //    StringConverter::toString(mScriptContext.lineNo) + "): " + line);
2322
2323            // Ignore comments & blanks
2324            if (!(line.length() == 0 || line.substr(0,2) == "//"))
2325            {
2326                if (nextIsOpenBrace)
2327                {
2328                    // NB, parser will have changed context already
2329                    if (line != "{")
2330                    {
2331                        logParseError("Expecting '{' but got " +
2332                            line + " instead.", mScriptContext);
2333                    }
2334                    nextIsOpenBrace = false;
2335                }
2336                else
2337                {
2338                    nextIsOpenBrace = parseScriptLine(line);
2339                }
2340
2341            }
2342        }
2343
2344        // Check all braces were closed
2345        if (mScriptContext.section != MSS_NONE)
2346        {
2347            logParseError("Unexpected end of file.", mScriptContext);
2348        }
2349
2350                // Make sure we invalidate our context shared pointer (don't wanna hold on)
2351                mScriptContext.material.setNull();
2352
2353    }
2354    //-----------------------------------------------------------------------
2355    bool MaterialSerializer::parseScriptLine(String& line)
2356    {
2357        switch(mScriptContext.section)
2358        {
2359        case MSS_NONE:
2360            if (line == "}")
2361            {
2362                logParseError("Unexpected terminating brace.", mScriptContext);
2363                return false;
2364            }
2365            else
2366            {
2367                // find & invoke a parser
2368                return invokeParser(line, mRootAttribParsers);
2369            }
2370            break;
2371        case MSS_MATERIAL:
2372            if (line == "}")
2373            {
2374                // End of material
2375                mScriptContext.section = MSS_NONE;
2376                mScriptContext.material.setNull();
2377                                //Reset all levels for next material
2378                                mScriptContext.passLev = -1;
2379                                mScriptContext.stateLev= -1;
2380                                mScriptContext.techLev = -1;
2381            }
2382            else
2383            {
2384                // find & invoke a parser
2385                return invokeParser(line, mMaterialAttribParsers);
2386            }
2387            break;
2388        case MSS_TECHNIQUE:
2389            if (line == "}")
2390            {
2391                // End of technique
2392                mScriptContext.section = MSS_MATERIAL;
2393                mScriptContext.technique = NULL;
2394                                mScriptContext.passLev = -1;    //Reset pass level (yes, the pass level)
2395            }
2396            else
2397            {
2398                // find & invoke a parser
2399                return invokeParser(line, mTechniqueAttribParsers);
2400            }
2401            break;
2402        case MSS_PASS:
2403            if (line == "}")
2404            {
2405                // End of pass
2406                mScriptContext.section = MSS_TECHNIQUE;
2407                mScriptContext.pass = NULL;
2408                                mScriptContext.stateLev = -1;   //Reset state level (yes, the state level)
2409            }
2410            else
2411            {
2412                // find & invoke a parser
2413                return invokeParser(line, mPassAttribParsers);
2414            }
2415            break;
2416        case MSS_TEXTUREUNIT:
2417            if (line == "}")
2418            {
2419                // End of texture unit
2420                mScriptContext.section = MSS_PASS;
2421                mScriptContext.textureUnit = NULL;
2422            }
2423            else
2424            {
2425                // find & invoke a parser
2426                return invokeParser(line, mTextureUnitAttribParsers);
2427            }
2428            break;
2429                case MSS_TEXTURESOURCE:
2430                        if( line == "}" )
2431                        {
2432                                //End texture source section
2433                                //Finish creating texture here
2434                                String sMaterialName = mScriptContext.material->getName();
2435                                if(     ExternalTextureSourceManager::getSingleton().getCurrentPlugIn() != 0)
2436                                        ExternalTextureSourceManager::getSingleton().getCurrentPlugIn()->
2437                                        createDefinedTexture( sMaterialName, mScriptContext.groupName );
2438                                //Revert back to texture unit
2439                                mScriptContext.section = MSS_TEXTUREUNIT;
2440                        }
2441                        else
2442                        {
2443                                // custom texture parameter, use original line
2444                                parseTextureCustomParameter(line, mScriptContext);
2445                        }
2446                        break;
2447        case MSS_PROGRAM_REF:
2448            if (line == "}")
2449            {
2450                // End of program
2451                mScriptContext.section = MSS_PASS;
2452                mScriptContext.program.setNull();
2453            }
2454            else
2455            {
2456                // find & invoke a parser
2457                return invokeParser(line, mProgramRefAttribParsers);
2458            }
2459            break;
2460        case MSS_PROGRAM:
2461                        // Program definitions are slightly different, they are deferred
2462                        // until all the information required is known
2463            if (line == "}")
2464            {
2465                // End of program
2466                                finishProgramDefinition();
2467                mScriptContext.section = MSS_NONE;
2468                delete mScriptContext.programDef;
2469                mScriptContext.defaultParamLines.clear();
2470                mScriptContext.programDef = NULL;
2471            }
2472            else
2473            {
2474                // find & invoke a parser
2475                                // do this manually because we want to call a custom
2476                                // routine when the parser is not found
2477                                // First, split line on first divisor only
2478                                StringVector splitCmd = StringUtil::split(line, " \t", 1);
2479                                // Find attribute parser
2480                                AttribParserList::iterator iparser = mProgramAttribParsers.find(splitCmd[0]);
2481                                if (iparser == mProgramAttribParsers.end())
2482                                {
2483                                        // custom parameter, use original line
2484                                        parseProgramCustomParameter(line, mScriptContext);
2485                                }
2486                                else
2487                                {
2488                    String cmd = splitCmd.size() >= 2? splitCmd[1]:StringUtil::BLANK;
2489                                        // Use parser with remainder
2490                    return iparser->second(cmd, mScriptContext );
2491                                }
2492                               
2493            }
2494            break;
2495        case MSS_DEFAULT_PARAMETERS:
2496            if (line == "}")
2497            {
2498                // End of default parameters
2499                mScriptContext.section = MSS_PROGRAM;
2500            }
2501            else
2502            {
2503                // Save default parameter lines up until we finalise the program
2504                mScriptContext.defaultParamLines.push_back(line);
2505            }
2506
2507
2508            break;
2509        };
2510
2511        return false;
2512    }
2513    //-----------------------------------------------------------------------
2514        void MaterialSerializer::finishProgramDefinition(void)
2515        {
2516                // Now it is time to create the program and propagate the parameters
2517                MaterialScriptProgramDefinition* def = mScriptContext.programDef;
2518        GpuProgramPtr gp;
2519                if (def->language == "asm")
2520                {
2521                        // Native assembler
2522                        // Validate
2523                        if (def->source.empty())
2524                        {
2525                                logParseError("Invalid program definition for " + def->name +
2526                                        ", you must specify a source file.", mScriptContext);
2527                        }
2528                        if (def->syntax.empty())
2529                        {
2530                                logParseError("Invalid program definition for " + def->name +
2531                                        ", you must specify a syntax code.", mScriptContext);
2532                        }
2533                        // Create
2534                        gp = GpuProgramManager::getSingleton().
2535                                createProgram(def->name, mScriptContext.groupName, def->source,
2536                    def->progType, def->syntax);
2537
2538                }
2539                else
2540                {
2541                        // High-level program
2542                        // Validate
2543                        if (def->source.empty())
2544                        {
2545                                logParseError("Invalid program definition for " + def->name +
2546                                        ", you must specify a source file.", mScriptContext);
2547                        }
2548                        // Create
2549            try
2550            {
2551                            HighLevelGpuProgramPtr hgp = HighLevelGpuProgramManager::getSingleton().
2552                                    createProgram(def->name, mScriptContext.groupName,
2553                        def->language, def->progType);
2554                // Assign to generalised version
2555                gp = hgp;
2556                // Set source file
2557                hgp->setSourceFile(def->source);
2558
2559                            // Set custom parameters
2560                            std::map<String, String>::const_iterator i, iend;
2561                            iend = def->customParameters.end();
2562                            for (i = def->customParameters.begin(); i != iend; ++i)
2563                            {
2564                                    if (!hgp->setParameter(i->first, i->second))
2565                                    {
2566                                            logParseError("Error in program " + def->name +
2567                                                    " parameter " + i->first + " is not valid.", mScriptContext);
2568                                    }
2569                            }
2570            }
2571            catch (Exception& e)
2572            {
2573                logParseError("Could not create GPU program '"
2574                    + def->name + "', error reported was: " + e.getFullDescription(), mScriptContext);
2575                                mScriptContext.program.setNull();
2576                mScriptContext.programParams.setNull();
2577                                return;
2578            }
2579        }
2580        // Set skeletal animation option
2581        gp->setSkeletalAnimationIncluded(def->supportsSkeletalAnimation);
2582                // set origin
2583                gp->_notifyOrigin(mScriptContext.filename);
2584
2585        // Set up to receive default parameters
2586        if (gp->isSupported()
2587            && !mScriptContext.defaultParamLines.empty())
2588        {
2589            mScriptContext.programParams = gp->getDefaultParameters();
2590            mScriptContext.program = gp;
2591            StringVector::iterator i, iend;
2592            iend = mScriptContext.defaultParamLines.end();
2593            for (i = mScriptContext.defaultParamLines.begin();
2594                i != iend; ++i)
2595            {
2596                // find & invoke a parser
2597                // do this manually because we want to call a custom
2598                // routine when the parser is not found
2599                // First, split line on first divisor only
2600                StringVector splitCmd = StringUtil::split(*i, " \t", 1);
2601                // Find attribute parser
2602                AttribParserList::iterator iparser
2603                    = mProgramDefaultParamAttribParsers.find(splitCmd[0]);
2604                if (iparser != mProgramDefaultParamAttribParsers.end())
2605                {
2606                    String cmd = splitCmd.size() >= 2? splitCmd[1]:StringUtil::BLANK;
2607                    // Use parser with remainder
2608                    iparser->second(cmd, mScriptContext );
2609                }
2610
2611            }
2612            // Reset
2613            mScriptContext.program.setNull();
2614            mScriptContext.programParams.setNull();
2615        }
2616
2617        }
2618    //-----------------------------------------------------------------------
2619        bool MaterialSerializer::invokeParser(String& line, AttribParserList& parsers)
2620    {
2621        // First, split line on first divisor only
2622        StringVector splitCmd(StringUtil::split(line, " \t", 1));
2623
2624        // Find attribute parser
2625        AttribParserList::iterator iparser = parsers.find(splitCmd[0]);
2626        if (iparser == parsers.end())
2627        {
2628            // BAD command. BAD!
2629            logParseError("Unrecognised command: " + splitCmd[0], mScriptContext);
2630            return false;
2631        }
2632        else
2633        {
2634            String cmd;
2635            if(splitCmd.size() >= 2)
2636                cmd = splitCmd[1];
2637            // Use parser, make sure we have 2 params before using splitCmd[1]
2638            return iparser->second( cmd, mScriptContext );
2639        }
2640    }
2641    //-----------------------------------------------------------------------
2642    void MaterialSerializer::exportMaterial(const MaterialPtr& pMat, const String &fileName, bool exportDefaults)
2643    {
2644        clearQueue();
2645        mDefaults = exportDefaults;
2646        writeMaterial(pMat);
2647        exportQueued(fileName);
2648    }
2649    //-----------------------------------------------------------------------
2650    void MaterialSerializer::exportQueued(const String &fileName)
2651    {
2652        if (mBuffer == "")
2653            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Queue is empty !", "MaterialSerializer::exportQueued");
2654
2655        LogManager::getSingleton().logMessage("MaterialSerializer : writing material(s) to material script : " + fileName, LML_CRITICAL);
2656        FILE *fp;
2657        fp = fopen(fileName.c_str(), "w");
2658        if (!fp)
2659            OGRE_EXCEPT(Exception::ERR_CANNOT_WRITE_TO_FILE, "Cannot create material file.",
2660            "MaterialSerializer::export");
2661
2662        fputs(mBuffer.c_str(), fp);
2663        fclose(fp);
2664        LogManager::getSingleton().logMessage("MaterialSerializer : done.", LML_CRITICAL);
2665        clearQueue();
2666    }
2667    //-----------------------------------------------------------------------
2668    void MaterialSerializer::queueForExport(const MaterialPtr& pMat, bool clearQueued, bool exportDefaults)
2669    {
2670        if (clearQueued)
2671            clearQueue();
2672
2673        mDefaults = exportDefaults;
2674        writeMaterial(pMat);
2675    }
2676    //-----------------------------------------------------------------------
2677    void MaterialSerializer::clearQueue()
2678    {
2679        mBuffer = "";
2680    }
2681    //-----------------------------------------------------------------------
2682    const String &MaterialSerializer::getQueuedAsString() const
2683    {
2684        return mBuffer;
2685    }
2686    //-----------------------------------------------------------------------
2687    void MaterialSerializer::writeMaterial(const MaterialPtr& pMat)
2688    {
2689        LogManager::getSingleton().logMessage("MaterialSerializer : writing material " + pMat->getName() + " to queue.", LML_CRITICAL);
2690        // Material name
2691        writeAttribute(0, "material " + pMat->getName());
2692        beginSection(0);
2693        {
2694            // Write LOD information
2695            Material::LodDistanceIterator distIt = pMat->getLodDistanceIterator();
2696            // Skip zero value
2697            if (distIt.hasMoreElements())
2698                distIt.getNext();
2699            String attributeVal;
2700            while (distIt.hasMoreElements())
2701            {
2702                Real sqdist = distIt.getNext();
2703                attributeVal.append(StringConverter::toString(Math::Sqrt(sqdist)));
2704                if (distIt.hasMoreElements())
2705                    attributeVal.append(" ");
2706            }
2707            if (!attributeVal.empty())
2708            {
2709                writeAttribute(1, "lod_distances");
2710                writeValue(attributeVal);
2711            }
2712
2713
2714            // Shadow receive
2715            if (mDefaults ||
2716                pMat->getReceiveShadows() != true)
2717            {
2718                writeAttribute(1, "receive_shadows");
2719                writeValue(pMat->getReceiveShadows() ? "on" : "off");
2720            }
2721
2722                        // When rendering shadows, treat transparent things as opaque?
2723                        if (mDefaults ||
2724                                pMat->getTransparencyCastsShadows() == true)
2725                        {
2726                                writeAttribute(1, "transparency_casts_shadows");
2727                                writeValue(pMat->getTransparencyCastsShadows() ? "on" : "off");
2728                        }
2729
2730            // Iterate over techniques
2731            Material::TechniqueIterator it = pMat->getTechniqueIterator();
2732            while (it.hasMoreElements())
2733            {
2734                writeTechnique(it.getNext());
2735            }
2736        }
2737        endSection(0);
2738    }
2739    //-----------------------------------------------------------------------
2740    void MaterialSerializer::writeTechnique(const Technique* pTech)
2741    {
2742        // Technique header
2743        writeAttribute(1, "technique");
2744        beginSection(1);
2745        {
2746            // Iterate over passes
2747            Technique::PassIterator it = const_cast<Technique*>(pTech)->getPassIterator();
2748            while (it.hasMoreElements())
2749            {
2750                writePass(it.getNext());
2751            }
2752        }
2753        endSection(1);
2754
2755    }
2756    //-----------------------------------------------------------------------
2757    void MaterialSerializer::writePass(const Pass* pPass)
2758    {
2759        writeAttribute(2, "pass");
2760        beginSection(2);
2761        {
2762            //lighting
2763            if (mDefaults ||
2764                pPass->getLightingEnabled() != true)
2765            {
2766                writeAttribute(3, "lighting");
2767                writeValue(pPass->getLightingEnabled() ? "on" : "off");
2768            }
2769                        // max_lights
2770            if (mDefaults ||
2771                pPass->getMaxSimultaneousLights() != OGRE_MAX_SIMULTANEOUS_LIGHTS)
2772            {
2773                writeAttribute(3, "max_lights");
2774                writeValue(StringConverter::toString(pPass->getMaxSimultaneousLights()));
2775            }
2776                        // iteration
2777            if (mDefaults ||
2778                pPass->getRunOncePerLight())
2779            {
2780                writeAttribute(3, "iteration");
2781                writeValue(pPass->getRunOncePerLight() ? "once_per_light" : "once");
2782                if (pPass->getRunOncePerLight() && pPass->getRunOnlyForOneLightType())
2783                {
2784                    switch (pPass->getOnlyLightType())
2785                    {
2786                    case Light::LT_DIRECTIONAL:
2787                        writeValue("directional");
2788                        break;
2789                    case Light::LT_POINT:
2790                        writeValue("point");
2791                        break;
2792                    case Light::LT_SPOTLIGHT:
2793                        writeValue("spot");
2794                        break;
2795                    };
2796                }
2797            }
2798                       
2799
2800            if (pPass->getLightingEnabled())
2801            {
2802                // Ambient
2803                if (mDefaults ||
2804                    pPass->getAmbient().r != 1 ||
2805                    pPass->getAmbient().g != 1 ||
2806                    pPass->getAmbient().b != 1 ||
2807                    pPass->getAmbient().a != 1)
2808                {
2809                    writeAttribute(3, "ambient");
2810                    writeColourValue(pPass->getAmbient(), true);
2811                }
2812
2813                // Diffuse
2814                if (mDefaults ||
2815                    pPass->getDiffuse().r != 1 ||
2816                    pPass->getDiffuse().g != 1 ||
2817                    pPass->getDiffuse().b != 1 ||
2818                    pPass->getDiffuse().a != 1)
2819                {
2820                    writeAttribute(3, "diffuse");
2821                    writeColourValue(pPass->getDiffuse(), true);
2822                }
2823
2824                // Specular
2825                if (mDefaults ||
2826                    pPass->getSpecular().r != 0 ||
2827                    pPass->getSpecular().g != 0 ||
2828                    pPass->getSpecular().b != 0 ||
2829                    pPass->getSpecular().a != 1 ||
2830                    pPass->getShininess() != 0)
2831                {
2832                    writeAttribute(3, "specular");
2833                    writeColourValue(pPass->getSpecular(), true);
2834                    writeValue(StringConverter::toString(pPass->getShininess()));
2835                }
2836
2837                // Emissive
2838                if (mDefaults ||
2839                    pPass->getSelfIllumination().r != 0 ||
2840                    pPass->getSelfIllumination().g != 0 ||
2841                    pPass->getSelfIllumination().b != 0 ||
2842                    pPass->getSelfIllumination().a != 1)
2843                {
2844                    writeAttribute(3, "emissive");
2845                    writeColourValue(pPass->getSelfIllumination(), true);
2846                }
2847            }
2848
2849            // scene blend factor
2850            if (mDefaults ||
2851                pPass->getSourceBlendFactor() != SBF_ONE ||
2852                pPass->getDestBlendFactor() != SBF_ZERO)
2853            {
2854                writeAttribute(3, "scene_blend");
2855                writeSceneBlendFactor(pPass->getSourceBlendFactor(), pPass->getDestBlendFactor());
2856            }
2857
2858
2859            //depth check
2860            if (mDefaults ||
2861                pPass->getDepthCheckEnabled() != true)
2862            {
2863                writeAttribute(3, "depth_check");
2864                writeValue(pPass->getDepthCheckEnabled() ? "on" : "off");
2865            }
2866                        // alpha_rejection
2867                        if (mDefaults ||
2868                                pPass->getAlphaRejectFunction() != CMPF_ALWAYS_PASS ||
2869                                pPass->getAlphaRejectValue() != 0)
2870                        {
2871                                writeAttribute(3, "alpha_rejection");
2872                                writeCompareFunction(pPass->getAlphaRejectFunction());
2873                                writeValue(StringConverter::toString(pPass->getAlphaRejectValue()));
2874                        }
2875
2876
2877            //depth write
2878            if (mDefaults ||
2879                pPass->getDepthWriteEnabled() != true)
2880            {
2881                writeAttribute(3, "depth_write");
2882                writeValue(pPass->getDepthWriteEnabled() ? "on" : "off");
2883            }
2884
2885            //depth function
2886            if (mDefaults ||
2887                pPass->getDepthFunction() != CMPF_LESS_EQUAL)
2888            {
2889                writeAttribute(3, "depth_func");
2890                writeCompareFunction(pPass->getDepthFunction());
2891            }
2892
2893            //depth bias
2894            if (mDefaults ||
2895                pPass->getDepthBias() != 0)
2896            {
2897                writeAttribute(3, "depth_bias");
2898                writeValue(StringConverter::toString(pPass->getDepthBias()));
2899            }
2900
2901            // hardware culling mode
2902            if (mDefaults ||
2903                pPass->getCullingMode() != CULL_CLOCKWISE)
2904            {
2905                CullingMode hcm = pPass->getCullingMode();
2906                writeAttribute(3, "cull_hardware");
2907                switch (hcm)
2908                {
2909                case CULL_NONE :
2910                    writeValue("none");
2911                    break;
2912                case CULL_CLOCKWISE :
2913                    writeValue("clockwise");
2914                    break;
2915                case CULL_ANTICLOCKWISE :
2916                    writeValue("anticlockwise");
2917                    break;
2918                }
2919            }
2920
2921            // software culling mode
2922            if (mDefaults ||
2923                pPass->getManualCullingMode() != MANUAL_CULL_BACK)
2924            {
2925                ManualCullingMode scm = pPass->getManualCullingMode();
2926                writeAttribute(3, "cull_software");
2927                switch (scm)
2928                {
2929                case MANUAL_CULL_NONE :
2930                    writeValue("none");
2931                    break;
2932                case MANUAL_CULL_BACK :
2933                    writeValue("back");
2934                    break;
2935                case MANUAL_CULL_FRONT :
2936                    writeValue("front");
2937                    break;
2938                }
2939            }
2940
2941            //shading
2942            if (mDefaults ||
2943                pPass->getShadingMode() != SO_GOURAUD)
2944            {
2945                writeAttribute(3, "shading");
2946                switch (pPass->getShadingMode())
2947                {
2948                case SO_FLAT:
2949                    writeValue("flat");
2950                    break;
2951                case SO_GOURAUD:
2952                    writeValue("gouraud");
2953                    break;
2954                case SO_PHONG:
2955                    writeValue("phong");
2956                    break;
2957                }
2958            }
2959
2960
2961            //fog override
2962            if (mDefaults ||
2963                pPass->getFogOverride() != false)
2964            {
2965                writeAttribute(3, "fog_override");
2966                writeValue(pPass->getFogOverride() ? "true" : "false");
2967                if (pPass->getFogOverride())
2968                {
2969                    switch (pPass->getFogMode())
2970                    {
2971                    case FOG_NONE:
2972                        writeValue("none");
2973                        break;
2974                    case FOG_LINEAR:
2975                        writeValue("linear");
2976                        break;
2977                    case FOG_EXP2:
2978                        writeValue("exp2");
2979                        break;
2980                    case FOG_EXP:
2981                        writeValue("exp");
2982                        break;
2983                    }
2984
2985                    if (pPass->getFogMode() != FOG_NONE)
2986                    {
2987                        writeColourValue(pPass->getFogColour());
2988                        writeValue(StringConverter::toString(pPass->getFogDensity()));
2989                        writeValue(StringConverter::toString(pPass->getFogStart()));
2990                        writeValue(StringConverter::toString(pPass->getFogEnd()));
2991                    }
2992                }
2993            }
2994
2995            // Nested texture layers
2996            Pass::TextureUnitStateIterator it = const_cast<Pass*>(pPass)->getTextureUnitStateIterator();
2997            while(it.hasMoreElements())
2998            {
2999                writeTextureUnit(it.getNext());
3000            }
3001        }
3002        endSection(2);
3003        LogManager::getSingleton().logMessage("MaterialSerializer : done.", LML_CRITICAL);
3004    }
3005    //-----------------------------------------------------------------------
3006    String MaterialSerializer::convertFiltering(FilterOptions fo)
3007    {
3008        switch (fo)
3009        {
3010        case FO_NONE:
3011            return "none";
3012        case FO_POINT:
3013            return "point";
3014        case FO_LINEAR:
3015            return "linear";
3016        case FO_ANISOTROPIC:
3017            return "anisotropic";
3018        }
3019
3020        return "point";
3021    }
3022    //-----------------------------------------------------------------------
3023    void MaterialSerializer::writeTextureUnit(const TextureUnitState *pTex)
3024    {
3025        LogManager::getSingleton().logMessage("MaterialSerializer : parsing texture layer.", LML_CRITICAL);
3026        mBuffer += "\n";
3027        writeAttribute(3, "texture_unit");
3028        beginSection(3);
3029        {
3030            //texture name
3031            if (pTex->getNumFrames() == 1 && pTex->getTextureName() != "" && !pTex->isCubic())
3032            {
3033                writeAttribute(4, "texture");
3034                writeValue(pTex->getTextureName());
3035                switch (pTex->getTextureType())
3036                {
3037                case TEX_TYPE_1D:
3038                    writeValue("1d");
3039                    break;
3040                case TEX_TYPE_2D:
3041                    // nothing, this is the default
3042                    break;
3043                case TEX_TYPE_3D:
3044                    writeValue("3d");
3045                    break;
3046                case TEX_TYPE_CUBE_MAP:
3047                    // nothing, deal with this as cubic_texture since it copes with all variants
3048                    break;
3049                default:
3050                    break;
3051                };
3052            }
3053
3054            //anim. texture
3055            if (pTex->getNumFrames() > 1 && !pTex->isCubic())
3056            {
3057                writeAttribute(4, "anim_texture");
3058                for (unsigned int n = 0; n < pTex->getNumFrames(); n++)
3059                    writeValue(pTex->getFrameTextureName(n));
3060                writeValue(StringConverter::toString(pTex->getAnimationDuration()));
3061            }
3062
3063            //cubic texture
3064            if (pTex->isCubic())
3065            {
3066                writeAttribute(4, "cubic_texture");
3067                for (unsigned int n = 0; n < pTex->getNumFrames(); n++)
3068                    writeValue(pTex->getFrameTextureName(n));
3069
3070                //combinedUVW/separateUW
3071                if (pTex->getTextureType() == TEX_TYPE_CUBE_MAP)
3072                    writeValue("combinedUVW");
3073                else
3074                    writeValue("separateUV");
3075            }
3076
3077            //anisotropy level
3078            if (mDefaults ||
3079                pTex->getTextureAnisotropy() != 1)
3080            {
3081                writeAttribute(4, "max_anisotropy");
3082                writeValue(StringConverter::toString(pTex->getTextureAnisotropy()));
3083            }
3084
3085            //texture coordinate set
3086            if (mDefaults ||
3087                pTex->getTextureCoordSet() != 0)
3088            {
3089                writeAttribute(4, "tex_coord_set");
3090                writeValue(StringConverter::toString(pTex->getTextureCoordSet()));
3091            }
3092
3093            //addressing mode
3094            if (mDefaults ||
3095                pTex->getTextureAddressingMode() != Ogre::TextureUnitState::TAM_WRAP)
3096            {
3097                writeAttribute(4, "tex_address_mode");
3098                switch (pTex->getTextureAddressingMode())
3099                {
3100                case Ogre::TextureUnitState::TAM_CLAMP:
3101                    writeValue("clamp");
3102                    break;
3103                case Ogre::TextureUnitState::TAM_MIRROR:
3104                    writeValue("mirror");
3105                    break;
3106                case Ogre::TextureUnitState::TAM_WRAP:
3107                    writeValue("wrap");
3108                    break;
3109                }
3110            }
3111
3112            //filtering
3113            if (mDefaults ||
3114                pTex->getTextureFiltering(FT_MIN) != FO_LINEAR ||
3115                pTex->getTextureFiltering(FT_MAG) != FO_LINEAR ||
3116                pTex->getTextureFiltering(FT_MIP) != FO_POINT)
3117            {
3118                writeAttribute(4, "filtering");
3119                writeValue(
3120                    convertFiltering(pTex->getTextureFiltering(FT_MIN))
3121                    + " "
3122                    + convertFiltering(pTex->getTextureFiltering(FT_MAG))
3123                    + " "
3124                    + convertFiltering(pTex->getTextureFiltering(FT_MIP)));
3125            }
3126
3127            // colour_op_ex
3128            if (mDefaults ||
3129                pTex->getColourBlendMode().operation != LBX_MODULATE ||
3130                pTex->getColourBlendMode().source1 != LBS_TEXTURE ||
3131                pTex->getColourBlendMode().source2 != LBS_CURRENT)
3132            {
3133                writeAttribute(4, "colour_op_ex");
3134                writeLayerBlendOperationEx(pTex->getColourBlendMode().operation);
3135                writeLayerBlendSource(pTex->getColourBlendMode().source1);
3136                writeLayerBlendSource(pTex->getColourBlendMode().source2);
3137                if (pTex->getColourBlendMode().operation == LBX_BLEND_MANUAL)
3138                    writeValue(StringConverter::toString(pTex->getColourBlendMode().factor));
3139                if (pTex->getColourBlendMode().source1 == LBS_MANUAL)
3140                    writeColourValue(pTex->getColourBlendMode().colourArg1, false);
3141                if (pTex->getColourBlendMode().source2 == LBS_MANUAL)
3142                    writeColourValue(pTex->getColourBlendMode().colourArg2, false);
3143
3144                //colour_op_multipass_fallback
3145                writeAttribute(4, "colour_op_multipass_fallback");
3146                writeSceneBlendFactor(pTex->getColourBlendFallbackSrc());
3147                writeSceneBlendFactor(pTex->getColourBlendFallbackDest());
3148            }
3149
3150            // alpha_op_ex
3151            if (mDefaults ||
3152                pTex->getAlphaBlendMode().operation != LBX_MODULATE ||
3153                pTex->getAlphaBlendMode().source1 != LBS_TEXTURE ||
3154                pTex->getAlphaBlendMode().source2 != LBS_CURRENT)
3155            {
3156                writeAttribute(4, "alpha_op_ex");
3157                writeLayerBlendOperationEx(pTex->getAlphaBlendMode().operation);
3158                writeLayerBlendSource(pTex->getAlphaBlendMode().source1);
3159                writeLayerBlendSource(pTex->getAlphaBlendMode().source2);
3160                if (pTex->getAlphaBlendMode().operation == LBX_BLEND_MANUAL)
3161                    writeValue(StringConverter::toString(pTex->getAlphaBlendMode().factor));
3162                else if (pTex->getAlphaBlendMode().source1 == LBS_MANUAL)
3163                    writeValue(StringConverter::toString(pTex->getAlphaBlendMode().alphaArg1));
3164                else if (pTex->getAlphaBlendMode().source2 == LBS_MANUAL)
3165                    writeValue(StringConverter::toString(pTex->getAlphaBlendMode().alphaArg2));
3166            }
3167
3168                        bool individualTransformElems = false;
3169            // rotate
3170            if (mDefaults ||
3171                pTex->getTextureRotate() != Radian(0))
3172            {
3173                writeAttribute(4, "rotate");
3174                writeValue(StringConverter::toString(pTex->getTextureRotate().valueDegrees()));
3175                                individualTransformElems = true;
3176            }
3177
3178            // scroll
3179            if (mDefaults ||
3180                pTex->getTextureUScroll() != 0 ||
3181                pTex->getTextureVScroll() != 0 )
3182            {
3183                writeAttribute(4, "scroll");
3184                writeValue(StringConverter::toString(pTex->getTextureUScroll()));
3185                writeValue(StringConverter::toString(pTex->getTextureVScroll()));
3186                                individualTransformElems = true;
3187            }
3188            // scale
3189            if (mDefaults ||
3190                pTex->getTextureUScale() != 1.0 ||
3191                pTex->getTextureVScale() != 1.0 )
3192            {
3193                writeAttribute(4, "scale");
3194                writeValue(StringConverter::toString(pTex->getTextureUScale()));
3195                writeValue(StringConverter::toString(pTex->getTextureVScale()));
3196                                individualTransformElems = true;
3197            }
3198
3199                        // free transform
3200                        if (!individualTransformElems &&
3201                                (mDefaults ||
3202                                pTex->getTextureTransform() != Matrix4::IDENTITY))
3203                        {
3204                                writeAttribute(4, "transform");
3205                                const Matrix4& xform = pTex->getTextureTransform();
3206                                for (int row = 0; row < 4; ++row)
3207                                {
3208                                        for (int col = 0; col < 4; ++col)
3209                                        {
3210                                                writeValue(StringConverter::toString(xform[row][col]));
3211                                        }
3212                                }
3213                        }
3214
3215            EffectMap m_ef = pTex->getEffects();
3216            if (!m_ef.empty())
3217            {
3218                EffectMap::const_iterator it;
3219                for (it = m_ef.begin(); it != m_ef.end(); ++it)
3220                {
3221                    const TextureUnitState::TextureEffect& ef = it->second;
3222                    switch (ef.type)
3223                    {
3224                    case TextureUnitState::ET_ENVIRONMENT_MAP :
3225                        writeEnvironmentMapEffect(ef, pTex);
3226                        break;
3227                    case TextureUnitState::ET_ROTATE :
3228                        writeRotationEffect(ef, pTex);
3229                        break;
3230                    case TextureUnitState::ET_SCROLL :
3231                        writeScrollEffect(ef, pTex);
3232                        break;
3233                    case TextureUnitState::ET_TRANSFORM :
3234                        writeTransformEffect(ef, pTex);
3235                        break;
3236                    default:
3237                        break;
3238                    }
3239                }
3240            }
3241        }
3242        endSection(3);
3243
3244    }
3245    //-----------------------------------------------------------------------
3246    void MaterialSerializer::writeEnvironmentMapEffect(const TextureUnitState::TextureEffect& effect, const TextureUnitState *pTex)
3247    {
3248        writeAttribute(4, "env_map");
3249        switch (effect.subtype)
3250        {
3251        case TextureUnitState::ENV_PLANAR:
3252            writeValue("planar");
3253            break;
3254        case TextureUnitState::ENV_CURVED:
3255            writeValue("spherical");
3256            break;
3257        case TextureUnitState::ENV_NORMAL:
3258            writeValue("cubic_normal");
3259            break;
3260        case TextureUnitState::ENV_REFLECTION:
3261            writeValue("cubic_reflection");
3262            break;
3263        }
3264    }
3265    //-----------------------------------------------------------------------
3266    void MaterialSerializer::writeRotationEffect(const TextureUnitState::TextureEffect& effect, const TextureUnitState *pTex)
3267    {
3268        if (effect.arg1)
3269        {
3270            writeAttribute(4, "rotate_anim");
3271            writeValue(StringConverter::toString(effect.arg1));
3272        }
3273    }
3274    //-----------------------------------------------------------------------
3275    void MaterialSerializer::writeTransformEffect(const TextureUnitState::TextureEffect& effect, const TextureUnitState *pTex)
3276    {
3277        writeAttribute(4, "wave_xform");
3278
3279        switch (effect.subtype)
3280        {
3281        case TextureUnitState::TT_ROTATE:
3282            writeValue("rotate");
3283            break;
3284        case TextureUnitState::TT_SCALE_U:
3285            writeValue("scale_x");
3286            break;
3287        case TextureUnitState::TT_SCALE_V:
3288            writeValue("scale_y");
3289            break;
3290        case TextureUnitState::TT_TRANSLATE_U:
3291            writeValue("scroll_x");
3292            break;
3293        case TextureUnitState::TT_TRANSLATE_V:
3294            writeValue("scroll_y");
3295            break;
3296        }
3297
3298        switch (effect.waveType)
3299        {
3300        case WFT_INVERSE_SAWTOOTH:
3301            writeValue("inverse_sawtooth");
3302            break;
3303        case WFT_SAWTOOTH:
3304            writeValue("sawtooth");
3305            break;
3306        case WFT_SINE:
3307            writeValue("sine");
3308            break;
3309        case WFT_SQUARE:
3310            writeValue("square");
3311            break;
3312        case WFT_TRIANGLE:
3313            writeValue("triangle");
3314            break;
3315        }
3316
3317        writeValue(StringConverter::toString(effect.base));
3318        writeValue(StringConverter::toString(effect.frequency));
3319        writeValue(StringConverter::toString(effect.phase));
3320        writeValue(StringConverter::toString(effect.amplitude));
3321    }
3322    //-----------------------------------------------------------------------
3323    void MaterialSerializer::writeScrollEffect(const TextureUnitState::TextureEffect& effect, const TextureUnitState *pTex)
3324    {
3325        if (effect.arg1 || effect.arg2)
3326        {
3327            writeAttribute(4, "scroll_anim");
3328            writeValue(StringConverter::toString(effect.arg1));
3329            writeValue(StringConverter::toString(effect.arg2));
3330        }
3331    }
3332    //-----------------------------------------------------------------------
3333    void MaterialSerializer::writeSceneBlendFactor(const SceneBlendFactor sbf)
3334    {
3335        switch (sbf)
3336        {
3337        case SBF_DEST_ALPHA:
3338            writeValue("dest_alpha");
3339            break;
3340        case SBF_DEST_COLOUR:
3341            writeValue("dest_colour");
3342            break;
3343        case SBF_ONE:
3344            writeValue("one");
3345            break;
3346        case SBF_ONE_MINUS_DEST_ALPHA:
3347            writeValue("one_minus_dest_alpha");
3348            break;
3349        case SBF_ONE_MINUS_DEST_COLOUR:
3350            writeValue("one_minus_dest_colour");
3351            break;
3352        case SBF_ONE_MINUS_SOURCE_ALPHA:
3353            writeValue("one_minus_src_alpha");
3354            break;
3355        case SBF_ONE_MINUS_SOURCE_COLOUR:
3356            writeValue("one_minus_src_colour");
3357            break;
3358        case SBF_SOURCE_ALPHA:
3359            writeValue("src_alpha");
3360            break;
3361        case SBF_SOURCE_COLOUR:
3362            writeValue("src_colour");
3363            break;
3364        case SBF_ZERO:
3365            writeValue("zero");
3366            break;
3367        }
3368    }
3369    //-----------------------------------------------------------------------
3370    void MaterialSerializer::writeSceneBlendFactor(const SceneBlendFactor sbf_src, const SceneBlendFactor sbf_dst)
3371    {
3372        if (sbf_src == SBF_ONE && sbf_dst == SBF_ONE )
3373            writeValue("add");
3374        else if (sbf_src == SBF_DEST_COLOUR && sbf_dst == SBF_ZERO)
3375            writeValue("modulate");
3376        else if (sbf_src == SBF_SOURCE_COLOUR && sbf_dst == SBF_ONE_MINUS_SOURCE_COLOUR)
3377            writeValue("colour_blend");
3378        else if (sbf_src == SBF_SOURCE_ALPHA && sbf_dst == SBF_ONE_MINUS_SOURCE_ALPHA)
3379            writeValue("alpha_blend");
3380        else
3381        {
3382            writeSceneBlendFactor(sbf_src);
3383            writeSceneBlendFactor(sbf_dst);
3384        }
3385    }
3386    //-----------------------------------------------------------------------
3387    void MaterialSerializer::writeCompareFunction(const CompareFunction cf)
3388    {
3389        switch (cf)
3390        {
3391        case CMPF_ALWAYS_FAIL:
3392            writeValue("always_fail");
3393            break;
3394        case CMPF_ALWAYS_PASS:
3395            writeValue("always_pass");
3396            break;
3397        case CMPF_EQUAL:
3398            writeValue("equal");
3399            break;
3400        case CMPF_GREATER:
3401            writeValue("greater");
3402            break;
3403        case CMPF_GREATER_EQUAL:
3404            writeValue("greater_equal");
3405            break;
3406        case CMPF_LESS:
3407            writeValue("less");
3408            break;
3409        case CMPF_LESS_EQUAL:
3410            writeValue("less_equal");
3411            break;
3412        case CMPF_NOT_EQUAL:
3413            writeValue("not_equal");
3414            break;
3415        }
3416    }
3417    //-----------------------------------------------------------------------
3418    void MaterialSerializer::writeColourValue(const ColourValue &colour, bool writeAlpha)
3419    {
3420        writeValue(StringConverter::toString(colour.r));
3421        writeValue(StringConverter::toString(colour.g));
3422        writeValue(StringConverter::toString(colour.b));
3423        if (writeAlpha)
3424            writeValue(StringConverter::toString(colour.a));
3425    }
3426    //-----------------------------------------------------------------------
3427    void MaterialSerializer::writeLayerBlendOperationEx(const LayerBlendOperationEx op)
3428    {
3429        switch (op)
3430        {
3431        case LBX_ADD:
3432            writeValue("add");
3433            break;
3434        case LBX_ADD_SIGNED:
3435            writeValue("add_signed");
3436            break;
3437        case LBX_ADD_SMOOTH:
3438            writeValue("add_smooth");
3439            break;
3440        case LBX_BLEND_CURRENT_ALPHA:
3441            writeValue("blend_current_alpha");
3442            break;
3443        case LBX_BLEND_DIFFUSE_ALPHA:
3444            writeValue("blend_diffuse_alpha");
3445            break;
3446        case LBX_BLEND_MANUAL:
3447            writeValue("blend_manual");
3448            break;
3449        case LBX_BLEND_TEXTURE_ALPHA:
3450            writeValue("blend_texture_alpha");
3451            break;
3452        case LBX_MODULATE:
3453            writeValue("modulate");
3454            break;
3455        case LBX_MODULATE_X2:
3456            writeValue("modulate_x2");
3457            break;
3458        case LBX_MODULATE_X4:
3459            writeValue("modulate_x4");
3460            break;
3461        case LBX_SOURCE1:
3462            writeValue("source1");
3463            break;
3464        case LBX_SOURCE2:
3465            writeValue("source2");
3466            break;
3467        case LBX_SUBTRACT:
3468            writeValue("subtract");
3469            break;
3470        case LBX_DOTPRODUCT:
3471            writeValue("dotproduct");
3472            break;
3473        }
3474    }
3475    //-----------------------------------------------------------------------
3476    void MaterialSerializer::writeLayerBlendSource(const LayerBlendSource lbs)
3477    {
3478        switch (lbs)
3479        {
3480        case LBS_CURRENT:
3481            writeValue("src_current");
3482            break;
3483        case LBS_DIFFUSE:
3484            writeValue("src_diffuse");
3485            break;
3486        case LBS_MANUAL:
3487            writeValue("src_manual");
3488            break;
3489        case LBS_SPECULAR:
3490            writeValue("src_specular");
3491            break;
3492        case LBS_TEXTURE:
3493            writeValue("src_texture");
3494            break;
3495        }
3496    }
3497}
Note: See TracBrowser for help on using the repository browser.