Added two new blend modes to image painting brushes, erase alpha and
add alpha, for painting transparency in images. When using the eraser tool of a tablet pen, the erase alpha blend mode is activated.
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user