Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreMaterialSerializer.cpp

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004 (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://ogre.sourceforge.net/
00006 
00007 Copyright © 2000-2002 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 #include "OgreStableHeaders.h"
00026 
00027 #include "OgreMaterialSerializer.h"
00028 #include "OgreStringConverter.h"
00029 #include "OgreLogManager.h"
00030 #include "OgreException.h"
00031 #include "OgreTechnique.h"
00032 #include "OgrePass.h"
00033 #include "OgreTextureUnitState.h"
00034 #include "OgreMaterialManager.h"
00035 #include "OgreGpuProgramManager.h"
00036 #include "OgreHighLevelGpuProgramManager.h"
00037 #include "OgreExternalTextureSourceManager.h"
00038 
00039 namespace Ogre 
00040 {
00041     //-----------------------------------------------------------------------
00042     // Internal parser methods
00043     //-----------------------------------------------------------------------
00044     void logParseError(const String& error, const MaterialScriptContext& context)
00045     {
00046         // log material name only if filename not specified
00047         if (context.filename.empty() && context.material)
00048         {
00049             LogManager::getSingleton().logMessage(
00050                 "Error in material " + context.material->getName() + 
00051                 " : " + error);
00052         }
00053         else
00054         {
00055             if (context.material)
00056             {
00057                 LogManager::getSingleton().logMessage(
00058                     "Error in material " + context.material->getName() +
00059                     " at line " + StringConverter::toString(context.lineNo) + 
00060                     " of " + context.filename + ": " + error);
00061             }
00062             else
00063             {
00064                 LogManager::getSingleton().logMessage(
00065                     "Error at line " + StringConverter::toString(context.lineNo) + 
00066                     " of " + context.filename + ": " + error);
00067             }
00068         }
00069     }
00070     //-----------------------------------------------------------------------
00071     ColourValue _parseColourValue(StringVector& vecparams)
00072     {
00073         return ColourValue(
00074             StringConverter::parseReal(vecparams[0]) ,
00075             StringConverter::parseReal(vecparams[1]) ,
00076             StringConverter::parseReal(vecparams[2]) ,
00077             (vecparams.size()==4) ? StringConverter::parseReal(vecparams[3]) : 1.0f ) ;
00078     }
00079     //-----------------------------------------------------------------------
00080     FilterOptions convertFiltering(const String& s)
00081     {
00082         if (s == "none")
00083         {
00084             return FO_NONE;
00085         }
00086         else if (s == "point")
00087         {
00088             return FO_POINT;
00089         }
00090         else if (s == "linear")
00091         {
00092             return FO_LINEAR;
00093         }
00094         else if (s == "anisotropic")
00095         {
00096             return FO_ANISOTROPIC;
00097         }
00098 
00099         return FO_POINT;
00100     }
00101     //-----------------------------------------------------------------------
00102     bool parseAmbient(String& params, MaterialScriptContext& context)
00103     {
00104         StringVector vecparams = params.split(" \t");
00105         // Must be 3 or 4 parameters 
00106         if (vecparams.size() != 3 && vecparams.size() != 4)
00107         {
00108             logParseError(
00109                 "Bad ambient attribute, wrong number of parameters (expected 3 or 4)", 
00110                 context);
00111         }
00112         else
00113         {
00114             context.pass->setAmbient( _parseColourValue(vecparams) );
00115         }
00116         return false;
00117     }
00118     //-----------------------------------------------------------------------
00119     bool parseDiffuse(String& params, MaterialScriptContext& context)
00120     {
00121         StringVector vecparams = params.split(" \t");
00122         // Must be 3 or 4 parameters 
00123         if (vecparams.size() != 3 && vecparams.size() != 4)
00124         {
00125             logParseError(
00126                 "Bad diffuse attribute, wrong number of parameters (expected 3 or 4)", 
00127                 context);
00128         }
00129         else
00130         {
00131             context.pass->setDiffuse( _parseColourValue(vecparams) );
00132         }
00133         return false;
00134     }
00135     //-----------------------------------------------------------------------
00136     bool parseSpecular(String& params, MaterialScriptContext& context)
00137     {
00138         StringVector vecparams = params.split(" \t");
00139         // Must be 4 or 5 parameters 
00140         if (vecparams.size() != 4 && vecparams.size() != 5)
00141         {
00142             logParseError(
00143                 "Bad specular attribute, wrong number of parameters (expected 4 or 5)",
00144                 context);
00145         }
00146         else
00147         {
00148             context.pass->setSpecular(
00149                 StringConverter::parseReal(vecparams[0]), 
00150                 StringConverter::parseReal(vecparams[1]), 
00151                 StringConverter::parseReal(vecparams[2]));
00152             context.pass->setShininess(
00153                 StringConverter::parseReal(vecparams[vecparams.size() - 1]) );
00154         }
00155         return false;
00156     }
00157     //-----------------------------------------------------------------------
00158     bool parseEmissive(String& params, MaterialScriptContext& context)
00159     {
00160         StringVector vecparams = params.split(" \t");
00161         // Must be 3 or 4 parameters 
00162         if (vecparams.size() != 3 && vecparams.size() != 4)
00163         {
00164             logParseError(
00165                 "Bad emissive attribute, wrong number of parameters (expected 3 or 4)", 
00166                 context);
00167         }
00168         else
00169         {
00170             context.pass->setSelfIllumination( _parseColourValue(vecparams) );
00171         }
00172         return false;
00173     }
00174     //-----------------------------------------------------------------------
00175     SceneBlendFactor convertBlendFactor(const String& param)
00176     {
00177         if (param == "one")
00178             return SBF_ONE;
00179         else if (param == "zero")
00180             return SBF_ZERO;
00181         else if (param == "dest_colour")
00182             return SBF_DEST_COLOUR;
00183         else if (param == "src_colour")
00184             return SBF_SOURCE_COLOUR;
00185         else if (param == "one_minus_dest_colour")
00186             return SBF_ONE_MINUS_DEST_COLOUR;
00187         else if (param == "one_minus_src_colour")
00188             return SBF_ONE_MINUS_SOURCE_COLOUR;
00189         else if (param == "dest_alpha")
00190             return SBF_DEST_ALPHA;
00191         else if (param == "src_alpha")
00192             return SBF_SOURCE_ALPHA;
00193         else if (param == "one_minus_dest_alpha")
00194             return SBF_ONE_MINUS_DEST_ALPHA;
00195         else if (param == "one_minus_src_alpha")
00196             return SBF_ONE_MINUS_SOURCE_ALPHA;
00197         else
00198         {
00199             Except(Exception::ERR_INVALIDPARAMS, "Invalid blend factor.", "convertBlendFactor");
00200         }
00201 
00202 
00203     }
00204     //-----------------------------------------------------------------------
00205     bool parseSceneBlend(String& params, MaterialScriptContext& context)
00206     {
00207         params.toLowerCase();
00208         StringVector vecparams = params.split(" \t");
00209         // Should be 1 or 2 params 
00210         if (vecparams.size() == 1)
00211         {
00212             //simple
00213             SceneBlendType stype;
00214             if (vecparams[0] == "add")
00215                 stype = SBT_ADD;
00216             else if (vecparams[0] == "modulate")
00217                 stype = SBT_TRANSPARENT_COLOUR;
00218             else if (vecparams[0] == "alpha_blend")
00219                 stype = SBT_TRANSPARENT_ALPHA;
00220             else
00221             {
00222                 logParseError(
00223                     "Bad scene_blend attribute, unrecognised parameter '" + vecparams[0] + "'",
00224                     context);
00225                 return false;
00226             }
00227             context.pass->setSceneBlending(stype);
00228 
00229         }
00230         else if (vecparams.size() == 2)
00231         {
00232             //src/dest
00233             SceneBlendFactor src, dest;
00234 
00235             try {
00236                 src = convertBlendFactor(vecparams[0]);
00237                 dest = convertBlendFactor(vecparams[1]);
00238                 context.pass->setSceneBlending(src,dest);
00239             }
00240             catch (Exception& e)
00241             {
00242                 logParseError("Bad scene_blend attribute, " + e.getFullDescription(), context);
00243             }
00244 
00245         }
00246         else
00247         {
00248             logParseError(
00249                 "Bad scene_blend attribute, wrong number of parameters (expected 1 or 2)", 
00250                 context);
00251         }
00252 
00253         return false;
00254 
00255     }
00256     //-----------------------------------------------------------------------
00257     CompareFunction convertCompareFunction(const String& param)
00258     {
00259         if (param == "always_fail")
00260             return CMPF_ALWAYS_FAIL;
00261         else if (param == "always_pass")
00262             return CMPF_ALWAYS_PASS;
00263         else if (param == "less")
00264             return CMPF_LESS;
00265         else if (param == "less_equal")
00266             return CMPF_LESS_EQUAL;
00267         else if (param == "equal")
00268             return CMPF_EQUAL;
00269         else if (param == "not_equal")
00270             return CMPF_NOT_EQUAL;
00271         else if (param == "greater_equal")
00272             return CMPF_GREATER_EQUAL;
00273         else if (param == "greater")
00274             return CMPF_GREATER;
00275         else
00276             Except(Exception::ERR_INVALIDPARAMS, "Invalid compare function", "convertCompareFunction");
00277 
00278     }
00279     //-----------------------------------------------------------------------
00280     bool parseDepthCheck(String& params, MaterialScriptContext& context)
00281     {
00282         params.toLowerCase();
00283         if (params == "on")
00284             context.pass->setDepthCheckEnabled(true);
00285         else if (params == "off")
00286             context.pass->setDepthCheckEnabled(false);
00287         else
00288             logParseError(
00289             "Bad depth_check attribute, valid parameters are 'on' or 'off'.", 
00290             context);
00291 
00292         return false;
00293     }
00294     //-----------------------------------------------------------------------
00295     bool parseDepthWrite(String& params, MaterialScriptContext& context)
00296     {
00297         params.toLowerCase();
00298         if (params == "on")
00299             context.pass->setDepthWriteEnabled(true);
00300         else if (params == "off")
00301             context.pass->setDepthWriteEnabled(false);
00302         else
00303             logParseError(
00304                 "Bad depth_write attribute, valid parameters are 'on' or 'off'.", 
00305                 context);
00306         return false;
00307     }
00308 
00309     //-----------------------------------------------------------------------
00310     bool parseDepthFunc(String& params, MaterialScriptContext& context)
00311     {
00312         params.toLowerCase();
00313         try {
00314             CompareFunction func = convertCompareFunction(params);
00315             context.pass->setDepthFunction(func);
00316         }
00317         catch (...)
00318         {
00319             logParseError("Bad depth_func attribute, invalid function parameter.", context);
00320         }
00321 
00322         return false;
00323     }
00324     //-----------------------------------------------------------------------
00325     bool parseColourWrite(String& params, MaterialScriptContext& context)
00326     {
00327         params.toLowerCase();
00328         if (params == "on")
00329             context.pass->setColourWriteEnabled(true);
00330         else if (params == "off")
00331             context.pass->setColourWriteEnabled(false);
00332         else
00333             logParseError(
00334                 "Bad colour_write attribute, valid parameters are 'on' or 'off'.", 
00335                 context);
00336         return false;
00337     }
00338 
00339     //-----------------------------------------------------------------------
00340     bool parseCullHardware(String& params, MaterialScriptContext& context)
00341     {
00342         params.toLowerCase();
00343         if (params=="none")
00344             context.pass->setCullingMode(CULL_NONE);
00345         else if (params=="anticlockwise")
00346             context.pass->setCullingMode(CULL_ANTICLOCKWISE);
00347         else if (params=="clockwise")
00348             context.pass->setCullingMode(CULL_CLOCKWISE);
00349         else
00350             logParseError(
00351                 "Bad cull_hardware attribute, valid parameters are "
00352                 "'none', 'clockwise' or 'anticlockwise'.", context);
00353         return false;
00354     }
00355     //-----------------------------------------------------------------------
00356     bool parseCullSoftware(String& params, MaterialScriptContext& context)
00357     {
00358         params.toLowerCase();
00359         if (params=="none")
00360             context.pass->setManualCullingMode(MANUAL_CULL_NONE);
00361         else if (params=="back")
00362             context.pass->setManualCullingMode(MANUAL_CULL_BACK);
00363         else if (params=="front")
00364             context.pass->setManualCullingMode(MANUAL_CULL_FRONT);
00365         else
00366             logParseError(
00367                 "Bad cull_software attribute, valid parameters are 'none', "
00368                 "'front' or 'back'.", context);
00369         return false;
00370     }
00371     //-----------------------------------------------------------------------
00372     bool parseLighting(String& params, MaterialScriptContext& context)
00373     {
00374         params.toLowerCase();
00375         if (params=="on")
00376             context.pass->setLightingEnabled(true);
00377         else if (params=="off")
00378             context.pass->setLightingEnabled(false);
00379         else
00380             logParseError(
00381                 "Bad lighting attribute, valid parameters are 'on' or 'off'.", context);
00382         return false;
00383     }
00384     //-----------------------------------------------------------------------
00385     bool parseMaxLights(String& params, MaterialScriptContext& context)
00386     {
00387         context.pass->setMaxSimultaneousLights(StringConverter::parseInt(params));
00388         return false;
00389     }
00390     //-----------------------------------------------------------------------
00391     bool parseIteration(String& params, MaterialScriptContext& context)
00392     {
00393         params.toLowerCase();
00394         StringVector vecparams = params.split(" \t");
00395         if (vecparams.size() != 1 && vecparams.size() != 2)
00396         {
00397             logParseError("Bad iteration attribute, expected 1 or 2 parameters.", context);
00398             return false;
00399         }
00400 
00401         if (vecparams[0]=="once")
00402             context.pass->setRunOncePerLight(false);
00403         else if (vecparams[0]=="once_per_light")
00404         {
00405             if (vecparams.size() == 2)
00406             {
00407                 // Parse light type
00408                 if (vecparams[1] == "directional")
00409                 {
00410                     context.pass->setRunOncePerLight(true, true, Light::LT_DIRECTIONAL);
00411                 }
00412                 else if (vecparams[1] == "point")
00413                 {
00414                     context.pass->setRunOncePerLight(true, true, Light::LT_POINT);
00415                 }
00416                 else if (vecparams[1] == "spot")
00417                 {
00418                     context.pass->setRunOncePerLight(true, true, Light::LT_SPOTLIGHT);
00419                 }
00420                 else
00421                 {
00422                     logParseError("Bad iteration attribute, valid values for second parameter "
00423                         "are 'point' or 'directional' or 'spot'.", context);
00424                 }
00425             }
00426             else
00427             {
00428                 context.pass->setRunOncePerLight(true, false);
00429             }
00430 
00431         }
00432         else
00433             logParseError(
00434                 "Bad iteration attribute, valid parameters are 'once' or 'once_per_light'.", context);
00435         return false;
00436     }
00437     //-----------------------------------------------------------------------
00438     bool parseFogging(String& params, MaterialScriptContext& context)
00439     {
00440         params.toLowerCase();
00441         StringVector vecparams = params.split(" \t");
00442         if (vecparams[0]=="true")
00443         {
00444             // if true, we need to see if they supplied all arguments, or just the 1... if just the one,
00445             // Assume they want to disable the default fog from effecting this material.
00446             if( vecparams.size() == 8 )
00447             {
00448                 FogMode mFogtype;
00449                 if( vecparams[1] == "none" )
00450                     mFogtype = FOG_NONE;
00451                 else if( vecparams[1] == "linear" )
00452                     mFogtype = FOG_LINEAR;
00453                 else if( vecparams[1] == "exp" )
00454                     mFogtype = FOG_EXP;
00455                 else if( vecparams[1] == "exp2" )
00456                     mFogtype = FOG_EXP2;
00457                 else
00458                 {
00459                     logParseError(
00460                         "Bad fogging attribute, valid parameters are "
00461                         "'none', 'linear', 'exp', or 'exp2'.", context);
00462                     return false;
00463                 }
00464 
00465                 context.pass->setFog(
00466                     true,
00467                     mFogtype,
00468                     ColourValue(
00469                     StringConverter::parseReal(vecparams[2]),
00470                     StringConverter::parseReal(vecparams[3]),
00471                     StringConverter::parseReal(vecparams[4])),
00472                     StringConverter::parseReal(vecparams[5]),
00473                     StringConverter::parseReal(vecparams[6]),
00474                     StringConverter::parseReal(vecparams[7])
00475                     );
00476             }
00477             else
00478             {
00479                 context.pass->setFog(true);
00480             }
00481         }
00482         else if (vecparams[0]=="false")
00483             context.pass->setFog(false);
00484         else
00485             logParseError(
00486                 "Bad fog_override attribute, valid parameters are 'true' or 'false'.", 
00487                 context);
00488 
00489         return false;
00490     }
00491     //-----------------------------------------------------------------------
00492     bool parseShading(String& params, MaterialScriptContext& context)
00493     {
00494         params.toLowerCase();
00495         if (params=="flat")
00496             context.pass->setShadingMode(SO_FLAT);
00497         else if (params=="gouraud")
00498             context.pass->setShadingMode(SO_GOURAUD);
00499         else if (params=="phong")
00500             context.pass->setShadingMode(SO_PHONG);
00501         else
00502             logParseError("Bad shading attribute, valid parameters are 'flat', "
00503                 "'gouraud' or 'phong'.", context);
00504 
00505         return false;
00506     }
00507     //-----------------------------------------------------------------------
00508     bool parseFiltering(String& params, MaterialScriptContext& context)
00509     {
00510         params.toLowerCase();
00511         StringVector vecparams = params.split(" \t");
00512         // Must be 1 or 3 parameters 
00513         if (vecparams.size() == 1)
00514         {
00515             // Simple format
00516             if (vecparams[0]=="none")
00517                 context.textureUnit->setTextureFiltering(TFO_NONE);
00518             else if (vecparams[0]=="bilinear")
00519                 context.textureUnit->setTextureFiltering(TFO_BILINEAR);
00520             else if (vecparams[0]=="trilinear")
00521                 context.textureUnit->setTextureFiltering(TFO_TRILINEAR);
00522             else if (vecparams[0]=="anisotropic")
00523                 context.textureUnit->setTextureFiltering(TFO_ANISOTROPIC);
00524             else
00525             {
00526                 logParseError("Bad filtering attribute, valid parameters for simple format are "
00527                     "'none', 'bilinear', 'trilinear' or 'anisotropic'.", context);
00528                 return false;
00529             }
00530         }
00531         else if (vecparams.size() == 3)
00532         {
00533             // Complex format
00534             context.textureUnit->setTextureFiltering(
00535                 convertFiltering(vecparams[0]), 
00536                 convertFiltering(vecparams[1]), 
00537                 convertFiltering(vecparams[2]));
00538 
00539 
00540         }
00541         else
00542         {
00543             logParseError(
00544                 "Bad filtering attribute, wrong number of parameters (expected 1 or 3)", 
00545                 context);
00546         }
00547 
00548         return false;
00549     }
00550     //-----------------------------------------------------------------------
00551     // Texture layer attributes
00552     bool parseTexture(String& params, MaterialScriptContext& context)
00553     {
00554         StringVector vecparams = params.split(" \t");
00555         if (vecparams.size() > 2)
00556         {
00557             logParseError("Invalid texture attribute - expected only 1 or 2 parameters.", 
00558                 context);
00559         }
00560         TextureType tt = TEX_TYPE_2D;
00561         if (vecparams.size() == 2)
00562         {
00563             vecparams[1].toLowerCase();
00564             if (vecparams[1] == "1d")
00565             {
00566                 tt = TEX_TYPE_1D;
00567             }
00568             else if (vecparams[1] == "2d")
00569             {
00570                 tt = TEX_TYPE_2D;
00571             }
00572             else if (vecparams[1] == "3d")
00573             {
00574                 tt = TEX_TYPE_3D;
00575             }
00576             else if (vecparams[1] == "cubic")
00577             {
00578                 tt = TEX_TYPE_CUBE_MAP;
00579             }
00580         }
00581         context.textureUnit->setTextureName(vecparams[0], tt);
00582         return false;
00583     }
00584     //-----------------------------------------------------------------------
00585     bool parseAnimTexture(String& params, MaterialScriptContext& context)
00586     {
00587         StringVector vecparams = params.split(" \t");
00588         size_t numParams = vecparams.size();
00589         // Determine which form it is
00590         // Must have at least 3 params though
00591         if (numParams < 3)
00592         {
00593             logParseError("Bad anim_texture attribute, wrong number of parameters "
00594                 "(expected at least 3)", context);
00595             return false;
00596         }
00597         if (numParams == 3 && StringConverter::parseInt(vecparams[1]) != 0 )
00598         {
00599             // First form using base name & number of frames
00600             context.textureUnit->setAnimatedTextureName(
00601                 vecparams[0], 
00602                 StringConverter::parseInt(vecparams[1]), 
00603                 StringConverter::parseReal(vecparams[2]));
00604         }
00605         else
00606         {
00607             // Second form using individual names
00608             context.textureUnit->setAnimatedTextureName(
00609                 (String*)&vecparams[0], 
00610                 numParams-1, 
00611                 StringConverter::parseReal(vecparams[numParams-1]));
00612         }
00613         return false;
00614 
00615     }
00616     //-----------------------------------------------------------------------
00617     bool parseCubicTexture(String& params, MaterialScriptContext& context)
00618     {
00619 
00620         StringVector vecparams = params.split(" \t");
00621         size_t numParams = vecparams.size();
00622 
00623         // Get final param
00624         bool useUVW;
00625         String uvOpt = vecparams[numParams-1].toLowerCase();
00626         if (uvOpt == "combineduvw")
00627             useUVW = true;
00628         else if (uvOpt == "separateuv")
00629             useUVW = false;
00630         else
00631         {
00632             logParseError("Bad cubic_texture attribute, final parameter must be "
00633                 "'combinedUVW' or 'separateUV'.", context);
00634             return false;
00635         }
00636         // Determine which form it is
00637         if (numParams == 2)
00638         {
00639             // First form using base name
00640             context.textureUnit->setCubicTextureName(vecparams[0], useUVW);
00641         }
00642         else if (numParams == 7)
00643         {
00644             // Second form using individual names
00645             // Can use vecparams[0] as array start point
00646             context.textureUnit->setCubicTextureName((String*)&vecparams[0], useUVW);
00647         }
00648         else
00649         {
00650             logParseError(
00651                 "Bad cubic_texture attribute, wrong number of parameters (expected 2 or 7)", 
00652                 context);
00653             return false;
00654         }
00655 
00656         return false;
00657     }
00658     //-----------------------------------------------------------------------
00659     bool parseTexCoord(String& params, MaterialScriptContext& context)
00660     {
00661         context.textureUnit->setTextureCoordSet(
00662             StringConverter::parseInt(params));
00663 
00664         return false;
00665     }
00666     //-----------------------------------------------------------------------
00667     bool parseTexAddressMode(String& params, MaterialScriptContext& context)
00668     {
00669         params.toLowerCase();
00670         if (params=="wrap")
00671             context.textureUnit->setTextureAddressingMode(TextureUnitState::TAM_WRAP);
00672         else if (params=="mirror")
00673             context.textureUnit->setTextureAddressingMode(TextureUnitState::TAM_MIRROR);
00674         else if (params=="clamp")
00675             context.textureUnit->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
00676         else
00677             logParseError("Bad tex_address_mode attribute, valid parameters are "
00678                 "'wrap', 'clamp' or 'mirror'.", context);
00679 
00680         return false;
00681     }
00682     //-----------------------------------------------------------------------
00683     bool parseColourOp(String& params, MaterialScriptContext& context)
00684     {
00685         params.toLowerCase();
00686         if (params=="replace")
00687             context.textureUnit->setColourOperation(LBO_REPLACE);
00688         else if (params=="add")
00689             context.textureUnit->setColourOperation(LBO_ADD);
00690         else if (params=="modulate")
00691             context.textureUnit->setColourOperation(LBO_MODULATE);
00692         else if (params=="alpha_blend")
00693             context.textureUnit->setColourOperation(LBO_ALPHA_BLEND);
00694         else
00695             logParseError("Bad colour_op attribute, valid parameters are "
00696                 "'replace', 'add', 'modulate' or 'alpha_blend'.", context);
00697 
00698         return false;
00699     }
00700     //-----------------------------------------------------------------------
00701     bool parseAlphaRejection(String& params, MaterialScriptContext& context)
00702     {
00703         params.toLowerCase();
00704         StringVector vecparams = params.split(" \t");
00705         if (vecparams.size() != 2)
00706         {
00707             logParseError(
00708                 "Bad alpha_rejection attribute, wrong number of parameters (expected 2)", 
00709                 context);
00710             return false;
00711         }
00712 
00713         CompareFunction cmp;
00714         try {
00715             cmp = convertCompareFunction(vecparams[0]);
00716         }
00717         catch (...)
00718         {
00719             logParseError("Bad alpha_rejection attribute, invalid compare function.", context);
00720             return false;
00721         }
00722 
00723         context.textureUnit->setAlphaRejectSettings(cmp, StringConverter::parseInt(vecparams[1]));
00724 
00725         return false;
00726     }
00727     //-----------------------------------------------------------------------
00728     LayerBlendOperationEx convertBlendOpEx(const String& param)
00729     {
00730         if (param == "source1")
00731             return LBX_SOURCE1;
00732         else if (param == "source2")
00733             return LBX_SOURCE2;
00734         else if (param == "modulate")
00735             return LBX_MODULATE;
00736         else if (param == "modulate_x2")
00737             return LBX_MODULATE_X2;
00738         else if (param == "modulate_x4")
00739             return LBX_MODULATE_X4;
00740         else if (param == "add")
00741             return LBX_ADD;
00742         else if (param == "add_signed")
00743             return LBX_ADD_SIGNED;
00744         else if (param == "add_smooth")
00745             return LBX_ADD_SMOOTH;
00746         else if (param == "subtract")
00747             return LBX_SUBTRACT;
00748         else if (param == "blend_diffuse_alpha")
00749             return LBX_BLEND_DIFFUSE_ALPHA;
00750         else if (param == "blend_texture_alpha")
00751             return LBX_BLEND_TEXTURE_ALPHA;
00752         else if (param == "blend_current_alpha")
00753             return LBX_BLEND_CURRENT_ALPHA;
00754         else if (param == "blend_manual")
00755             return LBX_BLEND_MANUAL;
00756         else if (param == "dotproduct")
00757             return LBX_DOTPRODUCT;
00758         else
00759             Except(Exception::ERR_INVALIDPARAMS, "Invalid blend function", "convertBlendOpEx");
00760     }
00761     //-----------------------------------------------------------------------
00762     LayerBlendSource convertBlendSource(const String& param)
00763     {
00764         if (param == "src_current")
00765             return LBS_CURRENT;
00766         else if (param == "src_texture")
00767             return LBS_TEXTURE;
00768         else if (param == "src_diffuse")
00769             return LBS_DIFFUSE;
00770         else if (param == "src_specular")
00771             return LBS_SPECULAR;
00772         else if (param == "src_manual")
00773             return LBS_MANUAL;
00774         else
00775             Except(Exception::ERR_INVALIDPARAMS, "Invalid blend source", "convertBlendSource");
00776     }
00777     //-----------------------------------------------------------------------
00778     bool parseColourOpEx(String& params, MaterialScriptContext& context)
00779     {
00780         params.toLowerCase();
00781         StringVector vecparams = params.split(" \t");
00782         size_t numParams = vecparams.size();
00783 
00784         if (numParams < 3 || numParams > 10)
00785         {
00786             logParseError(
00787                 "Bad colour_op_ex attribute, wrong number of parameters (expected 3 to 10)", 
00788                 context);
00789             return false;
00790         }
00791         LayerBlendOperationEx op;
00792         LayerBlendSource src1, src2;
00793         Real manual = 0.0;
00794         ColourValue colSrc1 = ColourValue::White;
00795         ColourValue colSrc2 = ColourValue::White;
00796 
00797         try {
00798             op = convertBlendOpEx(vecparams[0]);
00799             src1 = convertBlendSource(vecparams[1]);
00800             src2 = convertBlendSource(vecparams[2]);
00801 
00802             if (op == LBX_BLEND_MANUAL)
00803             {
00804                 if (numParams < 4)
00805                 {
00806                     logParseError("Bad colour_op_ex attribute, wrong number of parameters "
00807                         "(expected 4 for manual blend)", context);
00808                     return false;
00809                 }
00810                 manual = StringConverter::parseReal(vecparams[4]);
00811             }
00812 
00813             if (src1 == LBS_MANUAL)
00814             {
00815                 unsigned int parIndex = 3;
00816                 if (op == LBX_BLEND_MANUAL)
00817                     parIndex++;
00818 
00819                 if (numParams < parIndex + 3)
00820                 {
00821                     logParseError("Bad colour_op_ex attribute, wrong number of parameters "
00822                         "(expected " + StringConverter::toString(parIndex + 3) + ")", context);
00823                     return false;
00824                 }
00825 
00826                 colSrc1.r = StringConverter::parseReal(vecparams[parIndex++]);
00827                 colSrc1.g = StringConverter::parseReal(vecparams[parIndex++]);
00828                 colSrc1.b = StringConverter::parseReal(vecparams[parIndex]);
00829             }
00830 
00831             if (src2 == LBS_MANUAL)
00832             {
00833                 unsigned int parIndex = 3;
00834                 if (op == LBX_BLEND_MANUAL)
00835                     parIndex++;
00836                 if (src1 == LBS_MANUAL)
00837                     parIndex += 3;
00838 
00839                 if (numParams < parIndex + 3)
00840                 {
00841                     logParseError("Bad colour_op_ex attribute, wrong number of parameters "
00842                         "(expected " + StringConverter::toString(parIndex + 3) + ")", context);
00843                     return false;
00844                 }
00845 
00846                 colSrc2.r = StringConverter::parseReal(vecparams[parIndex++]);
00847                 colSrc2.g = StringConverter::parseReal(vecparams[parIndex++]);
00848                 colSrc2.b = StringConverter::parseReal(vecparams[parIndex]);
00849             }
00850         }
00851         catch (Exception& e)
00852         {
00853             logParseError("Bad colour_op_ex attribute, " + e.getFullDescription(), context);
00854             return false;
00855         }
00856 
00857         context.textureUnit->setColourOperationEx(op, src1, src2, colSrc1, colSrc2, manual);
00858         return false;
00859     }
00860     //-----------------------------------------------------------------------
00861     bool parseColourOpFallback(String& params, MaterialScriptContext& context)
00862     {
00863         params.toLowerCase();
00864         StringVector vecparams = params.split(" \t");
00865         if (vecparams.size() != 2)
00866         {
00867             logParseError("Bad colour_op_multipass_fallback attribute, wrong number "
00868                 "of parameters (expected 2)", context);
00869             return false;
00870         }
00871 
00872         //src/dest
00873         SceneBlendFactor src, dest;
00874 
00875         try {
00876             src = convertBlendFactor(vecparams[0]);
00877             dest = convertBlendFactor(vecparams[1]);
00878             context.textureUnit->setColourOpMultipassFallback(src,dest);
00879         }
00880         catch (Exception& e)
00881         {
00882             logParseError("Bad colour_op_multipass_fallback attribute, " 
00883                 + e.getFullDescription(), context);
00884         }
00885         return false;
00886     }
00887     //-----------------------------------------------------------------------
00888     bool parseAlphaOpEx(String& params, MaterialScriptContext& context)
00889     {
00890         params.toLowerCase();
00891         StringVector vecparams = params.split(" \t");
00892         size_t numParams = vecparams.size();
00893         if (numParams < 3 || numParams > 6)
00894         {
00895             logParseError("Bad alpha_op_ex attribute, wrong number of parameters "
00896                 "(expected 3 to 6)", context);
00897             return false;
00898         }
00899         LayerBlendOperationEx op;
00900         LayerBlendSource src1, src2;
00901         Real manual = 0.0;
00902         Real arg1 = 1.0, arg2 = 1.0;
00903 
00904         try {
00905             op = convertBlendOpEx(vecparams[0]);
00906             src1 = convertBlendSource(vecparams[1]);
00907             src2 = convertBlendSource(vecparams[2]);
00908             if (op == LBX_BLEND_MANUAL)
00909             {
00910                 if (numParams != 4)
00911                 {
00912                     logParseError("Bad alpha_op_ex attribute, wrong number of parameters "
00913                         "(expected 4 for manual blend)", context);
00914                     return false;
00915                 }
00916                 manual = StringConverter::parseReal(vecparams[4]);
00917             }
00918             if (src1 == LBS_MANUAL)
00919             {
00920                 unsigned int parIndex = 3;
00921                 if (op == LBX_BLEND_MANUAL)
00922                     parIndex++;
00923 
00924                 if (numParams < parIndex)
00925                 {
00926                     logParseError(
00927                         "Bad alpha_op_ex attribute, wrong number of parameters (expected " + 
00928                         StringConverter::toString(parIndex - 1) + ")", context);
00929                     return false;
00930                 }
00931 
00932                 arg1 = StringConverter::parseReal(vecparams[parIndex]);
00933             }
00934 
00935             if (src2 == LBS_MANUAL)
00936             {
00937                 unsigned int parIndex = 3;
00938                 if (op == LBX_BLEND_MANUAL)
00939                     parIndex++;
00940                 if (src1 == LBS_MANUAL)
00941                     parIndex++;
00942 
00943                 if (numParams < parIndex)
00944                 {
00945                     logParseError(
00946                         "Bad alpha_op_ex attribute, wrong number of parameters "
00947                         "(expected " + StringConverter::toString(parIndex - 1) + ")", context);
00948                     return false;
00949                 }
00950 
00951                 arg2 = StringConverter::parseReal(vecparams[parIndex]);
00952             }
00953         }
00954         catch (Exception& e)
00955         {
00956             logParseError("Bad alpha_op_ex attribute, " + e.getFullDescription(), context);
00957             return false;
00958         }
00959 
00960         context.textureUnit->setAlphaOperation(op, src1, src2, arg1, arg2, manual);
00961         return false;
00962     }
00963     //-----------------------------------------------------------------------
00964     bool parseEnvMap(String& params, MaterialScriptContext& context)
00965     {
00966         params.toLowerCase();
00967         if (params=="off")
00968             context.textureUnit->setEnvironmentMap(false);
00969         else if (params=="spherical")
00970             context.textureUnit->setEnvironmentMap(true, TextureUnitState::ENV_CURVED);
00971         else if (params=="planar")
00972             context.textureUnit->setEnvironmentMap(true, TextureUnitState::ENV_PLANAR);
00973         else if (params=="cubic_reflection")
00974             context.textureUnit->setEnvironmentMap(true, TextureUnitState::ENV_REFLECTION);
00975         else if (params=="cubic_normal")
00976             context.textureUnit->setEnvironmentMap(true, TextureUnitState::ENV_NORMAL);
00977         else
00978             logParseError("Bad env_map attribute, valid parameters are 'off', "
00979                 "'spherical', 'planar', 'cubic_reflection' and 'cubic_normal'.", context);
00980 
00981         return false;
00982     }
00983     //-----------------------------------------------------------------------
00984     bool parseScroll(String& params, MaterialScriptContext& context)
00985     {
00986         StringVector vecparams = params.split(" \t");
00987         if (vecparams.size() != 2)
00988         {
00989             logParseError("Bad scroll attribute, wrong number of parameters (expected 2)", context);
00990             return false;
00991         }
00992         context.textureUnit->setTextureScroll(
00993             StringConverter::parseReal(vecparams[0]), 
00994             StringConverter::parseReal(vecparams[1]));
00995 
00996     
00997         return false;
00998     }
00999     //-----------------------------------------------------------------------
01000     bool parseScrollAnim(String& params, MaterialScriptContext& context)
01001     {
01002         StringVector vecparams = params.split(" \t");
01003         if (vecparams.size() != 2)
01004         {
01005             logParseError("Bad scroll_anim attribute, wrong number of "
01006                 "parameters (expected 2)", context);
01007             return false;
01008         }
01009         context.textureUnit->setScrollAnimation(
01010             StringConverter::parseReal(vecparams[0]), 
01011             StringConverter::parseReal(vecparams[1]));
01012 
01013         return false;
01014     }
01015     //-----------------------------------------------------------------------
01016     bool parseRotate(String& params, MaterialScriptContext& context)
01017     {
01018         context.textureUnit->setTextureRotate(
01019             StringConverter::parseReal(params));
01020 
01021         return false;
01022     }
01023     //-----------------------------------------------------------------------
01024     bool parseRotateAnim(String& params, MaterialScriptContext& context)
01025     {
01026         context.textureUnit->setRotateAnimation(
01027             StringConverter::parseReal(params));
01028 
01029         return false;
01030     }
01031     //-----------------------------------------------------------------------
01032     bool parseScale(String& params, MaterialScriptContext& context)
01033     {
01034         StringVector vecparams = params.split(" \t");
01035         if (vecparams.size() != 2)
01036         {
01037             logParseError("Bad scale attribute, wrong number of parameters (expected 2)", context);
01038             return false;
01039         }
01040         context.textureUnit->setTextureScale(
01041             StringConverter::parseReal(vecparams[0]), 
01042             StringConverter::parseReal(vecparams[1]));
01043 
01044         return false;
01045     }
01046     //-----------------------------------------------------------------------
01047     bool parseWaveXform(String& params, MaterialScriptContext& context)
01048     {
01049         params.toLowerCase();
01050         StringVector vecparams = params.split(" \t");
01051 
01052         if (vecparams.size() != 6)
01053         {
01054             logParseError("Bad wave_xform attribute, wrong number of parameters "
01055                 "(expected 6)", context);
01056             return false;
01057         }
01058         TextureUnitState::TextureTransformType ttype;
01059         WaveformType waveType;
01060         // Check transform type
01061         if (vecparams[0]=="scroll_x")
01062             ttype = TextureUnitState::TT_TRANSLATE_U;
01063         else if (vecparams[0]=="scroll_y")
01064             ttype = TextureUnitState::TT_TRANSLATE_V;
01065         else if (vecparams[0]=="rotate")
01066             ttype = TextureUnitState::TT_ROTATE;
01067         else if (vecparams[0]=="scale_x")
01068             ttype = TextureUnitState::TT_SCALE_U;
01069         else if (vecparams[0]=="scale_y")
01070             ttype = TextureUnitState::TT_SCALE_V;
01071         else
01072         {
01073             logParseError("Bad wave_xform attribute, parameter 1 must be 'scroll_x', "
01074                 "'scroll_y', 'rotate', 'scale_x' or 'scale_y'", context);
01075             return false;
01076         }
01077         // Check wave type
01078         if (vecparams[1]=="sine")
01079             waveType = WFT_SINE;
01080         else if (vecparams[1]=="triangle")
01081             waveType = WFT_TRIANGLE;
01082         else if (vecparams[1]=="square")
01083             waveType = WFT_SQUARE;
01084         else if (vecparams[1]=="sawtooth")
01085             waveType = WFT_SAWTOOTH;
01086         else if (vecparams[1]=="inverse_sawtooth")
01087             waveType = WFT_INVERSE_SAWTOOTH;
01088         else
01089         {
01090             logParseError("Bad wave_xform attribute, parameter 2 must be 'sine', "
01091                 "'triangle', 'square', 'sawtooth' or 'inverse_sawtooth'", context);
01092             return false;
01093         }
01094 
01095         context.textureUnit->setTransformAnimation(
01096             ttype, 
01097             waveType, 
01098             StringConverter::parseReal(vecparams[2]), 
01099             StringConverter::parseReal(vecparams[3]),
01100             StringConverter::parseReal(vecparams[4]), 
01101             StringConverter::parseReal(vecparams[5]) );
01102 
01103         return false;
01104     }
01105     //-----------------------------------------------------------------------
01106     bool parseDepthBias(String& params, MaterialScriptContext& context)
01107     {
01108         context.pass->setDepthBias(
01109             StringConverter::parseReal(params));
01110 
01111         return false;
01112     }
01113     //-----------------------------------------------------------------------
01114     bool parseAnisotropy(String& params, MaterialScriptContext& context)
01115     {
01116         context.textureUnit->setTextureAnisotropy(
01117             StringConverter::parseInt(params));
01118 
01119         return false;
01120     }
01121     //-----------------------------------------------------------------------
01122     bool parseLodDistances(String& params, MaterialScriptContext& context)
01123     {
01124         StringVector vecparams = params.split(" \t");
01125 
01126         // iterate over the parameters and parse distances out of them
01127         Material::LodDistanceList lodList;
01128         StringVector::iterator i, iend;
01129         iend = vecparams.end();
01130         for (i = vecparams.begin(); i != iend; ++i)
01131         {
01132             lodList.push_back(StringConverter::parseReal(*i));
01133         }
01134 
01135         context.material->setLodLevels(lodList);
01136 
01137         return false;
01138     }
01139     //-----------------------------------------------------------------------
01140     bool parseLodIndex(String& params, MaterialScriptContext& context)
01141     {
01142         context.technique->setLodIndex(StringConverter::parseInt(params));
01143         return false;
01144     }
01145     //-----------------------------------------------------------------------
01146     void processManualProgramParam(size_t index, const String& commandname, 
01147         StringVector& vecparams, MaterialScriptContext& context)
01148     {
01149         // NB we assume that the first element of vecparams is taken up with either 
01150         // the index or the parameter name, which we ignore
01151 
01152         // Determine type
01153         size_t start, dims, i;
01154         bool isReal;
01155 
01156         vecparams[1].toLowerCase();
01157 
01158         if (vecparams[1] == "matrix4x4")
01159         {
01160             dims = 16;
01161             isReal = true;
01162         }
01163         else if ((start = vecparams[1].find("float")) != String::npos)
01164         {
01165             // find the dimensionality
01166             start = vecparams[1].find_first_not_of("float");
01167             dims = StringConverter::parseInt(vecparams[1].substr(start));
01168             isReal = true;
01169         }
01170         else if ((start = vecparams[1].find("int")) != String::npos)
01171         {
01172             // find the dimensionality
01173             start = vecparams[1].find_first_not_of("int");
01174             dims = StringConverter::parseInt(vecparams[1].substr(start));
01175             isReal = false;
01176         }
01177         else
01178         {
01179             logParseError("Invalid " + commandname + " attribute - unrecognised "
01180                 "parameter type " + vecparams[1], context);
01181             return;
01182         }
01183 
01184         if (vecparams.size() != 2 + dims)
01185         {
01186             logParseError("Invalid " + commandname + " attribute - you need " +
01187                 StringConverter::toString(2 + dims) + " parameters for a parameter of "
01188                 "type " + vecparams[1], context);
01189         }
01190 
01191         if (dims % 4 != 0)
01192         {
01193             logParseError("Invalid " + commandname + " attribute; parameter type must "
01194                 "have a cardinality which is a multiple of 4", context);
01195         }
01196 
01197         // Now parse all the values
01198         if (isReal)
01199         {
01200             Real* realBuffer = new Real[dims];
01201             for (i = 0; i < dims; ++i)
01202             {
01203                 realBuffer[i] = StringConverter::parseReal(vecparams[i+2]);
01204             }
01205             // Set
01206             context.programParams->setConstant(index, realBuffer, dims * 0.25);
01207             delete [] realBuffer;
01208         }
01209         else
01210         {
01211             int* intBuffer = new int[dims];
01212             for (i = 0; i < dims; ++i)
01213             {
01214                 intBuffer[i] = StringConverter::parseInt(vecparams[i+2]);
01215             }
01216             // Set
01217             context.programParams->setConstant(index, intBuffer, dims * 0.25);
01218             delete [] intBuffer;
01219         }
01220     }
01221     //-----------------------------------------------------------------------
01222     void processAutoProgramParam(size_t index, const String& commandname, 
01223         StringVector& vecparams, MaterialScriptContext& context)
01224     {
01225         // NB we assume that the first element of vecparams is taken up with either 
01226         // the index or the parameter name, which we ignore
01227 
01228         bool extras = false;
01229         GpuProgramParameters::AutoConstantType acType;
01230 
01231         vecparams[1].toLowerCase();
01232 
01233         if (vecparams[1] == "world_matrix")
01234         {
01235             acType = GpuProgramParameters::ACT_WORLD_MATRIX;
01236         }
01237         else if (vecparams[1] == "world_matrix_array")
01238         {
01239             acType = GpuProgramParameters::ACT_WORLD_MATRIX_ARRAY;
01240         }
01241         else if (vecparams[1] == "world_matrix_array_3x4")
01242         {
01243             acType = GpuProgramParameters::ACT_WORLD_MATRIX_ARRAY_3x4;
01244         }
01245         else if (vecparams[1] == "view_matrix")
01246         {
01247             acType = GpuProgramParameters::ACT_VIEW_MATRIX;
01248         }
01249         else if (vecparams[1] == "viewproj_matrix")
01250         {
01251             acType = GpuProgramParameters::ACT_VIEWPROJ_MATRIX;
01252         }
01253         else if (vecparams[1] == "worldview_matrix")
01254         {
01255             acType = GpuProgramParameters::ACT_WORLDVIEW_MATRIX;
01256         }
01257         else if (vecparams[1] == "worldviewproj_matrix")
01258         {
01259             acType = GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX;
01260         }
01261         else if (vecparams[1] == "inverse_world_matrix")
01262         {
01263             acType = GpuProgramParameters::ACT_INVERSE_WORLD_MATRIX;
01264         }
01265         else if (vecparams[1] == "inverse_worldview_matrix")
01266         {
01267             acType = GpuProgramParameters::ACT_INVERSE_WORLDVIEW_MATRIX;
01268         }
01269         else if (vecparams[1] == "light_diffuse_colour")
01270         {
01271             acType = GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR;
01272             extras = true;
01273         }
01274         else if (vecparams[1] == "light_specular_colour")
01275         {
01276             acType = GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR;
01277             extras = true;
01278         }
01279         else if (vecparams[1] == "light_attenuation")
01280         {
01281             acType = GpuProgramParameters::ACT_LIGHT_ATTENUATION;
01282             extras = true;
01283         }
01284         else if (vecparams[1] == "light_position")
01285         {
01286             acType = GpuProgramParameters::ACT_LIGHT_POSITION;
01287             extras = true;
01288         }
01289         else if (vecparams[1] == "light_direction")
01290         {
01291             acType = GpuProgramParameters::ACT_LIGHT_DIRECTION;
01292             extras = true;
01293         }
01294         else if (vecparams[1] == "light_position_object_space")
01295         {
01296             acType = GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE;
01297             extras = true;
01298         }
01299         else if (vecparams[1] == "light_direction_object_space")
01300         {
01301             acType = GpuProgramParameters::ACT_LIGHT_DIRECTION_OBJECT_SPACE;
01302             extras = true;
01303         }
01304         else if (vecparams[1] == "ambient_light_colour")
01305         {
01306             acType = GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR;
01307         }
01308         else if (vecparams[1] == "camera_position_object_space")
01309         {
01310             acType = GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE;
01311         }
01312         else if (vecparams[1] == "texture_viewproj_matrix")
01313         {
01314             acType = GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX;
01315         }
01316         else if (vecparams[1] == "time")
01317         {
01318             // Special case!
01319             Real factor = 1.0f;
01320             if (vecparams.size() == 3)
01321             {
01322                 factor = StringConverter::parseReal(vecparams[2]);
01323             }
01324             
01325             context.programParams->setConstantFromTime(index, factor);
01326             return;
01327         }
01328 
01329         // Do we need any extra parameters?
01330         size_t extraParam = 0;
01331         if (extras)
01332         {
01333             if (vecparams.size() != 3)
01334             {
01335                 logParseError("Invalid " + commandname + " attribute - "
01336                     "expected 3 parameters.", context);
01337                 return;
01338             }
01339             extraParam = StringConverter::parseInt(vecparams[2]);
01340         }
01341 
01342         context.programParams->setAutoConstant(index, acType, extraParam);
01343     }
01344     //-----------------------------------------------------------------------
01345     bool parseParamIndexed(String& params, MaterialScriptContext& context)
01346     {
01347         // NB skip this if the program is not supported or could not be found
01348         if (!context.program || !context.program->isSupported())
01349         {
01350             return false;
01351         }
01352 
01353         params.toLowerCase();
01354         StringVector vecparams = params.split(" \t");
01355         if (vecparams.size() < 3)
01356         {
01357             logParseError("Invalid param_indexed attribute - expected at least 3 parameters.", 
01358                 context);
01359             return false;
01360         }
01361 
01362         // Get start index
01363         size_t index = StringConverter::parseInt(vecparams[0]);
01364 
01365         processManualProgramParam(index, "param_indexed", vecparams, context);
01366 
01367         return false;
01368     }
01369     //-----------------------------------------------------------------------
01370     bool parseParamIndexedAuto(String& params, MaterialScriptContext& context)
01371     {
01372         // NB skip this if the program is not supported or could not be found
01373         if (!context.program || !context.program->isSupported())
01374         {
01375             return false;
01376         }
01377 
01378         params.toLowerCase();
01379         StringVector vecparams = params.split(" \t");
01380         if (vecparams.size() != 2 && vecparams.size() != 3)
01381         {
01382             logParseError("Invalid param_indexed_auto attribute - expected 2 or 3 parameters.", 
01383                 context);
01384             return false;
01385         }
01386 
01387         // Get start index
01388         size_t index = StringConverter::parseInt(vecparams[0]);
01389 
01390         processAutoProgramParam(index, "param_indexed_auto", vecparams, context);
01391 
01392         return false;
01393     }
01394     //-----------------------------------------------------------------------
01395     bool parseParamNamed(String& params, MaterialScriptContext& context)
01396     {
01397         // NB skip this if the program is not supported or could not be found
01398         if (!context.program || !context.program->isSupported())
01399         {
01400             return false;
01401         }
01402 
01403         StringVector vecparams = params.split(" \t");
01404         if (vecparams.size() < 3)
01405         {
01406             logParseError("Invalid param_named attribute - expected at least 3 parameters.", 
01407                 context);
01408             return false;
01409         }
01410 
01411         // Get start index from name
01412         size_t index;
01413         try {
01414             index = context.programParams->getParamIndex(vecparams[0]);
01415         }
01416         catch (Exception& e)
01417         {
01418             logParseError("Invalid param_named attribute - " + e.getFullDescription(), context);
01419             return false;
01420         }
01421 
01422         // TEST
01423         /*
01424         LogManager::getSingleton().logMessage("SETTING PARAMETER " + vecparams[0] + " as index " +
01425             StringConverter::toString(index));
01426         */
01427         processManualProgramParam(index, "param_named", vecparams, context);
01428 
01429         return false;
01430     }
01431     //-----------------------------------------------------------------------
01432     bool parseParamNamedAuto(String& params, MaterialScriptContext& context)
01433     {
01434         // NB skip this if the program is not supported or could not be found
01435         if (!context.program || !context.program->isSupported())
01436         {
01437             return false;
01438         }
01439 
01440         StringVector vecparams = params.split(" \t");
01441         if (vecparams.size() != 2 && vecparams.size() != 3)
01442         {
01443             logParseError("Invalid param_indexed_auto attribute - expected 2 or 3 parameters.", 
01444                 context);
01445             return false;
01446         }
01447 
01448         // Get start index from name
01449         size_t index;
01450         try {
01451             index = context.programParams->getParamIndex(vecparams[0]);
01452         }
01453         catch (Exception& e)
01454         {
01455             logParseError("Invalid param_named_auto attribute - " + e.getFullDescription(), context);
01456             return false;
01457         }
01458 
01459         processAutoProgramParam(index, "param_named_auto", vecparams, context);
01460 
01461         return false;
01462     }
01463     //-----------------------------------------------------------------------
01464     bool parseMaterial(String& params, MaterialScriptContext& context)
01465     {
01466         // Create a brand new material
01467         context.material = static_cast<Material*>(
01468             MaterialManager::getSingleton().create(params));
01469         // Remove pre-created technique from defaults
01470         context.material->removeAllTechniques();
01471 
01472         // update section
01473         context.section = MSS_MATERIAL;
01474 
01475         // Return TRUE because this must be followed by a {
01476         return true;
01477     }
01478     //-----------------------------------------------------------------------
01479     bool parseTechnique(String& params, MaterialScriptContext& context)
01480     {
01481         // Create a new technique
01482         context.technique = context.material->createTechnique();
01483 
01484         // update section
01485         context.section = MSS_TECHNIQUE;
01486 
01487         //Increase technique level depth
01488         context.techLev += 1;
01489 
01490         // Return TRUE because this must be followed by a {
01491         return true;
01492     }
01493     //-----------------------------------------------------------------------
01494     bool parsePass(String& params, MaterialScriptContext& context)
01495     {
01496         // Create a new pass
01497         context.pass = context.technique->createPass();
01498 
01499         // update section
01500         context.section = MSS_PASS;
01501 
01502         //Increase pass level depth
01503         context.passLev += 1;
01504 
01505         // Return TRUE because this must be followed by a {
01506         return true;
01507     }
01508     //-----------------------------------------------------------------------
01509     bool parseTextureUnit(String& params, MaterialScriptContext& context)
01510     {
01511         // Create a new texture unit
01512         context.textureUnit = context.pass->createTextureUnitState();
01513 
01514         // update section
01515         context.section = MSS_TEXTUREUNIT;
01516 
01517         // Increase texture unit depth
01518         context.stateLev += 1;
01519 
01520         // Return TRUE because this must be followed by a {
01521         return true;
01522     }
01523     //-----------------------------------------------------------------------
01524     bool parseVertexProgramRef(String& params, MaterialScriptContext& context)
01525     {
01526         // update section
01527         context.section = MSS_PROGRAM_REF;
01528 
01529         context.program = static_cast<GpuProgram*>(
01530             GpuProgramManager::getSingleton().getByName(params));
01531         if (context.program == 0)
01532         {
01533             // Unknown program
01534             logParseError("Invalid vertex_program_ref entry - vertex program " 
01535                 + params + " has not been defined.", context);
01536             return true;
01537         }
01538 
01539         context.isProgramShadowCaster = false;
01540         context.isProgramShadowReceiver = false;
01541         
01542         // Set the vertex program for this pass
01543         context.pass->setVertexProgram(params);
01544 
01545         // Create params? Skip this if program is not supported
01546         if (context.program->isSupported())
01547         {
01548             context.programParams = context.pass->getVertexProgramParameters();
01549         }
01550 
01551         // Return TRUE because this must be followed by a {
01552         return true;
01553     }
01554     //-----------------------------------------------------------------------
01555     bool parseShadowCasterVertexProgramRef(String& params, MaterialScriptContext& context)
01556     {
01557         // update section
01558         context.section = MSS_PROGRAM_REF;
01559 
01560         context.program = static_cast<GpuProgram*>(
01561             GpuProgramManager::getSingleton().getByName(params));
01562         if (context.program == 0)
01563         {
01564             // Unknown program
01565             logParseError("Invalid vertex_program_ref entry - vertex program " 
01566                 + params + " has not been defined.", context);
01567             return true;
01568         }
01569 
01570         context.isProgramShadowCaster = true;
01571         context.isProgramShadowReceiver = false;
01572 
01573         // Set the vertex program for this pass
01574         context.pass->setShadowCasterVertexProgram(params);
01575 
01576         // Create params? Skip this if program is not supported
01577         if (context.program->isSupported())
01578         {
01579             context.programParams = context.pass->getShadowCasterVertexProgramParameters();
01580         }
01581 
01582         // Return TRUE because this must be followed by a {
01583         return true;
01584     }
01585     //-----------------------------------------------------------------------
01586     bool parseShadowReceiverVertexProgramRef(String& params, MaterialScriptContext& context)
01587     {
01588         // update section
01589         context.section = MSS_PROGRAM_REF;
01590 
01591         context.program = static_cast<GpuProgram*>(
01592             GpuProgramManager::getSingleton().getByName(params));
01593         if (context.program == 0)
01594         {
01595             // Unknown program
01596             logParseError("Invalid vertex_program_ref entry - vertex program " 
01597                 + params + " has not been defined.", context);
01598             return true;
01599         }
01600 
01601         context.isProgramShadowCaster = false;
01602         context.isProgramShadowReceiver = true;
01603 
01604         // Set the vertex program for this pass
01605         context.pass->setShadowReceiverVertexProgram(params);
01606 
01607         // Create params? Skip this if program is not supported
01608         if (context.program->isSupported())
01609         {
01610             context.programParams = context.pass->getShadowReceiverVertexProgramParameters();
01611         }
01612 
01613         // Return TRUE because this must be followed by a {
01614         return true;
01615     }
01616     //-----------------------------------------------------------------------
01617     bool parseFragmentProgramRef(String& params, MaterialScriptContext& context)
01618     {
01619         // update section
01620         context.section = MSS_PROGRAM_REF;
01621 
01622         context.program = static_cast<GpuProgram*>(
01623             GpuProgramManager::getSingleton().getByName(params));
01624         if (context.program == 0)
01625         {
01626             // Unknown program
01627             logParseError("Invalid fragment_program_ref entry - fragment program " 
01628                 + params + " has not been defined.", context);
01629             return true;
01630         }
01631         
01632         // Set the vertex program for this pass
01633         context.pass->setFragmentProgram(params);
01634 
01635         // Create params? Skip this if program is not supported
01636         if (context.program->isSupported())
01637         {
01638             context.programParams = context.pass->getFragmentProgramParameters();
01639         }
01640 
01641         // Return TRUE because this must be followed by a {
01642         return true;
01643     }
01644     //-----------------------------------------------------------------------
01645     bool parseVertexProgram(String& params, MaterialScriptContext& context)
01646     {
01647         // update section
01648         context.section = MSS_PROGRAM;
01649 
01650         // Create new program definition-in-progress
01651         context.programDef = new MaterialScriptProgramDefinition();
01652         context.programDef->progType = GPT_VERTEX_PROGRAM;
01653         context.programDef->supportsSkeletalAnimation = false;
01654 
01655         // Get name and language code
01656         StringVector vecparams = params.split(" \t");
01657         if (vecparams.size() != 2)
01658         {
01659             logParseError("Invalid vertex_program entry - expected "
01660                 "2 parameters.", context);
01661             return true;
01662         }
01663         // Name, preserve case
01664         context.programDef->name = vecparams[0];
01665         // language code, make lower case
01666         context.programDef->language = vecparams[1].toLowerCase();
01667 
01668         // Return TRUE because this must be followed by a {
01669         return true;
01670     }
01671     //-----------------------------------------------------------------------
01672     bool parseFragmentProgram(String& params, MaterialScriptContext& context)
01673     {
01674         // update section
01675         context.section = MSS_PROGRAM;
01676 
01677         // Create new program definition-in-progress
01678         context.programDef = new MaterialScriptProgramDefinition();
01679         context.programDef->progType = GPT_FRAGMENT_PROGRAM;
01680         context.programDef->supportsSkeletalAnimation = false;
01681 
01682         // Get name and language code
01683         StringVector vecparams = params.split(" \t");
01684         if (vecparams.size() != 2)
01685         {
01686             logParseError("Invalid fragment_program entry - expected "
01687                 "2 parameters.", context);
01688             return true;
01689         }
01690         // Name, preserve case
01691         context.programDef->name = vecparams[0];
01692         // language code, make lower case
01693         context.programDef->language = vecparams[1].toLowerCase();
01694 
01695         // Return TRUE because this must be followed by a {
01696         return true;
01697     
01698     }
01699     //-----------------------------------------------------------------------
01700     bool parseProgramSource(String& params, MaterialScriptContext& context)
01701     {
01702         // Source filename, preserve case
01703         context.programDef->source = params;
01704 
01705         return false;
01706     }
01707     //-----------------------------------------------------------------------
01708     bool parseProgramSkeletalAnimation(String& params, MaterialScriptContext& context)
01709     {
01710         // Source filename, preserve case
01711         context.programDef->supportsSkeletalAnimation 
01712             = StringConverter::parseBool(params);
01713 
01714         return false;
01715     }
01716     //-----------------------------------------------------------------------
01717     bool parseProgramSyntax(String& params, MaterialScriptContext& context)
01718     {
01719         // Syntax code, make lower case
01720         context.programDef->syntax = params;
01721 
01722         return false;
01723     }
01724     //-----------------------------------------------------------------------
01725     bool parseProgramCustomParameter(String& params, MaterialScriptContext& context)
01726     {
01727         // This params object does not have the command stripped
01728         // Lower case the command, but not the value incase it's relevant
01729         // Split only up to first delimiter, program deals with the rest
01730         StringVector vecparams = params.split(" \t", 1);
01731         if (vecparams.size() != 2)
01732         {
01733             logParseError("Invalid custom program parameter entry; "
01734                 "there must be a parameter name and at least one value.", 
01735                 context);
01736             return false;
01737         }
01738 
01739         context.programDef->customParameters[vecparams[0]] = vecparams[1];
01740 
01741         return false;
01742     }
01743 
01744     //-----------------------------------------------------------------------
01745     bool parseTextureSource(String& params, MaterialScriptContext& context)
01746     {
01747         params.toLowerCase();
01748         StringVector vecparams = params.split(" \t");
01749         if (vecparams.size() != 1)
01750             logParseError("Invalid texture source attribute - expected 1 parameter.",                 context);
01751         //The only param should identify which ExternalTextureSource is needed
01752         ExternalTextureSourceManager::getSingleton().SetCurrentPlugIn( vecparams[0] );
01753 
01754         if( ExternalTextureSourceManager::getSingleton().getCurrentPlugIn() != 0 )
01755         {
01756             String tps;
01757             tps = StringConverter::toString( context.techLev ) + " "
01758                 + StringConverter::toString( context.passLev ) + " "
01759                 + StringConverter::toString( context.stateLev);
01760 
01761             ExternalTextureSourceManager::getSingleton().getCurrentPlugIn()->setParameter( "set_T_P_S", tps );
01762         }
01763             
01764         // update section
01765         context.section = MSS_TEXTURESOURCE;
01766         // Return TRUE because this must be followed by a {
01767         return true;
01768     }
01769 
01770     //-----------------------------------------------------------------------
01771     bool parseTextureCustomParameter(String& params, MaterialScriptContext& context)
01772     {
01773         // This params object does not have the command stripped
01774         // Split only up to first delimiter, program deals with the rest
01775         StringVector vecparams = params.split(" \t", 1);
01776         if (vecparams.size() != 2)
01777         {
01778             logParseError("Invalid texture parameter entry; "
01779                 "there must be a parameter name and at least one value.", 
01780                 context);
01781             return false;
01782         }
01783         
01784         if( ExternalTextureSourceManager::getSingleton().getCurrentPlugIn() != 0 )
01786             ExternalTextureSourceManager::getSingleton().getCurrentPlugIn()->setParameter( vecparams[0], vecparams[1] );
01787         
01788         return false;
01789     }
01790     //-----------------------------------------------------------------------
01791     bool parseReceiveShadows(String& params, MaterialScriptContext& context)
01792     {
01793         params.toLowerCase();
01794         if (params == "on")
01795             context.material->setReceiveShadows(true);
01796         else if (params == "off")
01797             context.material->setReceiveShadows(false);
01798         else
01799             logParseError(
01800             "Bad receive_shadows attribute, valid parameters are 'on' or 'off'.", 
01801             context);
01802 
01803         return false;
01804 
01805     }
01806     
01807     //-----------------------------------------------------------------------
01808     //-----------------------------------------------------------------------
01809     MaterialSerializer::MaterialSerializer()
01810     {
01811         // Set up root attribute parsers
01812         mRootAttribParsers.insert(AttribParserList::value_type("material", (ATTRIBUTE_PARSER)parseMaterial));
01813         mRootAttribParsers.insert(AttribParserList::value_type("vertex_program", (ATTRIBUTE_PARSER)parseVertexProgram));
01814         mRootAttribParsers.insert(AttribParserList::value_type("fragment_program", (ATTRIBUTE_PARSER)parseFragmentProgram));
01815         // Set up material attribute parsers
01816         mMaterialAttribParsers.insert(AttribParserList::value_type("lod_distances", (ATTRIBUTE_PARSER)parseLodDistances));
01817         mMaterialAttribParsers.insert(AttribParserList::value_type("receive_shadows", (ATTRIBUTE_PARSER)parseReceiveShadows));
01818         mMaterialAttribParsers.insert(AttribParserList::value_type("technique", (ATTRIBUTE_PARSER)parseTechnique));
01819         // Set up technique attribute parsers
01820         mTechniqueAttribParsers.insert(AttribParserList::value_type("lod_index", (ATTRIBUTE_PARSER)parseLodIndex));
01821         mTechniqueAttribParsers.insert(AttribParserList::value_type("pass", (ATTRIBUTE_PARSER)parsePass));
01822         // Set up pass attribute parsers
01823         mPassAttribParsers.insert(AttribParserList::value_type("ambient", (ATTRIBUTE_PARSER)parseAmbient));
01824         mPassAttribParsers.insert(AttribParserList::value_type("diffuse", (ATTRIBUTE_PARSER)parseDiffuse));
01825         mPassAttribParsers.insert(AttribParserList::value_type("specular", (ATTRIBUTE_PARSER)parseSpecular));
01826         mPassAttribParsers.insert(AttribParserList::value_type("emissive", (ATTRIBUTE_PARSER)parseEmissive));
01827         mPassAttribParsers.insert(AttribParserList::value_type("scene_blend", (ATTRIBUTE_PARSER)parseSceneBlend));
01828         mPassAttribParsers.insert(AttribParserList::value_type("depth_check", (ATTRIBUTE_PARSER)parseDepthCheck));
01829         mPassAttribParsers.insert(AttribParserList::value_type("depth_write", (ATTRIBUTE_PARSER)parseDepthWrite));
01830         mPassAttribParsers.insert(AttribParserList::value_type("depth_func", (ATTRIBUTE_PARSER)parseDepthFunc));
01831         mPassAttribParsers.insert(AttribParserList::value_type("colour_write", (ATTRIBUTE_PARSER)parseColourWrite));
01832         mPassAttribParsers.insert(AttribParserList::value_type("cull_hardware", (ATTRIBUTE_PARSER)parseCullHardware));
01833         mPassAttribParsers.insert(AttribParserList::value_type("cull_software", (ATTRIBUTE_PARSER)parseCullSoftware));
01834         mPassAttribParsers.insert(AttribParserList::value_type("lighting", (ATTRIBUTE_PARSER)parseLighting));
01835         mPassAttribParsers.insert(AttribParserList::value_type("fog_override", (ATTRIBUTE_PARSER)parseFogging));
01836         mPassAttribParsers.insert(AttribParserList::value_type("shading", (ATTRIBUTE_PARSER)parseShading));
01837         mPassAttribParsers.insert(AttribParserList::value_type("depth_bias", (ATTRIBUTE_PARSER)parseDepthBias));
01838         mPassAttribParsers.insert(AttribParserList::value_type("texture_unit", (ATTRIBUTE_PARSER)parseTextureUnit));
01839         mPassAttribParsers.insert(AttribParserList::value_type("vertex_program_ref", (ATTRIBUTE_PARSER)parseVertexProgramRef));
01840         mPassAttribParsers.insert(AttribParserList::value_type("shadow_caster_vertex_program_ref", (ATTRIBUTE_PARSER)parseShadowCasterVertexProgramRef));
01841         mPassAttribParsers.insert(AttribParserList::value_type("shadow_receiver_vertex_program_ref", (ATTRIBUTE_PARSER)parseShadowReceiverVertexProgramRef));
01842         mPassAttribParsers.insert(AttribParserList::value_type("fragment_program_ref", (ATTRIBUTE_PARSER)parseFragmentProgramRef));
01843         mPassAttribParsers.insert(AttribParserList::value_type("max_lights", (ATTRIBUTE_PARSER)parseMaxLights));
01844         mPassAttribParsers.insert(AttribParserList::value_type("iteration", (ATTRIBUTE_PARSER)parseIteration));
01845         mTextureUnitAttribParsers.insert(AttribParserList::value_type("texture_source", (ATTRIBUTE_PARSER)parseTextureSource));
01846 
01847         // Set up texture unit attribute parsers
01848         mTextureUnitAttribParsers.insert(AttribParserList::value_type("texture", (ATTRIBUTE_PARSER)parseTexture));
01849         mTextureUnitAttribParsers.insert(AttribParserList::value_type("anim_texture", (ATTRIBUTE_PARSER)parseAnimTexture));
01850         mTextureUnitAttribParsers.insert(AttribParserList::value_type("cubic_texture", (ATTRIBUTE_PARSER)parseCubicTexture));
01851         mTextureUnitAttribParsers.insert(AttribParserList::value_type("tex_coord_set", (ATTRIBUTE_PARSER)parseTexCoord));
01852         mTextureUnitAttribParsers.insert(AttribParserList::value_type("tex_address_mode", (ATTRIBUTE_PARSER)parseTexAddressMode));
01853         mTextureUnitAttribParsers.insert(AttribParserList::value_type("colour_op", (ATTRIBUTE_PARSER)parseColourOp));
01854         mTextureUnitAttribParsers.insert(AttribParserList::value_type("alpha_rejection", (ATTRIBUTE_PARSER)parseAlphaRejection));
01855         mTextureUnitAttribParsers.insert(AttribParserList::value_type("colour_op_ex", (ATTRIBUTE_PARSER)parseColourOpEx));
01856         mTextureUnitAttribParsers.insert(AttribParserList::value_type("colour_op_multipass_fallback", (ATTRIBUTE_PARSER)parseColourOpFallback));
01857         mTextureUnitAttribParsers.insert(AttribParserList::value_type("alpha_op_ex", (ATTRIBUTE_PARSER)parseAlphaOpEx));
01858         mTextureUnitAttribParsers.insert(AttribParserList::value_type("env_map", (ATTRIBUTE_PARSER)parseEnvMap));
01859         mTextureUnitAttribParsers.insert(AttribParserList::value_type("scroll", (ATTRIBUTE_PARSER)parseScroll));
01860         mTextureUnitAttribParsers.insert(AttribParserList::value_type("scroll_anim", (ATTRIBUTE_PARSER)parseScrollAnim));
01861         mTextureUnitAttribParsers.insert(AttribParserList::value_type("rotate", (ATTRIBUTE_PARSER)parseRotate));
01862         mTextureUnitAttribParsers.insert(AttribParserList::value_type("rotate_anim", (ATTRIBUTE_PARSER)parseRotateAnim));
01863         mTextureUnitAttribParsers.insert(AttribParserList::value_type("scale", (ATTRIBUTE_PARSER)parseScale));
01864         mTextureUnitAttribParsers.insert(AttribParserList::value_type("wave_xform", (ATTRIBUTE_PARSER)parseWaveXform));
01865         mTextureUnitAttribParsers.insert(AttribParserList::value_type("filtering", (ATTRIBUTE_PARSER)parseFiltering));
01866         mTextureUnitAttribParsers.insert(AttribParserList::value_type("max_anisotropy", (ATTRIBUTE_PARSER)parseAnisotropy));
01867 
01868         // Set up program reference attribute parsers
01869         mProgramRefAttribParsers.insert(AttribParserList::value_type("param_indexed", (ATTRIBUTE_PARSER)parseParamIndexed));
01870         mProgramRefAttribParsers.insert(AttribParserList::value_type("param_indexed_auto", (ATTRIBUTE_PARSER)parseParamIndexedAuto));
01871         mProgramRefAttribParsers.insert(AttribParserList::value_type("param_named", (ATTRIBUTE_PARSER)parseParamNamed));
01872         mProgramRefAttribParsers.insert(AttribParserList::value_type("param_named_auto", (ATTRIBUTE_PARSER)parseParamNamedAuto));
01873         mProgramRefAttribParsers.insert(AttribParserList::value_type("param_named", (ATTRIBUTE_PARSER)parseParamNamedAuto));
01874 
01875         // Set up program definition attribute parsers
01876         mProgramAttribParsers.insert(AttribParserList::value_type("source", (ATTRIBUTE_PARSER)parseProgramSource));
01877         mProgramAttribParsers.insert(AttribParserList::value_type("syntax", (ATTRIBUTE_PARSER)parseProgramSyntax));
01878         mProgramAttribParsers.insert(AttribParserList::value_type("includes_skeletal_animation", (ATTRIBUTE_PARSER)parseProgramSkeletalAnimation));
01879         
01880 
01881         mScriptContext.section = MSS_NONE;
01882         mScriptContext.material = 0;
01883         mScriptContext.technique = 0;
01884         mScriptContext.pass = 0;
01885         mScriptContext.textureUnit = 0;
01886         mScriptContext.program = 0;
01887         mScriptContext.lineNo = 0;
01888         mScriptContext.filename = "";
01889         mScriptContext.techLev = -1;
01890         mScriptContext.passLev = -1;
01891         mScriptContext.stateLev = -1;
01892 
01893         mBuffer = "";
01894     }
01895 
01896     //-----------------------------------------------------------------------
01897     void MaterialSerializer::parseScript(DataChunk& chunk, const String& filename)
01898     {
01899         String line;
01900         bool nextIsOpenBrace = false;
01901 
01902         mScriptContext.section = MSS_NONE;
01903         mScriptContext.material = 0;
01904         mScriptContext.technique = 0;
01905         mScriptContext.pass = 0;
01906         mScriptContext.textureUnit = 0;
01907         mScriptContext.program = 0;
01908         mScriptContext.lineNo = 0;
01909         mScriptContext.techLev = -1;
01910         mScriptContext.passLev = -1;
01911         mScriptContext.stateLev = -1;
01912         mScriptContext.filename = filename;
01913         while(!chunk.isEOF())
01914         {
01915             line = chunk.getLine();
01916             mScriptContext.lineNo++;
01917             
01918             // DEBUG LINE
01919             //LogManager::getSingleton().logMessage("About to attempt line: " + 
01920             //    StringConverter::toString(mScriptContext.lineNo));
01921 
01922             // Ignore comments & blanks
01923             if (!(line.length() == 0 || line.substr(0,2) == "//"))
01924             {
01925                 if (nextIsOpenBrace)
01926                 {
01927                     // NB, parser will have changed context already
01928                     if (line != "{")
01929                     {
01930                         logParseError("Expecting '{' but got " +
01931                             line + " instead.", mScriptContext);
01932                     }
01933                     nextIsOpenBrace = false;
01934                 }
01935                 else
01936                 {
01937                     nextIsOpenBrace = parseScriptLine(line);
01938                 }
01939 
01940             }
01941         }
01942 
01943         // Check all braces were closed
01944         if (mScriptContext.section != MSS_NONE)
01945         {
01946             logParseError("Unexpected end of file.", mScriptContext);
01947         }
01948 
01949     }
01950     //-----------------------------------------------------------------------
01951     bool MaterialSerializer::parseScriptLine(String& line)
01952     {
01953         switch(mScriptContext.section)
01954         {
01955         case MSS_NONE:
01956             if (line == "}")
01957             {
01958                 logParseError("Unexpected terminating brace.", mScriptContext);
01959                 return false;
01960             }
01961             else
01962             {
01963                 // find & invoke a parser
01964                 return invokeParser(line, mRootAttribParsers); 
01965             }
01966             break;
01967         case MSS_MATERIAL:
01968             if (line == "}")
01969             {
01970                 // End of material
01971                 mScriptContext.section = MSS_NONE;
01972                 mScriptContext.material = NULL;
01973                 //Reset all levels for next material
01974                 mScriptContext.passLev = -1;
01975                 mScriptContext.stateLev= -1;
01976                 mScriptContext.techLev = -1;
01977             }
01978             else
01979             {
01980                 // find & invoke a parser
01981                 return invokeParser(line, mMaterialAttribParsers); 
01982             }
01983             break;
01984         case MSS_TECHNIQUE:
01985             if (line == "}")
01986             {
01987                 // End of technique
01988                 mScriptContext.section = MSS_MATERIAL;
01989                 mScriptContext.technique = NULL;
01990                 mScriptContext.passLev = -1;    //Reset pass level (yes, the pass level)
01991             }
01992             else
01993             {
01994                 // find & invoke a parser
01995                 return invokeParser(line, mTechniqueAttribParsers); 
01996             }
01997             break;
01998         case MSS_PASS:
01999             if (line == "}")
02000             {
02001                 // End of pass
02002                 mScriptContext.section = MSS_TECHNIQUE;
02003                 mScriptContext.pass = NULL;
02004                 mScriptContext.stateLev = -1;   //Reset state level (yes, the state level)
02005             }
02006             else
02007             {
02008                 // find & invoke a parser
02009                 return invokeParser(line, mPassAttribParsers); 
02010             }
02011             break;
02012         case MSS_TEXTUREUNIT:
02013             if (line == "}")
02014             {
02015                 // End of texture unit
02016                 mScriptContext.section = MSS_PASS;
02017                 mScriptContext.textureUnit = NULL;
02018             }
02019             else
02020             {
02021                 // find & invoke a parser
02022                 return invokeParser(line, mTextureUnitAttribParsers); 
02023             }
02024             break;
02025         case MSS_TEXTURESOURCE:
02026             if( line == "}" )
02027             {
02028                 //End texture source section
02029                 //Finish creating texture here
02030                 String sMaterialName = mScriptContext.material->getName();
02031                 if( ExternalTextureSourceManager::getSingleton().getCurrentPlugIn() != 0)
02032                     ExternalTextureSourceManager::getSingleton().getCurrentPlugIn()->createDefinedTexture( sMaterialName );
02033                 //Revert back to texture unit
02034                 mScriptContext.section = MSS_TEXTUREUNIT;
02035             }
02036             else
02037             {
02038                 // custom texture parameter, use original line
02039                 parseTextureCustomParameter(line, mScriptContext);
02040             }
02041             break;
02042         case MSS_PROGRAM_REF:
02043             if (line == "}")
02044             {
02045                 // End of program
02046                 mScriptContext.section = MSS_PASS;
02047                 mScriptContext.program = NULL;
02048             }
02049             else
02050             {
02051                 // find & invoke a parser
02052                 return invokeParser(line, mProgramRefAttribParsers); 
02053             }
02054             break;
02055         case MSS_PROGRAM:
02056             // Program definitions are slightly different, they are deferred
02057             // until all the information required is known
02058             if (line == "}")
02059             {
02060                 // End of program
02061                 finishProgramDefinition();
02062                 mScriptContext.section = MSS_NONE;
02063                 delete mScriptContext.programDef;
02064                 mScriptContext.programDef = NULL;
02065             }
02066             else
02067             {
02068                 // find & invoke a parser
02069                 // do this manually because we want to call a custom
02070                 // routine when the parser is not found
02071                 // First, split line on first divisor only
02072                 StringVector splitCmd = line.split(" \t", 1);
02073                 // Find attribute parser
02074                 AttribParserList::iterator iparser = mProgramAttribParsers.find(splitCmd[0]);
02075                 if (iparser == mProgramAttribParsers.end())
02076                 {
02077                     // custom parameter, use original line
02078                     parseProgramCustomParameter(line, mScriptContext);
02079                 }
02080                 else
02081                 {
02082                     String cmd = splitCmd.size() >= 2? splitCmd[1]:String::BLANK;
02083                     // Use parser with remainder
02084                     iparser->second(cmd, mScriptContext );
02085                 }
02086                 
02087             }
02088             break;
02089         };
02090 
02091         return false;
02092     }
02093     //-----------------------------------------------------------------------
02094     void MaterialSerializer::finishProgramDefinition(void)
02095     {
02096         // Now it is time to create the program and propagate the parameters
02097         MaterialScriptProgramDefinition* def = mScriptContext.programDef;
02098         if (def->language == "asm")
02099         {
02100             // Native assembler
02101             // Validate
02102             if (def->source.empty())
02103             {
02104                 logParseError("Invalid program definition for " + def->name +
02105                     ", you must specify a source file.", mScriptContext);
02106             }
02107             if (def->syntax.empty())
02108             {
02109                 logParseError("Invalid program definition for " + def->name +
02110                     ", you must specify a syntax code.", mScriptContext);
02111             }
02112             // Create
02113             GpuProgram* gp = GpuProgramManager::getSingleton().
02114                 createProgram(def->name, def->source, def->progType, def->syntax);
02115             gp->setSkeletalAnimationIncluded(def->supportsSkeletalAnimation);
02116         }
02117         else
02118         {
02119             // High-level program
02120             // Validate
02121             if (def->source.empty())
02122             {
02123                 logParseError("Invalid program definition for " + def->name +
02124                     ", you must specify a source file.", mScriptContext);
02125             }
02126             // Create
02127             try 
02128             {
02129                 HighLevelGpuProgram* gp = HighLevelGpuProgramManager::getSingleton().
02130                     createProgram(def->name, def->language, def->progType);
02131                 // Set source file
02132                 gp->setSourceFile(def->source);
02133                 // Skel animation supported
02134                 gp->setSkeletalAnimationIncluded(def->supportsSkeletalAnimation);
02135 
02136                 // Set custom parameters
02137                 std::map<String, String>::const_iterator i, iend;
02138                 iend = def->customParameters.end();
02139                 for (i = def->customParameters.begin(); i != iend; ++i)
02140                 {
02141                     if (!gp->setParameter(i->first, i->second))
02142                     {
02143                         logParseError("Error in program " + def->name + 
02144                             " parameter " + i->first + " is not valid.", mScriptContext);
02145                     }
02146                 }
02147             }
02148             catch (Exception& e)
02149             {
02150                 LogManager::getSingleton().logMessage("Could not create GPU program '"
02151                     + def->name + "', error reported was: " + e.getFullDescription());
02152             }
02153         }
02154     }
02155     //-----------------------------------------------------------------------
02156     bool MaterialSerializer::invokeParser(String& line, AttribParserList& parsers)
02157     {
02158         // First, split line on first divisor only
02159         StringVector splitCmd = line.split(" \t", 1);
02160         // Find attribute parser
02161         AttribParserList::iterator iparser = parsers.find(splitCmd[0]);
02162         if (iparser == parsers.end())
02163         {
02164             // BAD command. BAD!
02165             logParseError("Unrecognised command: " + splitCmd[0], mScriptContext);
02166             return false;
02167         }
02168         else
02169         {
02170             String cmd = splitCmd.size() >= 2 ? splitCmd[1] : String::BLANK;
02171             // Use parser, make sure we have 2 params before using splitCmd[1]
02172             return iparser->second( cmd, mScriptContext );
02173         }
02174     }
02175     //-----------------------------------------------------------------------
02176     void MaterialSerializer::exportMaterial(const Material *pMat, const String &fileName, bool exportDefaults)
02177     {
02178         clearQueue();
02179         mDefaults = exportDefaults;
02180         writeMaterial(pMat);
02181         exportQueued(fileName);
02182     }
02183     //-----------------------------------------------------------------------
02184     void MaterialSerializer::exportQueued(const String &fileName)
02185     {
02186         if (mBuffer == "")
02187             Except(Exception::ERR_INVALIDPARAMS, "Queue is empty !", "MaterialSerializer::exportQueued");
02188 
02189         LogManager::getSingleton().logMessage("MaterialSerializer : writing material(s) to material script : " + fileName, LML_CRITICAL);
02190         FILE *fp;
02191         fp = fopen(fileName.c_str(), "w");
02192         if (!fp)
02193             Except(Exception::ERR_CANNOT_WRITE_TO_FILE, "Cannot create material file.",
02194             "MaterialSerializer::export");
02195 
02196         fputs(mBuffer.c_str(), fp);
02197         fclose(fp);
02198         LogManager::getSingleton().logMessage("MaterialSerializer : done.", LML_CRITICAL);
02199         clearQueue();
02200     }
02201     //-----------------------------------------------------------------------
02202     void MaterialSerializer::queueForExport(const Material *pMat, bool clearQueued, bool exportDefaults)
02203     {
02204         if (clearQueued)
02205             clearQueue();
02206 
02207         mDefaults = exportDefaults;
02208         writeMaterial(pMat);
02209     }
02210     //-----------------------------------------------------------------------
02211     void MaterialSerializer::clearQueue()
02212     {
02213         mBuffer = "";
02214     }
02215     //-----------------------------------------------------------------------
02216     const String &MaterialSerializer::getQueuedAsString() const
02217     {
02218         return mBuffer;
02219     }
02220     //-----------------------------------------------------------------------
02221     void MaterialSerializer::writeMaterial(const Material *pMat)
02222     {
02223         LogManager::getSingleton().logMessage("MaterialSerializer : writing material " + pMat->getName() + " to queue.", LML_CRITICAL);
02224         // Material name
02225         writeAttribute(0, "material " + pMat->getName());
02226         beginSection(0);
02227         {
02228             // Write LOD information
02229             Material::LodDistanceIterator distIt = pMat->getLodDistanceIterator();
02230             // Skip zero value
02231             if (distIt.hasMoreElements())
02232                 distIt.getNext();
02233             String attributeVal;
02234             while (distIt.hasMoreElements())
02235             {
02236                 Real sqdist = distIt.getNext();
02237                 attributeVal.append(StringConverter::toString(Math::Sqrt(sqdist)));
02238                 if (distIt.hasMoreElements())
02239                     attributeVal.append(" ");
02240             }
02241             if (!attributeVal.empty())
02242             {
02243                 writeAttribute(1, "lod_distances");
02244                 writeValue(attributeVal);
02245             }
02246 
02247 
02248             // Shadow receive
02249             if (mDefaults || 
02250                 pMat->getReceiveShadows() != true)
02251             {
02252                 writeAttribute(1, "receive_shadows");
02253                 writeValue(pMat->getReceiveShadows() ? "on" : "off");
02254             }
02255             // Iterate over techniques
02256             Material::TechniqueIterator it = 
02257                 const_cast<Material*>(pMat)->getTechniqueIterator();
02258             while (it.hasMoreElements())
02259             {
02260                 writeTechnique(it.getNext());
02261             }
02262         }
02263         endSection(0);
02264     }
02265     //-----------------------------------------------------------------------
02266     void MaterialSerializer::writeTechnique(const Technique* pTech)
02267     {
02268         // Technique header
02269         writeAttribute(1, "technique");
02270         beginSection(1);
02271         {
02272             // Iterate over passes
02273             Technique::PassIterator it = const_cast<Technique*>(pTech)->getPassIterator();
02274             while (it.hasMoreElements())
02275             {
02276                 writePass(it.getNext());
02277             }
02278         }
02279         endSection(1);
02280 
02281     }
02282     //-----------------------------------------------------------------------
02283     void MaterialSerializer::writePass(const Pass* pPass)
02284     {
02285         writeAttribute(2, "pass");
02286         beginSection(2);
02287         {
02288             //lighting
02289             if (mDefaults || 
02290                 pPass->getLightingEnabled() != true)
02291             {
02292                 writeAttribute(3, "lighting");
02293                 writeValue(pPass->getLightingEnabled() ? "on" : "off");
02294             }
02295             // max_lights
02296             if (mDefaults || 
02297                 pPass->getMaxSimultaneousLights() != OGRE_MAX_SIMULTANEOUS_LIGHTS)
02298             {
02299                 writeAttribute(3, "max_lights");
02300                 writeValue(StringConverter::toString(pPass->getMaxSimultaneousLights()));
02301             }
02302             // iteration
02303             if (mDefaults || 
02304                 pPass->getRunOncePerLight())
02305             {
02306                 writeAttribute(3, "iteration");
02307                 writeValue(pPass->getRunOncePerLight() ? "once_per_light" : "once");
02308                 if (pPass->getRunOncePerLight() && pPass->getRunOnlyForOneLightType())
02309                 {
02310                     switch (pPass->getOnlyLightType())
02311                     {
02312                     case Light::LT_DIRECTIONAL:
02313                         writeValue("directional");
02314                         break;
02315                     case Light::LT_POINT:
02316                         writeValue("point");
02317                         break;
02318                     case Light::LT_SPOTLIGHT:
02319                         writeValue("spot");
02320                         break;
02321                     };
02322                 }
02323             }
02324             
02325 
02326             if (pPass->getLightingEnabled())
02327             {
02328                 // Ambient
02329                 if (mDefaults ||
02330                     pPass->getAmbient().r != 1 ||
02331                     pPass->getAmbient().g != 1 ||
02332                     pPass->getAmbient().b != 1 ||
02333                     pPass->getAmbient().a != 1)
02334                 {
02335                     writeAttribute(3, "ambient");
02336                     writeColourValue(pPass->getAmbient(), true);
02337                 }
02338 
02339                 // Diffuse
02340                 if (mDefaults ||
02341                     pPass->getDiffuse().r != 1 ||
02342                     pPass->getDiffuse().g != 1 ||
02343                     pPass->getDiffuse().b != 1 ||
02344                     pPass->getDiffuse().a != 1)
02345                 {
02346                     writeAttribute(3, "diffuse");
02347                     writeColourValue(pPass->getDiffuse(), true);
02348                 }
02349 
02350                 // Specular
02351                 if (mDefaults ||
02352                     pPass->getSpecular().r != 0 ||
02353                     pPass->getSpecular().g != 0 ||
02354                     pPass->getSpecular().b != 0 ||
02355                     pPass->getSpecular().a != 1 ||
02356                     pPass->getShininess() != 0)
02357                 {
02358                     writeAttribute(3, "specular");
02359                     writeColourValue(pPass->getSpecular(), true);
02360                     writeValue(StringConverter::toString(pPass->getShininess()));
02361                 }
02362 
02363                 // Emissive
02364                 if (mDefaults ||
02365                     pPass->getSelfIllumination().r != 0 ||
02366                     pPass->getSelfIllumination().g != 0 ||
02367                     pPass->getSelfIllumination().b != 0 ||
02368                     pPass->getSelfIllumination().a != 1)
02369                 {
02370                     writeAttribute(3, "emissive");
02371                     writeColourValue(pPass->getSelfIllumination(), true);
02372                 }
02373             }
02374 
02375             // scene blend factor
02376             if (mDefaults || 
02377                 pPass->getSourceBlendFactor() != SBF_ONE || 
02378                 pPass->getDestBlendFactor() != SBF_ZERO)
02379             {
02380                 writeAttribute(3, "scene_blend");
02381                 writeSceneBlendFactor(pPass->getSourceBlendFactor(), pPass->getDestBlendFactor());
02382             }
02383 
02384 
02385             //depth check
02386             if (mDefaults || 
02387                 pPass->getDepthCheckEnabled() != true)
02388             {
02389                 writeAttribute(3, "depth_check");
02390                 writeValue(pPass->getDepthCheckEnabled() ? "on" : "off");
02391             }
02392 
02393             //depth write
02394             if (mDefaults || 
02395                 pPass->getDepthWriteEnabled() != true)
02396             {
02397                 writeAttribute(3, "depth_write");
02398                 writeValue(pPass->getDepthWriteEnabled() ? "on" : "off");
02399             }
02400 
02401             //depth function
02402             if (mDefaults || 
02403                 pPass->getDepthFunction() != CMPF_LESS_EQUAL)
02404             {
02405                 writeAttribute(3, "depth_func");
02406                 writeCompareFunction(pPass->getDepthFunction());
02407             }
02408 
02409             //depth bias
02410             if (mDefaults || 
02411                 pPass->getDepthBias() != 0)
02412             {
02413                 writeAttribute(3, "depth_bias");
02414                 writeValue(StringConverter::toString(pPass->getDepthBias()));
02415             }
02416 
02417             // hardware culling mode
02418             if (mDefaults || 
02419                 pPass->getCullingMode() != CULL_CLOCKWISE)
02420             {
02421                 CullingMode hcm = pPass->getCullingMode();
02422                 writeAttribute(3, "cull_hardware");
02423                 switch (hcm)
02424                 {
02425                 case CULL_NONE :
02426                     writeValue("none");
02427                     break;
02428                 case CULL_CLOCKWISE :
02429                     writeValue("clockwise");
02430                     break;
02431                 case CULL_ANTICLOCKWISE :
02432                     writeValue("anticlockwise");
02433                     break;
02434                 }
02435             }
02436 
02437             // software culling mode
02438             if (mDefaults || 
02439                 pPass->getManualCullingMode() != MANUAL_CULL_BACK)
02440             {
02441                 ManualCullingMode scm = pPass->getManualCullingMode();
02442                 writeAttribute(3, "cull_software");
02443                 switch (scm)
02444                 {
02445                 case MANUAL_CULL_NONE :
02446                     writeValue("none");
02447                     break;
02448                 case MANUAL_CULL_BACK :
02449                     writeValue("back");
02450                     break;
02451                 case MANUAL_CULL_FRONT :
02452                     writeValue("front");
02453                     break;
02454                 }
02455             }
02456 
02457             //shading
02458             if (mDefaults || 
02459                 pPass->getShadingMode() != SO_GOURAUD)
02460             {
02461                 writeAttribute(3, "shading");
02462                 switch (pPass->getShadingMode())
02463                 {
02464                 case SO_FLAT:
02465                     writeValue("flat");
02466                     break;
02467                 case SO_GOURAUD:
02468                     writeValue("gouraud");
02469                     break;
02470                 case SO_PHONG:
02471                     writeValue("phong");
02472                     break;
02473                 }
02474             }
02475 
02476 
02477             //fog override
02478             if (mDefaults || 
02479                 pPass->getFogOverride() != false)
02480             {
02481                 writeAttribute(3, "fog_override");
02482                 writeValue(pPass->getFogOverride() ? "true" : "false");
02483                 if (pPass->getFogOverride())
02484                 {
02485                     switch (pPass->getFogMode())
02486                     {
02487                     case FOG_NONE:
02488                         writeValue("none");
02489                         break;
02490                     case FOG_LINEAR:
02491                         writeValue("linear");
02492                         break;
02493                     case FOG_EXP2:
02494                         writeValue("exp2");
02495                         break;
02496                     case FOG_EXP:
02497                         writeValue("exp");
02498                         break;
02499                     }
02500 
02501                     if (pPass->getFogMode() != FOG_NONE)
02502                     {
02503                         writeColourValue(pPass->getFogColour());
02504                         writeValue(StringConverter::toString(pPass->getFogDensity()));
02505                         writeValue(StringConverter::toString(pPass->getFogStart()));
02506                         writeValue(StringConverter::toString(pPass->getFogEnd()));
02507                     }
02508                 }
02509             }
02510 
02511             // Nested texture layers
02512             Pass::TextureUnitStateIterator it = const_cast<Pass*>(pPass)->getTextureUnitStateIterator();
02513             while(it.hasMoreElements())
02514             {
02515                 writeTextureUnit(it.getNext());
02516             }
02517         }
02518         endSection(2);
02519         LogManager::getSingleton().logMessage("MaterialSerializer : done.", LML_CRITICAL);
02520     }
02521     //-----------------------------------------------------------------------
02522     String MaterialSerializer::convertFiltering(FilterOptions fo)
02523     {
02524         switch (fo)
02525         {
02526         case FO_NONE:
02527             return "none";
02528         case FO_POINT:
02529             return "point";
02530         case FO_LINEAR:
02531             return "linear";
02532         case FO_ANISOTROPIC:
02533             return "anisotropic";
02534         }
02535 
02536         return "point";
02537     }
02538     //-----------------------------------------------------------------------
02539     void MaterialSerializer::writeTextureUnit(const TextureUnitState *pTex)
02540     {
02541         LogManager::getSingleton().logMessage("MaterialSerializer : parsing texture layer.", LML_CRITICAL);
02542         mBuffer += "\n";
02543         writeAttribute(3, "texture_unit");
02544         beginSection(3);
02545         {
02546             //texture name
02547             if (pTex->getNumFrames() == 1 && pTex->getTextureName() != "" && !pTex->isCubic())
02548             {
02549                 writeAttribute(4, "texture");
02550                 writeValue(pTex->getTextureName());
02551                 switch (pTex->getTextureType())
02552                 {
02553                 case TEX_TYPE_1D:
02554                     writeValue("1d");
02555                     break;
02556                 case TEX_TYPE_2D:
02557                     // nothing, this is the default
02558                     break;
02559                 case TEX_TYPE_3D:
02560                     writeValue("3d");
02561                     break;
02562                 case TEX_TYPE_CUBE_MAP:
02563                     // nothing, deal with this as cubic_texture since it copes with all variants
02564                     break;
02565                 default:
02566                     break;
02567                 };
02568             }
02569 
02570             //anim. texture
02571             if (pTex->getNumFrames() > 1 && !pTex->isCubic())
02572             {
02573                 writeAttribute(4, "anim_texture");
02574                 for (unsigned int n = 0; n < pTex->getNumFrames(); n++)
02575                     writeValue(pTex->getFrameTextureName(n));
02576                 writeValue(StringConverter::toString(pTex->getAnimationDuration()));
02577             }
02578 
02579             //cubic texture
02580             if (pTex->isCubic())
02581             {
02582                 writeAttribute(4, "cubic_texture");
02583                 for (unsigned int n = 0; n < pTex->getNumFrames(); n++)
02584                     writeValue(pTex->getFrameTextureName(n));
02585 
02586                 //combinedUVW/separateUW
02587                 if (pTex->getTextureType() == TEX_TYPE_CUBE_MAP)
02588                     writeValue("combinedUVW");
02589                 else
02590                     writeValue("separateUV");
02591             }
02592 
02593             //anisotropy level
02594             if (mDefaults || 
02595                 pTex->getTextureAnisotropy() != 1)
02596             {
02597                 writeAttribute(4, "max_anisotropy");
02598                 writeValue(StringConverter::toString(pTex->getTextureAnisotropy()));
02599             }
02600 
02601             //texture coordinate set
02602             if (mDefaults || 
02603                 pTex->getTextureCoordSet() != 0)
02604             {
02605                 writeAttribute(4, "tex_coord_set");
02606                 writeValue(StringConverter::toString(pTex->getTextureCoordSet()));
02607             }
02608 
02609             //addressing mode
02610             if (mDefaults || 
02611                 pTex->getTextureAddressingMode() != Ogre::TextureUnitState::TAM_WRAP)
02612             {
02613                 writeAttribute(4, "tex_address_mode");
02614                 switch (pTex->getTextureAddressingMode())
02615                 {
02616                 case Ogre::TextureUnitState::TAM_CLAMP:
02617                     writeValue("clamp");
02618                     break;
02619                 case Ogre::TextureUnitState::TAM_MIRROR:
02620                     writeValue("mirror");
02621                     break;
02622                 case Ogre::TextureUnitState::TAM_WRAP:
02623                     writeValue("wrap");
02624                     break;
02625                 }
02626             }
02627 
02628             //filtering
02629             if (mDefaults || 
02630                 pTex->getTextureFiltering(FT_MIN) != FO_LINEAR ||
02631                 pTex->getTextureFiltering(FT_MAG) != FO_LINEAR ||
02632                 pTex->getTextureFiltering(FT_MIP) != FO_POINT)
02633             {
02634                 writeAttribute(4, "filtering");
02635                 writeValue(
02636                     convertFiltering(pTex->getTextureFiltering(FT_MIN))
02637                     + " "
02638                     + convertFiltering(pTex->getTextureFiltering(FT_MAG))
02639                     + " "
02640                     + convertFiltering(pTex->getTextureFiltering(FT_MIP)));
02641             }
02642 
02643             // alpha_rejection
02644             if (mDefaults || 
02645                 pTex->getAlphaRejectFunction() != CMPF_ALWAYS_PASS ||
02646                 pTex->getAlphaRejectValue() != 0)
02647             {
02648                 writeAttribute(4, "alpha_rejection");
02649                 writeCompareFunction(pTex->getAlphaRejectFunction());
02650                 writeValue(StringConverter::toString(pTex->getAlphaRejectValue()));
02651             }
02652 
02653             // colour_op_ex
02654             if (mDefaults || 
02655                 pTex->getColourBlendMode().operation != LBX_MODULATE ||
02656                 pTex->getColourBlendMode().source1 != LBS_TEXTURE ||
02657                 pTex->getColourBlendMode().source2 != LBS_CURRENT)
02658             {
02659                 writeAttribute(4, "colour_op_ex");
02660                 writeLayerBlendOperationEx(pTex->getColourBlendMode().operation);
02661                 writeLayerBlendSource(pTex->getColourBlendMode().source1);
02662                 writeLayerBlendSource(pTex->getColourBlendMode().source2);
02663                 if (pTex->getColourBlendMode().operation == LBX_BLEND_MANUAL)
02664                     writeValue(StringConverter::toString(pTex->getColourBlendMode().factor));
02665                 if (pTex->getColourBlendMode().source1 == LBS_MANUAL)
02666                     writeColourValue(pTex->getColourBlendMode().colourArg1, false);
02667                 if (pTex->getColourBlendMode().source2 == LBS_MANUAL)
02668                     writeColourValue(pTex->getColourBlendMode().colourArg2, false);
02669 
02670                 //colour_op_multipass_fallback
02671                 writeAttribute(4, "colour_op_multipass_fallback");
02672                 writeSceneBlendFactor(pTex->getColourBlendFallbackSrc());
02673                 writeSceneBlendFactor(pTex->getColourBlendFallbackDest());
02674             }
02675 
02676             // alpha_op_ex
02677             if (mDefaults || 
02678                 pTex->getAlphaBlendMode().operation != LBX_MODULATE ||
02679                 pTex->getAlphaBlendMode().source1 != LBS_TEXTURE ||
02680                 pTex->getAlphaBlendMode().source2 != LBS_CURRENT)
02681             {
02682                 writeAttribute(4, "alpha_op_ex");
02683                 writeLayerBlendOperationEx(pTex->getAlphaBlendMode().operation);
02684                 writeLayerBlendSource(pTex->getAlphaBlendMode().source1);
02685                 writeLayerBlendSource(pTex->getAlphaBlendMode().source2);
02686                 if (pTex->getAlphaBlendMode().operation == LBX_BLEND_MANUAL)
02687                     writeValue(StringConverter::toString(pTex->getAlphaBlendMode().factor));
02688                 else if (pTex->getAlphaBlendMode().source1 == LBS_MANUAL)
02689                     writeValue(StringConverter::toString(pTex->getAlphaBlendMode().alphaArg1));
02690                 else if (pTex->getAlphaBlendMode().source2 == LBS_MANUAL)
02691                     writeValue(StringConverter::toString(pTex->getAlphaBlendMode().alphaArg2));
02692             }
02693 
02694             // rotate
02695             if (mDefaults ||
02696                 pTex->getTextureRotate() != 0)
02697             {
02698                 writeAttribute(4, "rotate");
02699                 writeValue(StringConverter::toString(pTex->getTextureRotate()));
02700             }
02701 
02702             // scroll
02703             if (mDefaults ||
02704                 pTex->getTextureUScroll() != 0 || 
02705                 pTex->getTextureVScroll() != 0 )
02706             {
02707                 writeAttribute(4, "scroll");
02708                 writeValue(StringConverter::toString(pTex->getTextureUScroll()));
02709                 writeValue(StringConverter::toString(pTex->getTextureVScroll()));
02710             }
02711             // scale
02712             if (mDefaults ||
02713                 pTex->getTextureUScale() != 1.0 || 
02714                 pTex->getTextureVScale() != 1.0 )
02715             {
02716                 writeAttribute(4, "scale");
02717                 writeValue(StringConverter::toString(pTex->getTextureUScale()));
02718                 writeValue(StringConverter::toString(pTex->getTextureVScale()));
02719             }
02720 
02721             EffectMap m_ef = pTex->getEffects();
02722             if (!m_ef.empty())
02723             {
02724                 EffectMap::const_iterator it;
02725                 for (it = m_ef.begin(); it != m_ef.end(); ++it)
02726                 {
02727                     const TextureUnitState::TextureEffect& ef = it->second;
02728                     switch (ef.type)
02729                     {
02730                     case TextureUnitState::ET_ENVIRONMENT_MAP :
02731                         writeEnvironmentMapEffect(ef, pTex);
02732                         break;
02733                     case TextureUnitState::ET_ROTATE :
02734                         writeRotationEffect(ef, pTex);
02735                         break;
02736                     case TextureUnitState::ET_SCROLL :
02737                         writeScrollEffect(ef, pTex);
02738                         break;
02739                     case TextureUnitState::ET_TRANSFORM :
02740                         writeTransformEffect(ef, pTex);
02741                         break;
02742                     default:
02743                         break;
02744                     }
02745                 }
02746             }
02747         }
02748         endSection(3);
02749 
02750     }
02751     //-----------------------------------------------------------------------
02752     void MaterialSerializer::writeEnvironmentMapEffect(const TextureUnitState::TextureEffect& effect, const TextureUnitState *pTex)
02753     {
02754         writeAttribute(4, "env_map");
02755         switch (effect.subtype)
02756         {
02757         case TextureUnitState::ENV_PLANAR:
02758             writeValue("planar");
02759             break;
02760         case TextureUnitState::ENV_CURVED:
02761             writeValue("spherical");
02762             break;
02763         case TextureUnitState::ENV_NORMAL:
02764             writeValue("cubic_normal");
02765             break;
02766         case TextureUnitState::ENV_REFLECTION:
02767             writeValue("cubic_reflection");
02768             break;
02769         }
02770     }
02771     //-----------------------------------------------------------------------
02772     void MaterialSerializer::writeRotationEffect(const TextureUnitState::TextureEffect& effect, const TextureUnitState *pTex)
02773     {
02774         if (effect.arg1)
02775         {
02776             writeAttribute(4, "rotate_anim");
02777             writeValue(StringConverter::toString(effect.arg1));
02778         }
02779     }
02780     //-----------------------------------------------------------------------
02781     void MaterialSerializer::writeTransformEffect(const TextureUnitState::TextureEffect& effect, const TextureUnitState *pTex)
02782     {
02783         writeAttribute(4, "wave_xform");
02784 
02785         switch (effect.subtype)
02786         {
02787         case TextureUnitState::TT_ROTATE:
02788             writeValue("rotate");
02789             break;
02790         case TextureUnitState::TT_SCALE_U:
02791             writeValue("scale_x");
02792             break;
02793         case TextureUnitState::TT_SCALE_V:
02794             writeValue("scale_y");
02795             break;
02796         case TextureUnitState::TT_TRANSLATE_U:
02797             writeValue("scroll_x");
02798             break;
02799         case TextureUnitState::TT_TRANSLATE_V:
02800             writeValue("scroll_y");
02801             break;
02802         }
02803 
02804         switch (effect.waveType)
02805         {
02806         case WFT_INVERSE_SAWTOOTH:
02807             writeValue("inverse_sawtooth");
02808             break;
02809         case WFT_SAWTOOTH:
02810             writeValue("sawtooth");
02811             break;
02812         case WFT_SINE:
02813             writeValue("sine");
02814             break;
02815         case WFT_SQUARE:
02816             writeValue("square");
02817             break;
02818         case WFT_TRIANGLE:
02819             writeValue("triangle");
02820             break;
02821         }
02822 
02823         writeValue(StringConverter::toString(effect.base));
02824         writeValue(StringConverter::toString(effect.frequency));
02825         writeValue(StringConverter::toString(effect.phase));
02826         writeValue(StringConverter::toString(effect.amplitude));
02827     }
02828     //-----------------------------------------------------------------------
02829     void MaterialSerializer::writeScrollEffect(const TextureUnitState::TextureEffect& effect, const TextureUnitState *pTex)
02830     {
02831         if (effect.arg1 || effect.arg2)
02832         {
02833             writeAttribute(4, "scroll_anim");
02834             writeValue(StringConverter::toString(effect.arg1));
02835             writeValue(StringConverter::toString(effect.arg2));
02836         }
02837     }
02838     //-----------------------------------------------------------------------
02839     void MaterialSerializer::writeSceneBlendFactor(const SceneBlendFactor sbf)
02840     {
02841         switch (sbf)
02842         {
02843         case SBF_DEST_ALPHA:
02844             writeValue("dest_alpha");
02845             break;
02846         case SBF_DEST_COLOUR:
02847             writeValue("dest_colour");
02848             break;
02849         case SBF_ONE:
02850             writeValue("one");
02851             break;
02852         case SBF_ONE_MINUS_DEST_ALPHA:
02853             writeValue("one_minus_dest_alpha");
02854             break;
02855         case SBF_ONE_MINUS_DEST_COLOUR:
02856             writeValue("one_minus_dest_colour");
02857             break;
02858         case SBF_ONE_MINUS_SOURCE_ALPHA:
02859             writeValue("one_minus_src_alpha");
02860             break;
02861         case SBF_ONE_MINUS_SOURCE_COLOUR:
02862             writeValue("one_minus_src_colour");
02863             break;
02864         case SBF_SOURCE_ALPHA:
02865             writeValue("src_alpha");
02866             break;
02867         case SBF_SOURCE_COLOUR:
02868             writeValue("src_colour");
02869             break;
02870         case SBF_ZERO:
02871             writeValue("zero");
02872             break;
02873         }
02874     }
02875     //-----------------------------------------------------------------------
02876     void MaterialSerializer::writeSceneBlendFactor(const SceneBlendFactor sbf_src, const SceneBlendFactor sbf_dst)
02877     {
02878         if (sbf_src == SBF_ONE && sbf_dst == SBF_ONE )
02879             writeValue("add");
02880         else if (sbf_src == SBF_SOURCE_COLOUR && sbf_dst == SBF_ONE_MINUS_SOURCE_COLOUR)
02881             writeValue("modulate");
02882         else if (sbf_src == SBF_SOURCE_ALPHA && sbf_dst == SBF_ONE_MINUS_SOURCE_ALPHA)
02883             writeValue("alpha_blend");
02884         else
02885         {
02886             writeSceneBlendFactor(sbf_src);
02887             writeSceneBlendFactor(sbf_dst);
02888         }
02889     }
02890     //-----------------------------------------------------------------------
02891     void MaterialSerializer::writeCompareFunction(const CompareFunction cf)
02892     {
02893         switch (cf)
02894         {
02895         case CMPF_ALWAYS_FAIL:
02896             writeValue("always_fail");
02897             break;
02898         case CMPF_ALWAYS_PASS:
02899             writeValue("always_pass");
02900             break;
02901         case CMPF_EQUAL:
02902             writeValue("equal");
02903             break;
02904         case CMPF_GREATER:
02905             writeValue("greater");
02906             break;
02907         case CMPF_GREATER_EQUAL:
02908             writeValue("greater_equal");
02909             break;
02910         case CMPF_LESS:
02911             writeValue("less");
02912             break;
02913         case CMPF_LESS_EQUAL:
02914             writeValue("less_equal");
02915             break;
02916         case CMPF_NOT_EQUAL:
02917             writeValue("not_equal");
02918             break;
02919         }
02920     }
02921     //-----------------------------------------------------------------------
02922     void MaterialSerializer::writeColourValue(const ColourValue &colour, bool writeAlpha)
02923     {
02924         writeValue(StringConverter::toString(colour.r));
02925         writeValue(StringConverter::toString(colour.g));
02926         writeValue(StringConverter::toString(colour.b));
02927         if (writeAlpha)
02928             writeValue(StringConverter::toString(colour.a));
02929     }
02930     //-----------------------------------------------------------------------
02931     void MaterialSerializer::writeLayerBlendOperationEx(const LayerBlendOperationEx op)
02932     {
02933         switch (op)
02934         {
02935         case LBX_ADD:
02936             writeValue("add");
02937             break;
02938         case LBX_ADD_SIGNED:
02939             writeValue("add_signed");
02940             break;
02941         case LBX_ADD_SMOOTH:
02942             writeValue("add_smooth");
02943             break;
02944         case LBX_BLEND_CURRENT_ALPHA:
02945             writeValue("blend_current_alpha");
02946             break;
02947         case LBX_BLEND_DIFFUSE_ALPHA:
02948             writeValue("blend_diffuse_alpha");
02949             break;
02950         case LBX_BLEND_MANUAL:
02951             writeValue("blend_manual");
02952             break;
02953         case LBX_BLEND_TEXTURE_ALPHA:
02954             writeValue("blend_texture_alpha");
02955             break;
02956         case LBX_MODULATE:
02957             writeValue("modulate");
02958             break;
02959         case LBX_MODULATE_X2:
02960             writeValue("modulate_x2");
02961             break;
02962         case LBX_MODULATE_X4:
02963             writeValue("modulate_x4");
02964             break;
02965         case LBX_SOURCE1:
02966             writeValue("source1");
02967             break;
02968         case LBX_SOURCE2:
02969             writeValue("source2");
02970             break;
02971         case LBX_SUBTRACT:
02972             writeValue("subtract");
02973             break;
02974         case LBX_DOTPRODUCT:
02975             writeValue("dotproduct");
02976             break;
02977         }
02978     }
02979     //-----------------------------------------------------------------------
02980     void MaterialSerializer::writeLayerBlendSource(const LayerBlendSource lbs)
02981     {
02982         switch (lbs)
02983         {
02984         case LBS_CURRENT:
02985             writeValue("src_current");
02986             break;
02987         case LBS_DIFFUSE:
02988             writeValue("src_diffuse");
02989             break;
02990         case LBS_MANUAL:
02991             writeValue("src_manual");
02992             break;
02993         case LBS_SPECULAR:
02994             writeValue("src_specular");
02995             break;
02996         case LBS_TEXTURE:
02997             writeValue("src_texture");
02998             break;
02999         }
03000     }
03001 }

Copyright © 2002-2003 by The OGRE Team
Last modified Fri May 14 23:22:22 2004