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

Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:16 2004