/****************************************************************************************/
/*  SHADER_GEN.C                                                                        */
/*                                                                                      */
/*  Author: Timothy Roff	                                                            */
/*  Description:  Shader implementation                                                 */
/*                                                                                      */
/*  The contents of this file are subject to the Jet3D Public License                   */
/*  Version 1.02 (the "License"); you may not use this file except in                   */
/*  compliance with the License. You may obtain a copy of the License at                */
/*  http://www.jet3d.com                                                                */
/*                                                                                      */
/*  Software distributed under the License is distributed on an "AS IS"                 */
/*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
/*  the License for the specific language governing rights and limitations              */
/*  under the License.                                                                  */
/*                                                                                      */
/*  This file was not part of the original Jet3D, released December 12, 1999.           */
/*                                                                                      */
/****************************************************************************************/

#include "jeShaderDefs.h"
#include "jeShader_h.h"

//=====================================================================================
//	rgbaGenParseFunc
//=====================================================================================
jeBoolean rgbaGenParseFunc(int argc, char* argv[], shader_info_t *info)
{
	sh_rgbagen_t* gen;
	jeBoolean          is_rgbgen;

	assert(info != NULL);

   if (stricmp(argv[0], "rgbGen") == 0) {
      gen = &info->stage.rgbgen;
      is_rgbgen = JE_TRUE;
   }
   else {
      gen = &info->stage.alphagen;
      is_rgbgen = JE_FALSE;
   }

   // rgbGen identityLighting
   if (is_rgbgen && (stricmp(argv[1], "identityLighting") == 0)) {
      if (argc != 2) {
         jeShader_Error("identityLighting does not take any arguments");
         return JE_TRUE;
      }

      gen->func = SH_RGBAGEN_IDENTITY_LIGHTING;
   }
   // rgbGen|alphaGen identity
   else if (stricmp(argv[1], "identity") == 0) {
      if (argc != 2) {
         jeShader_Error("identity does not take any arguments");
         return JE_TRUE;
      }

      gen->func = SH_RGBAGEN_IDENTITY;
   }
   // rgbGen|alphaGen wave
   else if (stricmp(argv[1], "wave") == 0) {
      int form;

      if (argc != 7) {
         jeShader_Error("usage: %s wave <func> <base> <amp> <phase> <freq>", argv[0]);
         return JE_TRUE;
      }

      gen->func = SH_RGBAGEN_WAVE;

      form = ParseWaveForm(argv[2]);

      if (form < 0) return JE_TRUE;

      gen->args.wave.form = form;
     
      shader_number_parse(argv[3], &gen->args.wave.base);
      shader_number_parse(argv[4], &gen->args.wave.amp);
      shader_number_parse(argv[5], &gen->args.wave.phase);
      shader_number_parse(argv[6], &gen->args.wave.freq);
   }
   // rgbGen|alphaGen entity
   else if (stricmp(argv[1], "entity") == 0) {
      if (argc != 2) {
         jeShader_Error("entity does not take arguments");
         return JE_TRUE;
      }

      gen->func = SH_RGBAGEN_ENTITY;
   }
   // rgbGen|alphaGen oneMinusEntity
   else if (stricmp(argv[1], "oneMinusEntity") == 0) {
      if (argc != 2) {
         jeShader_Error("oneMinusEntity does not take arguments");
         return JE_TRUE;
      }

      gen->func = SH_RGBAGEN_ONE_MINUS_ENTITY;
   }
   // rgbGen|alphaGen vertex
   else if (stricmp(argv[1], "vertex") == 0) {
      if (argc != 2) {
         jeShader_Error("vertex does not take arguments");
         return JE_TRUE;
      }

      gen->func = SH_RGBAGEN_VERTEX;
   }
   // rgbGen|alphaGen oneMinusVertex
   else if (stricmp(argv[1], "oneMinusVertex") == 0) {
      if (argc != 2) {
         jeShader_Error("oneMinusVertex does not take arguments");
         return JE_TRUE;
      }

      gen->func = SH_RGBAGEN_ONE_MINUS_VERTEX;
   }
   // alphaGen portal
   else if (!is_rgbgen && (stricmp(argv[1], "portal") == 0)) {
      if (argc != 3) {
         jeShader_Error("usage: alphaGen portal <distance to opaque>");
         return JE_TRUE;
      }

      gen->func = SH_RGBAGEN_PORTAL;

      shader_number_parse(argv[2], &gen->args.portal.dist_to_opaque);
   }
   // rgbGen lightingDiffuse
   else if (is_rgbgen && stricmp(argv[1], "lightingDiffuse") == 0) {
      if (argc != 2) {
         jeShader_Error("lightingDiffuse does not take arguments");
         return JE_TRUE;
      }

      gen->func = SH_RGBAGEN_LIGHTING_DIFFUSE;
   }
   // alphaGen lightingSpecular
   else if (!is_rgbgen && stricmp(argv[1], "lightingSpecular") == 0) {
      jeShader_Error("lightingSpecular is an extension");

      if (argc != 2) {
         jeShader_Error("lightingSpecular does not take arguments");
         return JE_TRUE;
      }

      gen->func = SH_RGBAGEN_LIGHTING_SPECULAR;
   }

   // alphaGen _oneMinusPortal
   else if (!is_rgbgen && (stricmp(argv[1], "_oneMinusPortal") == 0)) {
      jeShader_Error("oneMinusPortal is an extension");

      if (argc != 3) {
         jeShader_Error("usage: alphaGen portal <distance to clear>");
         return JE_TRUE;
      }

      gen->func = SH_RGBAGEN_ONE_MINUS_PORTAL_EXT;

      shader_number_parse(argv[2], &gen->args.one_minus_portal.dist_to_clear);
   }
   else if (stricmp(argv[1], "_const") == 0) {
      // rgbGen _const
      jeShader_Error("const is an extension");

      if (is_rgbgen) {
         if (argc != 5) {
            jeShader_Error("usage: rgbGen _const <red> <green> <blue>");
            return JE_TRUE;
         }

         ParseColor(gen->args.constant.color, argv[2], argv[3], argv[4]);
      }
      else {
         if (argc != 3) {
            jeShader_Error("usage: alphaGen _const <alpha>");
            return JE_TRUE;
         }

         ParseColor(gen->args.constant.color, argv[2], argv[2], argv[2]);
      }

      gen->func = SH_RGBAGEN_CONST_EXT;
   }

   // error
   else {
      jeShader_Error("unknown function '%s'", argv[1]);
      return JE_TRUE;
   }

   if (gen == &info->stage.rgbgen) {
      info->stage.flags |= SH_STAGE_EXPLICIT_RGBGEN;
   }
   else {
      info->stage.flags |= SH_STAGE_EXPLICIT_ALPHAGEN;
   }

   return JE_TRUE;
}

