Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2006-08-27 17:29:00 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2006-08-27 17:29:00 +0400
commitb39f4b788dc9c5ccc9430b02852cbc1cbe56eca1 (patch)
tree7a1c91c3d4235db02b231ab5f504b31c2c0e4f15 /source/blender/src/imagepaint.c
parent84205fe0e0bfc524b8fd9ba09aedbf98b0b9457b (diff)
Texturepaint now supports all the imagepaint brush settings, with the
exception of the clone tool. One level undo for image- and texturepaint, only storing those tiles that changed. Test to improve texturepaint performance using glTexSubImage2D, only enabled with 2^n sized textures and mipmapping off. Painting a 2048x2048 texture is then pretty smooth here, as long as the geometry is not too complex.
Diffstat (limited to 'source/blender/src/imagepaint.c')
-rw-r--r--source/blender/src/imagepaint.c631
1 files changed, 357 insertions, 274 deletions
diff --git a/source/blender/src/imagepaint.c b/source/blender/src/imagepaint.c
index f80d5a6723d..1e372c3ec28 100644
--- a/source/blender/src/imagepaint.c
+++ b/source/blender/src/imagepaint.c
@@ -85,7 +85,7 @@
#include "blendef.h"
#include "mydevice.h"
-/* ImagePaint Utilities */
+/* Defines and Structs */
#define IMAPAINT_FLOAT_TO_CHAR(f) ((char)(f*255))
#define IMAPAINT_CHAR_TO_FLOAT(c) (c/255.0f)
@@ -96,30 +96,191 @@
f[1]=IMAPAINT_CHAR_TO_FLOAT(c[1]); f[2]=IMAPAINT_CHAR_TO_FLOAT(c[2]); }
#define IMAPAINT_FLOAT_RGB_COPY(a, b) VECCOPY(a, b)
-static void imapaint_blend_line(ImBuf *ibuf, ImBuf *ibufb, float *start, float *end)
+#define IMAPAINT_TILE_BITS 6
+#define IMAPAINT_TILE_SIZE (1 << IMAPAINT_TILE_BITS)
+#define IMAPAINT_TILE_NUMBER(size) (((size)+IMAPAINT_TILE_SIZE-1) >> IMAPAINT_TILE_BITS)
+
+typedef struct ImagePaintState {
+ Brush *brush;
+ short tool;
+ Image *image;
+ ImBuf *canvas;
+ ImBuf *clonecanvas;
+ short clonefreefloat;
+ char *warnpackedfile;
+
+ /* texture paint only */
+ Object *ob;
+ Mesh *me;
+ TFace *tface;
+ float uv[2];
+} ImagePaintState;
+
+typedef struct ImagePaintUndo {
+ Image *image;
+ ImBuf *tilebuf;
+ void **tiles;
+ int xtiles, ytiles;
+} ImagePaintUndo;
+
+typedef struct ImagePaintPartialRedraw {
+ int x1, y1, x2, y2;
+ int enabled;
+} ImagePaintPartialRedraw;
+
+static ImagePaintUndo imapaintundo = {NULL, NULL, NULL, 0, 0};
+static ImagePaintPartialRedraw imapaintpartial = {0, 0, 0, 0, 0};
+
+static void init_imagapaint_undo(Image *ima)
+{
+ int xt, yt;
+
+ imapaintundo.image = ima;
+ imapaintundo.xtiles = xt = IMAPAINT_TILE_NUMBER(ima->ibuf->x);
+ imapaintundo.ytiles = yt = IMAPAINT_TILE_NUMBER(ima->ibuf->y);
+ imapaintundo.tiles = MEM_callocN(sizeof(void*)*xt*yt, "ImagePaintUndoTiles");
+ imapaintundo.tilebuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE,
+ ima->ibuf->depth, (ima->ibuf->rect_float)? IB_rectfloat: IB_rect, 0);
+}
+
+static void imapaint_copy_tile(Image *ima, int tile, int x, int y, int swapundo)
+{
+ IMB_rectcpy(imapaintundo.tilebuf, ima->ibuf, 0, 0, x*IMAPAINT_TILE_SIZE,
+ y*IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
+
+ if (imapaintundo.tilebuf->rect_float)
+ SWAP(void*, imapaintundo.tilebuf->rect_float, imapaintundo.tiles[tile])
+ else
+ SWAP(void*, imapaintundo.tilebuf->rect, imapaintundo.tiles[tile])
+
+ if (swapundo)
+ IMB_rectcpy(ima->ibuf, imapaintundo.tilebuf, x*IMAPAINT_TILE_SIZE,
+ y*IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
+}
+
+static void imapaint_clear_partial_redraw()
+{
+ memset(&imapaintpartial, 0, sizeof(imapaintpartial));
+}
+
+static void imapaint_dirty_region(Image *ima, int x, int y, int w, int h)
+{
+ int srcx= 0, srcy= 0, origx, tile, allocsize;
+
+ IMB_rectclip(ima->ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h);
+
+ if (w == 0 || h == 0)
+ return;
+
+ if (!imapaintpartial.enabled) {
+ imapaintpartial.x1 = x;
+ imapaintpartial.y1 = y;
+ imapaintpartial.x2 = x+w;
+ imapaintpartial.y2 = y+h;
+ imapaintpartial.enabled = 1;
+ }
+ else {
+ imapaintpartial.x1 = MIN2(imapaintpartial.x1, x);
+ imapaintpartial.y1 = MIN2(imapaintpartial.y1, y);
+ imapaintpartial.x2 = MAX2(imapaintpartial.x2, x+w);
+ imapaintpartial.y2 = MAX2(imapaintpartial.y2, y+h);
+ }
+
+ w = ((x + w - 1) >> IMAPAINT_TILE_BITS);
+ h = ((y + h - 1) >> IMAPAINT_TILE_BITS);
+ origx = (x >> IMAPAINT_TILE_BITS);
+ y = (y >> IMAPAINT_TILE_BITS);
+
+ for (; y <= h; y++) {
+ for (x=origx; x <= w; x++) {
+ if (ima != imapaintundo.image) {
+ free_imagepaint();
+ init_imagapaint_undo(ima);
+ }
+
+ tile = y*imapaintundo.xtiles + x;
+ if (!imapaintundo.tiles[tile]) {
+ allocsize= (ima->ibuf->rect_float)? sizeof(float): sizeof(char);
+ imapaintundo.tiles[tile]= MEM_mapallocN(allocsize*4*
+ IMAPAINT_TILE_SIZE*IMAPAINT_TILE_SIZE, "ImagePaintUndoTile");
+ imapaint_copy_tile(ima, tile, x, y, 0);
+ }
+ }
+ }
+
+ ima->ibuf->userflags |= IB_BITMAPDIRTY;
+}
+
+static void imapaint_image_update(Image *image, short texpaint)
+{
+ if(image->ibuf->rect_float)
+ imb_freerectImBuf(image->ibuf); /* force recreate of char rect */
+
+ /* todo: should set_tpage create ->rect? */
+ if(texpaint || G.sima->lock) {
+ int w = imapaintpartial.x2 - imapaintpartial.x1;
+ int h = imapaintpartial.y2 - imapaintpartial.y1;
+ update_realtime_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h);
+ }
+}
+
+static void imapaint_redraw(int final, int texpaint, Image *image)
+{
+ if(final) {
+ if(texpaint)
+ allqueue(REDRAWIMAGE, 0);
+ else if(!G.sima->lock) {
+ if(image)
+ free_realtime_image(image); /* force OpenGL reload */
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ allqueue(REDRAWHEADERS, 0);
+ }
+ else if(!texpaint && G.sima->lock)
+ force_draw_plus(SPACE_VIEW3D, 0);
+ else
+ force_draw(0);
+}
+
+void imagepaint_undo()
{
- float numsteps, t, pos[2];
- int step, d[2], ipos[2];
+ int x, y, tile;
+ Image *ima= imapaintundo.image;
- d[0] = (int)(end[0] - start[0]);
- d[1] = (int)(end[1] - start[1]);
- numsteps = sqrt(d[0]*d[0] + d[1]*d[1])/(ibufb->x/4.0f);
+ if (!ima || !ima->ibuf || !(ima->ibuf->rect || ima->ibuf->rect_float))
+ return;
- if(numsteps < 1.0)
- numsteps = 1.0f;
+ for (tile = 0, y = 0; y < imapaintundo.ytiles; y++)
+ for (x = 0; x < imapaintundo.xtiles; x++, tile++)
+ if (imapaintundo.tiles[tile])
+ imapaint_copy_tile(ima, tile, x, y, 1);
- for (step=0; step < numsteps; step++) {
- t = (step+1)/numsteps;
- pos[0] = start[0] + d[0]*t;
- pos[1] = start[1] + d[1]*t;
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWVIEW3D, 0);
- ipos[0]= (int)(pos[0] - ibufb->x/2);
- ipos[1]= (int)(pos[1] - ibufb->y/2);
- IMB_rectblend(ibuf, ibufb, ipos[0], ipos[1], 0, 0,
- ibufb->x, ibufb->y, IMB_BLEND_MIX);
+ free_realtime_image(ima); /* force OpenGL reload */
+}
+
+void free_imagepaint()
+{
+ /* todo: does this need to be in the same places as editmode_undo_clear,
+ vertex paint isn't? */
+ int i, size = imapaintundo.xtiles*imapaintundo.ytiles;
+
+ if (imapaintundo.tiles) {
+ for (i = 0; i < size; i++)
+ if (imapaintundo.tiles[i])
+ MEM_freeN(imapaintundo.tiles[i]);
+ MEM_freeN(imapaintundo.tiles);
}
+ if (imapaintundo.tilebuf)
+ IMB_freeImBuf(imapaintundo.tilebuf);
+
+ memset(&imapaintundo, 0, sizeof(imapaintundo));
}
+/* Image Paint Operations */
+
static void imapaint_ibuf_get_set_rgb(ImBuf *ibuf, int x, int y, short torus, short set, float *rgb)
{
if (torus) {
@@ -160,8 +321,6 @@ static int imapaint_ibuf_add_if(ImBuf *ibuf, unsigned int x, unsigned int y, flo
return 1;
}
-/* ImagePaint Tools */
-
static void imapaint_lift_soften(ImBuf *ibuf, ImBuf *ibufb, int *pos, short torus)
{
int x, y, count, xi, yi, xo, yo;
@@ -236,15 +395,6 @@ static ImBuf *imapaint_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos)
return clonebuf;
}
-/* ImagePaint state and operations */
-
-typedef struct ImagePaintState {
- Brush *brush;
- short tool;
- ImBuf *canvas;
- ImBuf *clonecanvas;
-} ImagePaintState;
-
static void imapaint_convert_brushco(ImBuf *ibufb, float *pos, int *ipos)
{
ipos[0]= (int)(pos[0] - ibufb->x/2);
@@ -253,43 +403,45 @@ static void imapaint_convert_brushco(ImBuf *ibufb, float *pos, int *ipos)
static int imapaint_paint_op(void *state, ImBuf *ibufb, float *lastpos, float *pos)
{
- ImagePaintState s= *((ImagePaintState*)state);
+ ImagePaintState *s= ((ImagePaintState*)state);
ImBuf *clonebuf= NULL;
- short torus= s.brush->flag & BRUSH_TORUS;
- short blend= s.brush->blend;
- float *offset= s.brush->clone.offset;
+ short torus= s->brush->flag & BRUSH_TORUS;
+ short blend= s->brush->blend;
+ float *offset= s->brush->clone.offset;
float liftpos[2];
int bpos[2], blastpos[2], bliftpos[2];
- if ((s.tool == PAINT_TOOL_SMEAR) && (lastpos[0]==pos[0]) && (lastpos[1]==pos[1]))
- return 0;
-
imapaint_convert_brushco(ibufb, pos, bpos);
/* lift from canvas */
- if(s.tool == PAINT_TOOL_SOFTEN) {
- imapaint_lift_soften(s.canvas, ibufb, bpos, torus);
+ if(s->tool == PAINT_TOOL_SOFTEN) {
+ imapaint_lift_soften(s->canvas, ibufb, bpos, torus);
}
- else if(s.tool == PAINT_TOOL_SMEAR) {
+ else if(s->tool == PAINT_TOOL_SMEAR) {
+ if (lastpos[0]==pos[0] && lastpos[1]==pos[1])
+ return 0;
+
imapaint_convert_brushco(ibufb, lastpos, blastpos);
- imapaint_lift_smear(s.canvas, ibufb, blastpos);
+ imapaint_lift_smear(s->canvas, ibufb, blastpos);
}
- else if(s.tool == PAINT_TOOL_CLONE && s.clonecanvas) {
- liftpos[0]= pos[0] - offset[0]*s.canvas->x;
- liftpos[1]= pos[1] - offset[1]*s.canvas->y;
+ else if(s->tool == PAINT_TOOL_CLONE && s->clonecanvas) {
+ liftpos[0]= pos[0] - offset[0]*s->canvas->x;
+ liftpos[1]= pos[1] - offset[1]*s->canvas->y;
imapaint_convert_brushco(ibufb, liftpos, bliftpos);
- clonebuf= imapaint_lift_clone(s.clonecanvas, ibufb, bliftpos);
+ clonebuf= imapaint_lift_clone(s->clonecanvas, ibufb, bliftpos);
}
+ imapaint_dirty_region(s->image, bpos[0], bpos[1], ibufb->x, ibufb->y);
+
/* blend into canvas */
if(torus)
- IMB_rectblend_torus(s.canvas, (clonebuf)? clonebuf: ibufb,
+ IMB_rectblend_torus(s->canvas, (clonebuf)? clonebuf: ibufb,
bpos[0], bpos[1], 0, 0, ibufb->x, ibufb->y, blend);
else
- IMB_rectblend(s.canvas, (clonebuf)? clonebuf: ibufb,
+ IMB_rectblend(s->canvas, (clonebuf)? clonebuf: ibufb,
bpos[0], bpos[1], 0, 0, ibufb->x, ibufb->y, blend);
-
+
if(clonebuf) IMB_freeImBuf(clonebuf);
return 1;
@@ -302,299 +454,230 @@ static void imapaint_compute_uvco(short *mval, float *uv)
areamouseco_to_ipoco(G.v2d, mval, &uv[0], &uv[1]);
}
-static void imapaint_compute_imageco(ImBuf *ibuf, short *mval, float *mousepos)
-{
- areamouseco_to_ipoco(G.v2d, mval, &mousepos[0], &mousepos[1]);
- mousepos[0] *= ibuf->x;
- mousepos[1] *= ibuf->y;
-}
+/* 3D TexturePaint */
-void imapaint_redraw_tool(void)
-{
- if(G.scene->toolsettings->imapaint.flag & IMAGEPAINT_DRAW_TOOL_DRAWING)
- force_draw(0);
-}
+int facesel_face_pick(Mesh *me, short *mval, unsigned int *index, short rect);
+void texpaint_pick_uv(Object *ob, Mesh *mesh, TFace *tf, short *xy, float *mousepos);
-static void imapaint_redraw(int final, int painted)
+static int texpaint_break_stroke(float *prevuv, float *fwuv, float *bkuv, float *uv)
{
- if(!final && !painted) {
- imapaint_redraw_tool();
- return;
- }
+ float d1[2], d2[2];
+ float mismatch = Vec2Lenf(fwuv, uv);
+ float len1 = Vec2Lenf(prevuv, fwuv);
+ float len2 = Vec2Lenf(bkuv, uv);
- if(final || painted) {
- if (final || G.sima->lock) {
- /* Make OpenGL aware of a changed texture */
- free_realtime_image(G.sima->image);
- force_draw_plus(SPACE_VIEW3D,0);
- }
- else
- force_draw(0);
- }
+ Vec2Subf(d1, fwuv, prevuv);
+ Vec2Subf(d2, uv, bkuv);
- if(final)
- allqueue(REDRAWHEADERS, 0);
+ return ((Inp2f(d1, d2) < 0.0f) || (mismatch > MAX2(len1, len2)*2));
}
-static int imapaint_canvas_init(Brush *brush, short tool, ImBuf **canvas, ImBuf **clonecanvas, short *freefloat)
-{
- Image *ima= G.sima->image;
+/* ImagePaint Common */
- /* verify that we can paint and create canvas */
- if(!ima || !ima->ibuf || !(ima->ibuf->rect || ima->ibuf->rect_float))
+static int imapaint_canvas_set(ImagePaintState *s, Image *ima)
+{
+ /* verify that we can paint and set canvas */
+ if(ima->packedfile) {
+ s->warnpackedfile = ima->id.name + 2;
+ return 0;
+ }
+ else if(!ima || !ima->ibuf || !(ima->ibuf->rect || ima->ibuf->rect_float))
return 0;
else if(ima->packedfile)
return 0;
- *canvas= ima->ibuf;
+ s->image= ima;
+ s->canvas= ima->ibuf;
- /* create clone canvas */
- if(clonecanvas && (tool == PAINT_TOOL_CLONE)) {
- ima= brush->clone.image;
+ /* set clone canvas */
+ if(s->tool == PAINT_TOOL_CLONE) {
+ ima= s->brush->clone.image;
if(!ima || !ima->ibuf || !(ima->ibuf->rect || ima->ibuf->rect_float))
return 0;
- *clonecanvas= ima->ibuf;
+ s->clonecanvas= ima->ibuf;
- if((*canvas)->rect_float && !(*clonecanvas)->rect_float) {
+ if(s->canvas->rect_float && !s->clonecanvas->rect_float) {
/* temporarily add float rect for cloning */
- *freefloat= 1;
- IMB_float_from_rect(*clonecanvas);
+ IMB_float_from_rect(s->clonecanvas);
+ s->clonefreefloat= 1;
}
- else if(!(*canvas)->rect_float && !(*clonecanvas)->rect) {
- *freefloat= 0;
- IMB_rect_from_float(*clonecanvas);
+ else if(!s->canvas->rect_float && !s->clonecanvas->rect)
+ IMB_rect_from_float(s->clonecanvas);
+ }
+
+ return 1;
+}
+
+static void imapaint_canvas_free(ImagePaintState *s)
+{
+ if (s->clonefreefloat)
+ imb_freerectfloatImBuf(s->clonecanvas);
+}
+
+static int imapaint_do_paint(ImagePaintState *s, BrushPainter *painter, Image *image, short texpaint, float *uv, double time, int update)
+{
+ float pos[2];
+
+ pos[0] = uv[0]*image->ibuf->x;
+ pos[1] = uv[1]*image->ibuf->y;
+
+ brush_painter_require_imbuf(painter, ((image->ibuf->rect_float)? 1: 0), 0, 0);
+
+ if (brush_painter_paint(painter, imapaint_paint_op, pos, time, s)) {
+ if (update)
+ imapaint_image_update(image, texpaint);
+ return 1;
+ }
+ else return 0;
+}
+
+static void imapaint_do(ImagePaintState *s, BrushPainter *painter, short texpaint, short *prevmval, short *mval, double time)
+{
+ TFace *newtface = NULL;
+ Image *newimage = NULL;
+ float fwuv[2], bkuv[2], newuv[2];
+ unsigned int face_index;
+ int breakstroke = 0, redraw = 0;
+
+ if (texpaint) {
+
+ /* pick face and image */
+ if (facesel_face_pick(s->me, mval, &face_index, 0)) {
+ newtface = s->me->tface + face_index;
+ newimage = (Image*)newtface->tpage;
+ texpaint_pick_uv(s->ob, s->me, newtface, mval, newuv);
}
else
- *freefloat= 0;
+ newuv[0] = newuv[1] = 0.0f;
+
+ /* see if stroke is broken, and if so finish painting in old position */
+ if (s->image) {
+ if (newimage == s->image) {
+ texpaint_pick_uv(s->ob, s->me, s->tface, mval, fwuv);
+ texpaint_pick_uv(s->ob, s->me, newtface, prevmval, bkuv);
+ breakstroke= texpaint_break_stroke(s->uv, fwuv, bkuv, newuv);
+ }
+ else
+ breakstroke= 1;
+ }
+
+ if (breakstroke) {
+ texpaint_pick_uv(s->ob, s->me, s->tface, mval, fwuv);
+ redraw |= imapaint_do_paint(s, painter, s->image, texpaint, fwuv, time, 1);
+ imapaint_clear_partial_redraw();
+ brush_painter_break_stroke(painter);
+ }
+
+ /* set new canvas */
+ if (newimage && (newimage != s->image))
+ if (!imapaint_canvas_set(s, newimage))
+ newimage = NULL;
+
+ /* paint in new image */
+ if (newimage) {
+ if (breakstroke)
+ redraw|= imapaint_do_paint(s, painter, newimage, texpaint, bkuv, time, 0);
+ redraw|= imapaint_do_paint(s, painter, newimage, texpaint, newuv, time, 1);
+ }
+
+ /* update state */
+ s->image = newimage;
+ s->tface = newtface;
+ s->uv[0] = newuv[0];
+ s->uv[1] = newuv[1];
+ }
+ else {
+ imapaint_compute_uvco(mval, newuv);
+ redraw |= imapaint_do_paint(s, painter, s->image, texpaint, newuv, time, 1);
}
- else if(clonecanvas)
- *clonecanvas= NULL;
- return 1;
+ if (redraw) {
+ imapaint_redraw(0, texpaint, NULL);
+ imapaint_clear_partial_redraw();
+ }
}
-void imagepaint_paint(short mousebutton)
+void imagepaint_paint(short mousebutton, short texpaint)
{
ImagePaintState s;
BrushPainter *painter;
ToolSettings *settings= G.scene->toolsettings;
- short prevmval[2], mval[2], freefloat=0;
- float mousepos[2];
- double mousetime;
+ short prevmval[2], mval[2];
+ double time;
/* initialize state */
+ memset(&s, 0, sizeof(s));
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;
- if(!imapaint_canvas_init(s.brush, s.tool, &s.canvas, &s.clonecanvas, &freefloat)) {
- if(G.sima->image && G.sima->image->packedfile)
- error("Painting in packed images not supported");
+ if(!s.brush)
return;
+
+ if(texpaint) {
+ s.ob = OBACT;
+ if (!s.ob || !(s.ob->lay & G.vd->lay)) return;
+ s.me = get_mesh(s.ob);
+ if (!s.me) return;
+
+ persp(PERSP_VIEW);
+ }
+ else {
+ s.image = G.sima->image;
+
+ if(!imapaint_canvas_set(&s, G.sima->image)) {
+ if(s.warnpackedfile)
+ error("Painting in packed images not supported");
+ return;
+ }
}
settings->imapaint.flag |= IMAGEPAINT_DRAWING;
+ free_imagepaint();
/* create painter and paint once */
painter= brush_painter_new(s.brush);
- brush_painter_require_imbuf(painter, ((s.canvas->rect_float)? 1: 0), 0, 0);
getmouseco_areawin(mval);
- mousetime= PIL_check_seconds_timer();
+ time= PIL_check_seconds_timer();
prevmval[0]= mval[0];
prevmval[1]= mval[1];
- imapaint_compute_imageco(s.canvas, mval, mousepos);
- if(brush_painter_paint(painter, imapaint_paint_op, mousepos, mousetime, &s)) {
- if (s.canvas->rect_float)
- imb_freerectImBuf(s.canvas); /* force recreate */
- imapaint_redraw(0, 1);
- }
+ imapaint_do(&s, painter, texpaint, prevmval, mval, time);
/* paint loop */
while(get_mbut() & mousebutton) {
getmouseco_areawin(mval);
- mousetime= PIL_check_seconds_timer();
+ time= PIL_check_seconds_timer();
if((mval[0] != prevmval[0]) || (mval[1] != prevmval[1])) {
+ imapaint_do(&s, painter, texpaint, prevmval, mval, time);
prevmval[0]= mval[0];
prevmval[1]= mval[1];
- imapaint_compute_imageco(s.canvas, mval, mousepos);
}
- else if (!(s.brush->flag & BRUSH_AIRBRUSH))
- continue;
-
- if(brush_painter_paint(painter, imapaint_paint_op, mousepos, mousetime, &s)) {
- if (s.canvas->rect_float)
- imb_freerectImBuf(s.canvas); /* force recreate */
- imapaint_redraw(0, 1);
- }
-
- /* todo: check if we can wait here to not take up all cpu usage? */
+ else if (s.brush->flag & BRUSH_AIRBRUSH)
+ imapaint_do(&s, painter, texpaint, prevmval, mval, time);
+ else
+ BIF_wait_for_statechange();
}
/* clean up */
settings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
- s.canvas->userflags |= IB_BITMAPDIRTY;
-
- if (freefloat) imb_freerectfloatImBuf(s.clonecanvas);
-
+ imapaint_canvas_free(&s);
brush_painter_free(painter);
- imapaint_redraw(1, 0);
-}
-
-/* 3D TexturePaint */
+ imapaint_redraw(1, texpaint, s.image);
-/* these will be moved */
-int facesel_face_pick(Mesh *me, short *mval, unsigned int *index, short rect);
-void texpaint_pick_uv(Object *ob, Mesh *mesh, TFace *tf, short *xy, float *mousepos);
-
-static void texpaint_compute_imageco(ImBuf *ibuf, Object *ob, Mesh *mesh, TFace *tf, short *xy, float *imageco)
-{
- texpaint_pick_uv(ob, mesh, tf, xy, imageco);
- imageco[0] *= ibuf->x;
- imageco[1] *= ibuf->y;
-}
+ if (texpaint) {
+ if (s.warnpackedfile)
+ error("Painting in packed images is not supported: %s", s.warnpackedfile);
-void texturepaint_paint(short mousebutton)
-{
- Object *ob;
- Mesh *me;
- TFace *face, *face_old = 0;
- short xy[2], xy_old[2];
- //int a, index;
- Image *img=NULL, *img_old = NULL;
- ImBuf *brush, *canvas = 0;
- unsigned int face_index;
- char *warn_packed_file = 0;
- float uv[2], uv_old[2];
- extern VPaint Gvp;
- Brush tmpbrush;
-
- ob = OBACT;
- if (!ob || !(ob->lay & G.vd->lay)) return;
- me = get_mesh(ob);
- if (!me) return;
-
- /* create a fake Brush for now - will be replaced soon */
- memset(&tmpbrush, 0, sizeof(Brush));
- tmpbrush.size= Gvp.size;
- tmpbrush.alpha= Gvp.a;
- tmpbrush.innerradius= 0.5f;
- IMAPAINT_FLOAT_RGB_COPY(tmpbrush.rgb, &Gvp.r);
- brush = brush_imbuf_new(&tmpbrush, 0, 0, tmpbrush.size);
-
- persp(PERSP_VIEW);
-
- getmouseco_areawin(xy_old);
- while (get_mbut() & mousebutton) {
- getmouseco_areawin(xy);
- /* Check if cursor has moved */
- if ((xy[0] != xy_old[0]) || (xy[1] != xy_old[1])) {
-
- /* Get face to draw on */
- if (!facesel_face_pick(me, xy, &face_index, 0)) face = NULL;
- else face = (((TFace*)me->tface)+face_index);
-
- /* Check if this is another face. */
- if (face != face_old) {
- /* The active face changed, check the texture */
- if (face) {
- img = face->tpage;
- canvas = (img)? img->ibuf: NULL;
- }
- else {
- img = 0;
- }
-
- if (img != img_old) {
- /* Faces have different textures. Finish drawing in the old face. */
- if (face_old && canvas) {
- texpaint_compute_imageco(canvas, ob, me, face_old, xy, uv);
- imapaint_blend_line(canvas, brush, uv_old, uv);
- img_old->ibuf->userflags |= IB_BITMAPDIRTY;
- canvas = 0;
- }
-
- /* Create new canvas and start drawing in the new face. */
- if (img) {
- if (canvas && img->packedfile == 0) {
- /* MAART: skipx is not set most of the times. Make a guess. */
- if (canvas) {
- texpaint_compute_imageco(canvas, ob, me, face, xy_old, uv_old);
- texpaint_compute_imageco(canvas, ob, me, face, xy, uv);
- imapaint_blend_line(canvas, brush, uv_old, uv);
- canvas->userflags |= IB_BITMAPDIRTY;
- }
- }
- else {
- if (img->packedfile) {
- warn_packed_file = img->id.name + 2;
- img = 0;
- }
- }
- }
- }
- else {
- /* Face changed and faces have the same texture. */
- if (canvas) {
- /* Finish drawing in the old face. */
- if (face_old) {
- texpaint_compute_imageco(canvas, ob, me, face_old, xy, uv);
- imapaint_blend_line(canvas, brush, uv_old, uv);
- img_old->ibuf->userflags |= IB_BITMAPDIRTY;
- }
-
- /* Start drawing in the new face. */
- if (face) {
- texpaint_compute_imageco(canvas, ob, me, face, xy_old, uv_old);
- texpaint_compute_imageco(canvas, ob, me, face, xy, uv);
- imapaint_blend_line(canvas, brush, uv_old, uv);
- canvas->userflags |= IB_BITMAPDIRTY;
- }
- }
- }
- }
- else {
- /* Same face, continue drawing */
- if (face && canvas) {
- /* Get the new (u,v) coordinates */
- texpaint_compute_imageco(canvas, ob, me, face, xy, uv);
- imapaint_blend_line(canvas, brush, uv_old, uv);
- canvas->userflags |= IB_BITMAPDIRTY;
- }
- }
-
- if (face && img) {
- /* Make OpenGL aware of a change in the texture */
- free_realtime_image(img);
- /* Redraw the view */
- scrarea_do_windraw(curarea);
- screen_swapbuffers();
- }
-
- xy_old[0] = xy[0];
- xy_old[1] = xy[1];
- uv_old[0] = uv[0];
- uv_old[1] = uv[1];
- face_old = face;
- img_old = img;
- }
+ persp(PERSP_WIN);
}
- IMB_freeImBuf(brush);
-
- if (warn_packed_file)
- error("Painting in packed images is not supported: %s", warn_packed_file);
-
- persp(PERSP_WIN);
-
- BIF_undo_push("UV face draw");
- allqueue(REDRAWVIEW3D, 0);
- allqueue(REDRAWIMAGE, 0);
- allqueue(REDRAWHEADERS, 0);
+ /* todo: BIF_undo_push("Image paint"); */
}
void imagepaint_pick(short mousebutton)