Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreMaterialScriptCompiler.cpp @ 3

Last change on this file since 3 was 3, checked in by anonymous, 17 years ago

=update

File size: 122.6 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4(Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
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
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#include "OgreStableHeaders.h"
30#include "OgreMaterialScriptCompiler.h"
31#include "OgreStringConverter.h"
32#include "OgreLogManager.h"
33#include "OgreException.h"
34#include "OgreBlendMode.h"
35#include "OgreGpuProgram.h"
36#include "OgreTechnique.h"
37#include "OgrePass.h"
38#include "OgreMaterialManager.h"
39#include "OgreGpuProgramManager.h"
40#include "OgreHighLevelGpuProgramManager.h"
41#include "OgreExternalTextureSourceManager.h"
42
43namespace Ogre {
44
45    //-----------------------------------------------------------------------
46    // Static definitions
47    //-----------------------------------------------------------------------
48    MaterialScriptCompiler::TokenActionMap MaterialScriptCompiler::mTokenActionMap;
49
50    //-----------------------------------------------------------------------
51    const String& MaterialScriptCompiler::getClientBNFGrammer(void) const
52    {
53        // simplified Backus - Naur Form (BNF) grammer for material scripts
54        static const String materialScript_BNF =
55        "<Script> ::= {<Script_Properties>} \n"
56
57        "<Script_Properties> ::= <Material> | <Vertex_Program> | <Fragment_Program> \n"
58
59        "<Material> ::= 'material' <Flex_Label> [<Material_Clone>] '{' {<Material_Properties>} '}' \n"
60
61        "<Material_Properties> ::= <Technique> | <Set_Texture_Alias> | "
62        "                          <Lod_Distances> | <Receive_Shadows> | "
63        "                          <Transparency_Casts_Shadows> \n"
64
65        "    <Material_Clone> ::= ':' <Flex_Label> \n"
66        "    <Set_Texture_Alias> ::= 'set_texture_alias' <Label> [<Seperator>] <Label> \n"
67        "    <Lod_Distances> ::= 'lod_distances' <#distance> {<#distance>} \n"
68        "    <Receive_Shadows> ::= 'receive_shadows' <On_Off> \n"
69        "    <Transparency_Casts_Shadows> ::= 'transparency_casts_shadows' <On_Off> \n"
70
71        // Technique section rules
72        "<Technique> ::= 'technique' [<Label>] '{' {<Technique_Properties>} '}' \n"
73        "    <Technique_Properties> ::= <Pass> | <Lod_Index> | <Scheme> \n"
74        "    <Lod_Index> ::= 'lod_index' <#value> \n"
75        "    <Scheme> ::= 'scheme' <Label> \n"
76
77        // Pass section rules
78        "    <Pass> ::= 'pass' [<Label>] '{' {<Pass_Properties>} '}' \n"
79        "        <Pass_Properties> ::= <Ambient> | <Diffuse> | <Specular> | <Emissive> | \n"
80        "                              <Scene_Blend> | <Depth_Check> | <Depth_Write> | \n"
81        "                              <Texture_Unit> | \n"
82        "                              <Depth_Func> | <Depth_Bias> | <Alpha_Rejection> | \n"
83        "                              <Cull_Hardware> | <Cull_Software> | <Lighting> | \n"
84        "                              <GPU_Program_Ref> | \n"
85        "                              <Shading> | <PolygonMode> | <Fog_Override> | <Colour_Write> | \n"
86                "                              <Max_Lights> | <Start_Light> | <Iteration> | \n"
87                "                              <Point_Sprites> | <Point_Size_Attenuation> | \n"
88                "                              <Point_Size_Min> | <Point_Size_Max> | <Point_Size> \n"
89
90        "        <Ambient> ::= 'ambient' <ColourOptions> \n"
91        "        <Diffuse> ::= 'diffuse' <ColourOptions> \n"
92        "        <Specular> ::= 'specular' <SpecularOptions> \n"
93        "           <SpecularOptions> ::= <Specular_Colour_Params> | <Specular_Vertex> \n"
94        "           <Specular_Colour_Params> ::= <#red> <#green> <#blue> <#val> [<#val>] \n"
95        "           <Specular_Vertex> ::= 'vertexcolour' <#shininess> \n"
96        "        <Emissive> ::= 'emissive' <ColourOptions> \n"
97
98        "        <ColourOptions> ::= <Colour_Params> | 'vertexcolour' \n"
99
100        "        <Scene_Blend> ::= 'scene_blend' <SceneBlend_Options> \n"
101        "          <SceneBlend_Options> ::= <Simple_Blend> | <User_Blend> \n"
102        "            <Simple_Blend> ::= <Base_Blend> | 'colour_blend' \n"
103        "            <Base_Blend> ::= 'alpha_blend' | 'modulate' | 'add' \n"
104        "            <User_Blend> ::= <Blend_Factor> <Blend_Factor> \n"
105        "            <Blend_Factor> ::= 'dest_colour' | 'src_colour' | \n"
106        "                               'one_minus_dest_colour' | 'one_minus_src_colour' | \n"
107        "                               'dest_alpha' | 'src_alpha' | 'one_minus_dest_alpha' | \n"
108        "                               'one_minus_src_alpha' | 'one' | 'zero' \n"
109
110        "        <Depth_Check> ::= 'depth_check' <On_Off> \n"
111        "        <Depth_Write> ::= 'depth_write' <On_Off> \n"
112        "        <Depth_Func> ::= 'depth_func' <Compare_Func> \n"
113                "        <Depth_Bias> ::= 'depth_bias' <#constant> [<#slopescale>] \n"
114        "        <Alpha_Rejection> ::= 'alpha_rejection' <Compare_Func> <#value> \n"
115        "        <Compare_Func> ::= 'always_fail' | 'always_pass' | 'less_equal' | 'less' | \n"
116        "                           'equal' | 'not_equal' | 'greater_equal' | 'greater' \n"
117        "        <Cull_Hardware> ::= 'cull_hardware' <Cull_Hardware_Otions> \n"
118        "           <Cull_Hardware_Otions> ::= 'clockwise' | 'anticlockwise' | 'none' \n"
119        "        <Cull_Software> ::= 'cull_software' <Cull_Software_Otions> \n"
120        "           <Cull_Software_Otions> ::= 'back' | 'front' | 'none' \n"
121        "        <Lighting> ::= 'lighting' <On_Off> \n"
122        "        <Shading> ::= 'shading' <Shading_Options> \n"
123        "           <Shading_Options> ::= 'flat' | 'gouraud' | 'phong' \n"
124        "        <PolygonMode> ::= 'polygon_mode' <PolygonMode_Options> \n"
125        "           <PolygonMode_Options> ::= 'solid' | 'wireframe' | 'points' \n"
126        "        <Colour_Write> ::= 'colour_write' <On_Off> \n"
127                "        <Point_Size> ::= 'point_size' <#size> \n"
128                "        <Point_Sprites> ::= 'point_sprites' <On_Off> \n"
129                "        <Point_Size_Min> ::= 'point_size_min' <#size> \n"
130                "        <Point_Size_Max> ::= 'point_size_max' <#size> \n"
131                "        <Point_Size_Attenuation> ::= 'point_size_attenuation' <On_Off> [<Point_Size_Att_Params>] \n"
132                "            <Point_Size_Att_Params> ::= <#constant> <#linear> <#quadric> \n"
133        "        <Fog_Override> ::= 'fog_override' <Fog_Override_Options> \n"
134        "           <Fog_Override_Options> ::= 'false' | <fog_true> \n"
135        "             <fog_true> ::= 'true' [<Fog_True_Params>] \n"
136        "               <Fog_True_Params> ::= 'none' | <fog_True_Param_Option> \n"
137        "                   <fog_True_Param_Option> ::= <fog_type> <#red> <#green> <#blue> <#fog_density> <#start> <#end> \n"
138        "                       <fog_type> ::= 'linear' | 'exp2' | 'exp' \n"
139        "        <Max_Lights> ::= 'max_lights' <#number> \n"
140                "        <Start_Light> ::= 'start_light' <#number> \n"
141        "        <Iteration> ::= 'iteration' <Iteration_Options> \n"
142        "           <Iteration_Options> ::= <Iteration_Once_Params> | 'once' | <Iteration_Counted> \n"
143        "             <Iteration_Once_Params> ::= 'once_per_light' [<light_type>] \n"
144        "             <Iteration_Counted> ::= <#number> [<Per_Light_Options>] \n"
145                "               <Per_Light_Options> ::= <Per_Light> | <Per_N_Lights> \n"
146                "                 <Per_Light> ::= 'per_light' [<light_type>] \n"
147                "                 <Per_N_Lights> ::= 'per_n_lights' <#num_lights> [<light_type>] \n"
148        "             <light_type> ::= 'point' | 'directional' | 'spot' \n"
149        // Texture Unit section rules
150        "        <Texture_Unit> ::= 'texture_unit' [<Label>] '{' {<TUS_Properties>} '}' \n"
151        "        <TUS_Properties> ::= <Texture_Alias> | <Texture> | <Anim_Texture> | <Cubic_Texture> | \n"
152        "                             <Tex_Coord_Set> | <Tex_Address_Mode> | <Tex_Border_Colour> | <Filtering> | \n"
153        "                             <Max_Anisotropy> | <MipMap_Bias> | <Colour_Op_Ex> | <Colour_Op_Multipass_Fallback> | <Colour_Op> | \n"
154        "                             <Alpha_Op_Ex> | <Env_Map> | <Scroll_Anim> | <Scroll> | <Rotate_Anim> | <Rotate> | \n"
155                "                             <Scale> | <Wave_Xform> | <Transform> | <Binding_Type> | <Content_Type> \n"
156        "           <Texture_Alias> ::= 'texture_alias' <Label> \n"
157        "           <Texture> ::= 'texture' <Label> {<Texture_Properties>} \n"
158        "           <Texture_Properties> ::= '1d' | '2d' | '3d' | 'cubic' | 'unlimited' | 'alpha' | <#mipmap> \n"
159        "                                    | " + PixelUtil::getBNFExpressionOfPixelFormats(true) + " \n"
160        "           <Anim_Texture> ::= 'anim_texture' <Label> <Anim_Texture_Properties> \n"
161        "               <Anim_Texture_Properties> ::= <Numbered_Anim_Texture> | <Seperate_Anim_Textures> \n"
162        "               <Numbered_Anim_Texture> ::= <#frames> <#duration> \n"
163        "               <Seperate_Anim_Textures> ::= <anim_frame> {<anim_frame>} \n"
164        "                   <anim_frame> ::= (?!<TUS_Terminators>) <Label> [<Seperator>] \n"
165        "           <TUS_Terminators> ::= '}' | 'texture_alias' | 'texture' | 'anim_texture' | 'cubic_texture' | \n"
166        "                                 'tex_coord_set' | 'tex_address_mode' | 'tex_border_colour' | \n"
167        "                                 'filtering' | 'max_anisotropy' | 'mipmap_bias' | 'colour_op' | 'colour_op_ex' | \n"
168        "                                 'colour_op_multipass_fallback' | 'alpha_op_ex' | 'env_map' | \n"
169        "                                 'scroll' | 'rotate' | 'scale' | 'wave_xform' | 'transform' | 'binding_type' \n"
170        "           <Cubic_Texture> ::= 'cubic_texture' <Label> <Cubic_Texture_Options> \n"
171        "               <Cubic_Texture_Options> ::= 'combineduvw' | 'separateuv' | <Cubic_Seperate> \n"
172        "               <Cubic_Seperate> ::= <Label> [<Seperator>] <Label> [<Seperator>] <Label> \n"
173        "                                    [<Seperator>] <Label> [<Seperator>] <Label> 'separateuv' \n"
174        "           <Tex_Coord_Set> ::= 'tex_coord_set' <#set_num> \n"
175        "           <Tex_Address_Mode> ::= 'tex_address_mode' <UVW_Mode> [<UVW_Mode>] [<UVW_Mode>] \n"
176        "               <UVW_Mode> ::= 'wrap' | 'clamp' | 'mirror' | 'border' \n"
177        "           <Tex_Border_Colour> ::= 'tex_border_colour' <Colour_Params> \n"
178        "           <Filtering> ::= 'filtering' <Filtering_Options>"
179        "               <Filtering_Options> ::= <Simple_Filter> | <Complex_Filter> \n"
180        "                 <Simple_Filter> ::= 'bilinear' | 'trilinear' | 'anisotropic' | 'none' \n"
181        "                 <Complex_Filter> ::= <MinMagFilter> <MinMagFilter> <MipFilter> \n"
182        "                   <MinMagFilter> ::= 'linear' | 'point' | 'anisotropic' \n"
183        "                   <MipFilter> ::= 'linear' | 'point' | 'none' \n"
184        "           <Max_Anisotropy> ::= 'max_anisotropy' <#val> \n"
185        "           <MipMap_Bias> ::= 'mipmap_bias' <#val> \n"
186        "           <Colour_Op> ::= 'colour_op' <Colour_Op_Options> \n"
187        "               <Colour_Op_Options> ::= <Base_Blend> | 'replace' \n"
188        "           <Colour_Op_Ex> ::= 'colour_op_ex' <Combine_Operation> <Source_Option> <Source_Option> {<#val>} \n"
189        "               <Combine_Operation> ::= 'source1' | 'source2' | 'modulate_x2' | 'modulate_x4' | \n"
190        "                                       'modulate' | 'add_signed' | 'add_smooth' | 'add' | \n"
191        "                                       'subtract' | 'blend_diffuse_alpha' | 'blend_texture_alpha' | \n"
192        "                                       'blend_current_alpha' | 'blend_manual' | 'dotproduct' | \n"
193        "                                       'blend_diffuse_colour' \n"
194        "               <Source_Option> ::= 'src_current' | 'src_texture' | 'src_diffuse' | \n"
195        "                                   'src_specular' | 'src_manual' \n"
196        "           <Colour_Op_Multipass_Fallback> ::= 'colour_op_multipass_fallback' <Blend_Factor> <Blend_Factor> \n"
197        "           <Alpha_Op_Ex> ::= 'alpha_op_ex' <Combine_Operation> <Source_Option> <Source_Option> {<#val>} \n"
198        "           <Env_Map> ::= 'env_map' <Env_Map_Option> \n"
199        "               <Env_Map_Option> ::= 'spherical' | 'planar' | 'cubic_reflection' | 'cubic_normal' | 'off' \n"
200        "           <Scroll> ::= 'scroll' <#x> <#y> \n"
201        "           <Scroll_Anim> ::= 'scroll_anim' <#xspeed> <#yspeed> \n"
202        "           <Rotate> ::= 'rotate' <#angle> \n"
203        "           <Rotate_Anim> ::= 'rotate_anim' <#revs_per_second> \n"
204        "           <Scale> ::= 'scale' <#x> <#y> \n"
205        "           <Wave_Xform> ::= 'wave_xform' <Xform_Type> <Wave_Type> <#base> <#frequency> <#phase> <#amplitude> \n"
206        "               <Xform_Type> ::= 'scroll_x' | 'scroll_y' | 'rotate' | 'scale_x' | 'scale_y' \n"
207        "               <Wave_Type> ::= 'sine' | 'triangle' | 'square' | 'sawtooth' | 'inverse_sawtooth' \n"
208        "           <Transform> ::= 'transform' <#m00> <#m01> <#m02> <#m03> <#m10> <#m11> <#m12> <#m13> <#m20> <#m21> <#m22> <#m23> \n"
209        "                           <#m30> <#m31> <#m32> <#m33> \n"
210        "           <Binding_Type> ::= 'binding_type' <Program_Type_Options> \n"
211        "           <Program_Type_Options> ::= 'vertex' | 'fragment' \n"
212                "                       <Content_Type> ::= 'content_type' <Content_Type_Options> \n"
213                "           <Content_Type_Options> ::= 'named' | 'shadow' \n"
214        // GPU Programs
215        " \n"
216        "<Vertex_Program> ::= 'vertex_program' <Label> [<Seperator>] <Label> '{' {<Vertex_Program_Option>} '}' \n"
217        "   <Vertex_Program_Option> ::= <Vertex_Program_Animation> | <Vertex_Texture_Fetch> | <GPU_Program_Options> \n"
218        "   <Vertex_Program_Animation> ::= <Skeletal_Animation> | <Morph_Animation> | <Pose_Animation> \n"
219        "       <Skeletal_Animation> ::= 'includes_skeletal_animation' <True_False> \n"
220        "       <Morph_Animation> ::= 'includes_morph_animation' <True_False> \n"
221        "       <Pose_Animation> ::= 'includes_pose_animation' <#val> \n"
222        "       <Vertex_Texture_Fetch> ::= 'uses_vertex_texture_fetch' <True_False> \n"
223        "<Fragment_Program> ::= 'fragment_program' <Label> [<Seperator>] <Label> '{' {<GPU_Program_Options>}'}' \n"
224        // do custom parameters last since it will consume everything on the line in the source
225        "   <GPU_Program_Options> ::= <Program_Source> | <Syntax> | <Default_Params> | <Custom_Parameter> \n"
226        "       <Program_Source> ::= 'source' <Label> \n"
227        "       <Syntax> ::= 'syntax' <Label> \n"
228        "       <Default_Params> ::= 'default_params' '{' {<GPUParams_Option>} '}' \n"
229        "       <Custom_Parameter> ::= 'custom_parameter' : <Unquoted_Label> [<Seperator>] <Spaced_Label> \n"
230
231        "   <GPU_Program_Ref> ::= <GPU_Program_Ref_Type> [<Flex_Label>] '{' {<GPUParams_Option>} '}' \n"
232        "       <GPU_Program_Ref_Type> ::= 'vertex_program_ref' | 'fragment_program_ref' | \n"
233        "                                  'shadow_caster_vertex_program_ref' | \n"
234        "                                  'shadow_receiver_vertex_program_ref' | \n"
235        "                                  'shadow_receiver_fragment_program_ref' \n"
236
237        "   <GPUParams_Option> ::= <Param_Named_Auto> | <Param_Named> | <Param_Indexed_Auto> | <Param_Indexed> \n"
238        "       <Param_Named_Auto> ::= 'param_named_auto' <Unquoted_Label> [<Seperator>] <Unquoted_Label> [<#val>] \n"
239        "       <Param_Named> ::= 'param_named' <Unquoted_Label> [<Seperator>] <Param_Value_Option> \n"
240        "       <Param_Indexed_Auto> ::= 'param_indexed_auto' <#index> <Unquoted_Label> [<#val>] \n"
241        "       <Param_Indexed> ::= 'param_indexed' <#index> <Param_Value_Option> \n"
242        "       <Param_Value_Option> ::= <Unquoted_Label> {<#val>} \n"
243
244        // common rules
245        "<On_Off> ::= 'on' | 'off' \n"
246        "<True_False> ::= 'true' | 'false' \n"
247        "<Colour_Params> ::= <#red> <#green> <#blue> [<#alpha>] \n"
248        "<Seperator> ::= -' ' \n"
249
250        "<Labels_1_N> ::= <Label> [<Seperator>] {<More_Labels>} \n"
251        "<More_Labels> ::=  <Label> [<Seperator>] \n"
252                "<Label> ::= <Quoted_Label> | <Unquoted_Label> \n"
253                "<Flex_Label> ::= <Quoted_Label> | <Spaced_Label> \n"
254                "<Quoted_Label> ::= -'\"' <Spaced_Label> -'\"' \n"
255                "<Spaced_Label> ::= <Spaced_Label_Illegals> {<Spaced_Label_Illegals>} \n"
256        "<Unquoted_Label> ::= <Unquoted_Label_Illegals> {<Unquoted_Label_Illegals>} \n"
257                "<Spaced_Label_Illegals> ::= (!,:\n\r\t{}\") \n"
258                "<Unquoted_Label_Illegals> ::= (! :\n\r\t{}\") \n"
259
260        ;
261
262        return materialScript_BNF;
263    }
264    //-----------------------------------------------------------------------
265    const String& MaterialScriptCompiler::getClientGrammerName(void) const
266    {
267        static const String grammerName = "Material Script";
268        return grammerName;
269    }
270    //-----------------------------------------------------------------------
271    MaterialScriptCompiler::MaterialScriptCompiler(void)
272    {
273        // set default group resource name
274        mScriptContext.groupName = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME;
275    }
276    //-----------------------------------------------------------------------
277    MaterialScriptCompiler::~MaterialScriptCompiler(void)
278    {
279
280    }
281
282    //-----------------------------------------------------------------------
283    void MaterialScriptCompiler::parseScript(DataStreamPtr& stream, const String& groupName, const bool allowOverride)
284    {
285        mScriptContext.groupName = groupName;
286        mScriptContext.allowOverride = allowOverride;
287        Compiler2Pass::compile(stream->getAsString(),  stream->getName());
288    }
289
290    //-----------------------------------------------------------------------
291    void MaterialScriptCompiler::setupTokenDefinitions(void)
292    {
293        addLexemeAction("{", &MaterialScriptCompiler::parseOpenBrace);
294        addLexemeAction("}", &MaterialScriptCompiler::parseCloseBrace);
295        addLexemeTokenAction("vertex_program", ID_VERTEX_PROGRAM, &MaterialScriptCompiler::parseGPUProgram);
296            addLexemeAction("includes_skeletal_animation", &MaterialScriptCompiler::parseProgramSkeletalAnimation);
297            addLexemeAction("includes_morph_animation", &MaterialScriptCompiler::parseProgramMorphAnimation);
298            addLexemeAction("includes_pose_animation", &MaterialScriptCompiler::parseProgramPoseAnimation);
299            addLexemeAction("uses_vertex_texture_fetch", &MaterialScriptCompiler::parseProgramVertexTextureFetch);
300
301        addLexemeTokenAction("fragment_program", ID_FRAGMENT_PROGRAM, &MaterialScriptCompiler::parseGPUProgram);
302
303            addLexemeAction("source", &MaterialScriptCompiler::parseProgramSource);
304            addLexemeAction("syntax", &MaterialScriptCompiler::parseProgramSyntax);
305            addLexemeAction("default_params", &MaterialScriptCompiler::parseDefaultParams);
306            addLexemeAction("param_indexed", &MaterialScriptCompiler::parseParamIndexed);
307            addLexemeAction("param_indexed_auto", &MaterialScriptCompiler::parseParamIndexedAuto);
308            addLexemeAction("param_named", &MaterialScriptCompiler::parseParamNamed);
309            addLexemeAction("param_named_auto", &MaterialScriptCompiler::parseParamNamedAuto);
310            addLexemeAction("custom_parameter", &MaterialScriptCompiler::parseProgramCustomParameter);
311
312        addLexemeAction("material", &MaterialScriptCompiler::parseMaterial);
313            addLexemeToken(":", ID_CLONE);
314            addLexemeAction("lod_distances", &MaterialScriptCompiler::parseLodDistances);
315            addLexemeAction("receive_shadows", &MaterialScriptCompiler::parseReceiveShadows);
316            addLexemeAction("transparency_casts_shadows", &MaterialScriptCompiler::parseTransparencyCastsShadows);
317            addLexemeAction("set_texture_alias", &MaterialScriptCompiler::parseSetTextureAlias);
318
319        // Technique section
320        addLexemeAction("technique", &MaterialScriptCompiler::parseTechnique);
321            addLexemeAction("scheme", &MaterialScriptCompiler::parseScheme);
322            addLexemeAction("lod_index", &MaterialScriptCompiler::parseLodIndex);
323
324
325        // Pass section
326        addLexemeAction("pass", &MaterialScriptCompiler::parsePass);
327            addLexemeAction("ambient", &MaterialScriptCompiler::parseAmbient);
328            addLexemeAction("diffuse", &MaterialScriptCompiler::parseDiffuse);
329            addLexemeAction("specular", &MaterialScriptCompiler::parseSpecular);
330            addLexemeAction("emissive", &MaterialScriptCompiler::parseEmissive);
331            addLexemeToken("vertexcolour", ID_VERTEXCOLOUR);
332
333            addLexemeAction("scene_blend", &MaterialScriptCompiler::parseSceneBlend);
334                addLexemeToken("colour_blend", ID_COLOUR_BLEND);
335                addLexemeToken("dest_colour", ID_DEST_COLOUR);
336                addLexemeToken("src_colour", ID_SRC_COLOUR);
337                addLexemeToken("one_minus_dest_colour", ID_ONE_MINUS_DEST_COLOUR);
338                addLexemeToken("one_minus_src_colour", ID_ONE_MINUS_SRC_COLOUR);
339                addLexemeToken("dest_alpha", ID_DEST_ALPHA);
340                addLexemeToken("src_alpha", ID_SRC_ALPHA);
341                addLexemeToken("one_minus_dest_alpha", ID_ONE_MINUS_DEST_ALPHA);
342                addLexemeToken("one_minus_src_alpha", ID_ONE_MINUS_SRC_ALPHA);
343
344            addLexemeAction("depth_check", &MaterialScriptCompiler::parseDepthCheck);
345            addLexemeAction("depth_write", &MaterialScriptCompiler::parseDepthWrite);
346            addLexemeAction("depth_func", &MaterialScriptCompiler::parseDepthFunc);
347            addLexemeAction("depth_bias", &MaterialScriptCompiler::parseDepthBias);
348                addLexemeToken("always_fail", ID_ALWAYS_FAIL);
349                addLexemeToken("always_pass", ID_ALWAYS_PASS);
350                addLexemeToken("less_equal", ID_LESS_EQUAL);
351                addLexemeToken("less", ID_LESS);
352                addLexemeToken("equal", ID_EQUAL);
353                addLexemeToken("not_equal", ID_NOT_EQUAL);
354                addLexemeToken("greater_equal", ID_GREATER_EQUAL);
355                addLexemeToken("greater", ID_GREATER);
356            addLexemeAction("alpha_rejection", &MaterialScriptCompiler::parseAlphaRejection);
357            addLexemeAction("cull_hardware", &MaterialScriptCompiler::parseCullHardware);
358                addLexemeToken("clockwise", ID_CLOCKWISE);
359                addLexemeToken("anticlockwise", ID_ANTICLOCKWISE);
360            addLexemeAction("cull_software", &MaterialScriptCompiler::parseCullSoftware);
361                addLexemeToken("back", ID_CULL_BACK);
362                addLexemeToken("front", ID_CULL_FRONT);
363            addLexemeAction("lighting", &MaterialScriptCompiler::parseLighting);
364            addLexemeAction("shading", &MaterialScriptCompiler::parseShading);
365                addLexemeTokenAction("flat", ID_FLAT);
366                addLexemeToken("gouraud", ID_GOURAUD);
367                addLexemeToken("phong", ID_PHONG);
368            addLexemeAction("polygon_mode", &MaterialScriptCompiler::parsePolygonMode);
369                addLexemeTokenAction("solid", ID_SOLID);
370                addLexemeToken("wireframe", ID_WIREFRAME);
371                addLexemeToken("points", ID_POINTS);
372            addLexemeAction("fog_override", &MaterialScriptCompiler::parseFogOverride);
373                addLexemeToken("exp", ID_EXP);
374                addLexemeToken("exp2", ID_EXP2);
375            addLexemeAction("colour_write", &MaterialScriptCompiler::parseColourWrite);
376            addLexemeAction("max_lights", &MaterialScriptCompiler::parseMaxLights);
377                        addLexemeAction("start_light", &MaterialScriptCompiler::parseStartLight);
378            addLexemeAction("iteration", &MaterialScriptCompiler::parseIteration);
379                addLexemeToken("once", ID_ONCE);
380                addLexemeToken("once_per_light", ID_ONCE_PER_LIGHT);
381                addLexemeToken("per_light", ID_PER_LIGHT);
382                                addLexemeToken("per_n_lights", ID_PER_N_LIGHTS);
383                addLexemeToken("directional", ID_DIRECTIONAL);
384                addLexemeToken("spot", ID_SPOT);
385            addLexemeAction("point_size", &MaterialScriptCompiler::parsePointSize);
386            addLexemeAction("point_sprites", &MaterialScriptCompiler::parsePointSprites);
387            addLexemeAction("point_size_attenuation",  &MaterialScriptCompiler::parsePointSizeAttenuation);
388            addLexemeAction("point_size_min", &MaterialScriptCompiler::parsePointSizeMin);
389            addLexemeAction("point_size_max", &MaterialScriptCompiler::parsePointSizeMax);
390
391        // Texture Unit section
392        addLexemeAction("texture_unit", &MaterialScriptCompiler::parseTextureUnit);
393        addLexemeAction("texture_alias", &MaterialScriptCompiler::parseTextureAlias);
394        addLexemeAction("texture", &MaterialScriptCompiler::parseTexture);
395            addLexemeToken("1d", ID_1D);
396            addLexemeToken("2d", ID_2D);
397            addLexemeToken("3d", ID_3D);
398            addLexemeToken("cubic", ID_CUBIC);
399            addLexemeToken("unlimited", ID_UNLIMITED);
400            addLexemeToken("alpha", ID_ALPHA);
401        addLexemeAction("anim_texture", &MaterialScriptCompiler::parseAnimTexture);
402        addLexemeAction("cubic_texture", &MaterialScriptCompiler::parseCubicTexture);
403            addLexemeToken("separateuv", ID_SEPARATE_UV);
404            addLexemeToken("combineduvw", ID_COMBINED_UVW);
405        addLexemeAction("tex_coord_set", &MaterialScriptCompiler::parseTexCoord);
406        addLexemeAction("tex_address_mode", &MaterialScriptCompiler::parseTexAddressMode);
407            addLexemeToken("wrap", ID_WRAP);
408            addLexemeToken("clamp", ID_CLAMP);
409            addLexemeToken("mirror", ID_MIRROR);
410            addLexemeToken("border", ID_BORDER);
411        addLexemeAction("tex_border_colour", &MaterialScriptCompiler::parseTexBorderColour);
412        addLexemeAction("filtering", &MaterialScriptCompiler::parseFiltering);
413            addLexemeToken("bilinear", ID_BILINEAR);
414            addLexemeToken("trilinear", ID_TRILINEAR);
415            addLexemeToken("anisotropic", ID_ANISOTROPIC);
416        addLexemeAction("max_anisotropy", &MaterialScriptCompiler::parseMaxAnisotropy);
417        addLexemeAction("mipmap_bias", &MaterialScriptCompiler::parseMipMapBias);
418        addLexemeAction("colour_op", &MaterialScriptCompiler::parseColourOp);
419            addLexemeToken("replace", ID_REPLACE);
420        addLexemeAction("colour_op_ex", &MaterialScriptCompiler::parseColourOpEx);
421            addLexemeToken("source1", ID_SOURCE1);
422            addLexemeToken("source2", ID_SOURCE2);
423            addLexemeToken("modulate_x2", ID_MODULATE_X2);
424            addLexemeToken("modulate_x4", ID_MODULATE_X4);
425            addLexemeToken("add_signed", ID_ADD_SIGNED);
426            addLexemeToken("add_smooth", ID_ADD_SMOOTH);
427            addLexemeToken("subtract", ID_SUBTRACT);
428            addLexemeToken("blend_diffuse_colour", ID_BLEND_DIFFUSE_COLOUR);
429            addLexemeToken("blend_diffuse_alpha", ID_BLEND_DIFFUSE_ALPHA);
430            addLexemeToken("blend_texture_alpha", ID_BLEND_TEXTURE_ALPHA);
431            addLexemeToken("blend_current_alpha", ID_BLEND_CURRENT_ALPHA);
432            addLexemeToken("blend_manual", ID_BLEND_MANUAL);
433            addLexemeToken("dotproduct", ID_DOTPRODUCT);
434            addLexemeToken("src_current", ID_SRC_CURRENT);
435            addLexemeToken("src_texture", ID_SRC_TEXTURE);
436            addLexemeToken("src_diffuse", ID_SRC_DIFFUSE);
437            addLexemeToken("src_specular", ID_SRC_SPECULAR);
438            addLexemeToken("src_manual", ID_SRC_MANUAL);
439        addLexemeAction("colour_op_multipass_fallback", &MaterialScriptCompiler::parseColourOpMultipassFallback);
440        addLexemeAction("alpha_op_ex", &MaterialScriptCompiler::parseAlphaOpEx);
441        addLexemeAction("env_map", &MaterialScriptCompiler::parseEnvMap);
442            addLexemeToken("spherical", ID_SPHERICAL);
443            addLexemeToken("planar", ID_PLANAR);
444            addLexemeToken("cubic_reflection", ID_CUBIC_REFLECTION);
445            addLexemeToken("cubic_normal", ID_CUBIC_NORMAL);
446        addLexemeAction("scroll", &MaterialScriptCompiler::parseScroll);
447        addLexemeAction("scroll_anim", &MaterialScriptCompiler::parseScrollAnim);
448        addLexemeTokenAction("rotate", ID_ROTATE, &MaterialScriptCompiler::parseRotate);
449        addLexemeAction("rotate_anim", &MaterialScriptCompiler::parseRotateAnim);
450        addLexemeAction("scale", &MaterialScriptCompiler::parseScale);
451        addLexemeAction("wave_xform", &MaterialScriptCompiler::parseWaveXform);
452            addLexemeToken("scroll_x", ID_SCROLL_X);
453            addLexemeToken("scroll_y", ID_SCROLL_Y);
454            addLexemeToken("scale_x", ID_SCALE_X);
455            addLexemeToken("scale_y", ID_SCALE_Y);
456            addLexemeToken("sine", ID_SINE);
457            addLexemeToken("triangle", ID_TRIANGLE);
458            addLexemeToken("square", ID_SQUARE);
459            addLexemeToken("sawtooth", ID_SAWTOOTH);
460            addLexemeToken("inverse_sawtooth", ID_INVERSE_SAWTOOTH);
461        addLexemeAction("transform", &MaterialScriptCompiler::parseTransform);
462        addLexemeAction("binding_type", &MaterialScriptCompiler::parseBindingType);
463                addLexemeAction("content_type", &MaterialScriptCompiler::parseContentType);
464                        addLexemeToken("named", ID_NAMED);
465                        addLexemeToken("shadow", ID_SHADOW);
466        // GPU program reference
467        addLexemeAction("vertex_program_ref", &MaterialScriptCompiler::parseVertexProgramRef);
468        addLexemeAction("fragment_program_ref", &MaterialScriptCompiler::parseFragmentProgramRef);
469        addLexemeAction("shadow_caster_vertex_program_ref", &MaterialScriptCompiler::parseShadowCasterVertexProgramRef);
470        addLexemeAction("shadow_receiver_vertex_program_ref", &MaterialScriptCompiler::parseShadowReceiverVertexProgramRef);
471        addLexemeAction("shadow_receiver_fragment_program_ref", &MaterialScriptCompiler::parseShadowReceiverFragmentProgramRef);
472
473        // common section
474        addLexemeToken("on", ID_ON);
475        addLexemeToken("off", ID_OFF);
476        addLexemeToken("true", ID_TRUE);
477        addLexemeToken("false", ID_FALSE);
478        addLexemeToken("none", ID_NONE);
479        addLexemeToken("point", ID_POINT);
480        addLexemeToken("linear", ID_LINEAR);
481        addLexemeToken("add", ID_ADD);
482        addLexemeToken("modulate", ID_MODULATE);
483        addLexemeToken("alpha_blend", ID_ALPHA_BLEND);
484        addLexemeToken("one", ID_ONE);
485        addLexemeToken("zero", ID_ZERO);
486        addLexemeToken("vertex", ID_VERTEX);
487        addLexemeToken("fragment", ID_FRAGMENT);
488
489
490    }
491
492    //-----------------------------------------------------------------------
493    void MaterialScriptCompiler::addLexemeTokenAction(const String& lexeme, const size_t token, const MSC_Action action)
494    {
495        size_t newTokenID = addLexemeToken(lexeme, token, action != 0);
496        if (action)
497            mTokenActionMap[newTokenID] = action;
498    }
499
500    //-----------------------------------------------------------------------
501    void MaterialScriptCompiler::executeTokenAction(const size_t tokenID)
502    {
503        TokenActionIterator action = mTokenActionMap.find(tokenID);
504
505        if (action == mTokenActionMap.end())
506        {
507            // BAD command. BAD!
508            logParseError("Unrecognised Material Script command action");
509            return;
510        }
511        else
512        {
513            try
514            {
515                (this->*action->second)();
516            }
517            catch (Exception& ogreException)
518            {
519                if (ogreException.getNumber() == Exception::ERR_DUPLICATE_ITEM)
520                {
521                    // an exception for duplicate item was thrown.
522                    // this means that either a material name or gpu program name conflict exists.
523                    // Since it wasn't trapped at a lower level then re-throw in order to terminate parsing
524                    logParseError("Duplicate Item Exception trapped. Parsing terminated for this material script.");
525                    throw;
526                }
527                else
528                {
529                    // an unknown token found or BNF Grammer rule was not successful
530                    // in finding a valid terminal token to complete the rule expression.
531                    // don't relog the exception but do log the material script being parsed and the line number
532                    logParseError("Exception trapped, attempting to continue parsing");
533                }
534            }
535        }
536    }
537
538    //-----------------------------------------------------------------------
539    void MaterialScriptCompiler::logParseError(const String& error)
540    {
541        // log material name only if filename not specified
542        if (mSourceName.empty() && !mScriptContext.material.isNull())
543        {
544            LogManager::getSingleton().logMessage(
545                "Error in material " + mScriptContext.material->getName() +
546                " : " + error);
547        }
548        else
549        {
550            if (!mScriptContext.material.isNull())
551            {
552                LogManager::getSingleton().logMessage(
553                    "Error in material " + mScriptContext.material->getName() +
554                    " at line " + StringConverter::toString(mCurrentLine) +
555                    " of " + mSourceName + ": " + error);
556            }
557            else
558            {
559                LogManager::getSingleton().logMessage(
560                    "Error at line " + StringConverter::toString(mCurrentLine) +
561                    " of " + mSourceName + ": " + error);
562            }
563        }
564    }
565    //-----------------------------------------------------------------------
566    void MaterialScriptCompiler::parseOpenBrace(void)
567    {
568
569    }
570    //-----------------------------------------------------------------------
571    void MaterialScriptCompiler::parseCloseBrace(void)
572    {
573        switch(mScriptContext.section)
574        {
575        case MSS_NONE:
576            logParseError("Unexpected terminating brace.");
577            break;
578        case MSS_MATERIAL:
579            // End of material
580            // if texture aliases were found, pass them to the material
581            // to update texture names used in Texture unit states
582            if (!mScriptContext.textureAliases.empty())
583            {
584                // request material to update all texture names in TUS's
585                // that use texture aliases in the list
586                mScriptContext.material->applyTextureAliases(mScriptContext.textureAliases);
587            }
588
589            mScriptContext.section = MSS_NONE;
590            mScriptContext.material.setNull();
591            mScriptContext.textureAliases.clear();
592            break;
593        case MSS_TECHNIQUE:
594            // End of technique
595            mScriptContext.section = MSS_MATERIAL;
596            mScriptContext.technique = NULL;
597                        mScriptContext.passLev = -1;    //Reset pass level (yes, the pass level)
598            break;
599        case MSS_PASS:
600            // End of pass
601            mScriptContext.section = MSS_TECHNIQUE;
602            mScriptContext.pass = NULL;
603                        mScriptContext.stateLev = -1;   //Reset state level (yes, the state level)
604            break;
605        case MSS_TEXTUREUNIT:
606            // End of texture unit
607            mScriptContext.section = MSS_PASS;
608            mScriptContext.textureUnit = NULL;
609            break;
610                case MSS_TEXTURESOURCE:
611                        //End texture source section
612                        //Finish creating texture here
613
614                        if(     ExternalTextureSourceManager::getSingleton().getCurrentPlugIn() != 0)
615            {
616                const String sMaterialName = mScriptContext.material->getName();
617                                ExternalTextureSourceManager::getSingleton().getCurrentPlugIn()->
618                                createDefinedTexture( sMaterialName, mScriptContext.groupName );
619            }
620                        //Revert back to texture unit
621                        mScriptContext.section = MSS_TEXTUREUNIT;
622                        break;
623        case MSS_PROGRAM_REF:
624            // End of program
625            mScriptContext.section = MSS_PASS;
626            mScriptContext.program.setNull();
627            break;
628        case MSS_PROGRAM:
629                        // Program definitions are slightly different, they are deferred
630                        // until all the information required is known
631            // End of program
632                        finishProgramDefinition();
633            mScriptContext.section = MSS_NONE;
634            delete mScriptContext.programDef;
635            mScriptContext.pendingDefaultParams.clear();
636            mScriptContext.programDef = NULL;
637            break;
638        case MSS_DEFAULT_PARAMETERS:
639            // End of default parameters
640            mScriptContext.section = MSS_PROGRAM;
641            break;
642        };
643    }
644    //-----------------------------------------------------------------------
645    void MaterialScriptCompiler::parseGPUProgram(void)
646    {
647        // update section
648        mScriptContext.section = MSS_PROGRAM;
649
650                // Create new program definition-in-progress
651                mScriptContext.programDef = new MaterialScriptProgramDefinition();
652                mScriptContext.programDef->progType =
653            (getCurrentTokenID() == ID_VERTEX_PROGRAM) ? GPT_VERTEX_PROGRAM : GPT_FRAGMENT_PROGRAM;
654        mScriptContext.programDef->supportsSkeletalAnimation = false;
655                mScriptContext.programDef->supportsMorphAnimation = false;
656                mScriptContext.programDef->supportsPoseAnimation = 0;
657        mScriptContext.programDef->usesVertexTextureFetch = false;
658
659                // Get name and language code
660                // Name, preserve case
661                mScriptContext.programDef->name = getNextTokenLabel();
662                // trim trailing white space only
663                StringUtil::trim(mScriptContext.programDef->name);
664                // language code
665                mScriptContext.programDef->language = getNextTokenLabel();
666                // make sure language is lower case
667                StringUtil::toLowerCase(mScriptContext.programDef->language);
668        }
669    //-----------------------------------------------------------------------
670    void MaterialScriptCompiler::parseProgramSource(void)
671    {
672        assert(mScriptContext.programDef);
673                mScriptContext.programDef->source = getNextTokenLabel();
674        }
675    //-----------------------------------------------------------------------
676    void MaterialScriptCompiler::parseProgramSyntax(void)
677    {
678        assert(mScriptContext.programDef);
679                mScriptContext.programDef->syntax = getNextTokenLabel();
680                // make sure language is lower case
681                StringUtil::toLowerCase(mScriptContext.programDef->syntax);
682        }
683    //-----------------------------------------------------------------------
684    void MaterialScriptCompiler::parseProgramSkeletalAnimation(void)
685    {
686        assert(mScriptContext.programDef);
687        mScriptContext.programDef->supportsSkeletalAnimation = testNextTokenID(ID_TRUE);
688    }
689        //-----------------------------------------------------------------------
690        void MaterialScriptCompiler::parseProgramMorphAnimation(void)
691        {
692        assert(mScriptContext.programDef);
693                mScriptContext.programDef->supportsMorphAnimation = testNextTokenID(ID_TRUE);
694        }
695        //-----------------------------------------------------------------------
696        void MaterialScriptCompiler::parseProgramPoseAnimation(void)
697        {
698        assert(mScriptContext.programDef);
699                mScriptContext.programDef->supportsPoseAnimation = static_cast<ushort>(getNextTokenValue());
700        }
701        //-----------------------------------------------------------------------
702        void MaterialScriptCompiler::parseProgramVertexTextureFetch(void)
703        {
704        assert(mScriptContext.programDef);
705                mScriptContext.programDef->usesVertexTextureFetch = testNextTokenID(ID_TRUE);
706        }
707    //-----------------------------------------------------------------------
708    void MaterialScriptCompiler::parseProgramCustomParameter(void)
709    {
710        assert(mScriptContext.programDef);
711
712        String command = getNextTokenLabel();
713                StringUtil::toLowerCase(command);
714        String params = getNextTokenLabel();
715        StringUtil::trim(params);
716                mScriptContext.programDef->customParameters.push_back(
717                        std::pair<String, String>(command, params));
718        }
719    //-----------------------------------------------------------------------
720    void MaterialScriptCompiler::parseDefaultParams(void)
721    {
722        mScriptContext.section = MSS_DEFAULT_PARAMETERS;
723    }
724        //-----------------------------------------------------------------------
725    void MaterialScriptCompiler::parseMaterial(void)
726    {
727        // check params for reference to parent material to copy from
728        // syntax: material name : parentMaterialName
729        MaterialPtr basematerial;
730
731        String materialName = getNextTokenLabel();
732        StringUtil::trim(materialName);
733        // Create a brand new material
734        const size_t paramCount = getRemainingTokensForAction();
735        if (paramCount == 2)
736        {
737            // this gets the ':' token which we need to consume to get to the label
738            getNextToken();
739            // if a second parameter exists then assume its the name of the base material
740            // that this new material should clone from
741            String parentName = getNextTokenLabel();
742            StringUtil::trim(parentName);
743            // make sure base material exists
744            basematerial = MaterialManager::getSingleton().getByName(parentName);
745            // if it doesn't exist then report error in log and just create a new material
746            if (basematerial.isNull())
747            {
748                logParseError("parent material: " + parentName + " not found for new material:"
749                    + materialName);
750            }
751        }
752
753        /* attempt to create the material.  If the material name is already in use
754           then MaterialManager throws an exception.
755        */
756        try
757        {
758            mScriptContext.material =
759                MaterialManager::getSingleton().create(materialName, mScriptContext.groupName);
760        }
761        catch (Exception& e)
762        {
763            bool exceptionHandled = false;
764
765            if (mScriptContext.allowOverride && (e.getNumber() == Exception::ERR_DUPLICATE_ITEM))
766            {
767                /* the material already exists log a warning message about it being modified by
768                 another material script
769                */
770                mScriptContext.material = MaterialManager::getSingleton().getByName(materialName);
771                if ( !mScriptContext.material.isNull())
772                {
773                    logParseError("material " + materialName +
774                        ", defined in " + mScriptContext.material->getOrigin() +
775                        ", was overwritten by current material being parsed with same name");
776                    // update group ownership since the original material might have been in a different resource group
777                    mScriptContext.material->changeGroupOwnership(mScriptContext.groupName);
778                    exceptionHandled = true;
779                }
780            }
781            if (!exceptionHandled)
782            {
783                logParseError("material " + materialName +
784                        " was previously defined and can not override.\n"
785                        "Material Manager script override was not enabled." );
786
787                throw;
788            }
789        }
790
791        if (!basematerial.isNull())
792        {
793            // copy parent material details to new or pre-existing material
794            basematerial->copyDetailsTo(mScriptContext.material);
795        }
796        else
797        {
798            // Remove pre-created technique from defaults or original material
799            mScriptContext.material->removeAllTechniques();
800        }
801
802                mScriptContext.material->_notifyOrigin(mSourceName);
803
804        // update section
805        mScriptContext.section = MSS_MATERIAL;
806        //Reset all levels since this is the start of the material definition
807        mScriptContext.passLev = -1;
808        mScriptContext.stateLev= -1;
809        mScriptContext.techLev = -1;
810
811    }
812    //-----------------------------------------------------------------------
813    // material Section Actions
814    //-----------------------------------------------------------------------
815    void MaterialScriptCompiler::parseLodDistances(void)
816    {
817        // iterate over the parameters and parse distances out of them
818        Material::LodDistanceList lodList;
819                while (getRemainingTokensForAction() > 0)
820                {
821            lodList.push_back(getNextTokenValue());
822        }
823
824        mScriptContext.material->setLodLevels(lodList);
825    }
826    //-----------------------------------------------------------------------
827    void MaterialScriptCompiler::parseReceiveShadows(void)
828    {
829        mScriptContext.material->setReceiveShadows(testNextTokenID(ID_ON));
830    }
831        //-----------------------------------------------------------------------
832    void MaterialScriptCompiler::parseTransparencyCastsShadows(void)
833        {
834                mScriptContext.material->setTransparencyCastsShadows(testNextTokenID(ID_ON));
835        }
836        //-----------------------------------------------------------------------
837    void MaterialScriptCompiler::parseSetTextureAlias(void)
838        {
839            const String& aliasName = getNextTokenLabel();
840            const String& textureName = getNextTokenLabel();
841                mScriptContext.textureAliases[aliasName] = textureName;
842        }
843        //-----------------------------------------------------------------------
844        // Technique section Actions
845        //-----------------------------------------------------------------------
846    void MaterialScriptCompiler::parseTechnique(void)
847    {
848        String techniqueName;
849        if (getRemainingTokensForAction() > 0)
850            techniqueName = getNextTokenLabel();
851        // if params is not empty then see if the technique name already exists
852        if (!techniqueName.empty() && (mScriptContext.material->getNumTechniques() > 0))
853        {
854            Technique* foundTechnique = mScriptContext.material->getTechnique(techniqueName);
855            if (foundTechnique)
856            {
857                // figure out technique index by iterating through technique container
858                // would be nice if each technique remembered its index
859                int count = 0;
860                Material::TechniqueIterator i = mScriptContext.material->getTechniqueIterator();
861                while(i.hasMoreElements())
862                {
863                    if (foundTechnique == i.peekNext())
864                        break;
865                    i.moveNext();
866                    ++count;
867                }
868
869                mScriptContext.techLev = count;
870            }
871            else
872            {
873                // name was not found so a new technique is needed
874                // position technique level to the end index
875                // a new technique will be created later on
876                mScriptContext.techLev = mScriptContext.material->getNumTechniques();
877            }
878
879        }
880        else
881        {
882            // no name was given in the script so a new technique will be created
883                    // Increase technique level depth
884                    ++mScriptContext.techLev;
885        }
886
887        // Create a new technique if it doesn't already exist
888        if (mScriptContext.material->getNumTechniques() > mScriptContext.techLev)
889        {
890            mScriptContext.technique = mScriptContext.material->getTechnique(mScriptContext.techLev);
891        }
892        else
893        {
894            mScriptContext.technique = mScriptContext.material->createTechnique();
895            if (!techniqueName.empty())
896                mScriptContext.technique->setName(techniqueName);
897        }
898
899        // update section
900        mScriptContext.section = MSS_TECHNIQUE;
901
902    }
903        //-----------------------------------------------------------------------
904        void MaterialScriptCompiler::parseScheme(void)
905        {
906            assert(mScriptContext.technique);
907                mScriptContext.technique->setSchemeName(getNextTokenLabel());
908        }
909    //-----------------------------------------------------------------------
910    void MaterialScriptCompiler::parseLodIndex(void)
911    {
912            assert(mScriptContext.technique);
913        mScriptContext.technique->setLodIndex(static_cast<uint>(getNextTokenValue()));
914    }
915        //-----------------------------------------------------------------------
916        // Pass Section Actions
917        //-----------------------------------------------------------------------
918    void MaterialScriptCompiler::parsePass(void)
919    {
920        String passName;
921        if (getRemainingTokensForAction() > 0)
922            passName = getNextTokenLabel();
923        // if params is not empty then see if the pass name already exists
924        if (!passName.empty() && (mScriptContext.technique->getNumPasses() > 0))
925        {
926            Pass* foundPass = mScriptContext.technique->getPass(passName);
927            if (foundPass)
928            {
929                mScriptContext.passLev = foundPass->getIndex();
930            }
931            else
932            {
933                // name was not found so a new pass is needed
934                // position pass level to the end index
935                // a new pass will be created later on
936                mScriptContext.passLev = mScriptContext.technique->getNumPasses();
937            }
938
939        }
940        else
941        {
942                    //Increase pass level depth
943                    ++mScriptContext.passLev;
944        }
945
946        if (mScriptContext.technique->getNumPasses() > mScriptContext.passLev)
947        {
948            mScriptContext.pass = mScriptContext.technique->getPass(mScriptContext.passLev);
949        }
950        else
951        {
952            // Create a new pass
953            mScriptContext.pass = mScriptContext.technique->createPass();
954            if (!passName.empty())
955                mScriptContext.pass->setName(passName);
956        }
957
958        // update section
959        mScriptContext.section = MSS_PASS;
960    }
961    //-----------------------------------------------------------------------
962    ColourValue MaterialScriptCompiler::_parseColourValue(void)
963    {
964        Real r = getNextTokenValue();
965        Real g = getNextTokenValue();
966        Real b = getNextTokenValue();
967        Real a = getRemainingTokensForAction() == 1 ? getNextTokenValue() : 1.0f;
968        return ColourValue(r, g, b, a);
969    }
970    //-----------------------------------------------------------------------
971    void MaterialScriptCompiler::parseAmbient(void)
972    {
973        // Must be 1, 3 or 4 parameters
974        assert(mScriptContext.pass);
975        const size_t paramCount = getRemainingTokensForAction();
976        if (paramCount == 1) {
977            if(testNextTokenID(ID_VERTEXCOLOUR))
978            {
979                mScriptContext.pass->setVertexColourTracking(mScriptContext.pass->getVertexColourTracking() | TVC_AMBIENT);
980            }
981            else
982            {
983                logParseError("Bad ambient attribute, single parameter flag must be 'vertexcolour'");
984            }
985        }
986        else if (paramCount == 3 || paramCount == 4)
987        {
988            mScriptContext.pass->setAmbient( _parseColourValue() );
989            mScriptContext.pass->setVertexColourTracking(mScriptContext.pass->getVertexColourTracking() & ~TVC_AMBIENT);
990        }
991        else
992        {
993            logParseError("Bad ambient attribute, wrong number of parameters (expected 1, 3 or 4)");
994        }
995    }
996   //-----------------------------------------------------------------------
997    void MaterialScriptCompiler::parseDiffuse(void)
998    {
999        // Must be 1, 3 or 4 parameters
1000        assert(mScriptContext.pass);
1001        const size_t paramCount = getRemainingTokensForAction();
1002        if (paramCount == 1) {
1003            if(testNextTokenID(ID_VERTEXCOLOUR))
1004            {
1005               mScriptContext.pass->setVertexColourTracking(mScriptContext.pass->getVertexColourTracking() | TVC_DIFFUSE);
1006            }
1007            else
1008            {
1009                logParseError("Bad diffuse attribute, single parameter flag must be 'vertexcolour'");
1010            }
1011        }
1012        else if (paramCount == 3 || paramCount == 4)
1013        {
1014            mScriptContext.pass->setDiffuse( _parseColourValue() );
1015            mScriptContext.pass->setVertexColourTracking(mScriptContext.pass->getVertexColourTracking() & ~TVC_DIFFUSE);
1016        }
1017        else
1018        {
1019            logParseError("Bad diffuse attribute, wrong number of parameters (expected 1, 3 or 4)");
1020        }
1021    }
1022    //-----------------------------------------------------------------------
1023    void MaterialScriptCompiler::parseSpecular(void)
1024    {
1025        // Must be 2, 4 or 5 parameters
1026        assert(mScriptContext.pass);
1027        const size_t paramCount = getRemainingTokensForAction();
1028        if(paramCount == 2)
1029        {
1030            if(getNextTokenID() == ID_VERTEXCOLOUR)
1031            {
1032                mScriptContext.pass->setVertexColourTracking(mScriptContext.pass->getVertexColourTracking() | TVC_SPECULAR);
1033                mScriptContext.pass->setShininess(getNextTokenValue());
1034            }
1035            else
1036            {
1037                logParseError("Bad specular attribute, double parameter statement must be 'vertexcolour <shininess>'");
1038            }
1039        }
1040        else if(paramCount == 4 || paramCount == 5)
1041        {
1042            Real r = getNextTokenValue();
1043            Real g = getNextTokenValue();
1044            Real b = getNextTokenValue();
1045            Real a = paramCount == 5 ? getNextTokenValue() : 1.0f;
1046            mScriptContext.pass->setSpecular(r, g, b, a);
1047            mScriptContext.pass->setVertexColourTracking(mScriptContext.pass->getVertexColourTracking() & ~TVC_SPECULAR);
1048            mScriptContext.pass->setShininess( getNextTokenValue() );
1049        }
1050        else
1051        {
1052            logParseError("Bad specular attribute, wrong number of parameters (expected 2, 4 or 5)");
1053        }
1054    }
1055    //-----------------------------------------------------------------------
1056    void MaterialScriptCompiler::parseEmissive(void)
1057    {
1058        // Must be 1, 3 or 4 parameters
1059        assert(mScriptContext.pass);
1060        const size_t paramCount = getRemainingTokensForAction();
1061        if (paramCount == 1) {
1062            if(testNextTokenID(ID_VERTEXCOLOUR))
1063            {
1064               mScriptContext.pass->setVertexColourTracking(mScriptContext.pass->getVertexColourTracking() | TVC_EMISSIVE);
1065            }
1066            else
1067            {
1068                logParseError("Bad emissive attribute, single parameter flag must be 'vertexcolour'");
1069            }
1070        }
1071        else if (paramCount == 3 || paramCount == 4)
1072        {
1073            mScriptContext.pass->setSelfIllumination( _parseColourValue() );
1074            mScriptContext.pass->setVertexColourTracking(mScriptContext.pass->getVertexColourTracking() & ~TVC_EMISSIVE);
1075        }
1076        else
1077        {
1078            logParseError("Bad emissive attribute, wrong number of parameters (expected 1, 3 or 4)");
1079        }
1080    }
1081    //-----------------------------------------------------------------------
1082    SceneBlendFactor MaterialScriptCompiler::convertBlendFactor(void)
1083    {
1084        switch(getNextTokenID())
1085        {
1086        case ID_ONE:
1087            return SBF_ONE;
1088        case ID_ZERO:
1089            return SBF_ZERO;
1090        case ID_DEST_COLOUR:
1091            return SBF_DEST_COLOUR;
1092        case ID_SRC_COLOUR:
1093            return SBF_SOURCE_COLOUR;
1094        case ID_ONE_MINUS_DEST_COLOUR:
1095            return SBF_ONE_MINUS_DEST_COLOUR;
1096        case ID_ONE_MINUS_SRC_COLOUR:
1097            return SBF_ONE_MINUS_SOURCE_COLOUR;
1098        case ID_DEST_ALPHA:
1099            return SBF_DEST_ALPHA;
1100        case ID_SRC_ALPHA:
1101            return SBF_SOURCE_ALPHA;
1102        case ID_ONE_MINUS_DEST_ALPHA:
1103            return SBF_ONE_MINUS_DEST_ALPHA;
1104        case ID_ONE_MINUS_SRC_ALPHA:
1105            return SBF_ONE_MINUS_SOURCE_ALPHA;
1106        default:
1107            return SBF_ONE;
1108            break;
1109        }
1110    }
1111    //-----------------------------------------------------------------------
1112    void MaterialScriptCompiler::parseSceneBlend(void)
1113    {
1114        assert(mScriptContext.pass);
1115        const size_t paramCount = getRemainingTokensForAction();
1116        // Should be 1 or 2 params
1117        if (paramCount == 1)
1118        {
1119            //simple blend types
1120            SceneBlendType sbtype = SBT_REPLACE;
1121            switch(getNextTokenID())
1122            {
1123            case ID_ADD:
1124                sbtype = SBT_ADD;
1125                break;
1126            case ID_MODULATE:
1127                sbtype = SBT_MODULATE;
1128                break;
1129                        case ID_COLOUR_BLEND:
1130                                sbtype = SBT_TRANSPARENT_COLOUR;
1131                                break;
1132            case ID_ALPHA_BLEND:
1133                sbtype = SBT_TRANSPARENT_ALPHA;
1134                break;
1135            default:
1136                break;
1137            }
1138            mScriptContext.pass->setSceneBlending(sbtype);
1139
1140        }
1141        else if (paramCount == 2)
1142        {
1143            const SceneBlendFactor src = convertBlendFactor();
1144            const SceneBlendFactor dest = convertBlendFactor();
1145            mScriptContext.pass->setSceneBlending(src,dest);
1146        }
1147        else
1148        {
1149            logParseError(
1150                "Bad scene_blend attribute, wrong number of parameters (expected 1 or 2)");
1151        }
1152    }
1153    //-----------------------------------------------------------------------
1154    void MaterialScriptCompiler::parseDepthCheck(void)
1155    {
1156        assert(mScriptContext.pass);
1157        mScriptContext.pass->setDepthCheckEnabled(testNextTokenID(ID_ON));
1158    }
1159    //-----------------------------------------------------------------------
1160    void MaterialScriptCompiler::parseDepthWrite(void)
1161    {
1162        assert(mScriptContext.pass);
1163        mScriptContext.pass->setDepthWriteEnabled(testNextTokenID(ID_ON));
1164    }
1165    //-----------------------------------------------------------------------
1166    CompareFunction MaterialScriptCompiler::convertCompareFunction(void)
1167    {
1168        switch (getNextTokenID())
1169        {
1170        case ID_ALWAYS_FAIL:
1171            return CMPF_ALWAYS_FAIL;
1172        case ID_ALWAYS_PASS:
1173            return CMPF_ALWAYS_PASS;
1174        case ID_LESS:
1175            return CMPF_LESS;
1176        case ID_LESS_EQUAL:
1177            return CMPF_LESS_EQUAL;
1178        case ID_EQUAL:
1179            return CMPF_EQUAL;
1180        case ID_NOT_EQUAL:
1181            return CMPF_NOT_EQUAL;
1182        case ID_GREATER_EQUAL:
1183            return CMPF_GREATER_EQUAL;
1184        case ID_GREATER:
1185            return CMPF_GREATER;
1186        default:
1187            return CMPF_LESS_EQUAL;
1188            break;
1189        }
1190    }
1191
1192    //-----------------------------------------------------------------------
1193    void MaterialScriptCompiler::parseDepthFunc(void)
1194    {
1195        assert(mScriptContext.pass);
1196        mScriptContext.pass->setDepthFunction(convertCompareFunction());
1197    }
1198    //-----------------------------------------------------------------------
1199    void MaterialScriptCompiler::parseDepthBias(void)
1200    {
1201        assert(mScriptContext.pass);
1202                float constantBias = static_cast<float>(getNextTokenValue());
1203                float slopeScaleBias = 0.0f;
1204                if (getRemainingTokensForAction() == 1)
1205                {
1206                        slopeScaleBias = static_cast<float>(getNextTokenValue());
1207                }
1208
1209        mScriptContext.pass->setDepthBias(constantBias, slopeScaleBias);
1210    }
1211    //-----------------------------------------------------------------------
1212    void MaterialScriptCompiler::parseAlphaRejection(void)
1213    {
1214        assert(mScriptContext.pass);
1215        const CompareFunction cmp = convertCompareFunction();
1216        mScriptContext.pass->setAlphaRejectSettings(cmp, static_cast<unsigned char>(getNextTokenValue()));
1217    }
1218    //-----------------------------------------------------------------------
1219    void MaterialScriptCompiler::parseCullHardware(void)
1220    {
1221        assert(mScriptContext.pass);
1222        switch (getNextTokenID())
1223        {
1224        case ID_NONE:
1225            mScriptContext.pass->setCullingMode(CULL_NONE);
1226            break;
1227        case ID_ANTICLOCKWISE:
1228            mScriptContext.pass->setCullingMode(CULL_ANTICLOCKWISE);
1229            break;
1230        case ID_CLOCKWISE:
1231            mScriptContext.pass->setCullingMode(CULL_CLOCKWISE);
1232            break;
1233        default:
1234            break;
1235        }
1236    }
1237    //-----------------------------------------------------------------------
1238    void MaterialScriptCompiler::parseCullSoftware(void)
1239    {
1240        assert(mScriptContext.pass);
1241        switch (getNextTokenID())
1242        {
1243        case ID_NONE:
1244            mScriptContext.pass->setManualCullingMode(MANUAL_CULL_NONE);
1245            break;
1246        case ID_CULL_BACK:
1247            mScriptContext.pass->setManualCullingMode(MANUAL_CULL_BACK);
1248            break;
1249        case ID_CULL_FRONT:
1250            mScriptContext.pass->setManualCullingMode(MANUAL_CULL_FRONT);
1251            break;
1252        default:
1253            break;
1254        }
1255    }
1256    //-----------------------------------------------------------------------
1257    void MaterialScriptCompiler::parseLighting(void)
1258    {
1259        assert(mScriptContext.pass);
1260        mScriptContext.pass->setLightingEnabled(testNextTokenID(ID_ON));
1261    }
1262    //-----------------------------------------------------------------------
1263    void MaterialScriptCompiler::parseShading(void)
1264    {
1265        assert(mScriptContext.pass);
1266        switch (getNextTokenID())
1267        {
1268        case ID_FLAT:
1269            mScriptContext.pass->setShadingMode(SO_FLAT);
1270            break;
1271        case ID_GOURAUD:
1272            mScriptContext.pass->setShadingMode(SO_GOURAUD);
1273            break;
1274        case ID_PHONG:
1275            mScriptContext.pass->setShadingMode(SO_PHONG);
1276            break;
1277        default:
1278            break;
1279        }
1280    }
1281    //-----------------------------------------------------------------------
1282    void MaterialScriptCompiler::parsePolygonMode(void)
1283    {
1284        assert(mScriptContext.pass);
1285        switch (getNextTokenID())
1286        {
1287        case ID_SOLID:
1288            mScriptContext.pass->setPolygonMode(PM_SOLID);
1289            break;
1290        case ID_WIREFRAME:
1291            mScriptContext.pass->setPolygonMode(PM_WIREFRAME);
1292            break;
1293        case ID_POINTS:
1294            mScriptContext.pass->setPolygonMode(PM_POINTS);
1295            break;
1296        default:
1297            break;
1298        }
1299    }
1300    //-----------------------------------------------------------------------
1301    void MaterialScriptCompiler::parseFogOverride(void)
1302    {
1303        assert(mScriptContext.pass);
1304        if (getNextTokenID() == ID_TRUE)
1305        {
1306            // if true, we need to see if they supplied all arguments, or just the 1... if just the one,
1307            // Assume they want to disable the default fog from effecting this material.
1308            const size_t paramCount = getRemainingTokensForAction();
1309            if( paramCount == 7 )
1310            {
1311                FogMode fogtype;
1312                switch (getNextTokenID())
1313                {
1314                case ID_LINEAR:
1315                    fogtype = FOG_LINEAR;
1316                case ID_EXP:
1317                    fogtype = FOG_EXP;
1318                case ID_EXP2:
1319                    fogtype = FOG_EXP2;
1320                case ID_NONE:
1321                default:
1322                    fogtype = FOG_NONE;
1323                    break;
1324                }
1325
1326                const Real red = getNextTokenValue();
1327                const Real green = getNextTokenValue();
1328                const Real blue = getNextTokenValue();
1329                const Real density = getNextTokenValue();
1330                const Real start = getNextTokenValue();
1331                const Real end = getNextTokenValue();
1332
1333                mScriptContext.pass->setFog(
1334                    true,
1335                    fogtype,
1336                    ColourValue(red, green, blue),
1337                    density, start, end
1338                    );
1339            }
1340            else
1341            {
1342                mScriptContext.pass->setFog(true);
1343            }
1344        }
1345        else
1346            mScriptContext.pass->setFog(false);
1347
1348    }
1349   //-----------------------------------------------------------------------
1350    void MaterialScriptCompiler::parseColourWrite(void)
1351    {
1352        assert(mScriptContext.pass);
1353        mScriptContext.pass->setColourWriteEnabled(testNextTokenID(ID_ON));
1354    }
1355     //-----------------------------------------------------------------------
1356    void MaterialScriptCompiler::parseMaxLights(void)
1357    {
1358        assert(mScriptContext.pass);
1359                mScriptContext.pass->setMaxSimultaneousLights(static_cast<int>(getNextTokenValue()));
1360    }
1361        void MaterialScriptCompiler::parseStartLight(void)
1362        {
1363                assert(mScriptContext.pass);
1364                mScriptContext.pass->setStartLight(static_cast<int>(getNextTokenValue()));
1365        }
1366    //-----------------------------------------------------------------------
1367    void MaterialScriptCompiler::parseIterationLightTypes(void)
1368    {
1369        assert(mScriptContext.pass);
1370        // Parse light type
1371        switch(getNextTokenID())
1372        {
1373        case ID_DIRECTIONAL:
1374            mScriptContext.pass->setIteratePerLight(true, true, Light::LT_DIRECTIONAL);
1375            break;
1376        case ID_POINT:
1377            mScriptContext.pass->setIteratePerLight(true, true, Light::LT_POINT);
1378            break;
1379        case ID_SPOT:
1380            mScriptContext.pass->setIteratePerLight(true, true, Light::LT_SPOTLIGHT);
1381            break;
1382        }
1383    }
1384    //-----------------------------------------------------------------------
1385    void MaterialScriptCompiler::parseIteration(void)
1386    {
1387        assert(mScriptContext.pass);
1388        // we could have more than one parameter
1389        /** combinations could be:
1390            iteration once
1391            iteration once_per_light [light type]
1392            iteration <number>
1393            iteration <number> [per_light] [light type]
1394                        iteration <number> [per_n_lights] <number> [light type]
1395        */
1396        if (testNextTokenID(ID_ONCE))
1397            mScriptContext.pass->setIteratePerLight(false, false);
1398        else if (testNextTokenID(ID_ONCE_PER_LIGHT))
1399        {
1400            getNextToken();
1401            if (getRemainingTokensForAction() == 1)
1402            {
1403                parseIterationLightTypes();
1404            }
1405            else
1406            {
1407                mScriptContext.pass->setIteratePerLight(true, false);
1408            }
1409
1410        }
1411        else // could be using form: <number> [per_light] [light type]
1412        {
1413            uint passIterationCount = static_cast<uint>(getNextTokenValue());
1414            if (passIterationCount > 0)
1415            {
1416                mScriptContext.pass->setPassIterationCount(passIterationCount);
1417                if (getRemainingTokensForAction() > 1)
1418                {
1419                    const size_t tokenID = getNextTokenID();
1420                    if (tokenID == ID_PER_LIGHT)
1421                    {
1422                        if (getRemainingTokensForAction() == 1)
1423                        {
1424                            parseIterationLightTypes();
1425                        }
1426                        else
1427                        {
1428                            mScriptContext.pass->setIteratePerLight(true, false);
1429                        }
1430                    }
1431                                        else if (tokenID == ID_PER_N_LIGHTS)
1432                                        {
1433                                                // Number of lights per iteration
1434                                                mScriptContext.pass->setLightCountPerIteration(static_cast<short unsigned int>(getNextTokenValue()));
1435                                                if (getRemainingTokensForAction() == 1)
1436                                                {
1437                                                        parseIterationLightTypes();
1438                                                }
1439                                                else
1440                                                {
1441                                                        mScriptContext.pass->setIteratePerLight(true, false);
1442                                                }
1443                                        }
1444                    else
1445                        logParseError(
1446                            "Bad iteration attribute, valid parameters are <number> [per_light|per_n_lights <num_lights>] [light type].");
1447                }
1448            }
1449        }
1450    }
1451    //-----------------------------------------------------------------------
1452    void MaterialScriptCompiler::parsePointSize(void)
1453    {
1454        mScriptContext.pass->setPointSize(getNextTokenValue());
1455    }
1456    //-----------------------------------------------------------------------
1457    void MaterialScriptCompiler::parsePointSprites(void)
1458        {
1459        assert(mScriptContext.pass);
1460        mScriptContext.pass->setPointSpritesEnabled(testNextTokenID(ID_ON));
1461        }
1462    //-----------------------------------------------------------------------
1463        void MaterialScriptCompiler::parsePointSizeMin(void)
1464        {
1465        assert(mScriptContext.pass);
1466        mScriptContext.pass->setPointMinSize(getNextTokenValue());
1467        }
1468    //-----------------------------------------------------------------------
1469    void MaterialScriptCompiler::parsePointSizeMax(void)
1470        {
1471        assert(mScriptContext.pass);
1472        mScriptContext.pass->setPointMaxSize(getNextTokenValue());
1473        }
1474    //-----------------------------------------------------------------------
1475    void MaterialScriptCompiler::parsePointSizeAttenuation(void)
1476        {
1477        assert(mScriptContext.pass);
1478        const size_t paramCount = getRemainingTokensForAction();
1479        if (paramCount != 1 && paramCount != 4)
1480        {
1481            logParseError("Bad point_size_attenuation attribute, wrong number of parameters (expected 1 or 4)");
1482            return;
1483        }
1484        switch (getNextTokenID())
1485        {
1486        case ID_ON:
1487                        if (paramCount == 4)
1488                        {
1489                                Real constant = getNextTokenValue();
1490                                Real linear = getNextTokenValue();
1491                                Real quadric = getNextTokenValue();
1492                    mScriptContext.pass->setPointAttenuation(true, constant, linear, quadric);
1493                        }
1494                        else
1495                        {
1496                                mScriptContext.pass->setPointAttenuation(true);
1497                        }
1498
1499            break;
1500        case ID_OFF:
1501            mScriptContext.pass->setPointAttenuation(false);
1502            break;
1503        default:
1504            logParseError("Bad point_size_attenuation attribute, valid values are 'on' or 'off'.");
1505        }
1506        }
1507    //-----------------------------------------------------------------------
1508    void MaterialScriptCompiler::parseTextureCustomParameter(void)
1509    {
1510                // This params object does not have the command stripped
1511                // Split only up to first delimiter, program deals with the rest
1512
1513                if (getRemainingTokensForAction() != 2)
1514                {
1515            logParseError("Invalid texture parameter entry; "
1516                                "there must be a parameter name and at least one value.");
1517                }
1518
1519                else if( ExternalTextureSourceManager::getSingleton().getCurrentPlugIn() != 0 )
1520        {
1521                        ////First is command, next could be a string with one or more values
1522            const String& param1 = getNextTokenLabel();
1523            const String& param2 = getNextTokenLabel();
1524                        ExternalTextureSourceManager::getSingleton().getCurrentPlugIn()->setParameter( param1, param2 );
1525        }
1526        }
1527    //-----------------------------------------------------------------------
1528    void MaterialScriptCompiler::parseTextureUnit(void)
1529    {
1530        String tusName;
1531        if (getRemainingTokensForAction() > 0)
1532            tusName = getNextTokenLabel();
1533        // if params is a name then see if that texture unit exists
1534        // if not then log the warning and just move on to the next TU from current
1535        if (!tusName.empty() && (mScriptContext.pass->getNumTextureUnitStates() > 0))
1536        {
1537            // specifying a TUS name in the script for a TU means that a specific TU is being requested
1538            // try to get the specific TU
1539            // if the index requested is not valid, just creat a new TU
1540            // find the TUS with name
1541            TextureUnitState * foundTUS = mScriptContext.pass->getTextureUnitState(tusName);
1542            if (foundTUS)
1543            {
1544                mScriptContext.stateLev = mScriptContext.pass->getTextureUnitStateIndex(foundTUS);
1545            }
1546            else
1547            {
1548                // name was not found so a new TUS is needed
1549                // position TUS level to the end index
1550                // a new TUS will be created later on
1551                mScriptContext.stateLev = static_cast<uint>(mScriptContext.pass->getNumTextureUnitStates());
1552            }
1553        }
1554        else
1555        {
1556                    //Increase Texture Unit State level depth
1557                    ++mScriptContext.stateLev;
1558        }
1559
1560        if (mScriptContext.pass->getNumTextureUnitStates() > static_cast<size_t>(mScriptContext.stateLev))
1561        {
1562            mScriptContext.textureUnit = mScriptContext.pass->getTextureUnitState(mScriptContext.stateLev);
1563        }
1564        else
1565        {
1566            // Create a new texture unit
1567            mScriptContext.textureUnit = mScriptContext.pass->createTextureUnitState();
1568            if (!tusName.empty())
1569                mScriptContext.textureUnit->setName(tusName);
1570        }
1571        // update section
1572        mScriptContext.section = MSS_TEXTUREUNIT;
1573    }
1574    //-----------------------------------------------------------------------
1575    void MaterialScriptCompiler::parseTextureAlias(void)
1576    {
1577        assert(mScriptContext.textureUnit);
1578        mScriptContext.textureUnit->setTextureNameAlias(getNextTokenLabel());
1579    }
1580    //-----------------------------------------------------------------------
1581    // Texture layer attributes
1582    void MaterialScriptCompiler::parseTexture(void)
1583    {
1584        assert(mScriptContext.textureUnit);
1585        TextureType tt = TEX_TYPE_2D;
1586                int mipmaps = MIP_DEFAULT; // When passed to TextureManager::load, this means default to default number of mipmaps
1587        bool isAlpha = false;
1588        PixelFormat desiredFormat = PF_UNKNOWN;
1589        const String& textureName = getNextTokenLabel();
1590
1591                while (getRemainingTokensForAction() > 0)
1592                {
1593            switch(getNextTokenID())
1594            {
1595            case ID_1D:
1596                tt = TEX_TYPE_1D;
1597                break;
1598            case ID_2D:
1599                tt = TEX_TYPE_2D;
1600                break;
1601            case ID_3D:
1602                tt = TEX_TYPE_3D;
1603                break;
1604            case ID_CUBIC:
1605                tt = TEX_TYPE_CUBE_MAP;
1606                break;
1607            case ID_UNLIMITED:
1608                                mipmaps = MIP_UNLIMITED;
1609                break;
1610            case ID_ALPHA:
1611                isAlpha = true;
1612                break;
1613            case _value_:
1614                replaceToken();
1615                mipmaps = static_cast<int>(getNextTokenValue());
1616                break;
1617            default:
1618                desiredFormat = PixelUtil::getFormatFromName(getCurrentTokenLexeme(), true);
1619                break;
1620            }
1621                }
1622        mScriptContext.textureUnit->setTextureName(textureName, tt);
1623        mScriptContext.textureUnit->setNumMipmaps(mipmaps);
1624        mScriptContext.textureUnit->setIsAlpha(isAlpha);
1625        mScriptContext.textureUnit->setDesiredFormat(desiredFormat);
1626    }
1627    //-----------------------------------------------------------------------
1628    void MaterialScriptCompiler::parseAnimTexture(void)
1629    {
1630        assert(mScriptContext.textureUnit);
1631        StringVector vecparams;
1632        // first token will be a label
1633        vecparams.push_back(getNextTokenLabel());
1634        // Determine which form it is
1635        // if next token is a value then no more labels to be processed
1636        if (testNextTokenID(_value_))
1637        {
1638            // First form using base name & number of frames
1639            unsigned int frameCount = static_cast<unsigned int>(getNextTokenValue());
1640            mScriptContext.textureUnit->setAnimatedTextureName(
1641                vecparams[0],
1642                frameCount,
1643                getNextTokenValue());
1644        }
1645        else
1646        {
1647            unsigned int numParams = 1;
1648            while (getRemainingTokensForAction() > 1)
1649            {
1650                vecparams.push_back(getNextTokenLabel());
1651                ++numParams;
1652            }
1653            // the last label should be a number so convert string label to number
1654            // Second form using individual names
1655            mScriptContext.textureUnit->setAnimatedTextureName(
1656                (String*)&vecparams[0],
1657                numParams,
1658                StringConverter::parseReal(getNextTokenLabel()));
1659        }
1660    }
1661    //-----------------------------------------------------------------------
1662    void MaterialScriptCompiler::parseCubicTexture(void)
1663    {
1664        assert(mScriptContext.textureUnit);
1665        StringVector vecparams;
1666
1667        // first token will be a label
1668        vecparams.push_back(getNextTokenLabel());
1669        // Determine which form it is
1670        // if next token is a label then 5 more labels to be processed
1671        if (testNextTokenID(_character_))
1672        {
1673            // get next five texture names
1674            for (int i = 0; i < 5; ++i)
1675                vecparams.push_back(getNextTokenLabel());
1676        }
1677
1678        bool useUVW = testNextTokenID(ID_COMBINED_UVW);
1679
1680        if (vecparams.size() == 1)
1681        {
1682            mScriptContext.textureUnit->setCubicTextureName(vecparams[0], useUVW);
1683        }
1684        else
1685        {
1686            // Second form using individual names
1687            // Can use vecparams[0] as array start point
1688            mScriptContext.textureUnit->setCubicTextureName((String*)&vecparams[0], useUVW);
1689        }
1690    }
1691    //-----------------------------------------------------------------------
1692    void MaterialScriptCompiler::parseTexCoord(void)
1693    {
1694        assert(mScriptContext.textureUnit);
1695        mScriptContext.textureUnit->setTextureCoordSet(
1696            static_cast<unsigned int>(getNextTokenValue()));
1697    }
1698    //-----------------------------------------------------------------------
1699        TextureUnitState::TextureAddressingMode MaterialScriptCompiler::convTexAddressMode(void)
1700        {
1701            switch (getNextTokenID())
1702            {
1703                case ID_WRAP:
1704                        return TextureUnitState::TAM_WRAP;
1705                case ID_CLAMP:
1706                        return TextureUnitState::TAM_CLAMP;
1707                case ID_MIRROR:
1708                        return TextureUnitState::TAM_MIRROR;
1709                case ID_BORDER:
1710                        return TextureUnitState::TAM_BORDER;
1711                default:
1712            return TextureUnitState::TAM_WRAP;
1713            }
1714        }
1715    //-----------------------------------------------------------------------
1716    void MaterialScriptCompiler::parseTexAddressMode(void)
1717    {
1718        assert(mScriptContext.textureUnit);
1719        const size_t paramCount = getRemainingTokensForAction();
1720
1721                if (paramCount == 1)
1722                {
1723                        // Single-parameter option
1724                        mScriptContext.textureUnit->setTextureAddressingMode(
1725                                convTexAddressMode());
1726                }
1727                else
1728                {
1729                        // 2-3 parameter option
1730                        TextureUnitState::UVWAddressingMode uvw;
1731                        uvw.u = convTexAddressMode();
1732                        uvw.v = convTexAddressMode();
1733
1734                        if (paramCount == 3)
1735                        {
1736                                // w
1737                                uvw.w = convTexAddressMode();
1738                        }
1739                        else
1740                        {
1741                                uvw.w = TextureUnitState::TAM_WRAP;
1742                        }
1743                        mScriptContext.textureUnit->setTextureAddressingMode(uvw);
1744                }
1745    }
1746    //-----------------------------------------------------------------------
1747    void MaterialScriptCompiler::parseTexBorderColour(void)
1748    {
1749        assert(mScriptContext.textureUnit);
1750        mScriptContext.textureUnit->setTextureBorderColour( _parseColourValue() );
1751    }
1752    //-----------------------------------------------------------------------
1753    FilterOptions MaterialScriptCompiler::convertFiltering()
1754    {
1755        switch (getNextTokenID())
1756        {
1757        case ID_NONE:
1758            return FO_NONE;
1759        case ID_POINT:
1760            return FO_POINT;
1761        case ID_LINEAR:
1762            return FO_LINEAR;
1763        case ID_ANISOTROPIC:
1764            return FO_ANISOTROPIC;
1765        default:
1766            return FO_POINT;
1767        }
1768    }
1769    //-----------------------------------------------------------------------
1770    void MaterialScriptCompiler::parseFiltering(void)
1771    {
1772        assert(mScriptContext.textureUnit);
1773        // Must be 1 or 3 parameters
1774        const size_t paramCount = getRemainingTokensForAction();
1775        if (paramCount == 1)
1776        {
1777            // Simple format
1778            switch (getNextTokenID())
1779            {
1780            case ID_BILINEAR:
1781                mScriptContext.textureUnit->setTextureFiltering(TFO_BILINEAR);
1782                break;
1783            case ID_TRILINEAR:
1784                mScriptContext.textureUnit->setTextureFiltering(TFO_TRILINEAR);
1785                break;
1786            case ID_ANISOTROPIC:
1787                mScriptContext.textureUnit->setTextureFiltering(TFO_ANISOTROPIC);
1788                break;
1789            case ID_NONE:
1790                mScriptContext.textureUnit->setTextureFiltering(TFO_NONE);
1791                break;
1792            }
1793        }
1794        else
1795        {
1796            // Complex format
1797            const FilterOptions minFO = convertFiltering();
1798            const FilterOptions magFO = convertFiltering();
1799            const FilterOptions mipFO = convertFiltering();
1800            mScriptContext.textureUnit->setTextureFiltering(minFO, magFO, mipFO);
1801        }
1802    }
1803    //-----------------------------------------------------------------------
1804    void MaterialScriptCompiler::parseMaxAnisotropy(void)
1805    {
1806        assert(mScriptContext.textureUnit);
1807        mScriptContext.textureUnit->setTextureAnisotropy(
1808            static_cast<unsigned int>(getNextTokenValue()));
1809    }
1810    //-----------------------------------------------------------------------
1811    void MaterialScriptCompiler::parseMipMapBias(void)
1812    {
1813        assert(mScriptContext.textureUnit);
1814        mScriptContext.textureUnit->setTextureMipmapBias(getNextTokenValue());
1815    }
1816    //-----------------------------------------------------------------------
1817    void MaterialScriptCompiler::parseColourOp(void)
1818    {
1819        assert(mScriptContext.textureUnit);
1820        switch (getNextTokenID())
1821        {
1822        case ID_REPLACE:
1823            mScriptContext.textureUnit->setColourOperation(LBO_REPLACE);
1824            break;
1825        case ID_ADD:
1826            mScriptContext.textureUnit->setColourOperation(LBO_ADD);
1827            break;
1828        case ID_MODULATE:
1829            mScriptContext.textureUnit->setColourOperation(LBO_MODULATE);
1830            break;
1831        case ID_ALPHA_BLEND:
1832            mScriptContext.textureUnit->setColourOperation(LBO_ALPHA_BLEND);
1833            break;
1834        }
1835    }
1836    //-----------------------------------------------------------------------
1837    LayerBlendOperationEx MaterialScriptCompiler::convertBlendOpEx(void)
1838    {
1839        switch(getNextTokenID())
1840        {
1841        case ID_SOURCE1:
1842            return LBX_SOURCE1;
1843        case ID_SOURCE2:
1844            return LBX_SOURCE2;
1845        case ID_MODULATE:
1846            return LBX_MODULATE;
1847        case ID_MODULATE_X2:
1848            return LBX_MODULATE_X2;
1849        case ID_MODULATE_X4:
1850            return LBX_MODULATE_X4;
1851        case ID_ADD:
1852            return LBX_ADD;
1853        case ID_ADD_SIGNED:
1854            return LBX_ADD_SIGNED;
1855        case ID_ADD_SMOOTH:
1856            return LBX_ADD_SMOOTH;
1857        case ID_SUBTRACT:
1858            return LBX_SUBTRACT;
1859        case ID_BLEND_DIFFUSE_COLOUR:
1860            return LBX_BLEND_DIFFUSE_COLOUR;
1861        case ID_BLEND_DIFFUSE_ALPHA:
1862            return LBX_BLEND_DIFFUSE_ALPHA;
1863        case ID_BLEND_TEXTURE_ALPHA:
1864            return LBX_BLEND_TEXTURE_ALPHA;
1865        case ID_BLEND_CURRENT_ALPHA:
1866            return LBX_BLEND_CURRENT_ALPHA;
1867        case ID_BLEND_MANUAL:
1868            return LBX_BLEND_MANUAL;
1869        case ID_DOTPRODUCT:
1870            return LBX_DOTPRODUCT;
1871        default:
1872            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Invalid blend function", "convertBlendOpEx");
1873        }
1874    }
1875    //-----------------------------------------------------------------------
1876    LayerBlendSource MaterialScriptCompiler::convertBlendSource(void)
1877    {
1878        switch(getNextTokenID())
1879        {
1880        case ID_SRC_CURRENT:
1881            return LBS_CURRENT;
1882        case ID_SRC_TEXTURE:
1883            return LBS_TEXTURE;
1884        case ID_SRC_DIFFUSE:
1885            return LBS_DIFFUSE;
1886        case ID_SRC_SPECULAR:
1887            return LBS_SPECULAR;
1888        case ID_SRC_MANUAL:
1889            return LBS_MANUAL;
1890        default:
1891            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Invalid blend source", "convertBlendSource");
1892        }
1893    }
1894    //-----------------------------------------------------------------------
1895    void MaterialScriptCompiler::parseColourOpEx(void)
1896    {
1897
1898        assert(mScriptContext.textureUnit);
1899
1900        LayerBlendOperationEx op;
1901        LayerBlendSource src1, src2;
1902        Real manual = 0.0;
1903        ColourValue colSrc1 = ColourValue::White;
1904        ColourValue colSrc2 = ColourValue::White;
1905
1906        try {
1907            op = convertBlendOpEx();
1908            src1 = convertBlendSource();
1909            src2 = convertBlendSource();
1910
1911            if (op == LBX_BLEND_MANUAL)
1912                manual = getNextTokenValue();
1913
1914            if (src1 == LBS_MANUAL)
1915                colSrc1 = _parseColourValue();
1916
1917            if (src2 == LBS_MANUAL)
1918                colSrc2 = _parseColourValue();
1919        }
1920        catch (Exception& e)
1921        {
1922            logParseError("Bad colour_op_ex attribute, " + e.getDescription());
1923            return;
1924        }
1925
1926        mScriptContext.textureUnit->setColourOperationEx(op, src1, src2, colSrc1, colSrc2, manual);
1927    }
1928    //-----------------------------------------------------------------------
1929    void MaterialScriptCompiler::parseColourOpMultipassFallback(void)
1930    {
1931        assert(mScriptContext.textureUnit);
1932
1933        SceneBlendFactor src = convertBlendFactor();
1934        SceneBlendFactor dest = convertBlendFactor();
1935        mScriptContext.textureUnit->setColourOpMultipassFallback(src,dest);
1936    }
1937    //-----------------------------------------------------------------------
1938    void MaterialScriptCompiler::parseAlphaOpEx(void)
1939    {
1940        assert(mScriptContext.textureUnit);
1941
1942        LayerBlendOperationEx op;
1943        LayerBlendSource src1, src2;
1944        Real manual = 0.0;
1945        Real arg1 = 1.0, arg2 = 1.0;
1946
1947        try {
1948            op = convertBlendOpEx();
1949            src1 = convertBlendSource();
1950            src2 = convertBlendSource();
1951
1952            if (op == LBX_BLEND_MANUAL)
1953                manual = getNextTokenValue();
1954
1955            if (src1 == LBS_MANUAL)
1956                arg1 = getNextTokenValue();
1957
1958            if (src2 == LBS_MANUAL)
1959                arg2 = getNextTokenValue();
1960        }
1961        catch (Exception& e)
1962        {
1963            logParseError("Bad alpha_op_ex attribute, " + e.getDescription());
1964            return;
1965        }
1966
1967        mScriptContext.textureUnit->setAlphaOperation(op, src1, src2, arg1, arg2, manual);
1968    }
1969    //-----------------------------------------------------------------------
1970    void MaterialScriptCompiler::parseEnvMap(void)
1971    {
1972        assert(mScriptContext.textureUnit);
1973
1974        switch (getNextTokenID())
1975        {
1976        case ID_OFF:
1977            mScriptContext.textureUnit->setEnvironmentMap(false);
1978            break;
1979        case ID_SPHERICAL:
1980            mScriptContext.textureUnit->setEnvironmentMap(true, TextureUnitState::ENV_CURVED);
1981            break;
1982        case ID_PLANAR:
1983            mScriptContext.textureUnit->setEnvironmentMap(true, TextureUnitState::ENV_PLANAR);
1984            break;
1985        case ID_CUBIC_REFLECTION:
1986            mScriptContext.textureUnit->setEnvironmentMap(true, TextureUnitState::ENV_REFLECTION);
1987            break;
1988        case ID_CUBIC_NORMAL:
1989            mScriptContext.textureUnit->setEnvironmentMap(true, TextureUnitState::ENV_NORMAL);
1990            break;
1991        }
1992    }
1993    //-----------------------------------------------------------------------
1994    void MaterialScriptCompiler::parseScroll(void)
1995    {
1996        assert(mScriptContext.textureUnit);
1997
1998        const Real x = getNextTokenValue();
1999        const Real y = getNextTokenValue();
2000
2001        mScriptContext.textureUnit->setTextureScroll(x, y);
2002    }
2003    //-----------------------------------------------------------------------
2004    void MaterialScriptCompiler::parseScrollAnim(void)
2005    {
2006        assert(mScriptContext.textureUnit);
2007
2008        const Real xspeed = getNextTokenValue();
2009        const Real yspeed = getNextTokenValue();
2010
2011        mScriptContext.textureUnit->setScrollAnimation(xspeed, yspeed);
2012    }
2013    //-----------------------------------------------------------------------
2014    void MaterialScriptCompiler::parseRotate(void)
2015    {
2016        assert(mScriptContext.textureUnit);
2017        mScriptContext.textureUnit->setTextureRotate(Angle(getNextTokenValue()));
2018    }
2019    //-----------------------------------------------------------------------
2020    void MaterialScriptCompiler::parseRotateAnim(void)
2021    {
2022        assert(mScriptContext.textureUnit);
2023        mScriptContext.textureUnit->setRotateAnimation(getNextTokenValue());
2024    }
2025    //-----------------------------------------------------------------------
2026    void MaterialScriptCompiler::parseScale(void)
2027    {
2028        assert(mScriptContext.textureUnit);
2029        const Real xscale = getNextTokenValue();
2030        const Real yscale = getNextTokenValue();
2031        mScriptContext.textureUnit->setTextureScale(xscale, yscale);
2032    }
2033    //-----------------------------------------------------------------------
2034    void MaterialScriptCompiler::parseWaveXform(void)
2035    {
2036
2037        assert(mScriptContext.textureUnit);
2038
2039        TextureUnitState::TextureTransformType ttype;
2040        WaveformType waveType;
2041        // Check transform type
2042        switch (getNextTokenID())
2043        {
2044                default:
2045        case ID_SCROLL_X:
2046            ttype = TextureUnitState::TT_TRANSLATE_U;
2047            break;
2048        case ID_SCROLL_Y:
2049            ttype = TextureUnitState::TT_TRANSLATE_V;
2050            break;
2051        case ID_ROTATE:
2052            ttype = TextureUnitState::TT_ROTATE;
2053            break;
2054        case ID_SCALE_X:
2055            ttype = TextureUnitState::TT_SCALE_U;
2056            break;
2057        case ID_SCALE_Y:
2058            ttype = TextureUnitState::TT_SCALE_V;
2059            break;
2060        }
2061        // Check wave type
2062        switch (getNextTokenID())
2063        {
2064                default:
2065        case ID_SINE:
2066            waveType = WFT_SINE;
2067            break;
2068        case ID_TRIANGLE:
2069            waveType = WFT_TRIANGLE;
2070            break;
2071        case ID_SQUARE:
2072            waveType = WFT_SQUARE;
2073            break;
2074        case ID_SAWTOOTH:
2075            waveType = WFT_SAWTOOTH;
2076            break;
2077        case ID_INVERSE_SAWTOOTH:
2078            waveType = WFT_INVERSE_SAWTOOTH;
2079            break;
2080        }
2081
2082        const Real base = getNextTokenValue();
2083        const Real frequency = getNextTokenValue();
2084        const Real phase = getNextTokenValue();
2085        const Real amplitude = getNextTokenValue();
2086
2087        mScriptContext.textureUnit->setTransformAnimation(
2088            ttype,
2089            waveType,
2090            base,
2091            frequency,
2092            phase,
2093            amplitude );
2094    }
2095        //-----------------------------------------------------------------------
2096        void MaterialScriptCompiler::parseTransform(void)
2097        {
2098        assert(mScriptContext.textureUnit);
2099
2100        Real matrixArray[16];
2101
2102        for (size_t i = 0; i < 16; ++i)
2103        {
2104            matrixArray[i] = getNextTokenValue();
2105        }
2106
2107                Matrix4 xform(
2108                        matrixArray[0],
2109                        matrixArray[1],
2110                        matrixArray[2],
2111                        matrixArray[3],
2112                        matrixArray[4],
2113                        matrixArray[5],
2114                        matrixArray[6],
2115                        matrixArray[7],
2116                        matrixArray[8],
2117                        matrixArray[9],
2118                        matrixArray[10],
2119                        matrixArray[11],
2120                        matrixArray[12],
2121                        matrixArray[13],
2122                        matrixArray[14],
2123                        matrixArray[15]);
2124
2125                mScriptContext.textureUnit->setTextureTransform(xform);
2126        }
2127        //-----------------------------------------------------------------------
2128        void MaterialScriptCompiler::parseBindingType(void)
2129        {
2130        assert(mScriptContext.textureUnit);
2131        switch (getNextTokenID())
2132        {
2133        case ID_VERTEX:
2134            mScriptContext.textureUnit->setBindingType(TextureUnitState::BT_VERTEX);
2135            break;
2136        case ID_FRAGMENT:
2137            mScriptContext.textureUnit->setBindingType(TextureUnitState::BT_FRAGMENT);
2138            break;
2139        }
2140    }
2141        //-----------------------------------------------------------------------
2142        void MaterialScriptCompiler::parseContentType(void)
2143        {
2144                assert(mScriptContext.textureUnit);
2145                switch (getNextTokenID())
2146                {
2147                case ID_NAMED:
2148                        mScriptContext.textureUnit->setContentType(TextureUnitState::CONTENT_NAMED);
2149                        break;
2150                case ID_SHADOW:
2151                        mScriptContext.textureUnit->setContentType(TextureUnitState::CONTENT_SHADOW);
2152                        break;
2153                }
2154        }
2155    //-----------------------------------------------------------------------
2156    void MaterialScriptCompiler::parseVertexProgramRef(void)
2157    {
2158        assert(mScriptContext.pass);
2159        // update section
2160        mScriptContext.section = MSS_PROGRAM_REF;
2161        String name;
2162
2163        // get the name of the program definition if it was set
2164        if (getRemainingTokensForAction() == 1)
2165        {
2166            name = getNextTokenLabel();
2167            StringUtil::trim(name);
2168        }
2169
2170        // check if pass has a vertex program already
2171        if (mScriptContext.pass->hasVertexProgram())
2172        {
2173            // if existing pass vertex program has same name as params
2174            // or params is empty then use current vertex program
2175            if (name.empty() || (mScriptContext.pass->getVertexProgramName() == name))
2176            {
2177                mScriptContext.program = mScriptContext.pass->getVertexProgram();
2178            }
2179        }
2180
2181        // if context.program was not set then try to get the vertex program using the name
2182        // passed in params
2183        if (mScriptContext.program.isNull())
2184        {
2185            mScriptContext.program = GpuProgramManager::getSingleton().getByName(name);
2186            if (mScriptContext.program.isNull())
2187            {
2188                // Unknown program
2189                logParseError("Invalid vertex_program_ref entry - vertex program "
2190                    + name + " has not been defined.");
2191                return;
2192            }
2193
2194            // Set the vertex program for this pass
2195            mScriptContext.pass->setVertexProgram(name);
2196        }
2197
2198        mScriptContext.isProgramShadowCaster = false;
2199        mScriptContext.isVertexProgramShadowReceiver = false;
2200        mScriptContext.isFragmentProgramShadowReceiver = false;
2201
2202        // Create params? Skip this if program is not supported
2203        if (mScriptContext.program->isSupported())
2204        {
2205            mScriptContext.programParams = mScriptContext.pass->getVertexProgramParameters();
2206                        mScriptContext.numAnimationParametrics = 0;
2207        }
2208    }
2209    //-----------------------------------------------------------------------
2210    void MaterialScriptCompiler::parseShadowCasterVertexProgramRef(void)
2211    {
2212        assert(mScriptContext.pass);
2213        // update section
2214        mScriptContext.section = MSS_PROGRAM_REF;
2215        String name;
2216
2217        // get the name of the program definition if it was set
2218        if (getRemainingTokensForAction() == 1)
2219        {
2220            name = getNextTokenLabel();
2221            StringUtil::trim(name);
2222        }
2223
2224        // check if pass has a shadow caster vertex program already
2225        if (mScriptContext.pass->hasShadowCasterVertexProgram())
2226        {
2227            // if existing pass vertex program has same name as params
2228            // or params is empty then use current vertex program
2229            if (name.empty() || (mScriptContext.pass->getShadowCasterVertexProgramName() == name))
2230            {
2231                mScriptContext.program = mScriptContext.pass->getShadowCasterVertexProgram();
2232            }
2233        }
2234
2235        // if context.program was not set then try to get the vertex program using the name
2236        // passed in params
2237        if (mScriptContext.program.isNull())
2238        {
2239            mScriptContext.program = GpuProgramManager::getSingleton().getByName(name);
2240            if (mScriptContext.program.isNull())
2241            {
2242                // Unknown program
2243                logParseError("Invalid shadow_caster_vertex_program_ref entry - vertex program "
2244                    + name + " has not been defined.");
2245                return;
2246            }
2247
2248            // Set the vertex program for this pass
2249            mScriptContext.pass->setShadowCasterVertexProgram(name);
2250        }
2251
2252        mScriptContext.isProgramShadowCaster = true;
2253        mScriptContext.isVertexProgramShadowReceiver = false;
2254                mScriptContext.isFragmentProgramShadowReceiver = false;
2255
2256        // Create params? Skip this if program is not supported
2257        if (mScriptContext.program->isSupported())
2258        {
2259            mScriptContext.programParams = mScriptContext.pass->getShadowCasterVertexProgramParameters();
2260                        mScriptContext.numAnimationParametrics = 0;
2261        }
2262    }
2263    //-----------------------------------------------------------------------
2264    void MaterialScriptCompiler::parseShadowReceiverVertexProgramRef(void)
2265    {
2266        assert(mScriptContext.pass);
2267        // update section
2268        mScriptContext.section = MSS_PROGRAM_REF;
2269
2270        String name;
2271
2272        // get the name of the program definition if it was set
2273        if (getRemainingTokensForAction() == 1)
2274        {
2275            name = getNextTokenLabel();
2276            StringUtil::trim(name);
2277        }
2278
2279        // check if pass has a shadow caster vertex program already
2280        if (mScriptContext.pass->hasShadowReceiverVertexProgram())
2281        {
2282            // if existing pass vertex program has same name as params
2283            // or params is empty then use current vertex program
2284            if (name.empty() || (mScriptContext.pass->getShadowReceiverVertexProgramName() == name))
2285            {
2286                mScriptContext.program = mScriptContext.pass->getShadowReceiverVertexProgram();
2287            }
2288        }
2289
2290        // if context.program was not set then try to get the vertex program using the name
2291        // passed in params
2292        if (mScriptContext.program.isNull())
2293        {
2294            mScriptContext.program = GpuProgramManager::getSingleton().getByName(name);
2295            if (mScriptContext.program.isNull())
2296            {
2297                // Unknown program
2298                logParseError("Invalid shadow_receiver_vertex_program_ref entry - vertex program "
2299                    + name + " has not been defined.");
2300                return;
2301            }
2302
2303            // Set the vertex program for this pass
2304            mScriptContext.pass->setShadowReceiverVertexProgram(name);
2305        }
2306
2307        mScriptContext.isProgramShadowCaster = false;
2308        mScriptContext.isVertexProgramShadowReceiver = true;
2309                mScriptContext.isFragmentProgramShadowReceiver = false;
2310
2311        // Create params? Skip this if program is not supported
2312        if (mScriptContext.program->isSupported())
2313        {
2314            mScriptContext.programParams = mScriptContext.pass->getShadowReceiverVertexProgramParameters();
2315                        mScriptContext.numAnimationParametrics = 0;
2316        }
2317    }
2318        //-----------------------------------------------------------------------
2319        void MaterialScriptCompiler::parseShadowReceiverFragmentProgramRef(void)
2320        {
2321        assert(mScriptContext.pass);
2322                // update section
2323                mScriptContext.section = MSS_PROGRAM_REF;
2324
2325        String name;
2326
2327        // get the name of the program definition if it was set
2328        if (getRemainingTokensForAction() == 1)
2329        {
2330            name = getNextTokenLabel();
2331            StringUtil::trim(name);
2332        }
2333        // check if pass has a fragment program already
2334        if (mScriptContext.pass->hasShadowReceiverFragmentProgram())
2335        {
2336            // if existing pass fragment program has same name as params
2337            // or params is empty then use current fragment program
2338            if (name.empty() || (mScriptContext.pass->getShadowReceiverFragmentProgramName() == name))
2339            {
2340                mScriptContext.program = mScriptContext.pass->getShadowReceiverFragmentProgram();
2341            }
2342        }
2343
2344        // if context.program was not set then try to get the fragment program using the name
2345        // passed in
2346        if (mScriptContext.program.isNull())
2347        {
2348            mScriptContext.program = GpuProgramManager::getSingleton().getByName(name);
2349            if (mScriptContext.program.isNull())
2350            {
2351                // Unknown program
2352                logParseError("Invalid shadow_receiver_fragment_program_ref entry - fragment program "
2353                    + name + " has not been defined.");
2354                return;
2355            }
2356
2357            // Set the vertex program for this pass
2358            mScriptContext.pass->setShadowReceiverFragmentProgram(name);
2359        }
2360
2361        mScriptContext.isProgramShadowCaster = false;
2362        mScriptContext.isVertexProgramShadowReceiver = false;
2363        mScriptContext.isFragmentProgramShadowReceiver = true;
2364
2365                // Create params? Skip this if program is not supported
2366                if (mScriptContext.program->isSupported())
2367                {
2368                        mScriptContext.programParams = mScriptContext.pass->getShadowReceiverFragmentProgramParameters();
2369                        mScriptContext.numAnimationParametrics = 0;
2370                }
2371        }
2372    //-----------------------------------------------------------------------
2373    void MaterialScriptCompiler::parseFragmentProgramRef(void)
2374    {
2375        assert(mScriptContext.pass);
2376        // update section
2377        mScriptContext.section = MSS_PROGRAM_REF;
2378
2379        String name;
2380
2381        // get the name of the program definition if it was set
2382        if (getRemainingTokensForAction() == 1)
2383        {
2384            name = getNextTokenLabel();
2385            StringUtil::trim(name);
2386        }
2387        // check if pass has a fragment program already
2388        if (mScriptContext.pass->hasFragmentProgram())
2389        {
2390            // if existing pass fragment program has same name as params
2391            // or params is empty then use current fragment program
2392            if (name.empty() || (mScriptContext.pass->getFragmentProgramName() == name))
2393            {
2394                mScriptContext.program = mScriptContext.pass->getFragmentProgram();
2395            }
2396        }
2397
2398        // if context.program was not set then try to get the fragment program using the name
2399        // passed in params
2400        if (mScriptContext.program.isNull())
2401        {
2402            mScriptContext.program = GpuProgramManager::getSingleton().getByName(name);
2403            if (mScriptContext.program.isNull())
2404            {
2405                // Unknown program
2406                logParseError("Invalid fragment_program_ref entry - fragment program "
2407                    + name + " has not been defined.");
2408                return;
2409            }
2410
2411            // Set the vertex program for this pass
2412            mScriptContext.pass->setFragmentProgram(name);
2413        }
2414
2415        // Create params? Skip this if program is not supported
2416        if (mScriptContext.program->isSupported())
2417        {
2418            mScriptContext.programParams = mScriptContext.pass->getFragmentProgramParameters();
2419                        mScriptContext.numAnimationParametrics = 0;
2420        }
2421    }
2422    //-----------------------------------------------------------------------
2423        void MaterialScriptCompiler::processManualProgramParam(bool isNamed, 
2424                const String commandname, size_t index, const String& paramName)
2425    {
2426        // NB we assume that the first element of vecparams is taken up with either
2427        // the index or the parameter name, which we ignore
2428
2429        // Determine type
2430        size_t start, dims, roundedDims, i;
2431        bool isReal;
2432        bool isMatrix4x4 = false;
2433        String param(getNextTokenLabel());
2434
2435        StringUtil::toLowerCase(param);
2436
2437        if (param == "matrix4x4")
2438        {
2439            dims = 16;
2440            isReal = true;
2441            isMatrix4x4 = true;
2442        }
2443        else if ((start = param.find("float")) != String::npos)
2444        {
2445            // find the dimensionality
2446            start = param.find_first_not_of("float");
2447            // Assume 1 if not specified
2448            if (start == String::npos)
2449            {
2450                dims = 1;
2451            }
2452            else
2453            {
2454                dims = StringConverter::parseInt(param.substr(start));
2455            }
2456            isReal = true;
2457        }
2458        else if ((start = param.find("int")) != String::npos)
2459        {
2460            // find the dimensionality
2461            start = param.find_first_not_of("int");
2462            // Assume 1 if not specified
2463            if (start == String::npos)
2464            {
2465                dims = 1;
2466            }
2467            else
2468            {
2469                dims = StringConverter::parseInt(param.substr(start));
2470            }
2471            isReal = false;
2472        }
2473        else
2474        {
2475            logParseError("Invalid " + commandname + " attribute - unrecognised "
2476                "parameter type " + param);
2477            return;
2478        }
2479
2480        if (getRemainingTokensForAction() != dims)
2481        {
2482            logParseError("Invalid " + commandname + " attribute - you need " +
2483                StringConverter::toString(2 + dims) + " parameters for a parameter of "
2484                "type " + param);
2485        }
2486
2487                // clear any auto parameter bound to this constant, it would override this setting
2488                // can cause problems overriding materials or changing default params
2489                if (isNamed)
2490                        mScriptContext.programParams->clearNamedAutoConstant(paramName);
2491                else
2492                        mScriptContext.programParams->clearAutoConstant(index);
2493
2494                // Round dims to multiple of 4
2495                if (dims %4 != 0)
2496                {
2497                        roundedDims = dims + 4 - (dims % 4);
2498                }
2499                else
2500                {
2501                        roundedDims = dims;
2502                }
2503
2504                // Now parse all the values
2505        if (isReal)
2506        {
2507            Real* realBuffer = new Real[roundedDims];
2508            // Do specified values
2509            for (i = 0; i < dims; ++i)
2510            {
2511                realBuffer[i] = getNextTokenValue();
2512            }
2513                        // Fill up to multiple of 4 with zero
2514                        for (; i < roundedDims; ++i)
2515                        {
2516                                realBuffer[i] = 0.0f;
2517
2518                        }
2519
2520            if (isMatrix4x4)
2521            {
2522                // its a Matrix4x4 so pass as a Matrix4
2523                // use specialized setConstant that takes a matrix so matrix is transposed if required
2524                Matrix4 m4x4(
2525                    realBuffer[0],  realBuffer[1],  realBuffer[2],  realBuffer[3],
2526                    realBuffer[4],  realBuffer[5],  realBuffer[6],  realBuffer[7],
2527                    realBuffer[8],  realBuffer[9],  realBuffer[10], realBuffer[11],
2528                    realBuffer[12], realBuffer[13], realBuffer[14], realBuffer[15]
2529                    );
2530                                if (isNamed)
2531                                        mScriptContext.programParams->setNamedConstant(paramName, m4x4);
2532                                else
2533                                        mScriptContext.programParams->setConstant(index, m4x4);
2534            }
2535            else
2536            {
2537                // Set
2538                                if (isNamed)
2539                                {
2540                                        // For named, only set up to the precise number of elements
2541                                        // (no rounding to 4 elements)
2542                                        // GLSL can support sub-float4 elements and we support that
2543                                        // in the buffer now. Note how we set the 'multiple' param to 1
2544                                        mScriptContext.programParams->setNamedConstant(paramName, 
2545                                                realBuffer, dims, 1);
2546                                }
2547                                else
2548                                {
2549                        mScriptContext.programParams->setConstant(index, 
2550                                                realBuffer, static_cast<size_t>(roundedDims * 0.25));
2551                                }
2552
2553            }
2554
2555
2556            delete [] realBuffer;
2557        }
2558        else
2559        {
2560            int* intBuffer = new int[roundedDims];
2561            // Do specified values
2562            for (i = 0; i < dims; ++i)
2563            {
2564                intBuffer[i] = static_cast<int>(getNextTokenValue());
2565            }
2566                        // Fill to multiple of 4 with 0
2567                        for (; i < roundedDims; ++i)
2568                        {
2569                                intBuffer[i] = 0;
2570                        }
2571            // Set
2572                        if (isNamed)
2573                        {
2574                                // For named, only set up to the precise number of elements
2575                                // (no rounding to 4 elements)
2576                                // GLSL can support sub-float4 elements and we support that
2577                                // in the buffer now. Note how we set the 'multiple' param to 1
2578                                mScriptContext.programParams->setNamedConstant(paramName, intBuffer, 
2579                                        dims, 1);
2580                        }
2581                        else
2582                        {
2583                                mScriptContext.programParams->setConstant(index, intBuffer, 
2584                                        static_cast<size_t>(roundedDims * 0.25));
2585                        }
2586            delete [] intBuffer;
2587        }
2588    }
2589    //-----------------------------------------------------------------------
2590        void MaterialScriptCompiler::processAutoProgramParam(bool isNamed, const String commandname, 
2591                size_t index, const String& paramName)
2592    {
2593
2594        String autoConstantName(getNextTokenLabel());
2595        // make sure param is in lower case
2596        StringUtil::toLowerCase(autoConstantName);
2597
2598        // lookup the param to see if its a valid auto constant
2599        const GpuProgramParameters::AutoConstantDefinition* autoConstantDef =
2600            mScriptContext.programParams->getAutoConstantDefinition(autoConstantName);
2601
2602        // exit with error msg if the auto constant definition wasn't found
2603        if (!autoConstantDef)
2604                {
2605                        logParseError("Invalid " + commandname + " attribute - "
2606                                + autoConstantName);
2607                        return;
2608                }
2609
2610        // add AutoConstant based on the type of data it uses
2611        switch (autoConstantDef->dataType)
2612        {
2613        case GpuProgramParameters::ACDT_NONE:
2614                        if (isNamed)
2615                                mScriptContext.programParams->setNamedAutoConstant(paramName, autoConstantDef->acType, 0);
2616                        else
2617                                mScriptContext.programParams->setAutoConstant(index, autoConstantDef->acType, 0);
2618            break;
2619
2620        case GpuProgramParameters::ACDT_INT:
2621            {
2622                                // Special case animation_parametric, we need to keep track of number of times used
2623                                if (autoConstantDef->acType == GpuProgramParameters::ACT_ANIMATION_PARAMETRIC)
2624                                {
2625                                        if (isNamed)
2626                                                mScriptContext.programParams->setNamedAutoConstant(
2627                                                        paramName, autoConstantDef->acType, mScriptContext.numAnimationParametrics++);
2628                                        else
2629                                                mScriptContext.programParams->setAutoConstant(
2630                                                        index, autoConstantDef->acType, mScriptContext.numAnimationParametrics++);
2631                                }
2632                                // Special case texture projector - assume 0 if data not specified
2633                                else if (autoConstantDef->acType == GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX
2634                                        && getRemainingTokensForAction() == 0)
2635                                {
2636                                        if (isNamed)
2637                                                mScriptContext.programParams->setNamedAutoConstant(
2638                                                        paramName, autoConstantDef->acType, 0);
2639                                        else
2640                                                mScriptContext.programParams->setAutoConstant(
2641                                                        index, autoConstantDef->acType, 0);
2642
2643                                }
2644                                else
2645                                {
2646
2647                                        if (getRemainingTokensForAction() != 1)
2648                                        {
2649                                                logParseError("Invalid " + commandname + " attribute - "
2650                                                        "expected 3 parameters.");
2651                                                return;
2652                                        }
2653
2654                                        size_t extraParam = static_cast<size_t>(getNextTokenValue());
2655                                        if (isNamed)
2656                                                mScriptContext.programParams->setNamedAutoConstant(
2657                                                        paramName, autoConstantDef->acType, extraParam);
2658                                        else
2659                                                mScriptContext.programParams->setAutoConstant(
2660                                                        index, autoConstantDef->acType, extraParam);
2661                                }
2662            }
2663            break;
2664
2665        case GpuProgramParameters::ACDT_REAL:
2666            {
2667                // special handling for time
2668                if (autoConstantDef->acType == GpuProgramParameters::ACT_TIME ||
2669                    autoConstantDef->acType == GpuProgramParameters::ACT_FRAME_TIME)
2670                {
2671                    Real factor = 1.0f;
2672                    if (getRemainingTokensForAction() == 1)
2673                    {
2674                        factor = getNextTokenValue();
2675                    }
2676
2677                                        if (isNamed)
2678                                                mScriptContext.programParams->setNamedAutoConstantReal(
2679                                                        paramName, autoConstantDef->acType, factor);
2680                                        else
2681                                                mScriptContext.programParams->setAutoConstantReal(
2682                                                        index, autoConstantDef->acType, factor);
2683                }
2684                else // normal processing for auto constants that take an extra real value
2685                {
2686                    if (getRemainingTokensForAction() != 1)
2687                    {
2688                        logParseError("Invalid " + commandname + " attribute - "
2689                            "expected 3 parameters.");
2690                        return;
2691                    }
2692
2693                                const Real rData = getNextTokenValue();
2694                                        if (isNamed)
2695                                                mScriptContext.programParams->setNamedAutoConstantReal(
2696                                                        paramName, autoConstantDef->acType, rData);
2697                                        else
2698                                                mScriptContext.programParams->setAutoConstantReal(
2699                                                        index, autoConstantDef->acType, rData);
2700                }
2701            }
2702            break;
2703
2704        } // end switch
2705
2706
2707    }
2708
2709    //-----------------------------------------------------------------------
2710    void MaterialScriptCompiler::parseParamIndexed(void)
2711    {
2712        if (mScriptContext.section == MSS_DEFAULT_PARAMETERS)
2713        {
2714            // save the pass2 token que position for later processing
2715            mScriptContext.pendingDefaultParams.push_back(getPass2TokenQuePosition());
2716            return;
2717        }
2718
2719        // NB skip this if the program is not supported or could not be found
2720        if (mScriptContext.program.isNull() || !mScriptContext.program->isSupported())
2721        {
2722            return;
2723        }
2724
2725        // Get start index
2726        const size_t index = static_cast<size_t>(getNextTokenValue());
2727
2728        processManualProgramParam(false, "param_indexed", index);
2729
2730    }
2731    //-----------------------------------------------------------------------
2732    void MaterialScriptCompiler::parseParamIndexedAuto(void)
2733    {
2734        if (mScriptContext.section == MSS_DEFAULT_PARAMETERS)
2735        {
2736            // save the pass2 token que position for later processing
2737            mScriptContext.pendingDefaultParams.push_back(getPass2TokenQuePosition());
2738            return;
2739        }
2740        // NB skip this if the program is not supported or could not be found
2741        if (mScriptContext.program.isNull() || !mScriptContext.program->isSupported())
2742        {
2743            return;
2744        }
2745        // Get start index
2746        const size_t index = static_cast<size_t>(getNextTokenValue());
2747
2748        processAutoProgramParam(false, "param_indexed_auto", index);
2749
2750    }
2751    //-----------------------------------------------------------------------
2752    void MaterialScriptCompiler::parseParamNamed(void)
2753    {
2754        if (mScriptContext.section == MSS_DEFAULT_PARAMETERS)
2755        {
2756            // save the pass2 token que position for later processing
2757            mScriptContext.pendingDefaultParams.push_back(getPass2TokenQuePosition());
2758            return;
2759        }
2760        // NB skip this if the program is not supported or could not be found
2761        if (mScriptContext.program.isNull() || !mScriptContext.program->isSupported())
2762        {
2763            return;
2764        }
2765
2766        // Get start index from name
2767        const String& paramName = getNextTokenLabel();
2768        try {
2769            const GpuConstantDefinition& def =
2770                                mScriptContext.programParams->getConstantDefinition(paramName);
2771        }
2772        catch (Exception& e)
2773        {
2774            logParseError("Invalid param_named attribute - " + e.getDescription());
2775            return;
2776        }
2777
2778        processManualProgramParam(true, "param_named", 0, paramName);
2779
2780    }
2781    //-----------------------------------------------------------------------
2782    void MaterialScriptCompiler::parseParamNamedAuto(void)
2783    {
2784        if (mScriptContext.section == MSS_DEFAULT_PARAMETERS)
2785        {
2786            // save the pass2 token que position for later processing
2787            mScriptContext.pendingDefaultParams.push_back(getPass2TokenQuePosition());
2788            return;
2789        }
2790        // NB skip this if the program is not supported or could not be found
2791        if (mScriptContext.program.isNull() || !mScriptContext.program->isSupported())
2792        {
2793            return;
2794        }
2795
2796        // Get start index from name
2797        const String& paramName = getNextTokenLabel();
2798        try {
2799                        const GpuConstantDefinition& def =
2800                                mScriptContext.programParams->getConstantDefinition(paramName);
2801        }
2802        catch (Exception& e)
2803        {
2804            logParseError("Invalid param_named_auto attribute - " + e.getDescription());
2805            return;
2806        }
2807
2808        processAutoProgramParam(true, "param_named_auto", 0, paramName);
2809    }
2810    //-----------------------------------------------------------------------
2811        void MaterialScriptCompiler::finishProgramDefinition(void)
2812        {
2813                // Now it is time to create the program and propagate the parameters
2814                MaterialScriptProgramDefinition* def = mScriptContext.programDef;
2815        GpuProgramPtr gp;
2816
2817                if (def->language == "asm")
2818                {
2819                        // Native assembler
2820                        // Validate
2821                        if (def->source.empty())
2822                        {
2823                                logParseError("Invalid program definition for " + def->name +
2824                                        ", you must specify a source file.");
2825                        }
2826                        if (def->syntax.empty())
2827                        {
2828                                logParseError("Invalid program definition for " + def->name +
2829                                        ", you must specify a syntax code.");
2830                        }
2831
2832                        /*  attempt to create the gpu program.  This could fail if the gpu program name is
2833                already being used so must catch the exception and see if its possible to override
2834                the existing gpu program.
2835            */
2836                        try
2837                        {
2838                gp = GpuProgramManager::getSingleton().
2839                    createProgram(def->name, mScriptContext.groupName, def->source,
2840                        def->progType, def->syntax);
2841                        }
2842                        catch (Exception& e)
2843                        {
2844                            bool exceptionHandled = false;
2845
2846                            // attempt recovery if exception was caused by duplicate program name found
2847                if (mScriptContext.allowOverride && (e.getNumber() == Exception::ERR_DUPLICATE_ITEM))
2848                {
2849                    // the gpu program already exists so unload it and then change source and syntax
2850                    // the syntax code is not checked here
2851                    gp = GpuProgramManager::getSingleton().getByName(def->name);
2852                    if (!gp.isNull())
2853                    {
2854                        if (gp->getType() == def->progType)
2855                        {
2856                            logParseError("gpu asm program: " + def->name +
2857                                ", defined in " + gp->getOrigin() +
2858                                ", was overwritten by current gpu program definition being parsed with same name");
2859                            gp->unload();
2860                            /* updat group ownership since the original gpu program
2861                               might have been in a different resource group
2862                            */
2863                            gp->changeGroupOwnership(mScriptContext.groupName);
2864                            gp->setSyntaxCode(def->syntax);
2865                            gp->setSource(def->source);
2866                            // Need to do something about the existing default parameters
2867                            gp->load();
2868                            exceptionHandled = true;
2869                        }
2870                        else
2871                        {
2872                            // Don't create or override the gpu program due to incompitble program type so ignore the new definition
2873                            logParseError("gpu asm program: " + def->name + " program type conflict with current gpu program definition being parsed with same name");
2874                        }
2875                    }
2876                }
2877
2878                if (!exceptionHandled)
2879                {
2880                    // exception message already logged so no sense logging them in here and making two entries in the log
2881                    logParseError("gpu asm program: " + def->name +
2882                        " was previously defined and can not be overridden.\n"
2883                        "Material Manager script override was not enabled." );
2884                    mScriptContext.program.setNull();
2885                    mScriptContext.programParams.setNull();
2886                }
2887                        }
2888                }
2889                else
2890                {
2891                        // High-level program
2892                        // Validate
2893                        if (def->source.empty() && def->language != "unified")
2894                        {
2895                                logParseError("Invalid program definition for " + def->name +
2896                                        ", you must specify a source file.");
2897                        }
2898                        /*  attempt to create the high level gpu program.  This could fail if the gpu program name is
2899                already being used so must catch the exception and see if its possible to override
2900                the existing gpu program.
2901            */
2902            HighLevelGpuProgramPtr hgp;
2903            try
2904            {
2905                hgp = HighLevelGpuProgramManager::getSingleton().
2906                    createProgram(def->name, mScriptContext.groupName,
2907                        def->language, def->progType);
2908            }
2909            catch (Exception& e)
2910            {
2911                            bool exceptionHandled = false;
2912                            // attempt recovery if exception was caused by duplicate gpu program name found
2913                if (mScriptContext.allowOverride && (e.getNumber() == Exception::ERR_DUPLICATE_ITEM))
2914                {
2915                    hgp = HighLevelGpuProgramManager::getSingleton().getByName(def->name);
2916                    if (!hgp.isNull())
2917                    {
2918                        // the language and program type must still be the same otherwise reuse is not possible
2919                        if ((hgp->getLanguage() != def->language) || (hgp->getType() != def->progType))
2920                        {
2921                            logParseError("gpu high level program: " + def->name +
2922                                " already exists and can not be redefined with the language or program type defined in the material script");
2923                        }
2924                        else
2925                        {
2926                            logParseError("gpu high level program: " + def->name +
2927                                ", defined in " + hgp->getOrigin() +
2928                                ", was overwritten by current gpu program definition being parsed with same name");
2929                            // unload the previous source that was compiled
2930                            hgp->unload();
2931                            /* update group ownership since the original gpu program
2932                               might have been in a different resource group
2933                            */
2934                            hgp->changeGroupOwnership(mScriptContext.groupName);
2935                            exceptionHandled = true;
2936                        }
2937                    }
2938                }
2939
2940                if (!exceptionHandled)
2941                {
2942                    // exception message already logged so no sense logging them in here and making two entries in the log
2943                    logParseError("gpu high level program: " + def->name +
2944                        " was previously defined and can not be overridden.\n"
2945                        "Material Manager script override was not enabled." );
2946                    mScriptContext.program.setNull();
2947                    mScriptContext.programParams.setNull();
2948                }
2949            }
2950            // if the high level gpu program dosn't exist then don't continue
2951            if (hgp.isNull())
2952                return;
2953
2954            // Assign to generalised version
2955            gp = hgp;
2956
2957            // Set source file
2958            hgp->setSourceFile(def->source);
2959
2960            // Set custom parameters
2961                        std::vector<std::pair<String, String> >::const_iterator i, iend;
2962            iend = def->customParameters.end();
2963            for (i = def->customParameters.begin(); i != iend; ++i)
2964            {
2965                if (!hgp->setParameter(i->first, i->second))
2966                {
2967                    logParseError("Error in program " + def->name +
2968                        " parameter " + i->first + " is not valid.");
2969                }
2970            }
2971        }
2972
2973        // don't continue processing gpu program if it doesn't exist
2974        if (gp.isNull())
2975            return;
2976
2977        // Set skeletal animation option
2978        gp->setSkeletalAnimationIncluded(def->supportsSkeletalAnimation);
2979                // Set morph animation option
2980                gp->setMorphAnimationIncluded(def->supportsMorphAnimation);
2981                // Set pose animation option
2982                gp->setPoseAnimationIncluded(def->supportsPoseAnimation);
2983        // Set vertex texture usage
2984        gp->setVertexTextureFetchRequired(def->usesVertexTextureFetch);
2985
2986                // set origin
2987                gp->_notifyOrigin(mSourceName);
2988
2989        // Set up to receive default parameters
2990        if (gp->isSupported()
2991            && !mScriptContext.pendingDefaultParams.empty())
2992        {
2993            mScriptContext.programParams = gp->getDefaultParameters();
2994                        mScriptContext.numAnimationParametrics = 0;
2995            mScriptContext.program = gp;
2996            size_t i, iend;
2997            iend = mScriptContext.pendingDefaultParams.size();
2998            for (i = 0; i < iend; ++i)
2999            {
3000                // invoke the action for the pending default param in the token que
3001                setPass2TokenQuePosition(mScriptContext.pendingDefaultParams[i], true);
3002            }
3003            // Reset
3004            mScriptContext.program.setNull();
3005            mScriptContext.programParams.setNull();
3006        }
3007
3008        }
3009
3010
3011}
Note: See TracBrowser for help on using the repository browser.