//=====================================================================================
//	tcGenParseFunc
//=====================================================================================
jeBoolean tcGenParseFunc(int argc, char* argv[], shader_info_t *info)
{
	assert(info != NULL);

   // tcGen base
   if (stricmp(argv[1], "base") == 0) {
      if (argc != 2) {
         jeShader_Error("base does not take arguments");
         return JE_TRUE;
      }

      info->stage.tcgen.func = SH_TCGEN_BASE;
   }
   // tcGen lightmap
   else if (stricmp(argv[1], "lightmap") == 0) {
      if (argc != 2) {
         jeShader_Error("lightmap does not take arguments");
         return JE_TRUE;
      }

      info->stage.tcgen.func = SH_TCGEN_LIGHTMAP;
   }
   // tcGen environment
   else if (stricmp(argv[1], "environment") == 0) {
      if (argc != 2) {
         jeShader_Error("environment does not take arguments");
         return JE_TRUE;
      }

      info->stage.tcgen.func = SH_TCGEN_ENVIRONMENT;
   }
   // tcGen vector
   else if (stricmp(argv[1], "vector") == 0) {
      if (argc != 12) {
         jeShader_Error("usage: tcGen vector ( <sx> <sy> <sz> ) ( <tx> <ty> <tz> )");
         return JE_TRUE;
      }

      if (strcmp(argv[2],  "(") ||
          strcmp(argv[6],  ")") ||
          strcmp(argv[7],  "(") ||
          strcmp(argv[11], ")")) {
         jeShader_Error("make sure to put parentheses around the vectors and to space them out properly");
      }

      info->stage.tcgen.func = SH_TCGEN_VECTOR;
      shader_number_parse(argv[3],  &info->stage.tcgen.args.vector.sx);
      shader_number_parse(argv[4],  &info->stage.tcgen.args.vector.sy);
      shader_number_parse(argv[5],  &info->stage.tcgen.args.vector.sz);
      shader_number_parse(argv[8],  &info->stage.tcgen.args.vector.tx);
      shader_number_parse(argv[9],  &info->stage.tcgen.args.vector.ty);
      shader_number_parse(argv[10], &info->stage.tcgen.args.vector.tz);
   }

   // tcGen _sky
   else if (stricmp(argv[1], "_sky") == 0) {
      jeShader_Error("sky is an extension");

      if (argc != 3) {
         jeShader_Error("usage: tcGen _sky <cloudheight>");
         return JE_TRUE;
      }

      info->stage.tcgen.func = SH_TCGEN_SKY_EXT;
      shader_number_parse(argv[2], &info->stage.tcgen.args.sky.cloud_height);
   }

   // error
   else {
      jeShader_Error("unknown tcGen '%s'", argv[1]);
      return JE_TRUE;
   }

   info->stage.flags |= SH_STAGE_EXPLICIT_TCGEN;

   return JE_TRUE;
}


