/* 
 * This plugin ofsetts an image with or without wrap
 * Created by SirDude (mein@cs.umn.edu )
 * http://www.cs.umn.edu/~mein/blender
 * Tue Jan 15 03:07:46 CST 2002
 */

#include "plugin.h"

/* ******************** GLOBAL VARIABLES ***************** */
char name[24]= "Jitter";

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

VarStruct varstr[]= {
   { LABEL, "In: 1 strip", 		0.0, 0.0, 0.0, ""}, 
   { TOG|INT, "Random jitter",		1, 0.0, 1.0, 
        "Do you want Random Jitter?"}, 
   { NUMSLI|FLO,        "Seed",         0.0,-1,1,
        "Random seed" },
   { NUM|INT, "Xstep",			0.0, 0.0, 1000.0, 
	"Max X offset"}, 
   { NUM|INT, "Ystep",			10.0, 0.0, 1000.0, 
        "Max Y offset"}, 
   { LABEL,	"", 			0.0, 0.0, 0.0, ""}, 
   { TOG|INT,	"wrap",			0.0, 0.0, 1.0, 
        "Do you want image wrap?"}, 
   { TOG|INT,	"Use IPO Curves", 	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, use_rand;
        float seed;
        int xstep, ystep, dummy2, wrap, 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 get_source(int x, int y, int xo, int yo, Cast *cast, float facf0) {
   int done, tmp, count;

   if (cast->use_ipo == 1) {
      x = facf0 * xo;
      y = facf0 * yo;
   }
   if (cast->use_rand == 1) {
      srand(cast->seed + cfra);
      tmp = cast->xstep * 2;
      if (tmp > 0) {
         x += (rand()%tmp) - cast->xstep; 
      }
      tmp = cast->ystep * 2;
      if (tmp > 0) {
         y += (rand()%tmp) - cast->ystep;
      }
   }
   if (cast->wrap == 1) {
      done = 0;
      count = 0;
      while (!done) {
         done = 1;
         if (x < 0) {
            x = xo + x;
            done = 0;
         }
         if (y < 0) { 
            y = yo + y;
            done = 0;
         }
         if  (x > xo) {
            x = x - xo;
            done = 0;
         }
         if  (y > yo) {
            y = y - yo;
            done = 0;
         }
         if (count++> 100) {
            return -1;
         } 
      }
   } else {
      if ((x < 0) || (x >= xo) || (y < 0) || (y >= yo)) return -1;
   }
   return (x + y * xo)*4;
}

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

   for(y=0;y<yo;y++) {
      for(x=0;x<xo;x++) {
         source = get_source(x,y,xo,yo,cast,facf0);
         dest = (y * xo + x)*4;
         if (source < 0) {
            out[dest] = 0;
            out[dest+1] = 0;
            out[dest+2] = 0;
            out[dest+3] = 0;
         } else {
            out[dest] = in[source];
            out[dest+1] = in[source+1];
            out[dest+2] = in[source+2];
            out[dest+3] = in[source+3];
         }
      }
   }
}
