This is taking me longer than I wanted.
[blender.git] / release / plugins / sequence / scatter.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include "plugin.h"
34
35 /* ******************** GLOBAL VARIABLES ***************** */
36
37
38 char name[24]= "scatter";
39
40 /* structure for buttons, 
41  *  butcode      name           default  min  max  0
42  */
43
44 VarStruct varstr[]= {
45         LABEL,          "Input: 1 strip", 0.0, 0.0, 0.0, "", 
46         NUM|INT,        "seed: ",               1.0,    0.0, 10.0, "Offset in random table", 
47         NUMSLI|FLO,     "swing: ",              1.0,    0.0, 3.0, "The amplitude, width of the effect", 
48         TOG|INT,        "wrap",                 0.0,    0.0, 1.0, "Cyclic wrap around the left/right edges", 
49         NUM|INT,        "type: ",               1.0,    0.0, 1.0, "Type 1 is random for each frame", 
50 };
51
52 /* The cast struct is for input in the main doit function
53    Varstr and Cast must have the same variables in the same order */ 
54
55 typedef struct Cast {
56         int dummy;                      /* because of the 'label' button */
57         int seed;
58         float swing;
59         int wrap;
60         int type;
61 } Cast;
62
63 /* cfra: the current frame */
64
65 float cfra;
66
67 void plugin_seq_doit(Cast *, float, float, int, int, ImBuf *, ImBuf *, ImBuf *, ImBuf *);
68
69
70 /* ******************** Fixed functions ***************** */
71
72 int plugin_seq_getversion(void) 
73 {
74         return B_PLUGIN_VERSION;
75 }
76
77 void plugin_but_changed(int but) 
78 {
79 }
80
81 void plugin_init()
82 {
83 }
84
85 void plugin_getinfo(PluginInfo *info)
86 {
87         info->name= name;
88         info->nvars= sizeof(varstr)/sizeof(VarStruct);
89         info->cfra= &cfra;
90
91         info->varstr= varstr;
92
93         info->init= plugin_init;
94         info->seq_doit= (SeqDoit) plugin_seq_doit;
95         info->callback= plugin_but_changed;
96 }
97
98
99 /* ************************************************************
100         Scatter
101         
102    ************************************************************ */
103
104 static void rectcpy(ImBuf *dbuf, ImBuf *sbuf,   
105                                 int destx, int desty, 
106                                 int srcx, int srcy, int width, int height)
107 {
108         uint *drect,*srect;
109         float *dfrect, *sfrect;
110         int tmp;
111
112         if (dbuf == 0) return;
113
114         if (destx < 0){
115                 srcx -= destx ;
116                 width += destx ;
117                 destx = 0;
118         }
119         if (srcx < 0){
120                 destx -= srcx ;
121                 width += destx ;
122                 srcx = 0;
123         }
124         if (desty < 0){
125                 srcy -= desty ;
126                 height += desty ;
127                 desty = 0;
128         }
129         if (srcy < 0){
130                 desty -= srcy ;
131                 height += desty ;
132                 srcy = 0;
133         }
134
135         if (width > dbuf->x - destx) width = dbuf->x - destx;
136         if (height > dbuf->y - desty) height = dbuf->y - desty;
137         if (sbuf){
138                 if (width > sbuf->x - srcx) width = sbuf->x - srcx;
139                 if (height > sbuf->y - srcy) height = sbuf->y - srcy;
140                 srect = sbuf->rect;
141                 sfrect = sbuf->rect_float;
142         }
143
144         if (width <= 0) return;
145         if (height <= 0) return;
146
147         drect = dbuf->rect;
148         dfrect = dbuf->rect_float;
149
150         tmp = desty * dbuf->x + destx;
151
152         if (dbuf->rect_float) dfrect += tmp;
153         else drect += tmp;
154
155         destx = dbuf->x;
156
157         if (sbuf) {
158                 tmp = srcy * sbuf->x + srcx;
159                 if (dbuf->rect_float) sfrect += tmp;
160                 else srect += tmp;
161                 srcx = sbuf->x;
162         } else{
163                 if (dbuf->rect_float) sfrect = dfrect;
164                 else srect = drect;
165                 srcx = destx;
166         }
167
168         for (;height > 0; height--){
169                 if (dbuf->rect_float) {
170                         memcpy(dfrect,sfrect, srcx * sizeof(float));
171                         dfrect += destx;
172                         sfrect += srcx;
173                 } else {
174                         memcpy(drect,srect, srcx * sizeof(int));
175                         drect += destx;
176                         srect += srcx;
177                 }
178         }
179 }
180
181 static void fill_out(ImBuf *out, float r, float g, float b, float a)
182 {
183         int tot,x;
184         float *rectf = out->rect_float;
185         unsigned char *rect = (unsigned char *)out->rect;
186
187         tot = out->x * out->y;
188         if (out->rect_float) {
189                 for (x = 0;x < tot; x++) {
190                         rectf[0] = r;
191                         rectf[1] = g;
192                         rectf[2] = b;
193                         rectf[3] = a;
194                         rectf = rectf + 4;
195                 }
196         } else {
197                 for (x=0;x < tot;x++) {
198                         rect[0] = (int)(r * 255);
199                         rect[1] = (int)(g * 255);
200                         rect[2] = (int)(b * 255);
201                         rect[3] = (int)(a * 255);
202                         rect += 4;
203                 }
204         }
205 }
206
207
208 void plugin_seq_doit(Cast *cast, float facf0, float facf1, int sx, int sy, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *out, ImBuf *use)
209 {
210         float f1, f2, t1, t2, t3;
211         int x, y, lr;
212         
213         /* fill imbuf 'out' with black */
214         fill_out(out, 0,0,0,0);
215
216         switch (cast->type) {
217                 case 0:
218                         srand48(cast->seed);
219                         break;
220                 case 1:
221                         srand48(cast->seed + facf0 * 1000);
222                         break;
223         }
224
225         for (y = 0; y < sy; y++) {
226                 switch (cast->type) {
227                         case 0:
228                                 if ((y & 1) == 0) {
229                                         f1 = drand48() - 0.5;
230                                         f2 = drand48() - 0.5;
231                                         f1 = cast->swing * f1;
232                                         f2 = cast->swing * f2;
233                                         if (cast->wrap) f2 += 1.0;
234                                         lr = drand48()>0.5;
235                                         t1 = facf0;
236                                 } else t1 = facf1;
237                                 
238                                 t2 = 1.0 - t1;
239                                 t3 = 3.0 * (f1 * t1 * t1 * t2 + f2 * t1 * t2 * t2);
240                                 if (cast->wrap) t3 += t2 * t2 * t2;
241                                 x = sx * t3;
242                                 if (lr) x = -x;
243                                 break;
244                         case 1:
245                                 f1 = drand48() - 0.5;
246                                 f1 = f1 * cast->swing;
247                                 if ((y & 1) == 0) f1 *= facf0;
248                                 else f1 *= facf1;
249                                 x = f1 * sx;
250                                 break;
251                 }
252                 
253                 rectcpy(out, ibuf1, 0, y, x, y, 32767, 1);
254                 if (cast->wrap) {
255                         rectcpy(out, ibuf1, 0, y, x + sx, y, 32767, 1);
256                         rectcpy(out, ibuf1, 0, y, x + sx + sx, y, 32767, 1);
257                         rectcpy(out, ibuf1, 0, y, x - sx, y, 32767, 1);
258                         rectcpy(out, ibuf1, 0, y, x - sx - sx, y, 32767, 1);
259                 }
260         }
261 }
262