/*
 * Copyright (c) 1999, Guillermo Sanz Romero. 
 * Distribute under GPL
 */

#include <stdlib.h>
#include "math.h"
#include "plugin.h"

/* ******************** GLOBAL VARIABLES ***************** */

#define TRUE 1
#define FALSE 0

/* Texture name */

char name[24]= "Bricks";

/* Subtype names must be less than 15 characters */

#define NR_TYPES 1
char stnames[NR_TYPES][16]= {"Inten"};

/* Structure for buttons,
 *  butcode      name           default  min  max  0
 */

VarStruct varstr[]= {
 { NUM|FLO,   "brickX",   1.0, 0.0, 100.0, "Size of brick along X"},
 { NUM|FLO,   "mortarX",   0.1, 0.0, 100.0, "Qty. of mortar along X"},
 { NUM|FLO,   "brickY",   0.5, 0.0, 100.0, "Size of brick along Y"},
 { NUM|FLO,   "mortarY",   0.1, 0.0, 100.0, "Qty. of mortar along Y"},
 { NUM|FLO,   "brickZ",   0.2, 0.0, 100.0, "Size of brick along Z"},
 { NUM|FLO,   "mortarZ",   0.1, 0.0, 100.0, "Qty. of mortar along Z"},
 { LABEL,   "v 1.0",   0.0, 0.0,   0.0, "Color and bump in next versions"},
};

/* The cast struct is for input in the main doit function
   Varstr and Cast must have the same variables in the same order, 
   INCLUDING dummy variables for label fields. */ 

typedef struct Cast {
   float brickX;
   float mortarX;
   float brickY;
   float mortarY;
   float brickZ;
   float mortarZ;
} Cast;

/* result:
   Intensity, R, G, B, Alpha, nor.x, nor.y, nor.z
 */

float result[8];

/* cfra: the current frame */

float cfra;

int plugin_tex_doit(int, Cast*, float*, float*, float*);

/* ******************** Fixed Functions ***************** */

int plugin_tex_getversion(void) 
{
   return B_PLUGIN_VERSION;
}

void plugin_but_changed(int but) 
{
}

void plugin_init(void)
{
   
   srand(12);
}

/* this function should not be changed: */

void plugin_getinfo(PluginInfo *info)
{
   info->name = name;
   info->stypes = NR_TYPES;
   info->nvars = sizeof(varstr)/sizeof(VarStruct);
   
   info->snames = stnames[0];
   info->result = result;
   info->cfra = &cfra;
   info->varstr = varstr;

   info->init = plugin_init;
   info->tex_doit =  (TexDoit) plugin_tex_doit;
   info->callback = plugin_but_changed;
}

/* ********************* The Texture ******************** */

/* return 0: One channel texture
   return 1: RGB texture
   return 2: Normals texture */




int plugin_tex_doit(int stype, Cast *cast, float *texvec, float *dxt, float *dyt)
{
   /* Total size in each axis */
   float totalX, totalY, totalZ;
   /* Ranges from 0.0 to total[X|Y|Z] */
   float zoneX, zoneY, zoneZ;
   /* Local info, due fmod problems */
   float localX, localY, localZ;
   /* To mark shifted layers */
   int shift = FALSE;

   totalZ = cast->brickZ + cast->mortarZ;
   /* Trick to show something in texture preview */
   texvec[2] = texvec[2] + (totalZ * 0.5);
   /* To avoid problems with negative numbers when using fmod */
   localZ = fabs (texvec[2]);
   zoneZ = fmod (localZ, totalZ);

   if (
       (zoneZ < (cast->mortarZ / 2)) ||
       (zoneZ > (totalZ - (cast->mortarZ / 2)))
      )
   {
       /* We are in mortar zone, for sure */
       result[0] = 0.0;
   }
   else
   {
      /* We do not know, try Y axis */
      totalY = cast->brickY + cast->mortarY;
      localY = fabs (texvec[1]);
      zoneY = fmod (localY, totalY);

      /* Look in which layer we are */
      /* Odd layers are shifted */
      if ((fmod (fabs (floor (texvec[2] / totalZ)), 2)) >= 1.0)
      {
         shift = TRUE;
         /* Move half of the total */
         zoneY = zoneY + (totalY / 2);
         /* If went out of bound, make the number sane again */
         if (zoneY > totalY)
         {
            zoneY = zoneY - totalY;
         };
      };

      if (
          (zoneY < (cast->mortarY / 2)) ||
          (zoneY > (totalY - (cast->mortarY / 2)))
         )
      {
         /* We are in mortar zone, for sure */
         result[0] = 0.0;
      }
      else
      {
         /* We do not know, try X axis */
         totalX = cast->brickX + cast->mortarX;
         localX = fabs (texvec[0]);
         zoneX = fmod (localX, totalX);

         /* Shift zone if needed */
         if (shift)
         {
            zoneX = zoneX + (totalX / 2);
            /* Sanitize if needed */
            if (zoneX > totalX)
            {
               zoneX = zoneX - totalX;
            };
         };

         if (
             (zoneX < (cast->mortarX / 2)) ||
             (zoneX > (totalX - (cast->mortarX / 2)))
            )
         {
            /* Finally, mortar and out */
            result[0] = 0.0;
         }
         else
         {
            /* Yeah, we hit brick, bye "if-else"s */
            result[0] = 1.0;
         };
      };
   };
   return 0;
}
