Fix for bug #8746: the fake user button for datablocks was not a toggle
[blender.git] / source / blender / blenkernel / intern / brush.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 <math.h>
34
35 #include "MEM_guardedalloc.h"
36
37 #include "DNA_brush_types.h"
38 #include "DNA_image_types.h"
39 #include "DNA_texture_types.h"
40 #include "DNA_scene_types.h"
41
42 #include "BLI_arithb.h"
43 #include "BLI_blenlib.h"
44
45 #include "BKE_brush.h"
46 #include "BKE_global.h"
47 #include "BKE_library.h"
48 #include "BKE_main.h"
49 #include "BKE_texture.h"
50 #include "BKE_utildefines.h"
51
52 #include "IMB_imbuf.h"
53 #include "IMB_imbuf_types.h"
54
55 #include "RE_render_ext.h" /* externtex */
56
57 /* Datablock add/copy/free/make_local */
58
59 Brush *add_brush(char *name)
60 {
61         Brush *brush;
62
63         brush= alloc_libblock(&G.main->brush, ID_BR, name);
64
65         brush->rgb[0]= 1.0f;
66         brush->rgb[1]= 1.0f;
67         brush->rgb[2]= 1.0f;
68         brush->alpha= 0.2f;
69         brush->size= 25;
70         brush->spacing= 10.0f;
71         brush->rate= 0.1f;
72         brush->innerradius= 0.5f;
73         brush->clone.alpha= 0.5;
74
75         /* enable fake user by default */
76         brush->id.flag |= LIB_FAKEUSER;
77         brush_toggled_fake_user(brush);
78         
79         return brush;   
80 }
81
82 Brush *copy_brush(Brush *brush)
83 {
84         Brush *brushn;
85         MTex *mtex;
86         int a;
87         
88         brushn= copy_libblock(brush);
89
90         for(a=0; a<MAX_MTEX; a++) {
91                 mtex= brush->mtex[a];
92                 if(mtex) {
93                         brushn->mtex[a]= MEM_dupallocN(mtex);
94                         if(mtex->tex) id_us_plus((ID*)mtex->tex);
95                 }
96         }
97
98         /* enable fake user by default */
99         if (!(brushn->id.flag & LIB_FAKEUSER)) {
100                 brushn->id.flag |= LIB_FAKEUSER;
101                 brush_toggled_fake_user(brushn);
102         }
103         
104         return brushn;
105 }
106
107 /* not brush itself */
108 void free_brush(Brush *brush)
109 {
110         MTex *mtex;
111         int a;
112
113         for(a=0; a<MAX_MTEX; a++) {
114                 mtex= brush->mtex[a];
115                 if(mtex) {
116                         if(mtex->tex) mtex->tex->id.us--;
117                         MEM_freeN(mtex);
118                 }
119         }
120 }
121
122 void make_local_brush(Brush *brush)
123 {
124         /* - only lib users: do nothing
125                 * - only local users: set flag
126                 * - mixed: make copy
127                 */
128         
129         Brush *brushn;
130         Scene *scene;
131         int local= 0, lib= 0;
132
133         if(brush->id.lib==0) return;
134
135         if(brush->clone.image) {
136                 /* special case: ima always local immediately */
137                 brush->clone.image->id.lib= 0;
138                 brush->clone.image->id.flag= LIB_LOCAL;
139                 new_id(0, (ID *)brush->clone.image, 0);
140         }
141
142         for(scene= G.main->scene.first; scene; scene=scene->id.next)
143                 if(scene->toolsettings->imapaint.brush==brush) {
144                         if(scene->id.lib) lib= 1;
145                         else local= 1;
146                 }
147         
148         if(local && lib==0) {
149                 brush->id.lib= 0;
150                 brush->id.flag= LIB_LOCAL;
151                 new_id(0, (ID *)brush, 0);
152
153                 /* enable fake user by default */
154                 if (!(brush->id.flag & LIB_FAKEUSER)) {
155                         brush->id.flag |= LIB_FAKEUSER;
156                         brush_toggled_fake_user(brush);
157                 }
158         }
159         else if(local && lib) {
160                 brushn= copy_brush(brush);
161                 brushn->id.us= 1; /* only keep fake user */
162                 brushn->id.flag |= LIB_FAKEUSER;
163                 
164                 for(scene= G.main->scene.first; scene; scene=scene->id.next)
165                         if(scene->toolsettings->imapaint.brush==brush)
166                                 if(scene->id.lib==0) {
167                                         scene->toolsettings->imapaint.brush= brushn;
168                                         brushn->id.us++;
169                                         brush->id.us--;
170                                 }
171         }
172 }
173
174 /* Library Operations */
175
176 int brush_set_nr(Brush **current_brush, int nr)
177 {
178         ID *idtest, *id;
179         
180         id= (ID*)(*current_brush);
181         idtest= (ID*)BLI_findlink(&G.main->brush, nr-1);
182         
183         if(idtest==0) { /* new brush */
184                 if(id) idtest= (ID *)copy_brush((Brush *)id);
185                 else idtest= (ID *)add_brush("Brush");
186                 idtest->us--;
187         }
188         if(idtest!=id) {
189                 brush_delete(current_brush);
190                 *current_brush= (Brush *)idtest;
191                 id_us_plus(idtest);
192
193                 return 1;
194         }
195
196         return 0;
197 }
198
199 int brush_delete(Brush **current_brush)
200 {
201         if (*current_brush) {
202                 (*current_brush)->id.us--;
203                 *current_brush= NULL;
204
205                 return 1;
206         }
207
208         return 0;
209 }
210
211 void brush_toggled_fake_user(Brush *brush)
212 {
213         ID *id= (ID*)brush;
214         if(id) {
215                 if(id->flag & LIB_FAKEUSER) {
216                         id_us_plus(id);
217                 } else {
218                         id->us--;
219                 }
220         }
221 }
222
223 int brush_texture_set_nr(Brush *brush, int nr)
224 {
225         ID *idtest, *id=NULL;
226
227         if(brush->mtex[brush->texact])
228                 id= (ID *)brush->mtex[brush->texact]->tex;
229
230         idtest= (ID*)BLI_findlink(&G.main->tex, nr-1);
231         if(idtest==0) { /* new tex */
232                 if(id) idtest= (ID *)copy_texture((Tex *)id);
233                 else idtest= (ID *)add_texture("Tex");
234                 idtest->us--;
235         }
236         if(idtest!=id) {
237                 brush_texture_delete(brush);
238
239                 if(brush->mtex[brush->texact]==NULL) {
240                         brush->mtex[brush->texact]= add_mtex();
241                         brush->mtex[brush->texact]->r = 1.0f;
242                         brush->mtex[brush->texact]->g = 1.0f;
243                         brush->mtex[brush->texact]->b = 1.0f;
244                 }
245                 brush->mtex[brush->texact]->tex= (Tex*)idtest;
246                 id_us_plus(idtest);
247
248                 return 1;
249         }
250
251         return 0;
252 }
253
254 int brush_texture_delete(Brush *brush)
255 {
256         if(brush->mtex[brush->texact]) {
257                 if(brush->mtex[brush->texact]->tex)
258                         brush->mtex[brush->texact]->tex->id.us--;
259                 MEM_freeN(brush->mtex[brush->texact]);
260                 brush->mtex[brush->texact]= NULL;
261
262                 return 1;
263         }
264
265         return 0;
266 }
267
268 int brush_clone_image_set_nr(Brush *brush, int nr)
269 {
270         if(brush && nr > 0) {
271                 Image *ima= (Image*)BLI_findlink(&G.main->image, nr-1);
272
273                 if(ima) {
274                         brush_clone_image_delete(brush);
275                         brush->clone.image= ima;
276                         id_us_plus(&ima->id);
277                         brush->clone.offset[0]= brush->clone.offset[1]= 0.0f;
278
279                         return 1;
280                 }
281         }
282
283         return 0;
284 }
285
286 int brush_clone_image_delete(Brush *brush)
287 {
288         if (brush && brush->clone.image) {
289                 brush->clone.image->id.us--;
290                 brush->clone.image= NULL;
291                 return 1;
292         }
293
294         return 0;
295 }
296
297 void brush_check_exists(Brush **brush)
298 {
299         if(*brush==NULL)
300                 brush_set_nr(brush, 1);
301 }
302
303 /* Brush Sampling */
304
305 /*static float taylor_approx_cos(float f)
306 {
307         f = f*f;
308         f = 1.0f - f/2.0f + f*f/24.0f;
309         return f;
310 }*/
311
312 float brush_sample_falloff(Brush *brush, float dist)
313 {
314         float a, outer, inner;
315
316         outer = brush->size >> 1;
317         inner = outer*brush->innerradius;
318
319         if (dist <= inner) {
320                 return brush->alpha;
321         }
322         else if ((dist < outer) && (inner < outer)) {
323                 a = sqrt((dist - inner)/(outer - inner));
324                 return (1 - a)*brush->alpha;
325
326                 /* formula used by sculpt, with taylor approx 
327                 a = 0.5f*(taylor_approx_cos(3.0f*(dist - inner)/(outer - inner)) + 1.0f);
328                 return a*brush->alpha; */
329         }
330         else 
331                 return 0.0f;
332 }
333
334 void brush_sample_tex(Brush *brush, float *xy, float *rgba)
335 {
336         MTex *mtex= brush->mtex[brush->texact];
337
338         if (mtex && mtex->tex) {
339                 float co[3], tin, tr, tg, tb, ta;
340                 int hasrgb;
341                 
342                 co[0]= xy[0]/(brush->size >> 1);
343                 co[1]= xy[1]/(brush->size >> 1);
344                 co[2]= 0.0f;
345
346                 hasrgb= externtex(mtex, co, &tin, &tr, &tg, &tb, &ta);
347
348                 if (hasrgb) {
349                         rgba[0]= tr;
350                         rgba[1]= tg;
351                         rgba[2]= tb;
352                         rgba[3]= ta;
353                 }
354                 else {
355                         rgba[0]= tin;
356                         rgba[1]= tin;
357                         rgba[2]= tin;
358                         rgba[3]= 1.0f;
359                 }
360         }
361         else if (rgba)
362                 rgba[0]= rgba[1]= rgba[2]= rgba[3]= 1.0f;
363 }
364
365 #define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val))
366
367 void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **outbuf)
368 {
369         ImBuf *ibuf;
370         float xy[2], dist, rgba[4], *dstf;
371         int x, y, rowbytes, xoff, yoff, imbflag;
372         char *dst, crgb[3];
373
374         imbflag= (flt)? IB_rectfloat: IB_rect;
375         xoff = -size/2.0f + 0.5f;
376         yoff = -size/2.0f + 0.5f;
377         rowbytes= size*4;
378
379         if (*outbuf)
380                 ibuf= *outbuf;
381         else
382                 ibuf= IMB_allocImBuf(size, size, 32, imbflag, 0);
383
384         if (flt) {
385                 for (y=0; y < ibuf->y; y++) {
386                         dstf = ibuf->rect_float + y*rowbytes;
387
388                         for (x=0; x < ibuf->x; x++, dstf+=4) {
389                                 xy[0] = x + xoff;
390                                 xy[1] = y + yoff;
391
392                                 if (texfall == 0) {
393                                         dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
394
395                                         VECCOPY(dstf, brush->rgb);
396                                         dstf[3]= brush_sample_falloff(brush, dist);
397                                 }
398                                 else if (texfall == 1) {
399                                         brush_sample_tex(brush, xy, dstf);
400                                 }
401                                 else {
402                                         dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
403
404                                         brush_sample_tex(brush, xy, rgba);
405
406                                         dstf[0] = rgba[0]*brush->rgb[0];
407                                         dstf[1] = rgba[1]*brush->rgb[1];
408                                         dstf[2] = rgba[2]*brush->rgb[2];
409                                         dstf[3] = rgba[3]*brush_sample_falloff(brush, dist);
410                                 }
411                         }
412                 }
413         }
414         else {
415                 crgb[0]= FTOCHAR(brush->rgb[0]);
416                 crgb[1]= FTOCHAR(brush->rgb[1]);
417                 crgb[2]= FTOCHAR(brush->rgb[2]);
418
419                 for (y=0; y < ibuf->y; y++) {
420                         dst = (char*)ibuf->rect + y*rowbytes;
421
422                         for (x=0; x < ibuf->x; x++, dst+=4) {
423                                 xy[0] = x + xoff;
424                                 xy[1] = y + yoff;
425
426                                 if (texfall == 0) {
427                                         dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
428
429                                         dst[0]= crgb[0];
430                                         dst[1]= crgb[1];
431                                         dst[2]= crgb[2];
432                                         dst[3]= FTOCHAR(brush_sample_falloff(brush, dist));
433                                 }
434                                 else if (texfall == 1) {
435                                         brush_sample_tex(brush, xy, rgba);
436                                         dst[0]= FTOCHAR(rgba[0]);
437                                         dst[1]= FTOCHAR(rgba[1]);
438                                         dst[2]= FTOCHAR(rgba[2]);
439                                         dst[3]= FTOCHAR(rgba[3]);
440                                 }
441                                 else {
442                                         dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
443
444                                         brush_sample_tex(brush, xy, rgba);
445                                         dst[0] = FTOCHAR(rgba[0]*brush->rgb[0]);
446                                         dst[1] = FTOCHAR(rgba[1]*brush->rgb[1]);
447                                         dst[2] = FTOCHAR(rgba[2]*brush->rgb[2]);
448                                         dst[3] = FTOCHAR(rgba[3]*brush_sample_falloff(brush, dist));
449                                 }
450                         }
451                 }
452         }
453
454         *outbuf= ibuf;
455 }
456
457 /* Brush Painting */
458
459 typedef struct BrushPainterCache {
460         short enabled;
461
462         int size;                       /* size override, if 0 uses brush->size */
463         short flt;                      /* need float imbuf? */
464         short texonly;          /* no alpha, color or fallof, only texture in imbuf */
465
466         int lastsize;
467         float lastalpha;
468         float lastinnerradius;
469
470         ImBuf *ibuf;
471         ImBuf *texibuf;
472         ImBuf *maskibuf;
473 } BrushPainterCache;
474
475 struct BrushPainter {
476         Brush *brush;
477
478         float lastmousepos[2];  /* mouse position of last paint call */
479
480         float accumdistance;    /* accumulated distance of brush since last paint op */
481         float lastpaintpos[2];  /* position of last paint op */
482         float startpaintpos[2]; /* position of first paint */
483
484         double accumtime;               /* accumulated time since last paint op (airbrush) */
485         double lasttime;                /* time of last update */
486
487         float lastpressure;
488
489         short firsttouch;               /* first paint op */
490
491         float startsize;
492         float startalpha;
493         float startinnerradius;
494         float startspacing;
495
496         BrushPainterCache cache;
497 };
498
499 BrushPainter *brush_painter_new(Brush *brush)
500 {
501         BrushPainter *painter= MEM_callocN(sizeof(BrushPainter), "BrushPainter");
502
503         painter->brush= brush;
504         painter->firsttouch= 1;
505         painter->cache.lastsize= -1; /* force ibuf create in refresh */
506
507         painter->startsize = brush->size;
508         painter->startalpha = brush->alpha;
509         painter->startinnerradius = brush->innerradius;
510         painter->startspacing = brush->spacing;
511
512         return painter;
513 }
514
515 void brush_painter_require_imbuf(BrushPainter *painter, short flt, short texonly, int size)
516 {
517         if ((painter->cache.flt != flt) || (painter->cache.size != size) ||
518                 ((painter->cache.texonly != texonly) && texonly)) {
519                 if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
520                 if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
521                 painter->cache.ibuf= painter->cache.maskibuf= NULL;
522                 painter->cache.lastsize= -1; /* force ibuf create in refresh */
523         }
524
525         if (painter->cache.flt != flt) {
526                 if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
527                 painter->cache.texibuf= NULL;
528                 painter->cache.lastsize= -1; /* force ibuf create in refresh */
529         }
530
531         painter->cache.size= size;
532         painter->cache.flt= flt;
533         painter->cache.texonly= texonly;
534         painter->cache.enabled= 1;
535 }
536
537 void brush_painter_free(BrushPainter *painter)
538 {
539         Brush *brush = painter->brush;
540
541         brush->size = painter->startsize;
542         brush->alpha = painter->startalpha;
543         brush->innerradius = painter->startinnerradius;
544         brush->spacing = painter->startspacing;
545
546         if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
547         if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
548         if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
549         MEM_freeN(painter);
550 }
551
552 static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, int x, int y, int w, int h, int xt, int yt, float *pos)
553 {
554         Brush *brush= painter->brush;
555         ImBuf *ibuf, *maskibuf, *texibuf;
556         float *bf, *mf, *tf, *otf=NULL, xoff, yoff, xy[2], rgba[4];
557         char *b, *m, *t, *ot= NULL;
558         int dotexold, origx= x, origy= y;
559
560         xoff = -brush->size/2.0f + 0.5f;
561         yoff = -brush->size/2.0f + 0.5f;
562         xoff += (int)pos[0] - (int)painter->startpaintpos[0];
563         yoff += (int)pos[1] - (int)painter->startpaintpos[1];
564
565         ibuf = painter->cache.ibuf;
566         texibuf = painter->cache.texibuf;
567         maskibuf = painter->cache.maskibuf;
568
569         dotexold = (oldtexibuf != NULL);
570
571         if (painter->cache.flt) {
572                 for (; y < h; y++) {
573                         bf = ibuf->rect_float + (y*ibuf->x + origx)*4;
574                         tf = texibuf->rect_float + (y*texibuf->x + origx)*4;
575                         mf = maskibuf->rect_float + (y*maskibuf->x + origx)*4;
576
577                         if (dotexold)
578                                 otf = oldtexibuf->rect_float + ((y - origy + yt)*oldtexibuf->x + xt)*4;
579
580                         for (x=origx; x < w; x++, bf+=4, mf+=4, tf+=4) {
581                                 if (dotexold) {
582                                         VECCOPY(tf, otf);
583                                         tf[3] = otf[3];
584                                         otf += 4;
585                                 }
586                                 else {
587                                         xy[0] = x + xoff;
588                                         xy[1] = y + yoff;
589
590                                         brush_sample_tex(brush, xy, tf);
591                                 }
592
593                                 bf[0] = tf[0]*mf[0];
594                                 bf[1] = tf[1]*mf[1];
595                                 bf[2] = tf[2]*mf[2];
596                                 bf[3] = tf[3]*mf[3];
597                         }
598                 }
599         }
600         else {
601                 for (; y < h; y++) {
602                         b = (char*)ibuf->rect + (y*ibuf->x + origx)*4;
603                         t = (char*)texibuf->rect + (y*texibuf->x + origx)*4;
604                         m = (char*)maskibuf->rect + (y*maskibuf->x + origx)*4;
605
606                         if (dotexold)
607                                 ot = (char*)oldtexibuf->rect + ((y - origy + yt)*oldtexibuf->x + xt)*4;
608
609                         for (x=origx; x < w; x++, b+=4, m+=4, t+=4) {
610                                 if (dotexold) {
611                                         t[0] = ot[0];
612                                         t[1] = ot[1];
613                                         t[2] = ot[2];
614                                         t[3] = ot[3];
615                                         ot += 4;
616                                 }
617                                 else {
618                                         xy[0] = x + xoff;
619                                         xy[1] = y + yoff;
620
621                                         brush_sample_tex(brush, xy, rgba);
622                                         t[0]= FTOCHAR(rgba[0]);
623                                         t[1]= FTOCHAR(rgba[1]);
624                                         t[2]= FTOCHAR(rgba[2]);
625                                         t[3]= FTOCHAR(rgba[3]);
626                                 }
627
628                                 b[0] = t[0]*m[0]/255;
629                                 b[1] = t[1]*m[1]/255;
630                                 b[2] = t[2]*m[2]/255;
631                                 b[3] = t[3]*m[3]/255;
632                         }
633                 }
634         }
635 }
636
637 void brush_painter_fixed_tex_partial_update(BrushPainter *painter, float *pos)
638 {
639         Brush *brush= painter->brush;
640         BrushPainterCache *cache= &painter->cache;
641         ImBuf *oldtexibuf, *ibuf;
642         int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
643
644         imbflag= (cache->flt)? IB_rectfloat: IB_rect;
645         if (!cache->ibuf)
646                 cache->ibuf= IMB_allocImBuf(brush->size, brush->size, 32, imbflag, 0);
647         ibuf= cache->ibuf;
648
649         oldtexibuf= cache->texibuf;
650         cache->texibuf= IMB_allocImBuf(brush->size, brush->size, 32, imbflag, 0);
651
652         if (oldtexibuf) {
653                 srcx= srcy= 0;
654                 destx= (int)painter->lastpaintpos[0] - (int)pos[0];
655                 desty= (int)painter->lastpaintpos[1] - (int)pos[1];
656                 w= oldtexibuf->x;
657                 h= oldtexibuf->y;
658
659                 IMB_rectclip(cache->texibuf, oldtexibuf, &destx, &desty, &srcx, &srcy, &w, &h);
660         }
661         else {
662                 srcx= srcy= 0;
663                 destx= desty= 0;
664                 w= h= 0;
665         }
666         
667         x1= destx;
668         y1= desty;
669         x2= destx+w;
670         y2= desty+h;
671
672         /* blend existing texture in new position */
673         if ((x1 < x2) && (y1 < y2))
674                 brush_painter_do_partial(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy, pos);
675
676         if (oldtexibuf)
677                 IMB_freeImBuf(oldtexibuf);
678
679         /* sample texture in new areas */
680         if ((0 < x1) && (0 < ibuf->y))
681                 brush_painter_do_partial(painter, NULL, 0, 0, x1, ibuf->y, 0, 0, pos);
682         if ((x2 < ibuf->x) && (0 < ibuf->y))
683                 brush_painter_do_partial(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0, pos);
684         if ((x1 < x2) && (0 < y1))
685                 brush_painter_do_partial(painter, NULL, x1, 0, x2, y1, 0, 0, pos);
686         if ((x1 < x2) && (y2 < ibuf->y))
687                 brush_painter_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos);
688 }
689
690 static void brush_painter_refresh_cache(BrushPainter *painter, float *pos)
691 {
692         Brush *brush= painter->brush;
693         BrushPainterCache *cache= &painter->cache;
694         MTex *mtex= brush->mtex[brush->texact];
695         int size;
696         short flt;
697
698         if ((brush->size != cache->lastsize) || (brush->alpha != cache->lastalpha)
699             || (brush->innerradius != cache->lastinnerradius)) {
700                 if (cache->ibuf) {
701                         IMB_freeImBuf(cache->ibuf);
702                         cache->ibuf= NULL;
703                 }
704                 if (cache->maskibuf) {
705                         IMB_freeImBuf(cache->maskibuf);
706                         cache->maskibuf= NULL;
707                 }
708
709                 flt= cache->flt;
710                 size= (cache->size)? cache->size: brush->size;
711
712                 if (!(mtex && mtex->tex) || (mtex->tex->type==0)) {
713                         brush_imbuf_new(brush, flt, 0, size, &cache->ibuf);
714                 }
715                 else if (brush->flag & BRUSH_FIXED_TEX) {
716                         brush_imbuf_new(brush, flt, 0, size, &cache->maskibuf);
717                         brush_painter_fixed_tex_partial_update(painter, pos);
718                 }
719                 else
720                         brush_imbuf_new(brush, flt, 2, size, &cache->ibuf);
721
722                 cache->lastsize= brush->size;
723                 cache->lastalpha= brush->alpha;
724                 cache->lastinnerradius= brush->innerradius;
725         }
726         else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) {
727                 int dx = (int)painter->lastpaintpos[0] - (int)pos[0];
728                 int dy = (int)painter->lastpaintpos[1] - (int)pos[1];
729
730                 if ((dx != 0) || (dy != 0))
731                         brush_painter_fixed_tex_partial_update(painter, pos);
732         }
733 }
734
735 void brush_painter_break_stroke(BrushPainter *painter)
736 {
737         painter->firsttouch= 1;
738 }
739
740 static void brush_apply_pressure(BrushPainter *painter, Brush *brush, float pressure)
741 {
742         if (brush->flag & BRUSH_ALPHA_PRESSURE) 
743                 brush->alpha = MAX2(0.0, painter->startalpha*pressure);
744         if (brush->flag & BRUSH_SIZE_PRESSURE)
745                 brush->size = MAX2(1.0, painter->startsize*pressure);
746         if (brush->flag & BRUSH_RAD_PRESSURE)
747                 brush->innerradius = MAX2(0.0, painter->startinnerradius*pressure);
748         if (brush->flag & BRUSH_SPACING_PRESSURE)
749                 brush->spacing = MAX2(1.0, painter->startspacing*(1.5f-pressure));
750 }
751
752 int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, float pressure, void *user)
753 {
754         Brush *brush= painter->brush;
755         int totpaintops= 0;
756
757         if (pressure == 0.0f)
758                 pressure = 1.0f;        /* zero pressure == not using tablet */
759
760         if (painter->firsttouch) {
761                 /* paint exactly once on first touch */
762                 painter->startpaintpos[0]= pos[0];
763                 painter->startpaintpos[1]= pos[1];
764
765                 brush_apply_pressure(painter, brush, pressure);
766                 if (painter->cache.enabled)
767                         brush_painter_refresh_cache(painter, pos);
768                 totpaintops += func(user, painter->cache.ibuf, pos, pos);
769                 
770                 painter->lasttime= time;
771                 painter->firsttouch= 0;
772                 painter->lastpaintpos[0]= pos[0];
773                 painter->lastpaintpos[1]= pos[1];
774         }
775 #if 0
776         else if (painter->brush->flag & BRUSH_AIRBRUSH) {
777                 float spacing, step, paintpos[2], dmousepos[2], len;
778                 double starttime, curtime= time;
779
780                 /* compute brush spacing adapted to brush size */
781                 spacing= brush->rate; //brush->size*brush->spacing*0.01f;
782
783                 /* setup starting time, direction vector and accumulated time */
784                 starttime= painter->accumtime;
785                 Vec2Subf(dmousepos, pos, painter->lastmousepos);
786                 len= Normalize2(dmousepos);
787                 painter->accumtime += curtime - painter->lasttime;
788
789                 /* do paint op over unpainted time distance */
790                 while (painter->accumtime >= spacing) {
791                         step= (spacing - starttime)*len;
792                         paintpos[0]= painter->lastmousepos[0] + dmousepos[0]*step;
793                         paintpos[1]= painter->lastmousepos[1] + dmousepos[1]*step;
794
795                         if (painter->cache.enabled)
796                                 brush_painter_refresh_cache(painter);
797                         totpaintops += func(user, painter->cache.ibuf,
798                                 painter->lastpaintpos, paintpos);
799
800                         painter->lastpaintpos[0]= paintpos[0];
801                         painter->lastpaintpos[1]= paintpos[1];
802                         painter->accumtime -= spacing;
803                         starttime -= spacing;
804                 }
805                 
806                 painter->lasttime= curtime;
807         }
808 #endif
809         else {
810                 float startdistance, spacing, step, paintpos[2], dmousepos[2];
811                 float t, len, press;
812
813                 /* compute brush spacing adapted to brush size, spacing may depend
814                    on pressure, so update it */
815                 brush_apply_pressure(painter, brush, painter->lastpressure);
816                 spacing= MAX2(1.0f, brush->size)*brush->spacing*0.01f;
817
818                 /* setup starting distance, direction vector and accumulated distance */
819                 startdistance= painter->accumdistance;
820                 Vec2Subf(dmousepos, pos, painter->lastmousepos);
821                 len= Normalize2(dmousepos);
822                 painter->accumdistance += len;
823
824                 /* do paint op over unpainted distance */
825                 while ((len > 0.0f) && (painter->accumdistance >= spacing)) {
826                         step= spacing - startdistance;
827                         paintpos[0]= painter->lastmousepos[0] + dmousepos[0]*step;
828                         paintpos[1]= painter->lastmousepos[1] + dmousepos[1]*step;
829
830                         t = step/len;
831                         press= (1.0f-t)*painter->lastpressure + t*pressure;
832                         brush_apply_pressure(painter, brush, press);
833                         spacing= MAX2(1.0f, brush->size)*brush->spacing*0.01f;
834
835                         if (painter->cache.enabled)
836                                 brush_painter_refresh_cache(painter, paintpos);
837
838                         totpaintops +=
839                                 func(user, painter->cache.ibuf, painter->lastpaintpos, paintpos);
840
841                         painter->lastpaintpos[0]= paintpos[0];
842                         painter->lastpaintpos[1]= paintpos[1];
843                         painter->accumdistance -= spacing;
844                         startdistance -= spacing;
845                 }
846
847                 /* do airbrush paint ops, based on the number of paint ops left over
848                    from regular painting. this is a temporary solution until we have
849                    accurate time stamps for mouse move events */
850                 if (brush->flag & BRUSH_AIRBRUSH) {
851                         double curtime= time;
852                         double painttime= brush->rate*totpaintops;
853
854                         painter->accumtime += curtime - painter->lasttime;
855                         if (painter->accumtime <= painttime)
856                                 painter->accumtime= 0.0;
857                         else
858                                 painter->accumtime -= painttime;
859
860                         while (painter->accumtime >= brush->rate) {
861                                 brush_apply_pressure(painter, brush, pressure);
862                                 if (painter->cache.enabled)
863                                         brush_painter_refresh_cache(painter, paintpos);
864                                 totpaintops +=
865                                         func(user, painter->cache.ibuf, painter->lastmousepos, pos);
866                                 painter->accumtime -= brush->rate;
867                         }
868
869                         painter->lasttime= curtime;
870                 }
871         }
872
873         painter->lastmousepos[0]= pos[0];
874         painter->lastmousepos[1]= pos[1];
875         painter->lastpressure= pressure;
876
877         brush->alpha = painter->startalpha;
878         brush->size = painter->startsize;
879         brush->innerradius = painter->startinnerradius;
880         brush->spacing = painter->startspacing;
881
882         return totpaintops;
883 }
884
885