/* 
 * This plugin does 19 diffrent sweeps from one strip to
 * another, (If one of the strips doesn't exist it goes to black)
 * Created by mein@cs.umn.edu 
 */

#include "plugin.h"

enum {DO_LEFT_RIGHT, DO_RIGHT_LEFT, DO_DOWN_UP, DO_UP_DOWN, 
      DO_LOWER_LEFT_UPPER_RIGHT, DO_UPPER_RIGHT_LOWER_LEFT,
      DO_UPPER_LEFT_LOWER_RIGHT, DO_LOWER_RIGHT_UPPER_LEFT, 
      DO_HORZ_OUT, DO_HORZ_IN, DO_VERT_OUT, DO_VERT_IN,
      DO_HORZ_VERT_OUT, DO_HORZ_VERT_IN, DO_LEFT_DOWN_RIGHT_UP_OUT,
      DO_LEFT_DOWN_RIGHT_UP_IN, DO_LEFT_UP_RIGHT_DOWN_OUT, 
      DO_LEFT_UP_RIGHT_DOWN_IN, DO_DIAG_OUT, DO_DIAG_IN, DO_DIAG_OUT_2,
      DO_DIAG_IN_2};

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


char name[24]= "Sweep";	

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

VarStruct varstr[]= {
   { LABEL,	"In: 2 strips", 0.0, 0.0, 0.0, ""}, 
   { NUM|INT,	"Type",	    0.0,	0.0,	21.0, "Our type of Sweep"}, 
   { TOG|INT,	"Animated", 0.0,	0.0,	1.0, 
	"For (Ipo) animated blur"}, 
};

/* The cast struct is for input in the main doit function
   Varstr and Cast must have the same variables in the same order */ 

typedef struct Cast {
	int dummy;			/* because of the 'label' button */
	int sweeptype;
	float use_ipo;
} Cast;


/* cfra: the current frame */

float cfra;

void plugin_seq_doit(Cast *, float, float, int, int, 
   ImBuf *, ImBuf *, ImBuf *, ImBuf *);

/* ******************** Fixed functions ***************** */

int plugin_seq_getversion(void) {
	return B_PLUGIN_VERSION;
}

void plugin_but_changed(int but) {
}

void plugin_init() {
}

void plugin_getinfo(PluginInfo *info) {
	info->name= name;
	info->nvars= sizeof(varstr)/sizeof(VarStruct);
	info->cfra= &cfra;

	info->varstr= varstr;

	info->init= plugin_init;
	info->seq_doit= (SeqDoit) plugin_seq_doit;
	info->callback= plugin_but_changed;
}

