static void brush_pressure_apply(BrushPainter *painter, Brush *brush, float pressure) { if (BKE_brush_use_alpha_pressure(painter->scene, brush)) BKE_brush_alpha_set(painter->scene, brush, max_ff(0.0f, painter->startalpha * pressure)); if (BKE_brush_use_size_pressure(painter->scene, brush)) BKE_brush_size_set(painter->scene, brush, max_ff(1.0f, painter->startsize * pressure)); if (brush->flag & BRUSH_JITTER_PRESSURE) brush->jitter = max_ff(0.0f, painter->startjitter * pressure); if (brush->flag & BRUSH_SPACING_PRESSURE) brush->spacing = max_ff(1.0f, painter->startspacing * (1.5f - pressure)); }
void BKE_brush_painter_free(BrushPainter *painter) { Brush *brush = painter->brush; BKE_brush_size_set(painter->scene, brush, painter->startsize); BKE_brush_alpha_set(painter->scene, brush, painter->startalpha); brush->jitter = painter->startjitter; brush->spacing = painter->startspacing; if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf); if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf); if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf); MEM_freeN(painter); }
static int brush_scale_size_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Paint *paint = BKE_paint_get_active_from_context(C); Brush *brush = BKE_paint_brush(paint); // Object *ob = CTX_data_active_object(C); float scalar = RNA_float_get(op->ptr, "scalar"); if (brush) { // pixel radius { const int old_size = BKE_brush_size_get(scene, brush); int size = (int)(scalar * old_size); if (abs(old_size - size) < U.pixelsize) { if (scalar > 1) { size += U.pixelsize; } else if (scalar < 1) { size -= U.pixelsize; } } BKE_brush_size_set(scene, brush, size); } // unprojected radius { float unprojected_radius = scalar * BKE_brush_unprojected_radius_get(scene, brush); if (unprojected_radius < 0.001f) // XXX magic number unprojected_radius = 0.001f; BKE_brush_unprojected_radius_set(scene, brush, unprojected_radius); } WM_main_add_notifier(NC_BRUSH | NA_EDITED, brush); } return OPERATOR_FINISHED; }
static int brush_scale_size_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Paint *paint = BKE_paint_get_active_from_context(C); Brush *brush = BKE_paint_brush(paint); // Object *ob = CTX_data_active_object(C); float scalar = RNA_float_get(op->ptr, "scalar"); if (brush) { // pixel radius { const int old_size = BKE_brush_size_get(scene, brush); int size = (int)(scalar * old_size); if (old_size == size) { if (scalar > 1) { size++; } else if (scalar < 1) { size--; } } CLAMP(size, 1, 2000); // XXX magic number BKE_brush_size_set(scene, brush, size); } // unprojected radius { float unprojected_radius = scalar * BKE_brush_unprojected_radius_get(scene, brush); if (unprojected_radius < 0.001f) // XXX magic number unprojected_radius = 0.001f; BKE_brush_unprojected_radius_set(scene, brush, unprojected_radius); } } return OPERATOR_FINISHED; }
int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float pos[2], double time, float pressure, void *user, int use_color_correction) { Scene *scene = painter->scene; Brush *brush = painter->brush; int totpaintops = 0; if (pressure == 0.0f) { if (painter->lastpressure) // XXX - hack, operator misses pressure = painter->lastpressure; else pressure = 1.0f; /* zero pressure == not using tablet */ } if (painter->firsttouch) { /* paint exactly once on first touch */ painter->startpaintpos[0] = pos[0]; painter->startpaintpos[1] = pos[1]; brush_pressure_apply(painter, brush, pressure); if (painter->cache.enabled) brush_painter_refresh_cache(painter, pos, use_color_correction); totpaintops += func(user, painter->cache.ibuf, pos, pos); painter->lasttime = time; painter->firsttouch = 0; painter->lastpaintpos[0] = pos[0]; painter->lastpaintpos[1] = pos[1]; } #if 0 else if (painter->brush->flag & BRUSH_AIRBRUSH) { float spacing, step, paintpos[2], dmousepos[2], len; double starttime, curtime = time; /* compute brush spacing adapted to brush size */ spacing = brush->rate; //radius*brush->spacing * 0.01f; /* setup starting time, direction vector and accumulated time */ starttime = painter->accumtime; sub_v2_v2v2(dmousepos, pos, painter->lastmousepos); len = normalize_v2(dmousepos); painter->accumtime += curtime - painter->lasttime; /* do paint op over unpainted time distance */ while (painter->accumtime >= spacing) { step = (spacing - starttime) * len; paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step; paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step; if (painter->cache.enabled) brush_painter_refresh_cache(painter); totpaintops += func(user, painter->cache.ibuf, painter->lastpaintpos, paintpos); painter->lastpaintpos[0] = paintpos[0]; painter->lastpaintpos[1] = paintpos[1]; painter->accumtime -= spacing; starttime -= spacing; } painter->lasttime = curtime; } #endif else { float startdistance, spacing, step, paintpos[2], dmousepos[2], finalpos[2]; float t, len, press; const int radius = BKE_brush_size_get(scene, brush); /* compute brush spacing adapted to brush radius, spacing may depend * on pressure, so update it */ brush_pressure_apply(painter, brush, painter->lastpressure); spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f; /* setup starting distance, direction vector and accumulated distance */ startdistance = painter->accumdistance; sub_v2_v2v2(dmousepos, pos, painter->lastmousepos); len = normalize_v2(dmousepos); painter->accumdistance += len; if (brush->flag & BRUSH_SPACE) { /* do paint op over unpainted distance */ while ((len > 0.0f) && (painter->accumdistance >= spacing)) { step = spacing - startdistance; paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step; paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step; t = step / len; press = (1.0f - t) * painter->lastpressure + t * pressure; brush_pressure_apply(painter, brush, press); spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f; BKE_brush_jitter_pos(scene, brush, paintpos, finalpos); if (painter->cache.enabled) brush_painter_refresh_cache(painter, finalpos, use_color_correction); totpaintops += func(user, painter->cache.ibuf, painter->lastpaintpos, finalpos); painter->lastpaintpos[0] = paintpos[0]; painter->lastpaintpos[1] = paintpos[1]; painter->accumdistance -= spacing; startdistance -= spacing; } } else { BKE_brush_jitter_pos(scene, brush, pos, finalpos); if (painter->cache.enabled) brush_painter_refresh_cache(painter, finalpos, use_color_correction); totpaintops += func(user, painter->cache.ibuf, pos, finalpos); painter->lastpaintpos[0] = pos[0]; painter->lastpaintpos[1] = pos[1]; painter->accumdistance = 0; } /* do airbrush paint ops, based on the number of paint ops left over * from regular painting. this is a temporary solution until we have * accurate time stamps for mouse move events */ if (brush->flag & BRUSH_AIRBRUSH) { double curtime = time; double painttime = brush->rate * totpaintops; painter->accumtime += curtime - painter->lasttime; if (painter->accumtime <= painttime) painter->accumtime = 0.0; else painter->accumtime -= painttime; while (painter->accumtime >= (double)brush->rate) { brush_pressure_apply(painter, brush, pressure); BKE_brush_jitter_pos(scene, brush, pos, finalpos); if (painter->cache.enabled) brush_painter_refresh_cache(painter, finalpos, use_color_correction); totpaintops += func(user, painter->cache.ibuf, painter->lastmousepos, finalpos); painter->accumtime -= (double)brush->rate; } painter->lasttime = curtime; } } painter->lastmousepos[0] = pos[0]; painter->lastmousepos[1] = pos[1]; painter->lastpressure = pressure; BKE_brush_alpha_set(scene, brush, painter->startalpha); BKE_brush_size_set(scene, brush, painter->startsize); brush->jitter = painter->startjitter; brush->spacing = painter->startspacing; return totpaintops; }