merge with trunk. also tried to fix tesselator code; new code should've worked,...
[blender.git] / source / blender / blenkernel / intern / brush.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL 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.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <math.h>
31 #include <string.h>
32
33 #include "MEM_guardedalloc.h"
34
35 #include "DNA_brush_types.h"
36 #include "DNA_color_types.h"
37 #include "DNA_image_types.h"
38 #include "DNA_texture_types.h"
39 #include "DNA_scene_types.h"
40 #include "DNA_windowmanager_types.h"
41
42 #include "RNA_access.h"
43
44 #include "BLI_arithb.h"
45 #include "BLI_blenlib.h"
46
47 #include "BKE_brush.h"
48 #include "BKE_colortools.h"
49 #include "BKE_global.h"
50 #include "BKE_image.h"
51 #include "BKE_library.h"
52 #include "BKE_main.h"
53 #include "BKE_texture.h"
54 #include "BKE_utildefines.h"
55
56 #include "IMB_imbuf.h"
57 #include "IMB_imbuf_types.h"
58
59 #include "RE_render_ext.h" /* externtex */
60 #include "RE_shader_ext.h"
61
62 /* Datablock add/copy/free/make_local */
63
64 Brush *add_brush(char *name)
65 {
66         Brush *brush;
67
68         brush= alloc_libblock(&G.main->brush, ID_BR, name);
69
70         brush->rgb[0]= 1.0f;
71         brush->rgb[1]= 1.0f;
72         brush->rgb[2]= 1.0f;
73         brush->alpha= 0.2f;
74         brush->size= 25;
75         brush->spacing= 10.0f;
76         brush->rate= 0.1f;
77         brush->innerradius= 0.5f;
78         brush->clone.alpha= 0.5;
79         brush->sculpt_tool = SCULPT_TOOL_DRAW;
80
81         brush_curve_preset(brush, BRUSH_PRESET_SHARP);
82
83         /* enable fake user by default */
84         brush->id.flag |= LIB_FAKEUSER;
85         brush_toggled_fake_user(brush);
86         
87         return brush;   
88 }
89
90 Brush *copy_brush(Brush *brush)
91 {
92         Brush *brushn;
93         MTex *mtex;
94         int a;
95         
96         brushn= copy_libblock(brush);
97
98         for(a=0; a<MAX_MTEX; a++) {
99                 mtex= brush->mtex[a];
100                 if(mtex) {
101                         brushn->mtex[a]= MEM_dupallocN(mtex);
102                         if(mtex->tex) id_us_plus((ID*)mtex->tex);
103                 }
104         }
105
106         /* enable fake user by default */
107         if (!(brushn->id.flag & LIB_FAKEUSER)) {
108                 brushn->id.flag |= LIB_FAKEUSER;
109                 brush_toggled_fake_user(brushn);
110         }
111         
112         return brushn;
113 }
114
115 /* not brush itself */
116 void free_brush(Brush *brush)
117 {
118         MTex *mtex;
119         int a;
120
121         for(a=0; a<MAX_MTEX; a++) {
122                 mtex= brush->mtex[a];
123                 if(mtex) {
124                         if(mtex->tex) mtex->tex->id.us--;
125                         MEM_freeN(mtex);
126                 }
127         }
128
129         curvemapping_free(brush->curve);
130 }
131
132 void make_local_brush(Brush *brush)
133 {
134         /* - only lib users: do nothing
135                 * - only local users: set flag
136                 * - mixed: make copy
137                 */
138         
139         Brush *brushn;
140         Scene *scene;
141         int local= 0, lib= 0;
142
143         if(brush->id.lib==0) return;
144
145         if(brush->clone.image) {
146                 /* special case: ima always local immediately */
147                 brush->clone.image->id.lib= 0;
148                 brush->clone.image->id.flag= LIB_LOCAL;
149                 new_id(0, (ID *)brush->clone.image, 0);
150         }
151
152         for(scene= G.main->scene.first; scene; scene=scene->id.next)
153                 if(scene->toolsettings->imapaint.brush==brush) {
154                         if(scene->id.lib) lib= 1;
155                         else local= 1;
156                 }
157         
158         if(local && lib==0) {
159                 brush->id.lib= 0;
160                 brush->id.flag= LIB_LOCAL;
161                 new_id(0, (ID *)brush, 0);
162
163                 /* enable fake user by default */
164                 if (!(brush->id.flag & LIB_FAKEUSER)) {
165                         brush->id.flag |= LIB_FAKEUSER;
166                         brush_toggled_fake_user(brush);
167                 }
168         }
169         else if(local && lib) {
170                 brushn= copy_brush(brush);
171                 brushn->id.us= 1; /* only keep fake user */
172                 brushn->id.flag |= LIB_FAKEUSER;
173                 
174                 for(scene= G.main->scene.first; scene; scene=scene->id.next)
175                         if(scene->toolsettings->imapaint.brush==brush)
176                                 if(scene->id.lib==0) {
177                                         scene->toolsettings->imapaint.brush= brushn;
178                                         brushn->id.us++;
179                                         brush->id.us--;
180                                 }
181         }
182 }
183
184 /* Library Operations */
185
186 int brush_set_nr(Brush **current_brush, int nr)
187 {
188         ID *idtest, *id;
189         
190         id= (ID*)(*current_brush);
191         idtest= (ID*)BLI_findlink(&G.main->brush, nr-1);
192         
193         if(idtest==0) { /* new brush */
194                 if(id) idtest= (ID *)copy_brush((Brush *)id);
195                 else idtest= (ID *)add_brush("Brush");
196                 idtest->us--;
197         }
198         if(idtest!=id) {
199                 brush_delete(current_brush);
200                 *current_brush= (Brush *)idtest;
201                 id_us_plus(idtest);
202
203                 return 1;
204         }
205
206         return 0;
207 }
208
209 int brush_delete(Brush **current_brush)
210 {
211         if (*current_brush) {
212                 (*current_brush)->id.us--;
213                 *current_brush= NULL;
214
215                 return 1;
216         }
217
218         return 0;
219 }
220
221 void brush_toggled_fake_user(Brush *brush)
222 {
223         ID *id= (ID*)brush;
224         if(id) {
225                 if(id->flag & LIB_FAKEUSER) {
226                         id_us_plus(id);
227                 } else {
228                         id->us--;
229                 }
230         }
231 }
232
233 void brush_curve_preset(Brush *b, BrushCurvePreset preset)
234 {
235         CurveMap *cm = NULL;
236
237         if(!b->curve)
238                 b->curve = curvemapping_add(1, 0, 0, 1, 1);
239
240         cm = b->curve->cm;
241
242         if(cm->curve)
243                 MEM_freeN(cm->curve);
244
245         if(preset == BRUSH_PRESET_SHARP)
246                 cm->totpoint= 3;
247         if(preset == BRUSH_PRESET_SMOOTH)
248                 cm->totpoint= 6;
249         if(preset == BRUSH_PRESET_MAX)
250                 cm->totpoint= 2;
251
252
253         cm->curve= MEM_callocN(cm->totpoint*sizeof(CurveMapPoint), "curve points");
254         cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
255
256         if(preset == BRUSH_PRESET_SHARP) {
257                 cm->curve[0].x= 0;
258                 cm->curve[0].y= 1;
259                 cm->curve[1].x= 0.33;
260                 cm->curve[1].y= 0.33;
261                 cm->curve[2].x= 1;
262                 cm->curve[2].y= 0;
263         }
264         else if(preset == BRUSH_PRESET_SMOOTH) {
265                 cm->curve[0].x= 0;
266                 cm->curve[0].y= 1;
267                 cm->curve[1].x= 0.1;
268                 cm->curve[1].y= 0.97553;
269                 cm->curve[2].x= 0.3;
270                 cm->curve[2].y= 0.79389;
271                 cm->curve[3].x= 0.9;
272                 cm->curve[3].y= 0.02447;
273                 cm->curve[4].x= 0.7;
274                 cm->curve[4].y= 0.20611;
275                 cm->curve[5].x= 1;
276                 cm->curve[5].y= 0;
277         }
278         else if(preset == BRUSH_PRESET_MAX) {
279                 cm->curve[0].x= 0;
280                 cm->curve[0].y= 1;
281                 cm->curve[1].x= 1;
282                 cm->curve[1].y= 1;
283         }
284
285         curvemapping_changed(b->curve, 0);
286 }
287
288 int brush_texture_set_nr(Brush *brush, int nr)
289 {
290         ID *idtest, *id=NULL;
291
292         if(brush->mtex[brush->texact])
293                 id= (ID *)brush->mtex[brush->texact]->tex;
294
295         idtest= (ID*)BLI_findlink(&G.main->tex, nr-1);
296         if(idtest==0) { /* new tex */
297                 if(id) idtest= (ID *)copy_texture((Tex *)id);
298                 else idtest= (ID *)add_texture("Tex");
299                 idtest->us--;
300         }
301         if(idtest!=id) {
302                 brush_texture_delete(brush);
303
304                 if(brush->mtex[brush->texact]==NULL) {
305                         brush->mtex[brush->texact]= add_mtex();
306                         brush->mtex[brush->texact]->r = 1.0f;
307                         brush->mtex[brush->texact]->g = 1.0f;
308                         brush->mtex[brush->texact]->b = 1.0f;
309                 }
310                 brush->mtex[brush->texact]->tex= (Tex*)idtest;
311                 id_us_plus(idtest);
312
313                 return 1;
314         }
315
316         return 0;
317 }
318
319 int brush_texture_delete(Brush *brush)
320 {
321         if(brush->mtex[brush->texact]) {
322                 if(brush->mtex[brush->texact]->tex)
323                         brush->mtex[brush->texact]->tex->id.us--;
324                 MEM_freeN(brush->mtex[brush->texact]);
325                 brush->mtex[brush->texact]= NULL;
326
327                 return 1;
328         }
329
330         return 0;
331 }
332
333 int brush_clone_image_set_nr(Brush *brush, int nr)
334 {
335         if(brush && nr > 0) {
336                 Image *ima= (Image*)BLI_findlink(&G.main->image, nr-1);
337
338                 if(ima) {
339                         brush_clone_image_delete(brush);
340                         brush->clone.image= ima;
341                         id_us_plus(&ima->id);
342                         brush->clone.offset[0]= brush->clone.offset[1]= 0.0f;
343
344                         return 1;
345                 }
346         }
347
348         return 0;
349 }
350
351 int brush_clone_image_delete(Brush *brush)
352 {
353         if (brush && brush->clone.image) {
354                 brush->clone.image->id.us--;
355                 brush->clone.image= NULL;
356                 return 1;
357         }
358
359         return 0;
360 }
361
362 void brush_check_exists(Brush **brush)
363 {
364         if(*brush==NULL)
365                 brush_set_nr(brush, 1);
366 }
367
368 /* Brush Sampling */
369
370 /*static float taylor_approx_cos(float f)
371 {
372         f = f*f;
373         f = 1.0f - f/2.0f + f*f/24.0f;
374         return f;
375 }*/
376
377 float brush_sample_falloff(Brush *brush, float dist)
378 {
379         float a, outer, inner;
380
381         outer = brush->size >> 1;
382         inner = outer*brush->innerradius;
383
384         if (dist <= inner) {
385                 return brush->alpha;
386         }
387         else if ((dist < outer) && (inner < outer)) {
388                 a = sqrt((dist - inner)/(outer - inner));
389                 return (1 - a)*brush->alpha;
390
391                 /* formula used by sculpt, with taylor approx 
392                 a = 0.5f*(taylor_approx_cos(3.0f*(dist - inner)/(outer - inner)) + 1.0f);
393                 return a*brush->alpha; */
394         }
395         else 
396                 return 0.0f;
397 }
398
399 float brush_sample_falloff_noalpha(Brush *brush, float dist)
400 {
401         float outer, inner;
402
403         outer = brush->size >> 1;
404         inner = outer*brush->innerradius;
405
406         if (dist <= inner) {
407                 return 1.0f;
408         }
409         else if ((dist < outer) && (inner < outer)) {
410                 return 1.0f - sqrt((dist - inner)/(outer - inner));
411         }
412         else 
413                 return 0.0f;
414 }
415
416 void brush_sample_tex(Brush *brush, float *xy, float *rgba)
417 {
418         MTex *mtex= brush->mtex[brush->texact];
419
420         if (mtex && mtex->tex) {
421                 float co[3], tin, tr, tg, tb, ta;
422                 int hasrgb;
423                 
424                 co[0]= xy[0]/(brush->size >> 1);
425                 co[1]= xy[1]/(brush->size >> 1);
426                 co[2]= 0.0f;
427
428                 hasrgb= externtex(mtex, co, &tin, &tr, &tg, &tb, &ta);
429
430                 if (hasrgb) {
431                         rgba[0]= tr;
432                         rgba[1]= tg;
433                         rgba[2]= tb;
434                         rgba[3]= ta;
435                 }
436                 else {
437                         rgba[0]= tin;
438                         rgba[1]= tin;
439                         rgba[2]= tin;
440                         rgba[3]= 1.0f;
441                 }
442         }
443         else if (rgba)
444                 rgba[0]= rgba[1]= rgba[2]= rgba[3]= 1.0f;
445 }
446
447
448 void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **outbuf)
449 {
450         ImBuf *ibuf;
451         float xy[2], dist, rgba[4], *dstf;
452         int x, y, rowbytes, xoff, yoff, imbflag;
453         char *dst, crgb[3];
454
455         imbflag= (flt)? IB_rectfloat: IB_rect;
456         xoff = -size/2.0f + 0.5f;
457         yoff = -size/2.0f + 0.5f;
458         rowbytes= size*4;
459
460         if (*outbuf)
461                 ibuf= *outbuf;
462         else
463                 ibuf= IMB_allocImBuf(size, size, 32, imbflag, 0);
464
465         if (flt) {
466                 for (y=0; y < ibuf->y; y++) {
467                         dstf = ibuf->rect_float + y*rowbytes;
468
469                         for (x=0; x < ibuf->x; x++, dstf+=4) {
470                                 xy[0] = x + xoff;
471                                 xy[1] = y + yoff;
472
473                                 if (texfall == 0) {
474                                         dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
475
476                                         VECCOPY(dstf, brush->rgb);
477                                         dstf[3]= brush_sample_falloff(brush, dist);
478                                 }
479                                 else if (texfall == 1) {
480                                         brush_sample_tex(brush, xy, dstf);
481                                 }
482                                 else {
483                                         dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
484
485                                         brush_sample_tex(brush, xy, rgba);
486
487                                         dstf[0] = rgba[0]*brush->rgb[0];
488                                         dstf[1] = rgba[1]*brush->rgb[1];
489                                         dstf[2] = rgba[2]*brush->rgb[2];
490                                         dstf[3] = rgba[3]*brush_sample_falloff(brush, dist);
491                                 }
492                         }
493                 }
494         }
495         else {
496                 crgb[0]= FTOCHAR(brush->rgb[0]);
497                 crgb[1]= FTOCHAR(brush->rgb[1]);
498                 crgb[2]= FTOCHAR(brush->rgb[2]);
499
500                 for (y=0; y < ibuf->y; y++) {
501                         dst = (char*)ibuf->rect + y*rowbytes;
502
503                         for (x=0; x < ibuf->x; x++, dst+=4) {
504                                 xy[0] = x + xoff;
505                                 xy[1] = y + yoff;
506
507                                 if (texfall == 0) {
508                                         dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
509
510                                         dst[0]= crgb[0];
511                                         dst[1]= crgb[1];
512                                         dst[2]= crgb[2];
513                                         dst[3]= FTOCHAR(brush_sample_falloff(brush, dist));
514                                 }
515                                 else if (texfall == 1) {
516                                         brush_sample_tex(brush, xy, rgba);
517                                         dst[0]= FTOCHAR(rgba[0]);
518                                         dst[1]= FTOCHAR(rgba[1]);
519                                         dst[2]= FTOCHAR(rgba[2]);
520                                         dst[3]= FTOCHAR(rgba[3]);
521                                 }
522                                 else {
523                                         dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
524
525                                         brush_sample_tex(brush, xy, rgba);
526                                         dst[0] = FTOCHAR(rgba[0]*brush->rgb[0]);
527                                         dst[1] = FTOCHAR(rgba[1]*brush->rgb[1]);
528                                         dst[2] = FTOCHAR(rgba[2]*brush->rgb[2]);
529                                         dst[3] = FTOCHAR(rgba[3]*brush_sample_falloff(brush, dist));
530                                 }
531                         }
532                 }
533         }
534
535         *outbuf= ibuf;
536 }
537
538 /* Brush Painting */
539
540 typedef struct BrushPainterCache {
541         short enabled;
542
543         int size;                       /* size override, if 0 uses brush->size */
544         short flt;                      /* need float imbuf? */
545         short texonly;          /* no alpha, color or fallof, only texture in imbuf */
546
547         int lastsize;
548         float lastalpha;
549         float lastinnerradius;
550
551         ImBuf *ibuf;
552         ImBuf *texibuf;
553         ImBuf *maskibuf;
554 } BrushPainterCache;
555
556 struct BrushPainter {
557         Brush *brush;
558
559         float lastmousepos[2];  /* mouse position of last paint call */
560
561         float accumdistance;    /* accumulated distance of brush since last paint op */
562         float lastpaintpos[2];  /* position of last paint op */
563         float startpaintpos[2]; /* position of first paint */
564
565         double accumtime;               /* accumulated time since last paint op (airbrush) */
566         double lasttime;                /* time of last update */
567
568         float lastpressure;
569
570         short firsttouch;               /* first paint op */
571
572         float startsize;
573         float startalpha;
574         float startinnerradius;
575         float startspacing;
576
577         BrushPainterCache cache;
578 };
579
580 BrushPainter *brush_painter_new(Brush *brush)
581 {
582         BrushPainter *painter= MEM_callocN(sizeof(BrushPainter), "BrushPainter");
583
584         painter->brush= brush;
585         painter->firsttouch= 1;
586         painter->cache.lastsize= -1; /* force ibuf create in refresh */
587
588         painter->startsize = brush->size;
589         painter->startalpha = brush->alpha;
590         painter->startinnerradius = brush->innerradius;
591         painter->startspacing = brush->spacing;
592
593         return painter;
594 }
595
596 void brush_painter_require_imbuf(BrushPainter *painter, short flt, short texonly, int size)
597 {
598         if ((painter->cache.flt != flt) || (painter->cache.size != size) ||
599                 ((painter->cache.texonly != texonly) && texonly)) {
600                 if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
601                 if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
602                 painter->cache.ibuf= painter->cache.maskibuf= NULL;
603                 painter->cache.lastsize= -1; /* force ibuf create in refresh */
604         }
605
606         if (painter->cache.flt != flt) {
607                 if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
608                 painter->cache.texibuf= NULL;
609                 painter->cache.lastsize= -1; /* force ibuf create in refresh */
610         }
611
612         painter->cache.size= size;
613         painter->cache.flt= flt;
614         painter->cache.texonly= texonly;
615         painter->cache.enabled= 1;
616 }
617
618 void brush_painter_free(BrushPainter *painter)
619 {
620         Brush *brush = painter->brush;
621
622         brush->size = painter->startsize;
623         brush->alpha = painter->startalpha;
624         brush->innerradius = painter->startinnerradius;
625         brush->spacing = painter->startspacing;
626
627         if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
628         if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
629         if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
630         MEM_freeN(painter);
631 }
632
633 static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, int x, int y, int w, int h, int xt, int yt, float *pos)
634 {
635         Brush *brush= painter->brush;
636         ImBuf *ibuf, *maskibuf, *texibuf;
637         float *bf, *mf, *tf, *otf=NULL, xoff, yoff, xy[2], rgba[4];
638         char *b, *m, *t, *ot= NULL;
639         int dotexold, origx= x, origy= y;
640
641         xoff = -brush->size/2.0f + 0.5f;
642         yoff = -brush->size/2.0f + 0.5f;
643         xoff += (int)pos[0] - (int)painter->startpaintpos[0];
644         yoff += (int)pos[1] - (int)painter->startpaintpos[1];
645
646         ibuf = painter->cache.ibuf;
647         texibuf = painter->cache.texibuf;
648         maskibuf = painter->cache.maskibuf;
649
650         dotexold = (oldtexibuf != NULL);
651
652         if (painter->cache.flt) {
653                 for (; y < h; y++) {
654                         bf = ibuf->rect_float + (y*ibuf->x + origx)*4;
655                         tf = texibuf->rect_float + (y*texibuf->x + origx)*4;
656                         mf = maskibuf->rect_float + (y*maskibuf->x + origx)*4;
657
658                         if (dotexold)
659                                 otf = oldtexibuf->rect_float + ((y - origy + yt)*oldtexibuf->x + xt)*4;
660
661                         for (x=origx; x < w; x++, bf+=4, mf+=4, tf+=4) {
662                                 if (dotexold) {
663                                         VECCOPY(tf, otf);
664                                         tf[3] = otf[3];
665                                         otf += 4;
666                                 }
667                                 else {
668                                         xy[0] = x + xoff;
669                                         xy[1] = y + yoff;
670
671                                         brush_sample_tex(brush, xy, tf);
672                                 }
673
674                                 bf[0] = tf[0]*mf[0];
675                                 bf[1] = tf[1]*mf[1];
676                                 bf[2] = tf[2]*mf[2];
677                                 bf[3] = tf[3]*mf[3];
678                         }
679                 }
680         }
681         else {
682                 for (; y < h; y++) {
683                         b = (char*)ibuf->rect + (y*ibuf->x + origx)*4;
684                         t = (char*)texibuf->rect + (y*texibuf->x + origx)*4;
685                         m = (char*)maskibuf->rect + (y*maskibuf->x + origx)*4;
686
687                         if (dotexold)
688                                 ot = (char*)oldtexibuf->rect + ((y - origy + yt)*oldtexibuf->x + xt)*4;
689
690                         for (x=origx; x < w; x++, b+=4, m+=4, t+=4) {
691                                 if (dotexold) {
692                                         t[0] = ot[0];
693                                         t[1] = ot[1];
694                                         t[2] = ot[2];
695                                         t[3] = ot[3];
696                                         ot += 4;
697                                 }
698                                 else {
699                                         xy[0] = x + xoff;
700                                         xy[1] = y + yoff;
701
702                                         brush_sample_tex(brush, xy, rgba);
703                                         t[0]= FTOCHAR(rgba[0]);
704                                         t[1]= FTOCHAR(rgba[1]);
705                                         t[2]= FTOCHAR(rgba[2]);
706                                         t[3]= FTOCHAR(rgba[3]);
707                                 }
708
709                                 b[0] = t[0]*m[0]/255;
710                                 b[1] = t[1]*m[1]/255;
711                                 b[2] = t[2]*m[2]/255;
712                                 b[3] = t[3]*m[3]/255;
713                         }
714                 }
715         }
716 }
717
718 void brush_painter_fixed_tex_partial_update(BrushPainter *painter, float *pos)
719 {
720         Brush *brush= painter->brush;
721         BrushPainterCache *cache= &painter->cache;
722         ImBuf *oldtexibuf, *ibuf;
723         int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
724
725         imbflag= (cache->flt)? IB_rectfloat: IB_rect;
726         if (!cache->ibuf)
727                 cache->ibuf= IMB_allocImBuf(brush->size, brush->size, 32, imbflag, 0);
728         ibuf= cache->ibuf;
729
730         oldtexibuf= cache->texibuf;
731         cache->texibuf= IMB_allocImBuf(brush->size, brush->size, 32, imbflag, 0);
732
733         if (oldtexibuf) {
734                 srcx= srcy= 0;
735                 destx= (int)painter->lastpaintpos[0] - (int)pos[0];
736                 desty= (int)painter->lastpaintpos[1] - (int)pos[1];
737                 w= oldtexibuf->x;
738                 h= oldtexibuf->y;
739
740                 IMB_rectclip(cache->texibuf, oldtexibuf, &destx, &desty, &srcx, &srcy, &w, &h);
741         }
742         else {
743                 srcx= srcy= 0;
744                 destx= desty= 0;
745                 w= h= 0;
746         }
747         
748         x1= destx;
749         y1= desty;
750         x2= destx+w;
751         y2= desty+h;
752
753         /* blend existing texture in new position */
754         if ((x1 < x2) && (y1 < y2))
755                 brush_painter_do_partial(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy, pos);
756
757         if (oldtexibuf)
758                 IMB_freeImBuf(oldtexibuf);
759
760         /* sample texture in new areas */
761         if ((0 < x1) && (0 < ibuf->y))
762                 brush_painter_do_partial(painter, NULL, 0, 0, x1, ibuf->y, 0, 0, pos);
763         if ((x2 < ibuf->x) && (0 < ibuf->y))
764                 brush_painter_do_partial(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0, pos);
765         if ((x1 < x2) && (0 < y1))
766                 brush_painter_do_partial(painter, NULL, x1, 0, x2, y1, 0, 0, pos);
767         if ((x1 < x2) && (y2 < ibuf->y))
768                 brush_painter_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos);
769 }
770
771 static void brush_painter_refresh_cache(BrushPainter *painter, float *pos)
772 {
773         Brush *brush= painter->brush;
774         BrushPainterCache *cache= &painter->cache;
775         MTex *mtex= brush->mtex[brush->texact];
776         int size;
777         short flt;
778
779         if ((brush->size != cache->lastsize) || (brush->alpha != cache->lastalpha)
780             || (brush->innerradius != cache->lastinnerradius)) {
781                 if (cache->ibuf) {
782                         IMB_freeImBuf(cache->ibuf);
783                         cache->ibuf= NULL;
784                 }
785                 if (cache->maskibuf) {
786                         IMB_freeImBuf(cache->maskibuf);
787                         cache->maskibuf= NULL;
788                 }
789
790                 flt= cache->flt;
791                 size= (cache->size)? cache->size: brush->size;
792
793                 if (!(mtex && mtex->tex) || (mtex->tex->type==0)) {
794                         brush_imbuf_new(brush, flt, 0, size, &cache->ibuf);
795                 }
796                 else if (brush->flag & BRUSH_FIXED_TEX) {
797                         brush_imbuf_new(brush, flt, 0, size, &cache->maskibuf);
798                         brush_painter_fixed_tex_partial_update(painter, pos);
799                 }
800                 else
801                         brush_imbuf_new(brush, flt, 2, size, &cache->ibuf);
802
803                 cache->lastsize= brush->size;
804                 cache->lastalpha= brush->alpha;
805                 cache->lastinnerradius= brush->innerradius;
806         }
807         else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) {
808                 int dx = (int)painter->lastpaintpos[0] - (int)pos[0];
809                 int dy = (int)painter->lastpaintpos[1] - (int)pos[1];
810
811                 if ((dx != 0) || (dy != 0))
812                         brush_painter_fixed_tex_partial_update(painter, pos);
813         }
814 }
815
816 void brush_painter_break_stroke(BrushPainter *painter)
817 {
818         painter->firsttouch= 1;
819 }
820
821 static void brush_apply_pressure(BrushPainter *painter, Brush *brush, float pressure)
822 {
823         if (brush->flag & BRUSH_ALPHA_PRESSURE) 
824                 brush->alpha = MAX2(0.0, painter->startalpha*pressure);
825         if (brush->flag & BRUSH_SIZE_PRESSURE)
826                 brush->size = MAX2(1.0, painter->startsize*pressure);
827         if (brush->flag & BRUSH_RAD_PRESSURE)
828                 brush->innerradius = MAX2(0.0, painter->startinnerradius*pressure);
829         if (brush->flag & BRUSH_SPACING_PRESSURE)
830                 brush->spacing = MAX2(1.0, painter->startspacing*(1.5f-pressure));
831 }
832
833 int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, float pressure, void *user)
834 {
835         Brush *brush= painter->brush;
836         int totpaintops= 0;
837
838         if (pressure == 0.0f)
839                 pressure = 1.0f;        /* zero pressure == not using tablet */
840
841         if (painter->firsttouch) {
842                 /* paint exactly once on first touch */
843                 painter->startpaintpos[0]= pos[0];
844                 painter->startpaintpos[1]= pos[1];
845
846                 brush_apply_pressure(painter, brush, pressure);
847                 if (painter->cache.enabled)
848                         brush_painter_refresh_cache(painter, pos);
849                 totpaintops += func(user, painter->cache.ibuf, pos, pos);
850                 
851                 painter->lasttime= time;
852                 painter->firsttouch= 0;
853                 painter->lastpaintpos[0]= pos[0];
854                 painter->lastpaintpos[1]= pos[1];
855         }
856 #if 0
857         else if (painter->brush->flag & BRUSH_AIRBRUSH) {
858                 float spacing, step, paintpos[2], dmousepos[2], len;
859                 double starttime, curtime= time;
860
861                 /* compute brush spacing adapted to brush size */
862                 spacing= brush->rate; //brush->size*brush->spacing*0.01f;
863
864                 /* setup starting time, direction vector and accumulated time */
865                 starttime= painter->accumtime;
866                 Vec2Subf(dmousepos, pos, painter->lastmousepos);
867                 len= Normalize2(dmousepos);
868                 painter->accumtime += curtime - painter->lasttime;
869
870                 /* do paint op over unpainted time distance */
871                 while (painter->accumtime >= spacing) {
872                         step= (spacing - starttime)*len;
873                         paintpos[0]= painter->lastmousepos[0] + dmousepos[0]*step;
874                         paintpos[1]= painter->lastmousepos[1] + dmousepos[1]*step;
875
876                         if (painter->cache.enabled)
877                                 brush_painter_refresh_cache(painter);
878                         totpaintops += func(user, painter->cache.ibuf,
879                                 painter->lastpaintpos, paintpos);
880
881                         painter->lastpaintpos[0]= paintpos[0];
882                         painter->lastpaintpos[1]= paintpos[1];
883                         painter->accumtime -= spacing;
884                         starttime -= spacing;
885                 }
886                 
887                 painter->lasttime= curtime;
888         }
889 #endif
890         else {
891                 float startdistance, spacing, step, paintpos[2], dmousepos[2];
892                 float t, len, press;
893
894                 /* compute brush spacing adapted to brush size, spacing may depend
895                    on pressure, so update it */
896                 brush_apply_pressure(painter, brush, painter->lastpressure);
897                 spacing= MAX2(1.0f, brush->size)*brush->spacing*0.01f;
898
899                 /* setup starting distance, direction vector and accumulated distance */
900                 startdistance= painter->accumdistance;
901                 Vec2Subf(dmousepos, pos, painter->lastmousepos);
902                 len= Normalize2(dmousepos);
903                 painter->accumdistance += len;
904
905                 /* do paint op over unpainted distance */
906                 while ((len > 0.0f) && (painter->accumdistance >= spacing)) {
907                         step= spacing - startdistance;
908                         paintpos[0]= painter->lastmousepos[0] + dmousepos[0]*step;
909                         paintpos[1]= painter->lastmousepos[1] + dmousepos[1]*step;
910
911                         t = step/len;
912                         press= (1.0f-t)*painter->lastpressure + t*pressure;
913                         brush_apply_pressure(painter, brush, press);
914                         spacing= MAX2(1.0f, brush->size)*brush->spacing*0.01f;
915
916                         if (painter->cache.enabled)
917                                 brush_painter_refresh_cache(painter, paintpos);
918
919                         totpaintops +=
920                                 func(user, painter->cache.ibuf, painter->lastpaintpos, paintpos);
921
922                         painter->lastpaintpos[0]= paintpos[0];
923                         painter->lastpaintpos[1]= paintpos[1];
924                         painter->accumdistance -= spacing;
925                         startdistance -= spacing;
926                 }
927
928                 /* do airbrush paint ops, based on the number of paint ops left over
929                    from regular painting. this is a temporary solution until we have
930                    accurate time stamps for mouse move events */
931                 if (brush->flag & BRUSH_AIRBRUSH) {
932                         double curtime= time;
933                         double painttime= brush->rate*totpaintops;
934
935                         painter->accumtime += curtime - painter->lasttime;
936                         if (painter->accumtime <= painttime)
937                                 painter->accumtime= 0.0;
938                         else
939                                 painter->accumtime -= painttime;
940
941                         while (painter->accumtime >= brush->rate) {
942                                 brush_apply_pressure(painter, brush, pressure);
943                                 if (painter->cache.enabled)
944                                         brush_painter_refresh_cache(painter, paintpos);
945                                 totpaintops +=
946                                         func(user, painter->cache.ibuf, painter->lastmousepos, pos);
947                                 painter->accumtime -= brush->rate;
948                         }
949
950                         painter->lasttime= curtime;
951                 }
952         }
953
954         painter->lastmousepos[0]= pos[0];
955         painter->lastmousepos[1]= pos[1];
956         painter->lastpressure= pressure;
957
958         brush->alpha = painter->startalpha;
959         brush->size = painter->startsize;
960         brush->innerradius = painter->startinnerradius;
961         brush->spacing = painter->startspacing;
962
963         return totpaintops;
964 }
965
966 /* Uses the brush curve control to find a strength value between 0 and 1 */
967 float brush_curve_strength(Brush *br, float p, const float len)
968 {
969         if(p > len) p= len;
970         return curvemapping_evaluateF(br->curve, 0, p/len);
971 }
972
973 /* TODO: should probably be unified with BrushPainter stuff? */
974 unsigned int *brush_gen_texture_cache(Brush *br, int half_side)
975 {
976         unsigned int *texcache = NULL;
977         MTex *mtex = br->mtex[br->texact];
978         TexResult texres;
979         int hasrgb, ix, iy;
980         int side = half_side * 2;
981
982         memset(&texres, 0, sizeof(TexResult));
983         
984         if(mtex && mtex->tex) {
985                 float x, y, step = 2.0 / side, co[3];
986
987                 texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache");
988
989                 BKE_image_get_ibuf(mtex->tex->ima, NULL);
990                 
991                 /*do normalized cannonical view coords for texture*/
992                 for (y=-1.0, iy=0; iy<side; iy++, y += step) {
993                         for (x=-1.0, ix=0; ix<side; ix++, x += step) {
994                                 co[0]= x;
995                                 co[1]= y;
996                                 co[2]= 0.0f;
997                                 
998                                 /* This is copied from displace modifier code */
999                                 hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 1, &texres);
1000                         
1001                                 /* if the texture gave an RGB value, we assume it didn't give a valid
1002                                  * intensity, so calculate one (formula from do_material_tex).
1003                                  * if the texture didn't give an RGB value, copy the intensity across
1004                                  */
1005                                 if(hasrgb & TEX_RGB)
1006                                         texres.tin = (0.35 * texres.tr + 0.45 *
1007                                                       texres.tg + 0.2 * texres.tb);
1008
1009                                 texres.tin = texres.tin * 255.0;
1010                                 ((char*)texcache)[(iy*side+ix)*4] = (char)texres.tin;
1011                                 ((char*)texcache)[(iy*side+ix)*4+1] = (char)texres.tin;
1012                                 ((char*)texcache)[(iy*side+ix)*4+2] = (char)texres.tin;
1013                                 ((char*)texcache)[(iy*side+ix)*4+3] = (char)texres.tin;
1014                         }
1015                 }
1016         }
1017
1018         return texcache;
1019 }
1020
1021 /**** Radial Control ****/
1022 static struct ImBuf *brush_gen_radial_control_imbuf(Brush *br)
1023 {
1024         ImBuf *im = MEM_callocN(sizeof(ImBuf), "radial control texture");
1025         unsigned int *texcache;
1026         int side = 128;
1027         int half = side / 2;
1028         int i, j;
1029
1030         texcache = brush_gen_texture_cache(br, half);
1031         im->rect_float = MEM_callocN(sizeof(float) * side * side, "radial control rect");
1032         im->x = im->y = side;
1033
1034         for(i=0; i<side; ++i) {
1035                 for(j=0; j<side; ++j) {
1036                         float magn= sqrt(pow(i - half, 2) + pow(j - half, 2));
1037                         im->rect_float[i*side + j]= brush_curve_strength(br, magn, half);
1038                 }
1039         }
1040
1041         /* Modulate curve with texture */
1042         if(texcache) {
1043                 for(i=0; i<side; ++i) {
1044                         for(j=0; j<side; ++j) {
1045                                 const int col= texcache[i*side+j];
1046                                 im->rect_float[i*side+j]*= (((char*)&col)[0]+((char*)&col)[1]+((char*)&col)[2])/3.0f/255.0f;
1047                         }
1048                 }
1049
1050                 MEM_freeN(texcache);
1051         }
1052
1053         return im;
1054 }
1055
1056 void brush_radial_control_invoke(wmOperator *op, Brush *br)
1057 {
1058         int mode = RNA_int_get(op->ptr, "mode");
1059         float original_value= 0;
1060
1061         if(mode == WM_RADIALCONTROL_SIZE)
1062                 original_value = br->size;
1063         else if(mode == WM_RADIALCONTROL_STRENGTH)
1064                 original_value = br->alpha;
1065         else if(mode == WM_RADIALCONTROL_ANGLE)
1066                 original_value = br->rot;
1067
1068         RNA_float_set(op->ptr, "initial_value", original_value);
1069         op->customdata = brush_gen_radial_control_imbuf(br);
1070 }
1071
1072 int brush_radial_control_exec(wmOperator *op, Brush *br)
1073 {
1074         int mode = RNA_int_get(op->ptr, "mode");
1075         float new_value = RNA_float_get(op->ptr, "new_value");
1076         const float conv = 0.017453293;
1077
1078         if(mode == WM_RADIALCONTROL_SIZE)
1079                 br->size = new_value;
1080         else if(mode == WM_RADIALCONTROL_STRENGTH)
1081                 br->alpha = new_value;
1082         else if(mode == WM_RADIALCONTROL_ANGLE)
1083                 br->rot = new_value * conv;
1084
1085         return OPERATOR_FINISHED;
1086 }