/****************************************************************************************/
/*  SHADER_MODIFIES.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"

//Modifies (or mods) are commands that modify certain aspects of a thing
//For example, tcMod is a Texture Coordinate Modifyer. It lets you do things
//that modify the properties of a Texture Coordinate.
//Such things tcMod can do are Scale, Rotate, Scroll, Stretch, PaletteCycle, etc

//=====================================================================================
//	tcModParseFunc
//=====================================================================================
jeBoolean tcModParseFunc(int argc, char* argv[], shader_info_t *info)
{
	sh_tcmod_t* tcmod;
	sh_tcmod_t  ignored_tcmod;

	assert(info != NULL);

   if (info->stage.tcmod_count < JE_SHADER_MAX_TCMODS) {
      tcmod = &info->stage.tcmods[info->stage.tcmod_count];
   }
   else {
      jeShader_Error("number of tcMod commands exceeds JE_SHADER_MAX_TCMODS (%d) in info->shader %s", JE_SHADER_MAX_TCMODS, info->shader->name);
      tcmod = &ignored_tcmod;
   }

   // tcMod rotate <speed>
   if (stricmp(argv[1], "rotate") == 0) {
      if (argc != 3) {
         jeShader_Error("usage: tcMod rotate <speed>");
         return JE_TRUE;
      }

      tcmod->func = SH_TCMOD_ROTATE;
      shader_number_parse(argv[2], &tcmod->args.rotate.speed);
   }
   // tcMod scale <s> <t>
   else if (stricmp(argv[1], "scale") == 0) {
      if (argc != 4) {
         jeShader_Error("usage: tcMod scale <s> <t>");
         return JE_TRUE;
      }

      tcmod->func = SH_TCMOD_SCALE;
      shader_number_parse(argv[2], &tcmod->args.scale.s);
      shader_number_parse(argv[3], &tcmod->args.scale.t);
   }
   // tcMod scroll <s> <t>
   else if (stricmp(argv[1], "scroll") == 0) {
      if (argc != 4) {
         jeShader_Error("usage: tcMod scroll <s> <t>");
         return JE_TRUE;
      }

      tcmod->func = SH_TCMOD_SCROLL;
      shader_number_parse(argv[2], &tcmod->args.scroll.s);
      shader_number_parse(argv[3], &tcmod->args.scroll.t);
   }
   // tcMod stretch <func> <base> <amp> <phase> <freq>
   else if (stricmp(argv[1], "stretch") == 0) {
      int form;

      if (argc != 7) {
         jeShader_Error("usage: tcMod stretch <func> <base> <amp> <phase> <freq>");
         return JE_TRUE;
      }

      tcmod->func = SH_TCMOD_STRETCH;

      form = ParseWaveForm(argv[2]);

      if (form < 0) return JE_TRUE;

      tcmod->args.stretch.form  = form;
      shader_number_parse(argv[3], &tcmod->args.stretch.base);
      shader_number_parse(argv[4], &tcmod->args.stretch.amp);
      shader_number_parse(argv[5], &tcmod->args.stretch.phase);
      shader_number_parse(argv[6], &tcmod->args.stretch.freq);
   }
   // tcMod transform <m00> <m01> <m10> <m11> <t0> <t1>
   else if (stricmp(argv[1], "transform") == 0) {
      if (argc != 8) {
         jeShader_Error("usage: tcMod transform <m00> <m01> <m10> <m11> <t0> <t1>");
         return JE_TRUE;
      }

      tcmod->func = SH_TCMOD_TRANSFORM;
      shader_number_parse(argv[3], &tcmod->args.transform.m00);
      shader_number_parse(argv[3], &tcmod->args.transform.m01);
      shader_number_parse(argv[4], &tcmod->args.transform.m10);
      shader_number_parse(argv[5], &tcmod->args.transform.m11);
      shader_number_parse(argv[6], &tcmod->args.transform.t0);
      shader_number_parse(argv[7], &tcmod->args.transform.t1);
   }
   // tcMod turb <base> <amp> <phase> <freq>
   else if (stricmp(argv[1], "turb") == 0) {
      if (argc != 6) {
         jeShader_Error("usage: tcMod turb <base> <amp> <phase> <freq>");
         return JE_TRUE;
      }

      tcmod->func = SH_TCMOD_TURB;
      shader_number_parse(argv[2], &tcmod->args.turb.base);
      shader_number_parse(argv[3], &tcmod->args.turb.amp);
      shader_number_parse(argv[4], &tcmod->args.turb.phase);
      shader_number_parse(argv[5], &tcmod->args.turb.freq);
   }
   // error
   else {
      jeShader_Error("unknown tcMod '%s'", argv[2]);
      return JE_TRUE;
   }

   if (info->stage.tcmod_count < JE_SHADER_MAX_TCMODS) info->stage.tcmod_count++;

   return JE_TRUE;
}

//=====================================================================================
//	deformVertexesParseFunc
//=====================================================================================
jeBoolean deformVertexesParseFunc(int argc, char* argv[], shader_info_t *info)
{
   sh_vxmod_t* vxmod;
   sh_vxmod_t  ignored_vxmod;

   	assert(info != NULL);

   if (info->shader->vxmod_count < JE_SHADER_MAX_VXMODS) {
      vxmod = &info->shader->vxmods[info->shader->vxmod_count];
   }
   else {
      jeShader_Error("number of deformVertexes commands exceeds JE_SHADER_MAX_VXMODS (%d) in info->shader %s", JE_SHADER_MAX_VXMODS, info->shader->name);
      vxmod = &ignored_vxmod;
   }

   // deformVertexes wave <div> <func> <base> <amp> <phase> <freq>
   if (stricmp(argv[1], "wave") == 0) {
      int form;

      if (argc != 8) {
         jeShader_Error("usage: deformVertexes wave <div> <func> <base> <amp> <phase> <freq>");
         return JE_TRUE;
      }

      vxmod->func = SH_VXMOD_WAVE;

      shader_number_parse(argv[2], &vxmod->args.wave.div);

      form = ParseWaveForm(argv[3]);

      if (form < 0) return JE_TRUE;

      vxmod->args.wave.form = form;
      
      shader_number_parse(argv[4], &vxmod->args.wave.base);
      shader_number_parse(argv[5], &vxmod->args.wave.amp);
      shader_number_parse(argv[6], &vxmod->args.wave.phase);
      shader_number_parse(argv[7], &vxmod->args.wave.freq);
   }
   // deformVertexes normal <amp> <freq>
   else if (stricmp(argv[1], "normal") == 0) {
      if (argc != 4) {
         jeShader_Error("usage: deformVertexes normal <amp> <freq>");
         return JE_TRUE;
      }

      vxmod->func = SH_VXMOD_NORMAL;

      shader_number_parse(argv[2], &vxmod->args.normal.amp);
      shader_number_parse(argv[3], &vxmod->args.normal.freq);
   }
   // deformVertexes bulge <width> <height> <speed>
   else if (stricmp(argv[1], "bulge") == 0) {
      if (argc != 5) {
         jeShader_Error("usage: deformVertexes bulge <width> <height> <speed>");
         return JE_TRUE;
      }

      vxmod->func = SH_VXMOD_BULGE;

      shader_number_parse(argv[2], &vxmod->args.bulge.width);
      shader_number_parse(argv[3], &vxmod->args.bulge.height);
      shader_number_parse(argv[4], &vxmod->args.bulge.speed);
   }
   // deformVertexes move <x> <y> <z> <func> <base> <amp> <phase> <freq>
   else if (stricmp(argv[1], "move") == 0) {
      int form;

      if (argc != 10) {
         jeShader_Error("usage: deformVertexes move <x> <y> <z> <func> <base> <amplitude> <phase> <freq>");
         return JE_TRUE;
      }

      vxmod->func = SH_VXMOD_MOVE;

      shader_number_parse(argv[2], &vxmod->args.move.x);
      shader_number_parse(argv[3], &vxmod->args.move.y);
      shader_number_parse(argv[4], &vxmod->args.move.z);

      form = ParseWaveForm(argv[5]);

      if (form < 0) return JE_TRUE;

      vxmod->args.move.form = form;

      shader_number_parse(argv[6], &vxmod->args.move.base);
      shader_number_parse(argv[7], &vxmod->args.move.amp);
      shader_number_parse(argv[8], &vxmod->args.move.phase);
      shader_number_parse(argv[9], &vxmod->args.move.freq);
   }
   // deformVertexes autosprite
   else if (stricmp(argv[1], "autosprite") == 0) {
      if (argc != 2) {
         jeShader_Error("autosprite does not take any arguments");
      }

      vxmod->func = SH_VXMOD_AUTOSPRITE;
   }
   // deformVertexes autosprite2
   else if (stricmp(argv[1], "autosprite2") == 0) {
      if (argc != 2) {
         jeShader_Error("autosprite2 does not take any arguments");
      }

      vxmod->func = SH_VXMOD_AUTOSPRITE2;
   }
   // deformVertexes projectionShadow
   else if (stricmp(argv[1], "projectionShadow") == 0) {
      jeShader_Error("projectionShadow is not documented by Id");

      if (argc != 2) {
         jeShader_Error("projectionShadow does not take any arguments");
      }

      vxmod->func = SH_VXMOD_PROJECTION_SHADOW;
   }
   else if (stricmp(argv[1], "text0") == 0) {
      jeShader_Error("text0 is not documented by Id");

      if (argc != 2) {
         jeShader_Error("text0 does not take any arguments");
      }

      vxmod->func = SH_VXMOD_TEXT0;
   }
   else if (stricmp(argv[1], "text1") == 0) {
      jeShader_Error("text1 is not documented by Id");

      if (argc != 2) {
         jeShader_Error("text1 does not take any arguments");
      }

      vxmod->func = SH_VXMOD_TEXT1;
   }

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

      if (argc != 2) {
         jeShader_Error("_stencilShadow does not take any arguments");
      }

      vxmod->func = SH_VXMOD_STENCIL_SHADOW_EXT;
   }

   // error
   else {
      jeShader_Error("unrecognized command subtype '%s'", argv[1]);

      return JE_TRUE;
   }

   if (info->shader->vxmod_count < JE_SHADER_MAX_VXMODS) info->shader->vxmod_count++;

   return JE_TRUE;
}