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

# OgreMaterialSerializer.cpp

Go to the documentation of this file.

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

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:32 2004