Blender V2.61 - r43446

brush.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <math.h>
00034 #include <string.h>
00035 
00036 #include "MEM_guardedalloc.h"
00037 
00038 #include "DNA_brush_types.h"
00039 #include "DNA_color_types.h"
00040 #include "DNA_scene_types.h"
00041 #include "DNA_object_types.h"
00042 #include "DNA_windowmanager_types.h"
00043 
00044 #include "WM_types.h"
00045 
00046 #include "RNA_access.h"
00047 
00048 #include "BLI_bpath.h"
00049 #include "BLI_math.h"
00050 #include "BLI_blenlib.h"
00051 #include "BLI_rand.h"
00052 #include "BLI_utildefines.h"
00053 
00054 #include "BKE_brush.h"
00055 #include "BKE_colortools.h"
00056 #include "BKE_global.h"
00057 #include "BKE_image.h"
00058 #include "BKE_library.h"
00059 #include "BKE_main.h"
00060 #include "BKE_paint.h"
00061 #include "BKE_texture.h"
00062 #include "BKE_icons.h"
00063 
00064 #include "IMB_imbuf.h"
00065 #include "IMB_imbuf_types.h"
00066 
00067 #include "RE_render_ext.h" /* externtex */
00068 #include "RE_shader_ext.h"
00069 
00070 static void brush_set_defaults(Brush *brush)
00071 {
00072     brush->blend = 0;
00073     brush->flag = 0;
00074 
00075     brush->ob_mode = OB_MODE_ALL_PAINT;
00076 
00077     /* BRUSH SCULPT TOOL SETTINGS */
00078     brush->size= 35; /* radius of the brush in pixels */
00079     brush->alpha= 0.5f; /* brush strength/intensity probably variable should be renamed? */
00080     brush->autosmooth_factor= 0.0f;
00081     brush->crease_pinch_factor= 0.5f;
00082     brush->sculpt_plane = SCULPT_DISP_DIR_AREA;
00083     brush->plane_offset= 0.0f; /* how far above or below the plane that is found by averaging the faces */
00084     brush->plane_trim= 0.5f;
00085     brush->clone.alpha= 0.5f;
00086     brush->normal_weight= 0.0f;
00087     brush->flag |= BRUSH_ALPHA_PRESSURE;
00088 
00089     /* BRUSH PAINT TOOL SETTINGS */
00090     brush->rgb[0]= 1.0f; /* default rgb color of the brush when painting - white */
00091     brush->rgb[1]= 1.0f;
00092     brush->rgb[2]= 1.0f;
00093 
00094     /* BRUSH STROKE SETTINGS */
00095     brush->flag |= (BRUSH_SPACE|BRUSH_SPACE_ATTEN);
00096     brush->spacing= 10; /* how far each brush dot should be spaced as a percentage of brush diameter */
00097 
00098     brush->smooth_stroke_radius= 75;
00099     brush->smooth_stroke_factor= 0.9f;
00100 
00101     brush->rate= 0.1f; /* time delay between dots of paint or sculpting when doing airbrush mode */
00102 
00103     brush->jitter= 0.0f;
00104 
00105     /* BRUSH TEXTURE SETTINGS */
00106     default_mtex(&brush->mtex);
00107 
00108     brush->texture_sample_bias= 0; /* value to added to texture samples */
00109     brush->texture_overlay_alpha= 33;
00110 
00111     /* brush appearance  */
00112 
00113     brush->add_col[0]= 1.00; /* add mode color is light red */
00114     brush->add_col[1]= 0.39;
00115     brush->add_col[2]= 0.39;
00116 
00117     brush->sub_col[0]= 0.39; /* subtract mode color is light blue */
00118     brush->sub_col[1]= 0.39;
00119     brush->sub_col[2]= 1.00;
00120 }
00121 
00122 /* Datablock add/copy/free/make_local */
00123 
00124 Brush *add_brush(const char *name)
00125 {
00126     Brush *brush;
00127 
00128     brush= alloc_libblock(&G.main->brush, ID_BR, name);
00129 
00130     /* enable fake user by default */
00131     brush->id.flag |= LIB_FAKEUSER;
00132 
00133     brush_set_defaults(brush);
00134 
00135     brush->sculpt_tool = SCULPT_TOOL_DRAW; /* sculpting defaults to the draw tool for new brushes */
00136 
00137      /* the default alpha falloff curve */
00138     brush_curve_preset(brush, CURVE_PRESET_SMOOTH);
00139 
00140     return brush;
00141 }
00142 
00143 Brush *copy_brush(Brush *brush)
00144 {
00145     Brush *brushn;
00146     
00147     brushn= copy_libblock(&brush->id);
00148 
00149     if (brush->mtex.tex)
00150         id_us_plus((ID*)brush->mtex.tex);
00151 
00152     if (brush->icon_imbuf)
00153         brushn->icon_imbuf= IMB_dupImBuf(brush->icon_imbuf);
00154 
00155     brushn->preview = NULL;
00156 
00157     brushn->curve= curvemapping_copy(brush->curve);
00158 
00159     /* enable fake user by default */
00160     if (!(brushn->id.flag & LIB_FAKEUSER)) {
00161         brushn->id.flag |= LIB_FAKEUSER;
00162         brushn->id.us++;
00163     }
00164     
00165     return brushn;
00166 }
00167 
00168 /* not brush itself */
00169 void free_brush(Brush *brush)
00170 {
00171     if (brush->mtex.tex)
00172         brush->mtex.tex->id.us--;
00173 
00174     if (brush->icon_imbuf)
00175         IMB_freeImBuf(brush->icon_imbuf);
00176 
00177     BKE_previewimg_free(&(brush->preview));
00178 
00179     curvemapping_free(brush->curve);
00180 }
00181 
00182 static void extern_local_brush(Brush *brush)
00183 {
00184     id_lib_extern((ID *)brush->mtex.tex);
00185     id_lib_extern((ID *)brush->clone.image);
00186 }
00187 
00188 void make_local_brush(Brush *brush)
00189 {
00190 
00191     /* - only lib users: do nothing
00192      * - only local users: set flag
00193      * - mixed: make copy
00194      */
00195 
00196     Main *bmain= G.main;
00197     Scene *scene;
00198     int is_local= FALSE, is_lib= FALSE;
00199 
00200     if(brush->id.lib==NULL) return;
00201 
00202     if(brush->clone.image) {
00203         /* special case: ima always local immediately. Clone image should only
00204            have one user anyway. */
00205         id_clear_lib_data(bmain, &brush->clone.image->id);
00206         extern_local_brush(brush);
00207     }
00208 
00209     for(scene= bmain->scene.first; scene && ELEM(0, is_lib, is_local); scene=scene->id.next) {
00210         if(paint_brush(&scene->toolsettings->imapaint.paint)==brush) {
00211             if(scene->id.lib) is_lib= TRUE;
00212             else is_local= TRUE;
00213         }
00214     }
00215 
00216     if(is_local && is_lib == FALSE) {
00217         id_clear_lib_data(bmain, &brush->id);
00218         extern_local_brush(brush);
00219 
00220         /* enable fake user by default */
00221         if (!(brush->id.flag & LIB_FAKEUSER)) {
00222             brush->id.flag |= LIB_FAKEUSER;
00223             brush->id.us++;
00224         }
00225     }
00226     else if(is_local && is_lib) {
00227         Brush *brush_new= copy_brush(brush);
00228         brush_new->id.us= 1; /* only keep fake user */
00229         brush_new->id.flag |= LIB_FAKEUSER;
00230 
00231         /* Remap paths of new ID using old library as base. */
00232         BKE_id_lib_local_paths(bmain, brush->id.lib, &brush_new->id);
00233         
00234         for(scene= bmain->scene.first; scene; scene=scene->id.next) {
00235             if(paint_brush(&scene->toolsettings->imapaint.paint)==brush) {
00236                 if(scene->id.lib==NULL) {
00237                     paint_brush_set(&scene->toolsettings->imapaint.paint, brush_new);
00238                 }
00239             }
00240         }
00241     }
00242 }
00243 
00244 void brush_debug_print_state(Brush *br)
00245 {
00246     /* create a fake brush and set it to the defaults */
00247     Brush def= {{NULL}};
00248     brush_set_defaults(&def);
00249     
00250 #define BR_TEST(field, t)                   \
00251     if(br->field != def.field)              \
00252         printf("br->" #field " = %" #t ";\n", br->field)
00253 
00254 #define BR_TEST_FLAG(_f)                \
00255     if((br->flag & _f) && !(def.flag & _f))     \
00256         printf("br->flag |= " #_f ";\n");   \
00257     else if(!(br->flag & _f) && (def.flag & _f))    \
00258         printf("br->flag &= ~" #_f ";\n")
00259     
00260 
00261     /* print out any non-default brush state */
00262     BR_TEST(normal_weight, f);
00263 
00264     BR_TEST(blend, d);
00265     BR_TEST(size, d);
00266 
00267     /* br->flag */
00268     BR_TEST_FLAG(BRUSH_AIRBRUSH);
00269     BR_TEST_FLAG(BRUSH_TORUS);
00270     BR_TEST_FLAG(BRUSH_ALPHA_PRESSURE);
00271     BR_TEST_FLAG(BRUSH_SIZE_PRESSURE);
00272     BR_TEST_FLAG(BRUSH_JITTER_PRESSURE);
00273     BR_TEST_FLAG(BRUSH_SPACING_PRESSURE);
00274     BR_TEST_FLAG(BRUSH_FIXED_TEX);
00275     BR_TEST_FLAG(BRUSH_RAKE);
00276     BR_TEST_FLAG(BRUSH_ANCHORED);
00277     BR_TEST_FLAG(BRUSH_DIR_IN);
00278     BR_TEST_FLAG(BRUSH_SPACE);
00279     BR_TEST_FLAG(BRUSH_SMOOTH_STROKE);
00280     BR_TEST_FLAG(BRUSH_PERSISTENT);
00281     BR_TEST_FLAG(BRUSH_ACCUMULATE);
00282     BR_TEST_FLAG(BRUSH_LOCK_ALPHA);
00283     BR_TEST_FLAG(BRUSH_ORIGINAL_NORMAL);
00284     BR_TEST_FLAG(BRUSH_OFFSET_PRESSURE);
00285     BR_TEST_FLAG(BRUSH_SPACE_ATTEN);
00286     BR_TEST_FLAG(BRUSH_ADAPTIVE_SPACE);
00287     BR_TEST_FLAG(BRUSH_LOCK_SIZE);
00288     BR_TEST_FLAG(BRUSH_TEXTURE_OVERLAY);
00289     BR_TEST_FLAG(BRUSH_EDGE_TO_EDGE);
00290     BR_TEST_FLAG(BRUSH_RESTORE_MESH);
00291     BR_TEST_FLAG(BRUSH_INVERSE_SMOOTH_PRESSURE);
00292     BR_TEST_FLAG(BRUSH_RANDOM_ROTATION);
00293     BR_TEST_FLAG(BRUSH_PLANE_TRIM);
00294     BR_TEST_FLAG(BRUSH_FRONTFACE);
00295     BR_TEST_FLAG(BRUSH_CUSTOM_ICON);
00296 
00297     BR_TEST(jitter, f);
00298     BR_TEST(spacing, d);
00299     BR_TEST(smooth_stroke_radius, d);
00300     BR_TEST(smooth_stroke_factor, f);
00301     BR_TEST(rate, f);
00302 
00303     BR_TEST(alpha, f);
00304 
00305     BR_TEST(sculpt_plane, d);
00306 
00307     BR_TEST(plane_offset, f);
00308 
00309     BR_TEST(autosmooth_factor, f);
00310 
00311     BR_TEST(crease_pinch_factor, f);
00312 
00313     BR_TEST(plane_trim, f);
00314 
00315     BR_TEST(texture_sample_bias, f);
00316     BR_TEST(texture_overlay_alpha, d);
00317 
00318     BR_TEST(add_col[0], f);
00319     BR_TEST(add_col[1], f);
00320     BR_TEST(add_col[2], f);
00321     BR_TEST(sub_col[0], f);
00322     BR_TEST(sub_col[1], f);
00323     BR_TEST(sub_col[2], f);
00324 
00325     printf("\n");
00326     
00327 #undef BR_TEST
00328 #undef BR_TEST_FLAG
00329 }
00330 
00331 void brush_reset_sculpt(Brush *br)
00332 {
00333     /* enable this to see any non-default
00334        settings used by a brush:
00335 
00336     brush_debug_print_state(br);
00337     */
00338 
00339     brush_set_defaults(br);
00340     brush_curve_preset(br, CURVE_PRESET_SMOOTH);
00341 
00342     switch(br->sculpt_tool) {
00343     case SCULPT_TOOL_CLAY:
00344         br->flag |= BRUSH_FRONTFACE;
00345         break;
00346     case SCULPT_TOOL_CREASE:
00347         br->flag |= BRUSH_DIR_IN;
00348         br->alpha = 0.25;
00349         break;
00350     case SCULPT_TOOL_FILL:
00351         br->add_col[1] = 1;
00352         br->sub_col[0] = 0.25;
00353         br->sub_col[1] = 1;
00354         break;
00355     case SCULPT_TOOL_FLATTEN:
00356         br->add_col[1] = 1;
00357         br->sub_col[0] = 0.25;
00358         br->sub_col[1] = 1;
00359         break;
00360     case SCULPT_TOOL_INFLATE:
00361         br->add_col[0] = 0.750000;
00362         br->add_col[1] = 0.750000;
00363         br->add_col[2] = 0.750000;
00364         br->sub_col[0] = 0.250000;
00365         br->sub_col[1] = 0.250000;
00366         br->sub_col[2] = 0.250000;
00367         break;
00368     case SCULPT_TOOL_NUDGE:
00369         br->add_col[0] = 0.250000;
00370         br->add_col[1] = 1.000000;
00371         br->add_col[2] = 0.250000;
00372         break;
00373     case SCULPT_TOOL_PINCH:
00374         br->add_col[0] = 0.750000;
00375         br->add_col[1] = 0.750000;
00376         br->add_col[2] = 0.750000;
00377         br->sub_col[0] = 0.250000;
00378         br->sub_col[1] = 0.250000;
00379         br->sub_col[2] = 0.250000;
00380         break;
00381     case SCULPT_TOOL_SCRAPE:
00382         br->add_col[1] = 1.000000;
00383         br->sub_col[0] = 0.250000;
00384         br->sub_col[1] = 1.000000;
00385         break;
00386     case SCULPT_TOOL_ROTATE:
00387         br->alpha = 1.0;
00388         break;
00389     case SCULPT_TOOL_SMOOTH:
00390         br->flag &= ~BRUSH_SPACE_ATTEN;
00391         br->spacing = 5;
00392         br->add_col[0] = 0.750000;
00393         br->add_col[1] = 0.750000;
00394         br->add_col[2] = 0.750000;
00395         break;
00396     case SCULPT_TOOL_GRAB:
00397     case SCULPT_TOOL_SNAKE_HOOK:
00398     case SCULPT_TOOL_THUMB:
00399         br->size = 75;
00400         br->flag &= ~BRUSH_ALPHA_PRESSURE;
00401         br->flag &= ~BRUSH_SPACE;
00402         br->flag &= ~BRUSH_SPACE_ATTEN;
00403         br->add_col[0] = 0.250000;
00404         br->add_col[1] = 1.000000;
00405         br->add_col[2] = 0.250000;
00406         break;
00407     default:
00408         break;
00409     }
00410 }
00411 
00412 /* Library Operations */
00413 void brush_curve_preset(Brush *b, /*CurveMappingPreset*/int preset)
00414 {
00415     CurveMap *cm = NULL;
00416 
00417     if(!b->curve)
00418         b->curve = curvemapping_add(1, 0, 0, 1, 1);
00419 
00420     cm = b->curve->cm;
00421     cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
00422 
00423     b->curve->preset = preset;
00424     curvemap_reset(cm, &b->curve->clipr, b->curve->preset, CURVEMAP_SLOPE_NEGATIVE);
00425     curvemapping_changed(b->curve, 0);
00426 }
00427 
00428 int brush_texture_set_nr(Brush *brush, int nr)
00429 {
00430     ID *idtest, *id=NULL;
00431 
00432     id= (ID *)brush->mtex.tex;
00433 
00434     idtest= (ID*)BLI_findlink(&G.main->tex, nr-1);
00435     if(idtest==NULL) { /* new tex */
00436         if(id) idtest= (ID *)copy_texture((Tex *)id);
00437         else idtest= (ID *)add_texture("Tex");
00438         idtest->us--;
00439     }
00440     if(idtest!=id) {
00441         brush_texture_delete(brush);
00442 
00443         brush->mtex.tex= (Tex*)idtest;
00444         id_us_plus(idtest);
00445 
00446         return 1;
00447     }
00448 
00449     return 0;
00450 }
00451 
00452 int brush_texture_delete(Brush *brush)
00453 {
00454     if(brush->mtex.tex)
00455         brush->mtex.tex->id.us--;
00456 
00457     return 1;
00458 }
00459 
00460 int brush_clone_image_set_nr(Brush *brush, int nr)
00461 {
00462     if(brush && nr > 0) {
00463         Image *ima= (Image*)BLI_findlink(&G.main->image, nr-1);
00464 
00465         if(ima) {
00466             brush_clone_image_delete(brush);
00467             brush->clone.image= ima;
00468             id_us_plus(&ima->id);
00469             brush->clone.offset[0]= brush->clone.offset[1]= 0.0f;
00470 
00471             return 1;
00472         }
00473     }
00474 
00475     return 0;
00476 }
00477 
00478 int brush_clone_image_delete(Brush *brush)
00479 {
00480     if (brush && brush->clone.image) {
00481         brush->clone.image->id.us--;
00482         brush->clone.image= NULL;
00483         return 1;
00484     }
00485 
00486     return 0;
00487 }
00488 
00489 /* Brush Sampling */
00490 void brush_sample_tex(const Scene *scene, Brush *brush, const float xy[2], float rgba[4], const int thread)
00491 {
00492     MTex *mtex= &brush->mtex;
00493 
00494     if (mtex && mtex->tex) {
00495         float co[3], tin, tr, tg, tb, ta;
00496         int hasrgb;
00497         const int radius= brush_size(scene, brush);
00498 
00499         co[0]= xy[0]/radius;
00500         co[1]= xy[1]/radius;
00501         co[2]= 0.0f;
00502 
00503         hasrgb= externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread);
00504 
00505         if (hasrgb) {
00506             rgba[0]= tr;
00507             rgba[1]= tg;
00508             rgba[2]= tb;
00509             rgba[3]= ta;
00510         }
00511         else {
00512             rgba[0]= tin;
00513             rgba[1]= tin;
00514             rgba[2]= tin;
00515             rgba[3]= 1.0f;
00516         }
00517     }
00518     else {
00519         rgba[0]= rgba[1]= rgba[2]= rgba[3]= 1.0f;
00520     }
00521 }
00522 
00523 /* TODO, use define for 'texfall' arg */
00524 void brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texfall, int bufsize, ImBuf **outbuf, int use_color_correction)
00525 {
00526     ImBuf *ibuf;
00527     float xy[2], rgba[4], *dstf;
00528     int x, y, rowbytes, xoff, yoff, imbflag;
00529     const int radius= brush_size(scene, brush);
00530     char *dst, crgb[3];
00531     const float alpha= brush_alpha(scene, brush);
00532     float brush_rgb[3];
00533     
00534     imbflag= (flt)? IB_rectfloat: IB_rect;
00535     xoff = -bufsize/2.0f + 0.5f;
00536     yoff = -bufsize/2.0f + 0.5f;
00537     rowbytes= bufsize*4;
00538 
00539     if (*outbuf)
00540         ibuf= *outbuf;
00541     else
00542         ibuf= IMB_allocImBuf(bufsize, bufsize, 32, imbflag);
00543 
00544     if (flt) {
00545         copy_v3_v3(brush_rgb, brush->rgb);
00546         if(use_color_correction){
00547             srgb_to_linearrgb_v3_v3(brush_rgb, brush_rgb);
00548         }
00549 
00550         for (y=0; y < ibuf->y; y++) {
00551             dstf = ibuf->rect_float + y*rowbytes;
00552 
00553             for (x=0; x < ibuf->x; x++, dstf+=4) {
00554                 xy[0] = x + xoff;
00555                 xy[1] = y + yoff;
00556 
00557                 if (texfall == 0) {
00558                     copy_v3_v3(dstf, brush_rgb);
00559                     dstf[3]= alpha*brush_curve_strength_clamp(brush, len_v2(xy), radius);
00560                 }
00561                 else if (texfall == 1) {
00562                     brush_sample_tex(scene, brush, xy, dstf, 0);
00563                 }
00564                 else {
00565                     brush_sample_tex(scene, brush, xy, rgba, 0);
00566                     mul_v3_v3v3(dstf, rgba, brush_rgb);
00567                     dstf[3] = rgba[3]*alpha*brush_curve_strength_clamp(brush, len_v2(xy), radius);
00568                 }
00569             }
00570         }
00571     }
00572     else {
00573         float alpha_f; /* final float alpha to convert to char */
00574         F3TOCHAR3(brush->rgb, crgb);
00575 
00576         for (y=0; y < ibuf->y; y++) {
00577             dst = (char*)ibuf->rect + y*rowbytes;
00578 
00579             for (x=0; x < ibuf->x; x++, dst+=4) {
00580                 xy[0] = x + xoff;
00581                 xy[1] = y + yoff;
00582 
00583                 if (texfall == 0) {
00584                     alpha_f = alpha * brush_curve_strength(brush, len_v2(xy), radius);
00585 
00586                     dst[0] = crgb[0];
00587                     dst[1] = crgb[1];
00588                     dst[2] = crgb[2];
00589                     dst[3] = FTOCHAR(alpha_f);
00590                 }
00591                 else if (texfall == 1) {
00592                     brush_sample_tex(scene, brush, xy, rgba, 0);
00593                     dst[0] = FTOCHAR(rgba[0]);
00594                     dst[1] = FTOCHAR(rgba[1]);
00595                     dst[2] = FTOCHAR(rgba[2]);
00596                     dst[3] = FTOCHAR(rgba[3]);
00597                 }
00598                 else if (texfall == 2) {
00599                     brush_sample_tex(scene, brush, xy, rgba, 0);
00600                     mul_v3_v3(rgba, brush->rgb);
00601                     alpha_f = rgba[3] * alpha * brush_curve_strength_clamp(brush, len_v2(xy), radius);
00602 
00603                     dst[0] = FTOCHAR(rgba[0]);
00604                     dst[1] = FTOCHAR(rgba[1]);
00605                     dst[2] = FTOCHAR(rgba[2]);
00606                     dst[3] = FTOCHAR(alpha_f);
00607                 }
00608                 else {
00609                     brush_sample_tex(scene, brush, xy, rgba, 0);
00610                     alpha_f = rgba[3] * alpha * brush_curve_strength_clamp(brush, len_v2(xy), radius);
00611 
00612                     dst[0] = crgb[0];
00613                     dst[1] = crgb[1];
00614                     dst[2] = crgb[2];
00615                     dst[3] = FTOCHAR(alpha_f);
00616                 }
00617             }
00618         }
00619     }
00620 
00621     *outbuf= ibuf;
00622 }
00623 
00624 /* Unified Size and Strength */
00625 
00626 // XXX: be careful about setting size and unprojected radius
00627 // because they depend on one another
00628 // these functions do not set the other corresponding value
00629 // this can lead to odd behavior if size and unprojected
00630 // radius become inconsistent.
00631 // the biggest problem is that it isn't possible to change
00632 // unprojected radius because a view context is not
00633 // available.  my ussual solution to this is to use the
00634 // ratio of change of the size to change the unprojected
00635 // radius.  Not completely convinced that is correct.
00636 // In anycase, a better solution is needed to prevent
00637 // inconsistency.
00638 
00639 void brush_set_size(Scene *scene, Brush *brush, int size)
00640 {
00641     UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
00642 
00643     if (ups->flag & UNIFIED_PAINT_SIZE)
00644         ups->size= size;
00645     else
00646         brush->size= size;
00647 }
00648 
00649 int brush_size(const Scene *scene, Brush *brush)
00650 {
00651     UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
00652 
00653     return (ups->flag & UNIFIED_PAINT_SIZE) ? ups->size : brush->size;
00654 }
00655 
00656 int brush_use_locked_size(const Scene *scene, Brush *brush)
00657 {
00658     const short us_flag = scene->toolsettings->unified_paint_settings.flag;
00659 
00660     return (us_flag & UNIFIED_PAINT_SIZE) ?
00661             (us_flag & UNIFIED_PAINT_BRUSH_LOCK_SIZE) :
00662             (brush->flag & BRUSH_LOCK_SIZE);
00663 }
00664 
00665 int brush_use_size_pressure(const Scene *scene, Brush *brush)
00666 {
00667     const short us_flag = scene->toolsettings->unified_paint_settings.flag;
00668 
00669     return (us_flag & UNIFIED_PAINT_SIZE) ?
00670             (us_flag & UNIFIED_PAINT_BRUSH_SIZE_PRESSURE) :
00671             (brush->flag & BRUSH_SIZE_PRESSURE);
00672 }
00673 
00674 int brush_use_alpha_pressure(const Scene *scene, Brush *brush)
00675 {
00676     const short us_flag = scene->toolsettings->unified_paint_settings.flag;
00677 
00678     return (us_flag & UNIFIED_PAINT_ALPHA) ?
00679             (us_flag & UNIFIED_PAINT_BRUSH_ALPHA_PRESSURE) :
00680             (brush->flag & BRUSH_ALPHA_PRESSURE);
00681 }
00682 
00683 void brush_set_unprojected_radius(Scene *scene, Brush *brush, float unprojected_radius)
00684 {
00685     UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
00686 
00687     if (ups->flag & UNIFIED_PAINT_SIZE)
00688         ups->unprojected_radius= unprojected_radius;
00689     else
00690         brush->unprojected_radius= unprojected_radius;
00691 }
00692 
00693 float brush_unprojected_radius(const Scene *scene, Brush *brush)
00694 {
00695     UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
00696 
00697     return (ups->flag & UNIFIED_PAINT_SIZE) ?
00698             ups->unprojected_radius :
00699             brush->unprojected_radius;
00700 }
00701 
00702 static void brush_set_alpha(Scene *scene, Brush *brush, float alpha)
00703 {
00704     UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
00705 
00706     if (ups->flag & UNIFIED_PAINT_ALPHA)
00707         ups->alpha= alpha;
00708     else
00709         brush->alpha= alpha;
00710 }
00711 
00712 float brush_alpha(const Scene *scene, Brush *brush)
00713 {
00714     UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
00715 
00716     return (ups->flag & UNIFIED_PAINT_ALPHA) ? ups->alpha : brush->alpha;
00717 }
00718 
00719 /* scale unprojected radius to reflect a change in the brush's 2D size */
00720 void brush_scale_unprojected_radius(float *unprojected_radius,
00721                                     int new_brush_size,
00722                                     int old_brush_size)
00723 {
00724     float scale = new_brush_size;
00725     /* avoid division by zero */
00726     if(old_brush_size != 0)
00727         scale /= (float)old_brush_size;
00728     (*unprojected_radius) *= scale;
00729 }
00730 
00731 /* scale brush size to reflect a change in the brush's unprojected radius */
00732 void brush_scale_size(int *brush_size,
00733                       float new_unprojected_radius,
00734                       float old_unprojected_radius)
00735 {
00736     float scale = new_unprojected_radius;
00737     /* avoid division by zero */
00738     if(old_unprojected_radius != 0)
00739         scale /= new_unprojected_radius;
00740     (*brush_size)= (int)((float)(*brush_size) * scale);
00741 }
00742 
00743 /* Brush Painting */
00744 
00745 typedef struct BrushPainterCache {
00746     short enabled;
00747 
00748     int size;           /* size override, if 0 uses 2*brush_size(brush) */
00749     short flt;          /* need float imbuf? */
00750     short texonly;      /* no alpha, color or fallof, only texture in imbuf */
00751 
00752     int lastsize;
00753     float lastalpha;
00754     float lastjitter;
00755 
00756     ImBuf *ibuf;
00757     ImBuf *texibuf;
00758     ImBuf *maskibuf;
00759 } BrushPainterCache;
00760 
00761 struct BrushPainter {
00762     Scene *scene;
00763     Brush *brush;
00764 
00765     float lastmousepos[2];  /* mouse position of last paint call */
00766 
00767     float accumdistance;    /* accumulated distance of brush since last paint op */
00768     float lastpaintpos[2];  /* position of last paint op */
00769     float startpaintpos[2]; /* position of first paint */
00770 
00771     double accumtime;       /* accumulated time since last paint op (airbrush) */
00772     double lasttime;        /* time of last update */
00773 
00774     float lastpressure;
00775 
00776     short firsttouch;       /* first paint op */
00777 
00778     float startsize;
00779     float startalpha;
00780     float startjitter;
00781     float startspacing;
00782 
00783     BrushPainterCache cache;
00784 };
00785 
00786 BrushPainter *brush_painter_new(Scene *scene, Brush *brush)
00787 {
00788     BrushPainter *painter= MEM_callocN(sizeof(BrushPainter), "BrushPainter");
00789 
00790     painter->brush= brush;
00791     painter->scene= scene;
00792     painter->firsttouch= 1;
00793     painter->cache.lastsize= -1; /* force ibuf create in refresh */
00794 
00795     painter->startsize = brush_size(scene, brush);
00796     painter->startalpha = brush_alpha(scene, brush);
00797     painter->startjitter = brush->jitter;
00798     painter->startspacing = brush->spacing;
00799 
00800     return painter;
00801 }
00802 
00803 void brush_painter_require_imbuf(BrushPainter *painter, short flt, short texonly, int size)
00804 {
00805     if ((painter->cache.flt != flt) || (painter->cache.size != size) ||
00806         ((painter->cache.texonly != texonly) && texonly)) {
00807         if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
00808         if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
00809         painter->cache.ibuf= painter->cache.maskibuf= NULL;
00810         painter->cache.lastsize= -1; /* force ibuf create in refresh */
00811     }
00812 
00813     if (painter->cache.flt != flt) {
00814         if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
00815         painter->cache.texibuf= NULL;
00816         painter->cache.lastsize= -1; /* force ibuf create in refresh */
00817     }
00818 
00819     painter->cache.size= size;
00820     painter->cache.flt= flt;
00821     painter->cache.texonly= texonly;
00822     painter->cache.enabled= 1;
00823 }
00824 
00825 void brush_painter_free(BrushPainter *painter)
00826 {
00827     Brush *brush = painter->brush;
00828 
00829     brush_set_size(painter->scene, brush, painter->startsize);
00830     brush_set_alpha(painter->scene, brush, painter->startalpha);
00831     brush->jitter = painter->startjitter;
00832     brush->spacing = painter->startspacing;
00833 
00834     if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
00835     if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
00836     if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
00837     MEM_freeN(painter);
00838 }
00839 
00840 static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, int x, int y, int w, int h, int xt, int yt, float *pos)
00841 {
00842     Scene *scene= painter->scene;
00843     Brush *brush= painter->brush;
00844     ImBuf *ibuf, *maskibuf, *texibuf;
00845     float *bf, *mf, *tf, *otf=NULL, xoff, yoff, xy[2], rgba[4];
00846     char *b, *m, *t, *ot= NULL;
00847     int dotexold, origx= x, origy= y;
00848     const int radius= brush_size(painter->scene, brush);
00849 
00850     xoff = -radius + 0.5f;
00851     yoff = -radius + 0.5f;
00852     xoff += (int)pos[0] - (int)painter->startpaintpos[0];
00853     yoff += (int)pos[1] - (int)painter->startpaintpos[1];
00854 
00855     ibuf = painter->cache.ibuf;
00856     texibuf = painter->cache.texibuf;
00857     maskibuf = painter->cache.maskibuf;
00858 
00859     dotexold = (oldtexibuf != NULL);
00860 
00861     /* not sure if it's actually needed or it's a mistake in coords/sizes
00862        calculation in brush_painter_fixed_tex_partial_update(), but without this
00863        limitation memory gets corrupted at fast strokes with quite big spacing (sergey) */
00864     w = MIN2(w, ibuf->x);
00865     h = MIN2(h, ibuf->y);
00866 
00867     if (painter->cache.flt) {
00868         for (; y < h; y++) {
00869             bf = ibuf->rect_float + (y*ibuf->x + origx)*4;
00870             tf = texibuf->rect_float + (y*texibuf->x + origx)*4;
00871             mf = maskibuf->rect_float + (y*maskibuf->x + origx)*4;
00872 
00873             if (dotexold)
00874                 otf = oldtexibuf->rect_float + ((y - origy + yt)*oldtexibuf->x + xt)*4;
00875 
00876             for (x=origx; x < w; x++, bf+=4, mf+=4, tf+=4) {
00877                 if (dotexold) {
00878                     copy_v3_v3(tf, otf);
00879                     tf[3] = otf[3];
00880                     otf += 4;
00881                 }
00882                 else {
00883                     xy[0] = x + xoff;
00884                     xy[1] = y + yoff;
00885 
00886                     brush_sample_tex(scene, brush, xy, tf, 0);
00887                 }
00888 
00889                 bf[0] = tf[0]*mf[0];
00890                 bf[1] = tf[1]*mf[1];
00891                 bf[2] = tf[2]*mf[2];
00892                 bf[3] = tf[3]*mf[3];
00893             }
00894         }
00895     }
00896     else {
00897         for (; y < h; y++) {
00898             b = (char*)ibuf->rect + (y*ibuf->x + origx)*4;
00899             t = (char*)texibuf->rect + (y*texibuf->x + origx)*4;
00900             m = (char*)maskibuf->rect + (y*maskibuf->x + origx)*4;
00901 
00902             if (dotexold)
00903                 ot = (char*)oldtexibuf->rect + ((y - origy + yt)*oldtexibuf->x + xt)*4;
00904 
00905             for (x=origx; x < w; x++, b+=4, m+=4, t+=4) {
00906                 if (dotexold) {
00907                     t[0] = ot[0];
00908                     t[1] = ot[1];
00909                     t[2] = ot[2];
00910                     t[3] = ot[3];
00911                     ot += 4;
00912                 }
00913                 else {
00914                     xy[0] = x + xoff;
00915                     xy[1] = y + yoff;
00916 
00917                     brush_sample_tex(scene, brush, xy, rgba, 0);
00918                     t[0]= FTOCHAR(rgba[0]);
00919                     t[1]= FTOCHAR(rgba[1]);
00920                     t[2]= FTOCHAR(rgba[2]);
00921                     t[3]= FTOCHAR(rgba[3]);
00922                 }
00923 
00924                 b[0] = t[0]*m[0]/255;
00925                 b[1] = t[1]*m[1]/255;
00926                 b[2] = t[2]*m[2]/255;
00927                 b[3] = t[3]*m[3]/255;
00928             }
00929         }
00930     }
00931 }
00932 
00933 static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, float *pos)
00934 {
00935     const Scene *scene= painter->scene;
00936     Brush *brush= painter->brush;
00937     BrushPainterCache *cache= &painter->cache;
00938     ImBuf *oldtexibuf, *ibuf;
00939     int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
00940     const int diameter= 2*brush_size(scene, brush);
00941 
00942     imbflag= (cache->flt)? IB_rectfloat: IB_rect;
00943     if (!cache->ibuf)
00944         cache->ibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag);
00945     ibuf= cache->ibuf;
00946 
00947     oldtexibuf= cache->texibuf;
00948     cache->texibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag);
00949 
00950     if (oldtexibuf) {
00951         srcx= srcy= 0;
00952         destx= (int)painter->lastpaintpos[0] - (int)pos[0];
00953         desty= (int)painter->lastpaintpos[1] - (int)pos[1];
00954         w= oldtexibuf->x;
00955         h= oldtexibuf->y;
00956 
00957         IMB_rectclip(cache->texibuf, oldtexibuf, &destx, &desty, &srcx, &srcy, &w, &h);
00958     }
00959     else {
00960         srcx= srcy= 0;
00961         destx= desty= 0;
00962         w= h= 0;
00963     }
00964     
00965     x1= destx;
00966     y1= desty;
00967     x2= destx+w;
00968     y2= desty+h;
00969 
00970     /* blend existing texture in new position */
00971     if ((x1 < x2) && (y1 < y2))
00972         brush_painter_do_partial(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy, pos);
00973 
00974     if (oldtexibuf)
00975         IMB_freeImBuf(oldtexibuf);
00976 
00977     /* sample texture in new areas */
00978     if ((0 < x1) && (0 < ibuf->y))
00979         brush_painter_do_partial(painter, NULL, 0, 0, x1, ibuf->y, 0, 0, pos);
00980     if ((x2 < ibuf->x) && (0 < ibuf->y))
00981         brush_painter_do_partial(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0, pos);
00982     if ((x1 < x2) && (0 < y1))
00983         brush_painter_do_partial(painter, NULL, x1, 0, x2, y1, 0, 0, pos);
00984     if ((x1 < x2) && (y2 < ibuf->y))
00985         brush_painter_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos);
00986 }
00987 
00988 static void brush_painter_refresh_cache(BrushPainter *painter, float *pos, int use_color_correction)
00989 {
00990     const Scene *scene= painter->scene;
00991     Brush *brush= painter->brush;
00992     BrushPainterCache *cache= &painter->cache;
00993     MTex *mtex= &brush->mtex;
00994     int size;
00995     short flt;
00996     const int diameter= 2*brush_size(scene, brush);
00997     const float alpha= brush_alpha(scene, brush);
00998 
00999     if (diameter != cache->lastsize ||
01000         alpha != cache->lastalpha ||
01001         brush->jitter != cache->lastjitter)
01002     {
01003         if (cache->ibuf) {
01004             IMB_freeImBuf(cache->ibuf);
01005             cache->ibuf= NULL;
01006         }
01007         if (cache->maskibuf) {
01008             IMB_freeImBuf(cache->maskibuf);
01009             cache->maskibuf= NULL;
01010         }
01011 
01012         flt= cache->flt;
01013         size= (cache->size)? cache->size: diameter;
01014 
01015         if (brush->flag & BRUSH_FIXED_TEX) {
01016             brush_imbuf_new(scene, brush, flt, 3, size, &cache->maskibuf, use_color_correction);
01017             brush_painter_fixed_tex_partial_update(painter, pos);
01018         }
01019         else
01020             brush_imbuf_new(scene, brush, flt, 2, size, &cache->ibuf, use_color_correction);
01021 
01022         cache->lastsize= diameter;
01023         cache->lastalpha= alpha;
01024         cache->lastjitter= brush->jitter;
01025     }
01026     else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) {
01027         int dx = (int)painter->lastpaintpos[0] - (int)pos[0];
01028         int dy = (int)painter->lastpaintpos[1] - (int)pos[1];
01029 
01030         if ((dx != 0) || (dy != 0))
01031             brush_painter_fixed_tex_partial_update(painter, pos);
01032     }
01033 }
01034 
01035 void brush_painter_break_stroke(BrushPainter *painter)
01036 {
01037     painter->firsttouch= 1;
01038 }
01039 
01040 static void brush_apply_pressure(BrushPainter *painter, Brush *brush, float pressure)
01041 {
01042     if (brush_use_alpha_pressure(painter->scene, brush)) 
01043         brush_set_alpha(painter->scene, brush, MAX2(0.0f, painter->startalpha*pressure));
01044     if (brush_use_size_pressure(painter->scene, brush))
01045         brush_set_size(painter->scene, brush, MAX2(1.0f, painter->startsize*pressure));
01046     if (brush->flag & BRUSH_JITTER_PRESSURE)
01047         brush->jitter = MAX2(0.0f, painter->startjitter*pressure);
01048     if (brush->flag & BRUSH_SPACING_PRESSURE)
01049         brush->spacing = MAX2(1.0f, painter->startspacing*(1.5f-pressure));
01050 }
01051 
01052 void brush_jitter_pos(const Scene *scene, Brush *brush, float pos[2], float jitterpos[2])
01053 {
01054     int use_jitter= brush->jitter != 0;
01055 
01056     /* jitter-ed brush gives weird and unpredictable result for this
01057        kinds of stroke, so manyally disable jitter usage (sergey) */
01058     use_jitter&= (brush->flag & (BRUSH_RESTORE_MESH|BRUSH_ANCHORED)) == 0;
01059 
01060     if(use_jitter){
01061         float rand_pos[2];
01062         const int radius= brush_size(scene, brush);
01063         const int diameter= 2*radius;
01064 
01065         // find random position within a circle of diameter 1
01066         do {
01067             rand_pos[0] = BLI_frand()-0.5f;
01068             rand_pos[1] = BLI_frand()-0.5f;
01069         } while (len_v2(rand_pos) > 0.5f);
01070 
01071         jitterpos[0] = pos[0] + 2*rand_pos[0]*diameter*brush->jitter;
01072         jitterpos[1] = pos[1] + 2*rand_pos[1]*diameter*brush->jitter;
01073     }
01074     else {
01075         copy_v2_v2(jitterpos, pos);
01076     }
01077 }
01078 
01079 int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, float pressure, void *user, int use_color_correction)
01080 {
01081     Scene *scene= painter->scene;
01082     Brush *brush= painter->brush;
01083     int totpaintops= 0;
01084 
01085     if (pressure == 0.0f) {
01086         if(painter->lastpressure) // XXX - hack, operator misses
01087             pressure= painter->lastpressure;
01088         else
01089             pressure = 1.0f;    /* zero pressure == not using tablet */
01090     }
01091     if (painter->firsttouch) {
01092         /* paint exactly once on first touch */
01093         painter->startpaintpos[0]= pos[0];
01094         painter->startpaintpos[1]= pos[1];
01095 
01096         brush_apply_pressure(painter, brush, pressure);
01097         if (painter->cache.enabled)
01098             brush_painter_refresh_cache(painter, pos, use_color_correction);
01099         totpaintops += func(user, painter->cache.ibuf, pos, pos);
01100         
01101         painter->lasttime= time;
01102         painter->firsttouch= 0;
01103         painter->lastpaintpos[0]= pos[0];
01104         painter->lastpaintpos[1]= pos[1];
01105     }
01106 #if 0
01107     else if (painter->brush->flag & BRUSH_AIRBRUSH) {
01108         float spacing, step, paintpos[2], dmousepos[2], len;
01109         double starttime, curtime= time;
01110 
01111         /* compute brush spacing adapted to brush size */
01112         spacing= brush->rate; //radius*brush->spacing*0.01f;
01113 
01114         /* setup starting time, direction vector and accumulated time */
01115         starttime= painter->accumtime;
01116         sub_v2_v2v2(dmousepos, pos, painter->lastmousepos);
01117         len= normalize_v2(dmousepos);
01118         painter->accumtime += curtime - painter->lasttime;
01119 
01120         /* do paint op over unpainted time distance */
01121         while (painter->accumtime >= spacing) {
01122             step= (spacing - starttime)*len;
01123             paintpos[0]= painter->lastmousepos[0] + dmousepos[0]*step;
01124             paintpos[1]= painter->lastmousepos[1] + dmousepos[1]*step;
01125 
01126             if (painter->cache.enabled)
01127                 brush_painter_refresh_cache(painter);
01128             totpaintops += func(user, painter->cache.ibuf,
01129                 painter->lastpaintpos, paintpos);
01130 
01131             painter->lastpaintpos[0]= paintpos[0];
01132             painter->lastpaintpos[1]= paintpos[1];
01133             painter->accumtime -= spacing;
01134             starttime -= spacing;
01135         }
01136         
01137         painter->lasttime= curtime;
01138     }
01139 #endif
01140     else {
01141         float startdistance, spacing, step, paintpos[2], dmousepos[2], finalpos[2];
01142         float t, len, press;
01143         const int radius= brush_size(scene, brush);
01144 
01145         /* compute brush spacing adapted to brush radius, spacing may depend
01146            on pressure, so update it */
01147         brush_apply_pressure(painter, brush, painter->lastpressure);
01148         spacing= MAX2(1.0f, radius)*brush->spacing*0.01f;
01149 
01150         /* setup starting distance, direction vector and accumulated distance */
01151         startdistance= painter->accumdistance;
01152         sub_v2_v2v2(dmousepos, pos, painter->lastmousepos);
01153         len= normalize_v2(dmousepos);
01154         painter->accumdistance += len;
01155 
01156         if (brush->flag & BRUSH_SPACE) {
01157             /* do paint op over unpainted distance */
01158             while ((len > 0.0f) && (painter->accumdistance >= spacing)) {
01159                 step= spacing - startdistance;
01160                 paintpos[0]= painter->lastmousepos[0] + dmousepos[0]*step;
01161                 paintpos[1]= painter->lastmousepos[1] + dmousepos[1]*step;
01162 
01163                 t = step/len;
01164                 press= (1.0f-t)*painter->lastpressure + t*pressure;
01165                 brush_apply_pressure(painter, brush, press);
01166                 spacing= MAX2(1.0f, radius)*brush->spacing*0.01f;
01167 
01168                 brush_jitter_pos(scene, brush, paintpos, finalpos);
01169 
01170                 if (painter->cache.enabled)
01171                     brush_painter_refresh_cache(painter, finalpos, use_color_correction);
01172 
01173                 totpaintops +=
01174                     func(user, painter->cache.ibuf, painter->lastpaintpos, finalpos);
01175 
01176                 painter->lastpaintpos[0]= paintpos[0];
01177                 painter->lastpaintpos[1]= paintpos[1];
01178                 painter->accumdistance -= spacing;
01179                 startdistance -= spacing;
01180             }
01181         } else {
01182             brush_jitter_pos(scene, brush, pos, finalpos);
01183 
01184             if (painter->cache.enabled)
01185                 brush_painter_refresh_cache(painter, finalpos, use_color_correction);
01186 
01187             totpaintops += func(user, painter->cache.ibuf, pos, finalpos);
01188 
01189             painter->lastpaintpos[0]= pos[0];
01190             painter->lastpaintpos[1]= pos[1];
01191             painter->accumdistance= 0;
01192         }
01193 
01194         /* do airbrush paint ops, based on the number of paint ops left over
01195            from regular painting. this is a temporary solution until we have
01196            accurate time stamps for mouse move events */
01197         if (brush->flag & BRUSH_AIRBRUSH) {
01198             double curtime= time;
01199             double painttime= brush->rate*totpaintops;
01200 
01201             painter->accumtime += curtime - painter->lasttime;
01202             if (painter->accumtime <= painttime)
01203                 painter->accumtime= 0.0;
01204             else
01205                 painter->accumtime -= painttime;
01206 
01207             while (painter->accumtime >= (double)brush->rate) {
01208                 brush_apply_pressure(painter, brush, pressure);
01209 
01210                 brush_jitter_pos(scene, brush, pos, finalpos);
01211 
01212                 if (painter->cache.enabled)
01213                     brush_painter_refresh_cache(painter, finalpos, use_color_correction);
01214 
01215                 totpaintops +=
01216                     func(user, painter->cache.ibuf, painter->lastmousepos, finalpos);
01217                 painter->accumtime -= (double)brush->rate;
01218             }
01219 
01220             painter->lasttime= curtime;
01221         }
01222     }
01223 
01224     painter->lastmousepos[0]= pos[0];
01225     painter->lastmousepos[1]= pos[1];
01226     painter->lastpressure= pressure;
01227 
01228     brush_set_alpha(scene, brush, painter->startalpha);
01229     brush_set_size(scene, brush, painter->startsize);
01230     brush->jitter = painter->startjitter;
01231     brush->spacing = painter->startspacing;
01232 
01233     return totpaintops;
01234 }
01235 
01236 /* Uses the brush curve control to find a strength value between 0 and 1 */
01237 float brush_curve_strength_clamp(Brush *br, float p, const float len)
01238 {
01239     if(p >= len)    return 0;
01240     else            p= p/len;
01241 
01242     p= curvemapping_evaluateF(br->curve, 0, p);
01243     if(p < 0.0f)        p= 0.0f;
01244     else if(p > 1.0f)   p= 1.0f;
01245     return p;
01246 }
01247 /* same as above but can return negative values if the curve enables
01248  * used for sculpt only */
01249 float brush_curve_strength(Brush *br, float p, const float len)
01250 {
01251     if(p >= len)
01252         p= 1.0f;
01253     else
01254         p= p/len;
01255 
01256     return curvemapping_evaluateF(br->curve, 0, p);
01257 }
01258 
01259 /* TODO: should probably be unified with BrushPainter stuff? */
01260 unsigned int *brush_gen_texture_cache(Brush *br, int half_side)
01261 {
01262     unsigned int *texcache = NULL;
01263     MTex *mtex = &br->mtex;
01264     TexResult texres= {0};
01265     int hasrgb, ix, iy;
01266     int side = half_side * 2;
01267     
01268     if(mtex->tex) {
01269         float x, y, step = 2.0 / side, co[3];
01270 
01271         texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache");
01272 
01273         BKE_image_get_ibuf(mtex->tex->ima, NULL);
01274         
01275         /*do normalized cannonical view coords for texture*/
01276         for (y=-1.0, iy=0; iy<side; iy++, y += step) {
01277             for (x=-1.0, ix=0; ix<side; ix++, x += step) {
01278                 co[0]= x;
01279                 co[1]= y;
01280                 co[2]= 0.0f;
01281                 
01282                 /* This is copied from displace modifier code */
01283                 hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres);
01284             
01285                 /* if the texture gave an RGB value, we assume it didn't give a valid
01286                  * intensity, so calculate one (formula from do_material_tex).
01287                  * if the texture didn't give an RGB value, copy the intensity across
01288                  */
01289                 if(hasrgb & TEX_RGB)
01290                     texres.tin = (0.35f * texres.tr + 0.45f *
01291                                   texres.tg + 0.2f * texres.tb);
01292 
01293                 texres.tin = texres.tin * 255.0f;
01294                 ((char*)texcache)[(iy*side+ix)*4] = (char)texres.tin;
01295                 ((char*)texcache)[(iy*side+ix)*4+1] = (char)texres.tin;
01296                 ((char*)texcache)[(iy*side+ix)*4+2] = (char)texres.tin;
01297                 ((char*)texcache)[(iy*side+ix)*4+3] = (char)texres.tin;
01298             }
01299         }
01300     }
01301 
01302     return texcache;
01303 }
01304 
01305 /**** Radial Control ****/
01306 struct ImBuf *brush_gen_radial_control_imbuf(Brush *br)
01307 {
01308     ImBuf *im = MEM_callocN(sizeof(ImBuf), "radial control texture");
01309     unsigned int *texcache;
01310     int side = 128;
01311     int half = side / 2;
01312     int i, j;
01313 
01314     texcache = brush_gen_texture_cache(br, half);
01315     im->rect_float = MEM_callocN(sizeof(float) * side * side, "radial control rect");
01316     im->x = im->y = side;
01317 
01318     for(i=0; i<side; ++i) {
01319         for(j=0; j<side; ++j) {
01320             float magn= sqrt(pow(i - half, 2) + pow(j - half, 2));
01321             im->rect_float[i*side + j]= brush_curve_strength_clamp(br, magn, half);
01322         }
01323     }
01324 
01325     /* Modulate curve with texture */
01326     if(texcache) {
01327         for(i=0; i<side; ++i) {
01328             for(j=0; j<side; ++j) {
01329                 const int col= texcache[i*side+j];
01330                 im->rect_float[i*side+j]*= (((char*)&col)[0]+((char*)&col)[1]+((char*)&col)[2])/3.0f/255.0f;
01331             }
01332         }
01333 
01334         MEM_freeN(texcache);
01335     }
01336 
01337     return im;
01338 }