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

Revision 692, 47.4 KB checked in by mattausch, 19 years ago (diff)

adding ogre 1.2 and dependencies

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.stevestreeting.com/ogre/
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 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 General Public License for more details.
18
19You should have received a copy of the GNU 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/gpl.html.
23-----------------------------------------------------------------------------
24*/
25#include "OgreStableHeaders.h"
26#include "OgreMaterialScriptCompiler.h"
27#include "OgreStringConverter.h"
28#include "OgreLogManager.h"
29#include "OgreException.h"
30#include "OgreMaterial.h"
31#include "OgreBlendMode.h"
32#include "OgreTextureUnitState.h"
33#include "OgreGpuProgram.h"
34#include "OgreTechnique.h"
35#include "OgrePass.h"
36#include "OgreMaterialManager.h"
37#include "OgreGpuProgramManager.h"
38#include "OgreHighLevelGpuProgramManager.h"
39#include "OgreExternalTextureSourceManager.h"
40
41namespace Ogre {
42
43    //-----------------------------------------------------------------------
44    // Static definitions
45    //-----------------------------------------------------------------------
46    MaterialScriptCompiler::TokenActionMap MaterialScriptCompiler::mTokenActionMap;
47
48    String MaterialScriptCompiler::materialScript_BNF =
49        "<Script> ::= {<Script_Properties>} \n"
50
51        "<Script_Properties> ::= <Material_Def> | <Vertex_Program_Def> | <Fragment_Program_Def> \n"
52
53        "<Material_Def> ::= 'material' <Label> [<Material_Clone>] '{' {<Material_Properties>} '}' \n"
54
55        "<Material_Properties> ::= <Technique_Def> | <Set_Texture_Alias_Def> | "
56        "                          <Lod_Distances_Def> | <Receive_Shadows_Def> | "
57        "                          <transparency_casts_shadows_def> \n"
58
59        "    <Material_Clone> ::= ':' <Label> \n"
60        "    <Set_Texture_Alias_Def> ::= 'set_texture_alias' <Label> <Label> \n"
61        "    <Lod_Distances_Def> ::= 'lod_distances' <#distance> {<#distance>} \n"
62        "    <Receive_Shadows_Def> ::= 'receive_shadows' <On_Off> \n"
63        "    <transparency_casts_shadows_def> ::= 'transparency_casts_shadows' <On_Off> \n"
64
65        // Technique section rules
66        "<Technique_Def> ::= 'technique' [<Label>] '{' {<Technique_Properties>} '}' \n"
67        "    <Technique_Properties> ::= <Pass_Def> | <Lod_Index_Def> | <Scheme_Def> \n"
68        "    <Lod_Index_Def> ::= 'lod_index' <#value> \n"
69        "    <Scheme_Def> ::= 'scheme' <Label> \n"
70
71        // Pass section rules
72        "    <Pass_Def> ::= 'pass' [<Label>] '{' {<Pass_Properties>} '}' \n"
73        "        <Pass_Properties> ::= <Ambient_Def> | <Diffuse_Def> | <Specular_Def> | <Emissive_Def> | \n"
74        "                              <Scene_Blend_Def> | <Depth_Check_Def> | <Depth_Write_Def> | "
75        "                              <Depth_Func_Def> | <Colour_Write_Def> | <Cull_Hardware_Def> | "
76        "                              <Cull_Software_Def> | <Lighting_Def> | <Shading_Def> | "
77                "                              <Point_Size_Def> | <Point_Sprites_Def> | <Point_Size_Attenuation_Def> | "
78                "                              <Point_Size_Min_Def> | <Point_Size_Max_Def> \n"
79
80        "        <Ambient_Def> ::= 'ambient' <Colour_Params> | <Vertexcolour_Def> \n"
81        "        <Diffuse_Def> ::= 'diffuse' <Colour_Params> | <Vertexcolour_Def> \n"
82        "        <Specular_Def> ::= 'specular' <Specular_Params> <#shininess> \n"
83        "            <Specular_Params> ::= <Colour_Params> | <Vertexcolour_Def> \n"
84        "        <Emissive_Def> ::= 'emissive' <Colour_Params> | <Vertexcolour_Def> \n"
85
86        "        <Vertexcolour_Def> ::= 'vertexcolour' \n"
87
88        "        <Scene_Blend_Def> ::= 'scene_blend' <Simple_Blend> | <User_Blend> \n"
89        "          <Simple_Blend> ::= 'add' | 'modulate' | 'colour_blend' | 'alpha_blend' \n"
90        "          <User_Blend> ::= <Blend_Factor> <Blend_Factor> \n"
91        "          <Blend_Factor> ::= 'one' | 'zero' | 'dest_colour' | 'src_colour' | \n"
92        "                             'one_minus_dest_colour' | 'one_minus_src_colour' | \n"
93        "                             'dest_alpha' | 'src_alpha' | 'one_minus_dest_alpha' | \n"
94        "                             'one_minus_src_alpha' \n"
95
96        "        <Depth_Check_Def> ::= 'depth_check' <On_Off> \n"
97        "        <Depth_Write_Def> ::= 'depth_write' <On_Off> \n"
98        "        <Depth_Func_Def> ::= 'depth_func' <Compare_Func_Def> \n"
99        "        <Depth_Bias_Def> ::= 'depth_bias' <#value> \n"
100        "        <Alpha_Rejection_Def> ::= 'alpha_rejection' <Compare_Func_Def> <#value> \n"
101        "        <Compare_Func_Def> ::= 'always_fail' | 'always_pass' | 'less_equal' | 'less' | \n"
102        "                               'equal' | 'not_equal' | 'greater_equal' | 'greater' \n"
103        "        <Colour_Write_Def> ::= 'colour_write' <On_Off> \n"
104        "        <Cull_Hardware_Def> ::= 'cull_hardware' 'clockwise' | 'anticlockwise' | 'none' \n"
105        "        <Cull_Software_Def> ::= 'cull_software' 'back' | 'front' | 'none' \n"
106        "        <Lighting_Def> ::= 'lighting' <On_Off> \n"
107        "        <Shading_Def> ::= 'shading' 'flat' | 'gouraud' | 'phong' \n"
108                "        <Point_Size_Def> ::= 'point_size' <#size> \n"
109                "        <Point_Sprites_Def> ::= 'point_sprites' <On_Off> \n"
110                "        <Point_Size_Min_Def> ::= 'point_size_min' <#size> \n"
111                "        <Point_Size_Max_Def> ::= 'point_size_max' <#size> \n"
112                "        <Point_Size_Attenuation_Def> ::= 'point_size_attenuation' <On_Off> [<Point_Size_Att_Params>] \n"
113                "            <Point_Size_Att_Params> ::= <#constant> <#linear> <#quadric> \n"
114        "        <Fog_Override_Def> ::= 'fog_override' <fog_false> | <fog_true> \n"
115        "           <fog_false> ::= 'false' \n"
116        "           <fog_true> ::= 'true' [<Fog_parameters>] \n"
117        "               <Fog_parameters> ::= <fog_type> <fog_colour> <#fog_density> <#start> <#end> \n"
118        "                   <fog_type> ::= 'none' | 'linear' | 'exp' | 'exp2' \n"
119        "                   <fog_colour> ::= <#red> <#green> <#blue> \n"
120        "        <Max_Lights_Def> ::= 'max_lights' <#number> \n"
121        "        <Iteration_Def> ::= 'iteration' 'once' | <Iteration_Once_Params> | <Iteration_Counted> \n"
122        "           <Iteration_Once_Params> ::= 'once_per_light' [<light_type>] \n"
123        "           <Iteration_Counted> ::= <#number> [<Per_Light>] \n"
124        "               <Per_Light> ::= 'per_light' <light_type> \n"
125        "           <light_type> ::= 'point' | 'directional' | 'spot' \n"
126        // Texture Unit section rules
127        "        <Texture_Unit_Def> ::= 'texture_unit' [<Label>] '{' {<TUS_Properties>} '}' \n"
128        "        <TUS_Properties> ::= '****FILLER****' \n"
129        " "
130        "<Vertex_Program_Def> ::= 'vertex_program' \n"
131        "<Fragment_Program_Def> ::= 'fragment_program' \n"
132
133        // common rules
134        "<On_Off> ::= 'on' | 'off' \n"
135        "<Colour_Params> ::= <#red> <#green> <#blue> [<#alpha>] \n"
136
137
138        "<Label> ::= <Unquoted_Label> | <Quoted_Label> \n"
139        "<Quoted_Label> ::= '\"' <Character> {<Alphanumeric_Space>} '\"' \n"
140        "<Unquoted_Label> ::= <Character> {<Alphanumeric>} \n"
141        "<Alphanumeric_Space> ::= <Alphanumeric> | ' ' \n"
142        "<Alphanumeric> ::= <Character> | <Number> \n"
143        "<Character> ::= (abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$#%!_*&\\/) \n"
144        "<Number> ::= (0123456789) \n"
145
146        ;
147
148    //-----------------------------------------------------------------------
149    MaterialScriptCompiler::MaterialScriptCompiler(void)
150    {
151    }
152    //-----------------------------------------------------------------------
153    MaterialScriptCompiler::~MaterialScriptCompiler(void)
154    {
155
156    }
157    //-----------------------------------------------------------------------
158    void MaterialScriptCompiler::setupTokenDefinitions(void)
159    {
160        addLexemeTokenAction("{", ID_OPENBRACE, &MaterialScriptCompiler::parseOpenBrace);
161        addLexemeTokenAction("}", ID_CLOSEBRACE, &MaterialScriptCompiler::parseCloseBrace);
162        addLexemeTokenAction("vertex_program", ID_VERTEX_PROGRAM, &MaterialScriptCompiler::parseVertexProgram);
163        addLexemeTokenAction("fragment_program", ID_FRAGMENT_PROGRAM, &MaterialScriptCompiler::parseFragmentProgram);
164        addLexemeTokenAction("material", ID_MATERIAL, &MaterialScriptCompiler::parseMaterial);
165            addLexemeTokenAction(":", ID_CLONE);
166
167        // Technique section
168        addLexemeTokenAction("technique", ID_TECHNIQUE, &MaterialScriptCompiler::parseTechnique);
169            addLexemeTokenAction("transparency_casts_shadows", ID_TRANSPARENCY_CASTS_SHADOWS, &MaterialScriptCompiler::parseTransparencyCastsShadows);
170            addLexemeTokenAction("receive_shadows", ID_RECEIVE_SHADOWS, &MaterialScriptCompiler::parseReceiveShadows);
171           
172
173        // Pass section
174        addLexemeTokenAction("pass", ID_PASS, &MaterialScriptCompiler::parsePass);
175            addLexemeTokenAction("ambient", ID_AMBIENT, &MaterialScriptCompiler::parseAmbient);
176            addLexemeTokenAction("diffuse", ID_DIFFUSE, &MaterialScriptCompiler::parseDiffuse);
177            addLexemeTokenAction("specular", ID_SPECULAR, &MaterialScriptCompiler::parseSpecular);
178            addLexemeTokenAction("emissive", ID_EMISSIVE, &MaterialScriptCompiler::parseEmissive);
179            addLexemeTokenAction("depth_check", ID_DEPTH_CHECK, &MaterialScriptCompiler::parseDepthCheck);
180            addLexemeTokenAction("depth_write", ID_DEPTH_WRITE, &MaterialScriptCompiler::parseDepthWrite);
181            addLexemeTokenAction("depth_func", ID_DEPTH_FUNC, &MaterialScriptCompiler::parseDepthFunc);
182                addLexemeTokenAction("always_fail", ID_ALWAYS_FAIL);
183                addLexemeTokenAction("always_pass", ID_ALWAYS_PASS);
184                addLexemeTokenAction("less_equal", ID_LESS_EQUAL);
185                addLexemeTokenAction("less", ID_LESS);
186                addLexemeTokenAction("equal", ID_EQUAL);
187                addLexemeTokenAction("not_equal", ID_NOT_EQUAL);
188                addLexemeTokenAction("greater_equal", ID_GREATER_EQUAL);
189                addLexemeTokenAction("greater", ID_GREATER);
190            addLexemeTokenAction("colour_write", ID_COLOUR_WRITE, &MaterialScriptCompiler::parseColourWrite);
191            addLexemeTokenAction("cull_hardware", ID_CULL_HARDWARE, &MaterialScriptCompiler::parseCullHardware);
192                addLexemeTokenAction("clockwise", ID_CLOCKWISE);
193                addLexemeTokenAction("anticlockwise", ID_ANTICLOCKWISE);
194                addLexemeTokenAction("none", ID_CULL_NONE);
195            addLexemeTokenAction("cull_software", ID_CULL_SOFTWARE, &MaterialScriptCompiler::parseCullSoftware);
196                addLexemeTokenAction("back", ID_CULL_BACK);
197                addLexemeTokenAction("front", ID_CULL_FRONT);
198            addLexemeTokenAction("lighting", ID_LIGHTING, &MaterialScriptCompiler::parseLighting);
199            addLexemeTokenAction("max_lights", ID_MAX_LIGHTS, &MaterialScriptCompiler::parseMaxLights);
200            addLexemeTokenAction("shading", ID_SHADING, &MaterialScriptCompiler::parseShading);
201                addLexemeTokenAction("flat", ID_FLAT);
202                addLexemeTokenAction("gouraud", ID_GOURAUD);
203                addLexemeTokenAction("phong", ID_PHONG);
204            addLexemeTokenAction("point_size", ID_POINT_SIZE, &MaterialScriptCompiler::parsePointSize);
205            addLexemeTokenAction("point_sprites", ID_POINT_SPRITES, &MaterialScriptCompiler::parsePointSprites);
206            addLexemeTokenAction("point_size_attenuation", ID_POINT_SIZE_ATTENUATION, &MaterialScriptCompiler::parsePointSizeAttenuation);
207            addLexemeTokenAction("point_size_min", ID_POINT_SIZE_MIN, &MaterialScriptCompiler::parsePointSizeMin);
208            addLexemeTokenAction("point_size_max", ID_POINT_SIZE_MAX, &MaterialScriptCompiler::parsePointSizeMax);
209
210        // Texture Unit section
211        addLexemeTokenAction("texture_unit", ID_TEXTURE_UNIT, &MaterialScriptCompiler::parseTextureUnit);
212
213        // common section
214        addLexemeTokenAction("on", ID_ON);
215        addLexemeTokenAction("off", ID_OFF);
216
217    }
218
219    //-----------------------------------------------------------------------
220    void MaterialScriptCompiler::addLexemeTokenAction(const String& lexeme, const size_t token, const MSC_Action action)
221    {
222        addLexemeToken(lexeme, token, action != 0);
223        mTokenActionMap[token] = action;
224    }
225
226    //-----------------------------------------------------------------------
227    void MaterialScriptCompiler::executeTokenAction(const size_t tokenID)
228    {
229        TokenActionIterator action = mTokenActionMap.find(tokenID);
230
231        if (action == mTokenActionMap.end())
232        {
233            // BAD command. BAD!
234            logParseError("Unrecognised Material Script command action");
235            return;
236        }
237        else
238        {
239            try
240            {
241                (this->*action->second)();
242            }
243            catch (Exception& ogreException)
244            {
245                // an unknown token found or BNF Grammer rule was not successful
246                // in finding a valid terminal token to complete the rule expression.
247                logParseError(ogreException.getDescription());
248            }
249        }
250    }
251
252    //-----------------------------------------------------------------------
253    void MaterialScriptCompiler::logParseError(const String& error)
254    {
255        // log material name only if filename not specified
256        if (mScriptContext.filename.empty() && !mScriptContext.material.isNull())
257        {
258            LogManager::getSingleton().logMessage(
259                "Error in material " + mScriptContext.material->getName() +
260                " : " + error);
261        }
262        else
263        {
264            if (!mScriptContext.material.isNull())
265            {
266                LogManager::getSingleton().logMessage(
267                    "Error in material " + mScriptContext.material->getName() +
268                    " at line " + StringConverter::toString(mCurrentLine) +
269                    " of " + mScriptContext.filename + ": " + error);
270            }
271            else
272            {
273                LogManager::getSingleton().logMessage(
274                    "Error at line " + StringConverter::toString(mCurrentLine) +
275                    " of " + mScriptContext.filename + ": " + error);
276            }
277        }
278    }
279    //-----------------------------------------------------------------------
280    void MaterialScriptCompiler::parseOpenBrace(void)
281    {
282
283    }
284    //-----------------------------------------------------------------------
285    void MaterialScriptCompiler::parseCloseBrace(void)
286    {
287        switch(mScriptContext.section)
288        {
289        case MSS_NONE:
290            logParseError("Unexpected terminating brace.");
291            break;
292        case MSS_MATERIAL:
293            // End of material
294            // if texture aliases were found, pass them to the material
295            // to update texture names used in Texture unit states
296            if (!mScriptContext.textureAliases.empty())
297            {
298                // request material to update all texture names in TUS's
299                // that use texture aliases in the list
300                mScriptContext.material->applyTextureAliases(mScriptContext.textureAliases);
301            }
302
303            mScriptContext.section = MSS_NONE;
304            mScriptContext.material.setNull();
305                        //Reset all levels for next material
306                        mScriptContext.passLev = -1;
307                        mScriptContext.stateLev= -1;
308                        mScriptContext.techLev = -1;
309            mScriptContext.textureAliases.clear();
310            break;
311        case MSS_TECHNIQUE:
312            // End of technique
313            mScriptContext.section = MSS_MATERIAL;
314            mScriptContext.technique = NULL;
315                        mScriptContext.passLev = -1;    //Reset pass level (yes, the pass level)
316            break;
317        case MSS_PASS:
318            // End of pass
319            mScriptContext.section = MSS_TECHNIQUE;
320            mScriptContext.pass = NULL;
321                        mScriptContext.stateLev = -1;   //Reset state level (yes, the state level)
322            break;
323        case MSS_TEXTUREUNIT:
324            // End of texture unit
325            mScriptContext.section = MSS_PASS;
326            mScriptContext.textureUnit = NULL;
327            break;
328                case MSS_TEXTURESOURCE:
329                        //End texture source section
330                        //Finish creating texture here
331
332                        if(     ExternalTextureSourceManager::getSingleton().getCurrentPlugIn() != 0)
333            {
334                const String sMaterialName = mScriptContext.material->getName();
335                                ExternalTextureSourceManager::getSingleton().getCurrentPlugIn()->
336                                createDefinedTexture( sMaterialName, mScriptContext.groupName );
337            }
338                        //Revert back to texture unit
339                        mScriptContext.section = MSS_TEXTUREUNIT;
340                        break;
341        case MSS_PROGRAM_REF:
342            // End of program
343            mScriptContext.section = MSS_PASS;
344            mScriptContext.program.setNull();
345            break;
346        case MSS_PROGRAM:
347                        // Program definitions are slightly different, they are deferred
348                        // until all the information required is known
349            // End of program
350                        finishProgramDefinition();
351            mScriptContext.section = MSS_NONE;
352            delete mScriptContext.programDef;
353            mScriptContext.defaultParamLines.clear();
354            mScriptContext.programDef = NULL;
355            break;
356        case MSS_DEFAULT_PARAMETERS:
357            // End of default parameters
358            mScriptContext.section = MSS_PROGRAM;
359            break;
360        };
361    }
362    //-----------------------------------------------------------------------
363    void MaterialScriptCompiler::parseVertexProgram(void)
364    {
365        // update section
366        mScriptContext.section = MSS_PROGRAM;
367
368                // Create new program definition-in-progress
369                mScriptContext.programDef = new MaterialScriptProgramDefinition();
370                mScriptContext.programDef->progType = GPT_VERTEX_PROGRAM;
371        mScriptContext.programDef->supportsSkeletalAnimation = false;
372                mScriptContext.programDef->supportsMorphAnimation = false;
373                mScriptContext.programDef->supportsPoseAnimation = 0;
374
375                // Get name and language code
376        const size_t paramCount = getRemainingTokensForAction();
377                if (paramCount != 2)
378                {
379            logParseError("Invalid vertex_program entry - expected "
380                                "2 parameters.");
381            return;
382                }
383                // Name, preserve case
384                mScriptContext.programDef->name = getNextTokenLabel();
385                // language code, make lower case
386                mScriptContext.programDef->language = getNextTokenLabel();
387                StringUtil::toLowerCase(mScriptContext.programDef->language);
388        }
389    //-----------------------------------------------------------------------
390    void MaterialScriptCompiler::parseFragmentProgram(void)
391    {
392        // update section
393        mScriptContext.section = MSS_PROGRAM;
394
395                // Create new program definition-in-progress
396                mScriptContext.programDef = new MaterialScriptProgramDefinition();
397                mScriptContext.programDef->progType = GPT_FRAGMENT_PROGRAM;
398                mScriptContext.programDef->supportsSkeletalAnimation = false;
399                mScriptContext.programDef->supportsMorphAnimation = false;
400                mScriptContext.programDef->supportsPoseAnimation = 0;
401
402                // Get name and language code
403        const size_t paramCount = getRemainingTokensForAction();
404                if (paramCount != 2)
405                {
406            logParseError("Invalid fragment_program entry - expected "
407                                "2 parameters.");
408            return;
409                }
410                // Name, preserve case
411                mScriptContext.programDef->name = getNextTokenLabel();
412                // language code, make lower case
413                mScriptContext.programDef->language = getNextTokenLabel();
414                StringUtil::toLowerCase(mScriptContext.programDef->language);
415        }
416        //-----------------------------------------------------------------------
417    void MaterialScriptCompiler::parseMaterial(void)
418    {
419        // check params for reference to parent material to copy from
420        // syntax: material name : parentMaterialName
421        MaterialPtr basematerial;
422
423        const String materialName = getNextTokenLabel();
424        // Create a brand new material
425        const size_t paramCount = getRemainingTokensForAction();
426        if (paramCount == 2)
427        {
428            getNextToken();
429            // if a second parameter exists then assume its the name of the base material
430            // that this new material should clone from
431            const String parentName = getNextTokenLabel();
432            // make sure base material exists
433            basematerial = MaterialManager::getSingleton().getByName(parentName);
434            // if it doesn't exist then report error in log and just create a new material
435            if (basematerial.isNull())
436            {
437                logParseError("parent material: " + parentName + " not found for new material:"
438                    + materialName);
439            }
440        }
441
442        mScriptContext.material =
443                        MaterialManager::getSingleton().create(materialName, mScriptContext.groupName);
444
445        if (!basematerial.isNull())
446        {
447            // copy parent material details to new material
448            basematerial->copyDetailsTo(mScriptContext.material);
449        }
450        else
451        {
452            // Remove pre-created technique from defaults
453            mScriptContext.material->removeAllTechniques();
454        }
455
456                mScriptContext.material->_notifyOrigin(mScriptContext.filename);
457
458        // update section
459        mScriptContext.section = MSS_MATERIAL;
460
461    }
462        //-----------------------------------------------------------------------
463    void MaterialScriptCompiler::parseTechnique(void)
464    {
465        String techniqueName;
466        const size_t paramCount = getRemainingTokensForAction();
467        // if params is not empty then see if the technique name already exists
468        if ((paramCount > 0) && (mScriptContext.material->getNumTechniques() > 0))
469        {
470            // find the technique with name = params
471            techniqueName = getNextTokenLabel();
472            Technique * foundTechnique = mScriptContext.material->getTechnique(techniqueName);
473            if (foundTechnique)
474            {
475                // figure out technique index by iterating through technique container
476                // would be nice if each technique remembered its index
477                int count = 0;
478                Material::TechniqueIterator i = mScriptContext.material->getTechniqueIterator();
479                while(i.hasMoreElements())
480                {
481                    if (foundTechnique == i.peekNext())
482                        break;
483                    i.moveNext();
484                    ++count;
485                }
486
487                mScriptContext.techLev = count;
488            }
489            else
490            {
491                // name was not found so a new technique is needed
492                // position technique level to the end index
493                // a new technique will be created later on
494                mScriptContext.techLev = mScriptContext.material->getNumTechniques();
495            }
496
497        }
498        else
499        {
500            // no name was given in the script so a new technique will be created
501                    // Increase technique level depth
502                    ++mScriptContext.techLev;
503        }
504
505        // Create a new technique if it doesn't already exist
506        if (mScriptContext.material->getNumTechniques() > mScriptContext.techLev)
507        {
508            mScriptContext.technique = mScriptContext.material->getTechnique(mScriptContext.techLev);
509        }
510        else
511        {
512            mScriptContext.technique = mScriptContext.material->createTechnique();
513            if (!techniqueName.empty())
514                mScriptContext.technique->setName(techniqueName);
515        }
516
517        // update section
518        mScriptContext.section = MSS_TECHNIQUE;
519
520    }
521        //-----------------------------------------------------------------------
522    void MaterialScriptCompiler::parseTransparencyCastsShadows(void)
523        {
524        switch (getNextToken().tokenID)
525        {
526        case ID_ON:
527                        mScriptContext.material->setTransparencyCastsShadows(true);
528            break;
529        case ID_OFF:
530                        mScriptContext.material->setTransparencyCastsShadows(false);
531            break;
532        default:
533            replaceToken();
534                        logParseError(
535                        "Bad transparency_casts_shadows attribute, valid parameters are 'on' or 'off'.");
536        }
537
538        }
539    //-----------------------------------------------------------------------
540    void MaterialScriptCompiler::parseReceiveShadows(void)
541    {
542        switch (getNextToken().tokenID)
543        {
544        case ID_ON:
545            mScriptContext.material->setReceiveShadows(true);
546            break;
547        case ID_OFF:
548            mScriptContext.material->setReceiveShadows(false);
549            break;
550        default:
551            replaceToken();
552            logParseError("Bad receive_shadows attribute, valid parameters are 'on' or 'off'.");
553        }
554    }
555
556        //-----------------------------------------------------------------------
557    void MaterialScriptCompiler::parsePass(void)
558    {
559        String passName;
560        const size_t paramCount = getRemainingTokensForAction();
561        // if params is not empty then see if the pass name already exists
562        if ((paramCount > 0) && (mScriptContext.technique->getNumPasses() > 0))
563        {
564            passName = getNextTokenLabel();
565            // find the pass with name = params
566            Pass * foundPass = mScriptContext.technique->getPass(passName);
567            if (foundPass)
568            {
569                mScriptContext.passLev = foundPass->getIndex();
570            }
571            else
572            {
573                // name was not found so a new pass is needed
574                // position pass level to the end index
575                // a new pass will be created later on
576                mScriptContext.passLev = mScriptContext.technique->getNumPasses();
577            }
578
579        }
580        else
581        {
582                    //Increase pass level depth
583                    ++mScriptContext.passLev;
584        }
585
586        if (mScriptContext.technique->getNumPasses() > mScriptContext.passLev)
587        {
588            mScriptContext.pass = mScriptContext.technique->getPass(mScriptContext.passLev);
589        }
590        else
591        {
592            // Create a new pass
593            mScriptContext.pass = mScriptContext.technique->createPass();
594            if (!passName.empty())
595                mScriptContext.pass->setName(passName);
596        }
597
598        // update section
599        mScriptContext.section = MSS_PASS;
600    }
601    //-----------------------------------------------------------------------
602    ColourValue MaterialScriptCompiler::_parseColourValue(void)
603    {
604        Real r = getNextTokenValue();
605        Real g = getNextTokenValue();
606        Real b = getNextTokenValue();
607        Real a = getRemainingTokensForAction() == 1 ? getNextTokenValue() : 1.0f;
608        return ColourValue(r, g, b, a);
609    }
610    //-----------------------------------------------------------------------
611    void MaterialScriptCompiler::parseAmbient(void)
612    {
613        // Must be 1, 3 or 4 parameters
614        const size_t paramCount = getRemainingTokensForAction();
615        if (paramCount == 1) {
616            if(getNextToken().tokenID == ID_VERTEXCOLOUR)
617            {
618                mScriptContext.pass->setVertexColourTracking(mScriptContext.pass->getVertexColourTracking() | TVC_AMBIENT);
619            }
620            else
621            {
622                replaceToken();
623                logParseError("Bad ambient attribute, single parameter flag must be 'vertexcolour'");
624            }
625        }
626        else if (paramCount == 3 || paramCount == 4)
627        {
628            mScriptContext.pass->setAmbient( _parseColourValue() );
629            mScriptContext.pass->setVertexColourTracking(mScriptContext.pass->getVertexColourTracking() & ~TVC_AMBIENT);
630        }
631        else
632        {
633            logParseError("Bad ambient attribute, wrong number of parameters (expected 1, 3 or 4)");
634        }
635    }
636   //-----------------------------------------------------------------------
637    void MaterialScriptCompiler::parseDiffuse(void)
638    {
639        // Must be 1, 3 or 4 parameters
640        const size_t paramCount = getRemainingTokensForAction();
641        if (paramCount == 1) {
642            if(getNextToken().tokenID == ID_VERTEXCOLOUR)
643            {
644               mScriptContext.pass->setVertexColourTracking(mScriptContext.pass->getVertexColourTracking() | TVC_DIFFUSE);
645            }
646            else
647            {
648                replaceToken();
649                logParseError("Bad diffuse attribute, single parameter flag must be 'vertexcolour'");
650            }
651        }
652        else if (paramCount == 3 || paramCount == 4)
653        {
654            mScriptContext.pass->setDiffuse( _parseColourValue() );
655            mScriptContext.pass->setVertexColourTracking(mScriptContext.pass->getVertexColourTracking() & ~TVC_DIFFUSE);
656        }
657        else
658        {
659            logParseError("Bad diffuse attribute, wrong number of parameters (expected 1, 3 or 4)");
660        }
661    }
662    //-----------------------------------------------------------------------
663    void MaterialScriptCompiler::parseSpecular(void)
664    {
665        // Must be 2, 4 or 5 parameters
666        const size_t paramCount = getRemainingTokensForAction();
667        if(paramCount == 2)
668        {
669            if(getNextToken().tokenID == ID_VERTEXCOLOUR)
670            {
671                mScriptContext.pass->setVertexColourTracking(mScriptContext.pass->getVertexColourTracking() | TVC_SPECULAR);
672                mScriptContext.pass->setShininess(getNextTokenValue());
673            }
674            else
675            {
676                replaceToken();
677                logParseError("Bad specular attribute, double parameter statement must be 'vertexcolour <shininess>'");
678            }
679        }
680        else if(paramCount == 4 || paramCount == 5)
681        {
682            Real r = getNextTokenValue();
683            Real g = getNextTokenValue();
684            Real b = getNextTokenValue();
685            Real a = paramCount == 5 ? getNextTokenValue() : 1.0f;
686            mScriptContext.pass->setSpecular(r, g, b, a);
687            mScriptContext.pass->setVertexColourTracking(mScriptContext.pass->getVertexColourTracking() & ~TVC_SPECULAR);
688            mScriptContext.pass->setShininess( getNextTokenValue() );
689        }
690        else
691        {
692            logParseError("Bad specular attribute, wrong number of parameters (expected 2, 4 or 5)");
693        }
694    }
695    //-----------------------------------------------------------------------
696    void MaterialScriptCompiler::parseEmissive(void)
697    {
698        // Must be 1, 3 or 4 parameters
699        const size_t paramCount = getRemainingTokensForAction();
700        if (paramCount == 1) {
701            if(getNextToken().tokenID == ID_VERTEXCOLOUR)
702            {
703               mScriptContext.pass->setVertexColourTracking(mScriptContext.pass->getVertexColourTracking() | TVC_EMISSIVE);
704            }
705            else
706            {
707                replaceToken();
708                logParseError("Bad emissive attribute, single parameter flag must be 'vertexcolour'");
709            }
710        }
711        else if (paramCount == 3 || paramCount == 4)
712        {
713            mScriptContext.pass->setSelfIllumination( _parseColourValue() );
714            mScriptContext.pass->setVertexColourTracking(mScriptContext.pass->getVertexColourTracking() & ~TVC_EMISSIVE);
715        }
716        else
717        {
718            logParseError("Bad emissive attribute, wrong number of parameters (expected 1, 3 or 4)");
719        }
720    }
721    //-----------------------------------------------------------------------
722    void MaterialScriptCompiler::parseDepthCheck(void)
723    {
724        switch (getNextToken().tokenID)
725        {
726        case ID_ON:
727            mScriptContext.pass->setDepthCheckEnabled(true);
728            break;
729        case ID_OFF:
730            mScriptContext.pass->setDepthCheckEnabled(false);
731            break;
732        default:
733            logParseError("Bad depth_check attribute, valid parameters are 'on' or 'off'.");
734        }
735    }
736    //-----------------------------------------------------------------------
737    void MaterialScriptCompiler::parseDepthWrite(void)
738    {
739        switch (getNextToken().tokenID)
740        {
741        case ID_ON:
742            mScriptContext.pass->setDepthWriteEnabled(true);
743            break;
744        case ID_OFF:
745            mScriptContext.pass->setDepthWriteEnabled(false);
746            break;
747        default:
748            logParseError("Bad depth_write attribute, valid parameters are 'on' or 'off'.");
749        }
750    }
751    //-----------------------------------------------------------------------
752    CompareFunction MaterialScriptCompiler::convertCompareFunction(void)
753    {
754        switch (getNextToken().tokenID)
755        {
756        case ID_ALWAYS_FAIL:
757            return CMPF_ALWAYS_FAIL;
758        case ID_ALWAYS_PASS:
759            return CMPF_ALWAYS_PASS;
760        case ID_LESS:
761            return CMPF_LESS;
762        case ID_LESS_EQUAL:
763            return CMPF_LESS_EQUAL;
764        case ID_EQUAL:
765            return CMPF_EQUAL;
766        case ID_NOT_EQUAL:
767            return CMPF_NOT_EQUAL;
768        case ID_GREATER_EQUAL:
769            return CMPF_GREATER_EQUAL;
770        case ID_GREATER:
771            return CMPF_GREATER;
772        }
773
774        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Invalid compare function", "convertCompareFunction");
775    }
776
777    //-----------------------------------------------------------------------
778    void MaterialScriptCompiler::parseDepthFunc(void)
779    {
780        const CompareFunction func = convertCompareFunction();
781        mScriptContext.pass->setDepthFunction(func);
782    }
783    //-----------------------------------------------------------------------
784    void MaterialScriptCompiler::parseAlphaRejection(void)
785    {
786        const size_t paramCount = getRemainingTokensForAction();
787        if (paramCount != 2)
788        {
789            logParseError("Bad alpha_rejection attribute, wrong number of parameters (expected 2)");
790            return;
791        }
792
793        const CompareFunction cmp = convertCompareFunction();
794        mScriptContext.pass->setAlphaRejectSettings(cmp, static_cast<unsigned char>(getNextTokenValue()));
795    }
796    //-----------------------------------------------------------------------
797    void MaterialScriptCompiler::parseColourWrite(void)
798    {
799        switch (getNextToken().tokenID)
800        {
801        case ID_ON:
802            mScriptContext.pass->setColourWriteEnabled(true);
803            break;
804        case ID_OFF:
805            mScriptContext.pass->setColourWriteEnabled(false);
806            break;
807        default:
808            logParseError("Bad colour_write attribute, valid parameters are 'on' or 'off'.");
809        }
810    }
811    //-----------------------------------------------------------------------
812    void MaterialScriptCompiler::parseCullHardware(void)
813    {
814        switch (getNextToken().tokenID)
815        {
816        case ID_CULL_NONE:
817            mScriptContext.pass->setCullingMode(CULL_NONE);
818            break;
819        case ID_ANTICLOCKWISE:
820            mScriptContext.pass->setCullingMode(CULL_ANTICLOCKWISE);
821            break;
822        case ID_CLOCKWISE:
823            mScriptContext.pass->setCullingMode(CULL_CLOCKWISE);
824            break;
825        default:
826            logParseError(
827                "Bad cull_hardware attribute, valid parameters are "
828                "'none', 'clockwise' or 'anticlockwise'.");
829        }
830    }
831    //-----------------------------------------------------------------------
832    void MaterialScriptCompiler::parseCullSoftware(void)
833    {
834        switch (getNextToken().tokenID)
835        {
836        case ID_CULL_NONE:
837            mScriptContext.pass->setManualCullingMode(MANUAL_CULL_NONE);
838            break;
839        case ID_CULL_BACK:
840            mScriptContext.pass->setManualCullingMode(MANUAL_CULL_BACK);
841            break;
842        case ID_CULL_FRONT:
843            mScriptContext.pass->setManualCullingMode(MANUAL_CULL_FRONT);
844            break;
845        default:
846            logParseError(
847                "Bad cull_software attribute, valid parameters are 'none', "
848                "'front' or 'back'.");
849        }
850    }
851    //-----------------------------------------------------------------------
852    void MaterialScriptCompiler::parseLighting(void)
853    {
854        switch (getNextToken().tokenID)
855        {
856        case ID_ON:
857            mScriptContext.pass->setLightingEnabled(true);
858            break;
859        case ID_OFF:
860            mScriptContext.pass->setLightingEnabled(false);
861            break;
862        default:
863            logParseError("Bad lighting attribute, valid parameters are 'on' or 'off'.");
864        }
865    }
866    //-----------------------------------------------------------------------
867    void MaterialScriptCompiler::parseMaxLights(void)
868    {
869                mScriptContext.pass->setMaxSimultaneousLights(static_cast<int>(getNextTokenValue()));
870    }
871    //-----------------------------------------------------------------------
872    void MaterialScriptCompiler::parseShading(void)
873    {
874        switch (getNextToken().tokenID)
875        {
876        case ID_FLAT:
877            mScriptContext.pass->setShadingMode(SO_FLAT);
878            break;
879        case ID_GOURAUD:
880            mScriptContext.pass->setShadingMode(SO_GOURAUD);
881            break;
882        case ID_PHONG:
883            mScriptContext.pass->setShadingMode(SO_PHONG);
884            break;
885        default:
886            logParseError("Bad shading attribute, valid parameters are 'flat', "
887                "'gouraud' or 'phong'.");
888        }
889    }
890    //-----------------------------------------------------------------------
891    void MaterialScriptCompiler::parsePointSize(void)
892    {
893        mScriptContext.pass->setPointSize(getNextTokenValue());
894    }
895    //-----------------------------------------------------------------------
896    void MaterialScriptCompiler::parsePointSprites(void)
897        {
898        switch (getNextToken().tokenID)
899        {
900        case ID_ON:
901            mScriptContext.pass->setPointSpritesEnabled(true);
902            break;
903        case ID_OFF:
904            mScriptContext.pass->setPointSpritesEnabled(false);
905            break;
906        default:
907            logParseError("Bad point_sprites attribute, valid parameters are 'on' or 'off'.");
908        }
909        }
910    //-----------------------------------------------------------------------
911        void MaterialScriptCompiler::parsePointSizeMin(void)
912        {
913        mScriptContext.pass->setPointMinSize(getNextTokenValue());
914        }
915    //-----------------------------------------------------------------------
916    void MaterialScriptCompiler::parsePointSizeMax(void)
917        {
918        mScriptContext.pass->setPointMaxSize(getNextTokenValue());
919        }
920    //-----------------------------------------------------------------------
921    void MaterialScriptCompiler::parsePointSizeAttenuation(void)
922        {
923        const size_t paramCount = getRemainingTokensForAction();
924        if (paramCount != 1 && paramCount != 4)
925        {
926            logParseError("Bad point_size_attenuation attribute, wrong number of parameters (expected 1 or 4)");
927            return;
928        }
929        switch (getNextToken().tokenID)
930        {
931        case ID_ON:
932                        if (paramCount == 4)
933                        {
934                                Real constant = getNextTokenValue();
935                                Real linear = getNextTokenValue();
936                                Real quadric = getNextTokenValue();
937                    mScriptContext.pass->setPointAttenuation(true, constant, linear, quadric);
938                        }
939                        else
940                        {
941                                mScriptContext.pass->setPointAttenuation(true);
942                        }
943
944            break;
945        case ID_OFF:
946            mScriptContext.pass->setPointAttenuation(false);
947            break;
948        default:
949            logParseError("Bad point_size_attenuation attribute, valid values are 'on' or 'off'.");
950        }
951        }
952    //-----------------------------------------------------------------------
953    void MaterialScriptCompiler::parseTextureCustomParameter(void)
954    {
955                // This params object does not have the command stripped
956                // Split only up to first delimiter, program deals with the rest
957
958                if (getRemainingTokensForAction() != 2)
959                {
960            logParseError("Invalid texture parameter entry; "
961                                "there must be a parameter name and at least one value.");
962                }
963
964                else if( ExternalTextureSourceManager::getSingleton().getCurrentPlugIn() != 0 )
965        {
966                        ////First is command, next could be a string with one or more values
967            const String& param1 = getNextTokenLabel();
968            const String& param2 = getNextTokenLabel();
969                        ExternalTextureSourceManager::getSingleton().getCurrentPlugIn()->setParameter( param1, param2 );
970        }
971        }
972    //-----------------------------------------------------------------------
973    void MaterialScriptCompiler::parseTextureUnit(void)
974    {
975        String tusName;
976        const size_t paramCount = getRemainingTokensForAction();
977        // if params is a name then see if that texture unit exists
978        // if not then log the warning and just move on to the next TU from current
979        if ((paramCount > 0) && (mScriptContext.pass->getNumTextureUnitStates() > 0))
980        {
981            // specifying a TUS name in the script for a TU means that a specific TU is being requested
982            // try to get the specific TU
983            // if the index requested is not valid, just creat a new TU
984            // find the TUS with name
985            tusName = getNextTokenLabel();
986            TextureUnitState * foundTUS = mScriptContext.pass->getTextureUnitState(tusName);
987            if (foundTUS)
988            {
989                mScriptContext.stateLev = mScriptContext.pass->getTextureUnitStateIndex(foundTUS);
990            }
991            else
992            {
993                // name was not found so a new TUS is needed
994                // position TUS level to the end index
995                // a new TUS will be created later on
996                mScriptContext.stateLev = static_cast<uint>(mScriptContext.pass->getNumTextureUnitStates());
997            }
998        }
999        else
1000        {
1001                    //Increase Texture Unit State level depth
1002                    ++mScriptContext.stateLev;
1003        }
1004
1005        if (mScriptContext.pass->getNumTextureUnitStates() > static_cast<size_t>(mScriptContext.stateLev))
1006        {
1007            mScriptContext.textureUnit = mScriptContext.pass->getTextureUnitState(mScriptContext.stateLev);
1008        }
1009        else
1010        {
1011            // Create a new texture unit
1012            mScriptContext.textureUnit = mScriptContext.pass->createTextureUnitState();
1013            if (!tusName.empty())
1014                mScriptContext.textureUnit->setName(tusName);
1015        }
1016        // update section
1017        mScriptContext.section = MSS_TEXTUREUNIT;
1018    }
1019    //-----------------------------------------------------------------------
1020        void MaterialScriptCompiler::finishProgramDefinition(void)
1021        {
1022                // Now it is time to create the program and propagate the parameters
1023                MaterialScriptProgramDefinition* def = mScriptContext.programDef;
1024        GpuProgramPtr gp;
1025                if (def->language == "asm")
1026                {
1027                        // Native assembler
1028                        // Validate
1029                        if (def->source.empty())
1030                        {
1031                                logParseError("Invalid program definition for " + def->name +
1032                                        ", you must specify a source file.");
1033                        }
1034                        if (def->syntax.empty())
1035                        {
1036                                logParseError("Invalid program definition for " + def->name +
1037                                        ", you must specify a syntax code.");
1038                        }
1039                        // Create
1040                        gp = GpuProgramManager::getSingleton().
1041                                createProgram(def->name, mScriptContext.groupName, def->source,
1042                    def->progType, def->syntax);
1043
1044                }
1045                else
1046                {
1047                        // High-level program
1048                        // Validate
1049                        if (def->source.empty())
1050                        {
1051                                logParseError("Invalid program definition for " + def->name +
1052                                        ", you must specify a source file.");
1053                        }
1054                        // Create
1055            try
1056            {
1057                            HighLevelGpuProgramPtr hgp = HighLevelGpuProgramManager::getSingleton().
1058                                    createProgram(def->name, mScriptContext.groupName,
1059                        def->language, def->progType);
1060                // Assign to generalised version
1061                gp = hgp;
1062                // Set source file
1063                hgp->setSourceFile(def->source);
1064
1065                            // Set custom parameters
1066                            std::map<String, String>::const_iterator i, iend;
1067                            iend = def->customParameters.end();
1068                            for (i = def->customParameters.begin(); i != iend; ++i)
1069                            {
1070                                    if (!hgp->setParameter(i->first, i->second))
1071                                    {
1072                                            logParseError("Error in program " + def->name +
1073                                                    " parameter " + i->first + " is not valid.");
1074                                    }
1075                            }
1076            }
1077            catch (Exception& e)
1078            {
1079                logParseError("Could not create GPU program '"
1080                    + def->name + "', error reported was: " + e.getFullDescription());
1081                                mScriptContext.program.setNull();
1082                mScriptContext.programParams.setNull();
1083                                return;
1084            }
1085        }
1086        // Set skeletal animation option
1087        gp->setSkeletalAnimationIncluded(def->supportsSkeletalAnimation);
1088                // Set morph animation option
1089                gp->setMorphAnimationIncluded(def->supportsMorphAnimation);
1090                // Set pose animation option
1091                gp->setPoseAnimationIncluded(def->supportsPoseAnimation);
1092                // set origin
1093                gp->_notifyOrigin(mScriptContext.filename);
1094
1095        // Set up to receive default parameters
1096        if (gp->isSupported()
1097            && !mScriptContext.defaultParamLines.empty())
1098        {
1099            mScriptContext.programParams = gp->getDefaultParameters();
1100                        mScriptContext.numAnimationParametrics = 0;
1101            mScriptContext.program = gp;
1102            StringVector::iterator i, iend;
1103            iend = mScriptContext.defaultParamLines.end();
1104            for (i = mScriptContext.defaultParamLines.begin();
1105                i != iend; ++i)
1106            {
1107                // find & invoke a parser
1108                // do this manually because we want to call a custom
1109                // routine when the parser is not found
1110                // First, split line on first divisor only
1111                StringVector splitCmd = StringUtil::split(*i, " \t", 1);
1112                // Find attribute parser
1113                //******************** FIX THIS
1114                //AttribParserList::iterator iparser
1115                //    = mProgramDefaultParamAttribParsers.find(splitCmd[0]);
1116                //if (iparser != mProgramDefaultParamAttribParsers.end())
1117                //{
1118                //    String cmd = splitCmd.size() >= 2? splitCmd[1]:StringUtil::BLANK;
1119                //    // Use parser with remainder
1120                //    iparser->second(cmd, mScriptContext );
1121                //}
1122
1123            }
1124            // Reset
1125            mScriptContext.program.setNull();
1126            mScriptContext.programParams.setNull();
1127        }
1128
1129        }
1130
1131
1132}
Note: See TracBrowser for help on using the repository browser.