diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 5eaac146c4e..79d2d148c19 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -227,6 +227,8 @@ typedef enum IMB_BlendMode { IMB_BLEND_MUL = 3, IMB_BLEND_LIGHTEN = 4, IMB_BLEND_DARKEN = 5, + IMB_BLEND_ERASE_ALPHA = 6, + IMB_BLEND_ADD_ALPHA = 7, IMB_BLEND_COPY = 1000, IMB_BLEND_COPY_RGB = 1001, diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c index 1b8e64d6ff6..41183ce91da 100644 --- a/source/blender/imbuf/intern/rectop.c +++ b/source/blender/imbuf/intern/rectop.c @@ -117,7 +117,8 @@ static void blend_color_darken(char *cp, char *cp1, char *cp2, int fac) unsigned int IMB_blend_color(unsigned int src1, unsigned int src2, int fac, IMB_BlendMode mode) { - unsigned int dst, temp; + unsigned int dst; + int temp; char *cp, *cp1, *cp2; if (fac==0) @@ -141,11 +142,19 @@ unsigned int IMB_blend_color(unsigned int src1, unsigned int src2, int fac, IMB_ case IMB_BLEND_DARKEN: blend_color_darken(cp, cp1, cp2, fac); break; default: - return src1; + cp[0]= cp1[0]; + cp[1]= cp1[1]; + cp[2]= cp1[2]; } - temp= (cp1[3] + fac*cp2[3]/255); - cp[3]= (temp > 255)? 255: temp; + if (mode == IMB_BLEND_ERASE_ALPHA) { + temp= (cp1[3] - fac*cp2[3]/255); + cp[3]= (temp < 0)? 0: temp; + } + else { /* this does ADD_ALPHA also */ + temp= (cp1[3] + fac*cp2[3]/255); + cp[3]= (temp > 255)? 255: temp; + } return dst; } @@ -244,8 +253,14 @@ void IMB_blend_color_float(float *dst, float *src1, float *src2, float fac, IMB_ dst[2]= src1[2]; } - dst[3]= (src1[3] + fac*src2[3]); - if (dst[3] > 1.0f) dst[3] = 1.0f; + if (mode == IMB_BLEND_ERASE_ALPHA) { + dst[3]= (src1[3] - fac*src2[3]); + if (dst[3] < 0.0f) dst[3] = 0.0f; + } + else { /* this does ADD_ALPHA also */ + dst[3]= (src1[3] + fac*src2[3]); + if (dst[3] > 1.0f) dst[3] = 1.0f; + } } /* clipping */ diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 40347c9834f..1c272105067 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -73,12 +73,14 @@ typedef struct Brush { #define BRUSH_FIXED_TEX 64 /* Brush.blend */ -#define BRUSH_BLEND_MIX 0 -#define BRUSH_BLEND_ADD 1 -#define BRUSH_BLEND_SUB 2 -#define BRUSH_BLEND_MUL 3 -#define BRUSH_BLEND_LIGHTEN 4 -#define BRUSH_BLEND_DARKEN 5 +#define BRUSH_BLEND_MIX 0 +#define BRUSH_BLEND_ADD 1 +#define BRUSH_BLEND_SUB 2 +#define BRUSH_BLEND_MUL 3 +#define BRUSH_BLEND_LIGHTEN 4 +#define BRUSH_BLEND_DARKEN 5 +#define BRUSH_BLEND_ERASE_ALPHA 6 +#define BRUSH_BLEND_ADD_ALPHA 7 #define PAINT_TOOL_DRAW 0 #define PAINT_TOOL_SOFTEN 1 diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 760c0d22648..23e66924509 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -4544,7 +4544,7 @@ static void editing_panel_mesh_paint(void) if(brush && !brush->id.lib) { butw= 320-(xco+10); - uiDefButS(block, MENU, B_NOP, "Mix %x0|Add %x1|Subtract %x2|Multiply %x3|Lighten %x4|Darken %x5", xco+10,yco,butw,19, &brush->blend, 0, 0, 0, 0, "Blending method for applying brushes"); + uiDefButS(block, MENU, B_NOP, "Mix %x0|Add %x1|Subtract %x2|Multiply %x3|Lighten %x4|Darken %x5|Erase Alpha %x6|Add Alpha %x7", xco+10,yco,butw,19, &brush->blend, 0, 0, 0, 0, "Blending method for applying brushes"); uiDefButBitS(block, TOG|BIT, BRUSH_TORUS, B_BRUSHCHANGE, "Wrap", xco+10,yco-25,butw,19, &brush->flag, 0, 0, 0, 0, "Enables torus wrapping"); diff --git a/source/blender/src/drawimage.c b/source/blender/src/drawimage.c index 812f5946663..516a1e2b8f3 100644 --- a/source/blender/src/drawimage.c +++ b/source/blender/src/drawimage.c @@ -804,7 +804,7 @@ static void image_editvertex_buts(uiBlock *block) digits= 2; } - uiDefBut(block, LABEL, 0, "UV Vertex:",10,55,302,19,0,0,0,0,0,""); + uiDefBut(block, LABEL, 0, "UV Vertex:",10,55,300,19,0,0,0,0,0,""); uiBlockBeginAlign(block); if(nactive==1) { uiDefButF(block, NUM, B_TRANS_IMAGE, "Vertex X:", 10, 35, 290, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, ""); @@ -1084,7 +1084,7 @@ static void image_panel_paint(short cntrl) // IMAGE_HANDLER_PROPERTIES if(brush && !brush->id.lib) { butw= 320-(xco+10); - uiDefButS(block, MENU, B_SIMANOTHING, "Mix %x0|Add %x1|Subtract %x2|Multiply %x3|Lighten %x4|Darken %x5", xco+10,yco,butw,19, &brush->blend, 0, 0, 0, 0, "Blending method for applying brushes"); + uiDefButS(block, MENU, B_SIMANOTHING, "Mix %x0|Add %x1|Subtract %x2|Multiply %x3|Lighten %x4|Darken %x5|Erase Alpha %x6|Add Alpha %x7", xco+10,yco,butw,19, &brush->blend, 0, 0, 0, 0, "Blending method for applying brushes"); uiDefButBitS(block, TOG|BIT, BRUSH_TORUS, B_SIMABRUSHCHANGE, "Wrap", xco+10,yco-25,butw,19, &brush->flag, 0, 0, 0, 0, "Enables torus wrapping"); diff --git a/source/blender/src/imagepaint.c b/source/blender/src/imagepaint.c index 64a61f0acf0..f2266d9ac4a 100644 --- a/source/blender/src/imagepaint.c +++ b/source/blender/src/imagepaint.c @@ -103,7 +103,7 @@ typedef struct ImagePaintState { Brush *brush; - short tool; + short tool, blend; Image *image; ImBuf *canvas; ImBuf *clonecanvas; @@ -409,7 +409,7 @@ static int imapaint_paint_op(void *state, ImBuf *ibufb, float *lastpos, float *p ImagePaintState *s= ((ImagePaintState*)state); ImBuf *clonebuf= NULL; short torus= s->brush->flag & BRUSH_TORUS; - short blend= s->brush->blend; + short blend= s->blend; float *offset= s->brush->clone.offset; float liftpos[2]; int bpos[2], blastpos[2], bliftpos[2]; @@ -518,7 +518,7 @@ static void imapaint_canvas_free(ImagePaintState *s) imb_freerectfloatImBuf(s->clonecanvas); } -static int imapaint_do_paint(ImagePaintState *s, BrushPainter *painter, Image *image, short texpaint, float *uv, double time, int update, float pressure) +static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, Image *image, short texpaint, float *uv, double time, int update, float pressure) { float pos[2]; @@ -535,7 +535,7 @@ static int imapaint_do_paint(ImagePaintState *s, BrushPainter *painter, Image *i else return 0; } -static void imapaint_do(ImagePaintState *s, BrushPainter *painter, short texpaint, short *prevmval, short *mval, double time, float pressure) +static void imapaint_paint_stroke(ImagePaintState *s, BrushPainter *painter, short texpaint, short *prevmval, short *mval, double time, float pressure) { Image *newimage = NULL; float fwuv[2], bkuv[2], newuv[2]; @@ -565,7 +565,7 @@ static void imapaint_do(ImagePaintState *s, BrushPainter *painter, short texpain if (breakstroke) { texpaint_pick_uv(s->ob, s->me, s->faceindex, mval, fwuv); - redraw |= imapaint_do_paint(s, painter, s->image, texpaint, fwuv, + redraw |= imapaint_paint_sub_stroke(s, painter, s->image, texpaint, fwuv, time, 1, pressure); imapaint_clear_partial_redraw(); brush_painter_break_stroke(painter); @@ -579,9 +579,9 @@ static void imapaint_do(ImagePaintState *s, BrushPainter *painter, short texpain /* paint in new image */ if (newimage) { if (breakstroke) - redraw|= imapaint_do_paint(s, painter, newimage, texpaint, + redraw|= imapaint_paint_sub_stroke(s, painter, newimage, texpaint, bkuv, time, 0, pressure); - redraw|= imapaint_do_paint(s, painter, newimage, texpaint, newuv, + redraw|= imapaint_paint_sub_stroke(s, painter, newimage, texpaint, newuv, time, 1, pressure); } @@ -593,7 +593,7 @@ static void imapaint_do(ImagePaintState *s, BrushPainter *painter, short texpain } else { imapaint_compute_uvco(mval, newuv); - redraw |= imapaint_do_paint(s, painter, s->image, texpaint, newuv, + redraw |= imapaint_paint_sub_stroke(s, painter, s->image, texpaint, newuv, time, 1, pressure); } @@ -613,15 +613,16 @@ void imagepaint_paint(short mousebutton, short texpaint) float pressure; const GHOST_TabletData *td; + if(!settings->imapaint.brush) + return; + /* initialize state */ memset(&s, 0, sizeof(s)); - s.brush= settings->imapaint.brush; - s.tool= settings->imapaint.tool; + s.brush = settings->imapaint.brush; + s.tool = settings->imapaint.tool; if(texpaint && (s.tool == PAINT_TOOL_CLONE)) s.tool = PAINT_TOOL_DRAW; - - if(!s.brush) - return; + s.blend = s.brush->blend; if(texpaint) { s.ob = OBACT; @@ -653,8 +654,9 @@ void imagepaint_paint(short mousebutton, short texpaint) time= PIL_check_seconds_timer(); prevmval[0]= mval[0]; prevmval[1]= mval[1]; + s.blend = (td->Active == 2)? BRUSH_BLEND_ERASE_ALPHA: s.brush->blend; - imapaint_do(&s, painter, texpaint, prevmval, mval, time, pressure); + imapaint_paint_stroke(&s, painter, texpaint, prevmval, mval, time, pressure); /* paint loop */ do { @@ -662,16 +664,17 @@ void imagepaint_paint(short mousebutton, short texpaint) if(td) { td= get_tablet_data(); pressure= (td)? td->Pressure: 1.0f; + s.blend = (td->Active == 2)? BRUSH_BLEND_ERASE_ALPHA: s.brush->blend; } time= PIL_check_seconds_timer(); if((mval[0] != prevmval[0]) || (mval[1] != prevmval[1])) { - imapaint_do(&s, painter, texpaint, prevmval, mval, time, pressure); + imapaint_paint_stroke(&s, painter, texpaint, prevmval, mval, time, pressure); prevmval[0]= mval[0]; prevmval[1]= mval[1]; } else if (s.brush->flag & BRUSH_AIRBRUSH) - imapaint_do(&s, painter, texpaint, prevmval, mval, time, pressure); + imapaint_paint_stroke(&s, painter, texpaint, prevmval, mval, time, pressure); else BIF_wait_for_statechange();