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