int check_zone(int x, int y, int xo, int yo, Cast *cast, float facf0) {

   float posx, posy;
   float halfx = xo/2;
   float halfy = yo/2;

      posx = facf0 *xo;
      posy = facf0 *yo;

   switch (cast->sweeptype) {
      case DO_LEFT_RIGHT:
         if (x > posx) return 1;
         return 0;
         break;
      case DO_RIGHT_LEFT:
         if (x < (xo - posx)) return 1;
         return 0;
	 break;
      case DO_DOWN_UP:
         if (y > posy ) return 1;
         return 0;
	 break;
      case DO_UP_DOWN:
         if (y < (yo - posy)) return 1;
         return 0;
	 break;
      case DO_LOWER_LEFT_UPPER_RIGHT:
         if (posy < posx) posx = posy;
         if ((x + yo - y) < posx*2) return 0;
         return 1;
	 break;
      case DO_UPPER_RIGHT_LOWER_LEFT:
         if (posy < posx) posx = posy;
         if ((xo - x + y) < posx*2) return 0;
         return 1;
	 break;
      case DO_UPPER_LEFT_LOWER_RIGHT:
         if (posy < posx) posx = posy;
         if ((x + y) < posx*2 ) return 0;
         return 1;
	 break;
      case DO_LOWER_RIGHT_UPPER_LEFT:
         if (posy < posx) posx = posy;
         if ((xo - x + yo - y) < posx*2) return 0;
         return 1;
	 break;
      case DO_HORZ_OUT:
         if ((x < (halfx - (posx/2)) ) || (x > (halfx + posx/2) )) return 1;
         return 0;
	 break;
      case DO_HORZ_IN:
         if ((x >posx/2) && (x < (xo - posx/2))) return 1;
         return 0;
	 break;
      case DO_VERT_OUT:
         if ((y < (halfy - posy/2)) || (y > (halfy + posy/2))) return 1;
         return 0;
	 break;
      case DO_VERT_IN:
         if ((y >posy/2) && (y < (yo - posy/2))) return 1;
         return 0;
	 break;
      case DO_HORZ_VERT_OUT:
         if (posy < posx) posx = posy;
         if (((x > (halfx - posx/2)) && (x < (halfx + posx/2))) || 
             ((y > (halfy - posx/2)) && (y < (halfy + posx/2)))) return 0;
         return 1;
	 break;
      case DO_HORZ_VERT_IN:
         if (posy < posx) posx = posy;
         if ((x <posx/2) || ((xo - x) <  posx/2) || (y < posx/2) || 
	     ((yo - y) < posx/2)) return 0;
         return 1;
	 break;
      case DO_LEFT_DOWN_RIGHT_UP_OUT:
         if (posy < posx) posx = posy;
         if (((x - halfx + y - halfy) < posx) && 
             ((halfx -x + halfy -y ) < posx)) return 0;
         return 1;
	 break;
      case DO_LEFT_DOWN_RIGHT_UP_IN:
         if (posy < posx) posx = posy;
         if (((y + xo - x) < posx) || ((yo - y + x) < posx)) return 0;
         return 1;
	 break;
      case DO_LEFT_UP_RIGHT_DOWN_OUT:
         if (posy < posx) posx = posy;
         if (((x - halfx + yo - y - halfy) < posx) && 
             ((halfx - x + halfy - yo + y ) < posx)) return 0;
         return 1;
	 break;
      case DO_LEFT_UP_RIGHT_DOWN_IN:
         if (posy < posx) posx = posy;
         if (((x+ y) < posx) || ((xo -x + yo - y) < posx )) return 0;
         return 1;
	 break;
      case DO_DIAG_OUT:
         if (posy < posx) posx = posy;
         if ((((x - halfx + y - halfy) < posx) && 
             ((halfx -x + halfy -y ) < posx)) && 
             (((x - halfx + yo - y - halfy) < posx)) && 
             ((halfx -x + halfy -yo + y) < posx)) return 0;
         return 1;
	 break;
      case DO_DIAG_IN:
         if (posy < posx) posx = posy;
         if ((x + y) < posx || ((xo -x + yo - y) < posx) ||
             ((x + yo -y) < posx) || ((y + xo - x) < posx)) return 0;
         return 1;
 	 break;
      case DO_DIAG_OUT_2:
         if (posy < posx) posx = posy;
         if ((((x - halfx + y - halfy) < posx/2) &&
             ((halfx -x + halfy -y ) < posx/2)) ||
             ((((x - halfx + yo - y - halfy) < posx/2)) &&
             ((halfx - x + halfy - yo + y) < posx/2))) return 0;
         return 1;
         break;
       case DO_DIAG_IN_2:
         if (posy < posx) posx = posy;
         if ((((y + xo - x) < posx) || ((yo - y + x) < posx)) &&
         (((x+ y) < posx) || ((xo -x + yo - y) < posx ))) return 0;
         return 1;
         break;
   }
   return 0;
}

void plugin_seq_doit(Cast *cast, float facf0, float facf1, int xo, int yo, 
	ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *outbuf, ImBuf *use) {
   int x;
   int y;
   char *in1, *in2;
   char *out=(char *)outbuf->rect;
   in1=(char *)ibuf1->rect;
   in2=(char *)ibuf2->rect;

   for(y=0;y<yo;y++) {
      for(x=0;x<xo;x++) {
         if (check_zone(x,y,xo,yo,cast,facf0)) {
            if (in1) {
               out[0] = in1[0];
               out[1] = in1[1];
               out[2] = in1[2];
               out[3] = in1[3];
            } else {
               out[0] = 0;
               out[1] = 0;
               out[2] = 0;
               out[3] = 255;
            }
         } else {
            if (in2) {
               out[0] = in2[0];
               out[1] = in2[1];
               out[2] = in2[2];
               out[3] = in2[3];
            } else {
               out[0] = 0;
               out[1] = 0;
               out[2] = 0;
               out[3] = 255;
            }
         }
         out+=4;
         if (in1 !=NULL) {
           in1+=4;
         }
         if (in2 !=NULL) {
            in2+=4;
         }
      }
   }
}
