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:
-rw-r--r--source/blender/blenkernel/BKE_brush.h10
-rw-r--r--source/blender/blenkernel/BKE_paint.h2
-rw-r--r--source/blender/blenkernel/intern/brush.c44
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c47
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c561
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c667
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h26
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c6
8 files changed, 642 insertions, 721 deletions
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index cfae15961d7..95c39bad344 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -79,13 +79,13 @@ struct BrushPainter;
typedef struct BrushPainter BrushPainter;
typedef int (*BrushFunc)(void *user, struct ImBuf *ibuf, const float lastpos[2], const float pos[2]);
-BrushPainter *BKE_brush_painter_new(struct Scene *scene, struct Brush *brush);
-void BKE_brush_painter_require_imbuf(BrushPainter *painter, short flt,
+BrushPainter *brush_painter_2d_new(struct Scene *scene, struct Brush *brush);
+void brush_painter_2d_require_imbuf(BrushPainter *painter, short flt,
short texonly, int size);
-int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float pos[2],
+int brush_painter_2d_paint(BrushPainter *painter, BrushFunc func, const float pos[2],
double time, float pressure, void *user, int use_color_correction);
-void BKE_brush_painter_break_stroke(BrushPainter *painter);
-void BKE_brush_painter_free(BrushPainter *painter);
+void brush_painter_2d_break_stroke(BrushPainter *painter);
+void brush_painter_2d_free(BrushPainter *painter);
/* texture */
unsigned int *BKE_brush_gen_texture_cache(struct Brush *br, int half_side);
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 98184bfa65d..c46bc1dada6 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -54,7 +54,7 @@ extern const char PAINT_CURSOR_VERTEX_PAINT[3];
extern const char PAINT_CURSOR_WEIGHT_PAINT[3];
extern const char PAINT_CURSOR_TEXTURE_PAINT[3];
-typedef enum {
+typedef enum PaintMode{
PAINT_SCULPT,
PAINT_VERTEX,
PAINT_WEIGHT,
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index ba69fa4336e..798dde9f985 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -53,6 +53,7 @@
#include "IMB_imbuf_types.h"
#include "RE_render_ext.h" /* externtex */
+#include "RE_shader_ext.h"
static void brush_defaults(Brush *brush)
{
@@ -841,6 +842,49 @@ float BKE_brush_curve_strength(Brush *br, float p, const float len)
return curvemapping_evaluateF(br->curve, 0, p);
}
+/* TODO: should probably be unified with BrushPainter stuff? */
+unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side)
+{
+ unsigned int *texcache = NULL;
+ MTex *mtex = &br->mtex;
+ TexResult texres = {0};
+ int hasrgb, ix, iy;
+ int side = half_side * 2;
+
+ if (mtex->tex) {
+ float x, y, step = 2.0 / side, co[3];
+
+ texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache");
+
+ /*do normalized cannonical view coords for texture*/
+ for (y = -1.0, iy = 0; iy < side; iy++, y += step) {
+ for (x = -1.0, ix = 0; ix < side; ix++, x += step) {
+ co[0] = x;
+ co[1] = y;
+ co[2] = 0.0f;
+
+ /* This is copied from displace modifier code */
+ hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres, NULL);
+
+ /* if the texture gave an RGB value, we assume it didn't give a valid
+ * intensity, so calculate one (formula from do_material_tex).
+ * if the texture didn't give an RGB value, copy the intensity across
+ */
+ if (hasrgb & TEX_RGB)
+ texres.tin = rgb_to_grayscale(&texres.tr);
+
+ ((char *)texcache)[(iy * side + ix) * 4] =
+ ((char *)texcache)[(iy * side + ix) * 4 + 1] =
+ ((char *)texcache)[(iy * side + ix) * 4 + 2] =
+ ((char *)texcache)[(iy * side + ix) * 4 + 3] = (char)(texres.tin * 255.0f);
+ }
+ }
+ }
+
+ return texcache;
+}
+
+
/**** Radial Control ****/
struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br)
{
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 63a111c9165..87f08207d6c 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -140,9 +140,6 @@ BLI_INLINE unsigned char f_to_char(const float val)
#define IMAPAINT_TILE_SIZE (1 << IMAPAINT_TILE_BITS)
#define IMAPAINT_TILE_NUMBER(size) (((size) + IMAPAINT_TILE_SIZE - 1) >> IMAPAINT_TILE_BITS)
-static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint);
-
-
typedef struct ImagePaintState {
SpaceImage *sima;
View2D *v2d;
@@ -171,11 +168,6 @@ typedef struct ImagePaintState {
MTFace *dm_mtface;
} ImagePaintState;
-typedef struct ImagePaintPartialRedraw {
- int x1, y1, x2, y2; /* XXX, could use 'rcti' */
- int enabled;
-} ImagePaintPartialRedraw;
-
typedef struct ImagePaintRegion {
int destx, desty;
int srcx, srcy;
@@ -411,8 +403,19 @@ typedef struct UndoImageTile {
char gen_type;
} UndoImageTile;
+/* this is a static resource for non-globality,
+ * Maybe it should be exposed as part of the
+ * paint operation, but for now just give a public interface */
static ImagePaintPartialRedraw imapaintpartial = {0, 0, 0, 0, 0};
+ImagePaintPartialRedraw *get_imapaintpartial(void) {
+ return &imapaintpartial;
+}
+
+void set_imapaintpartial(struct ImagePaintPartialRedraw *ippr) {
+ imapaintpartial = *ippr;
+}
+
/* UNDO */
static void undo_copy_tile(UndoImageTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, int restore)
@@ -433,7 +436,7 @@ static void undo_copy_tile(UndoImageTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, int
tile->y * IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
}
-static void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile)
+void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile)
{
ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
UndoImageTile *tile;
@@ -4349,7 +4352,7 @@ static int project_paint_sub_stroke(ProjPaintState *ps, BrushPainter *painter, c
// we may want to use this later
// BKE_brush_painter_require_imbuf(painter, ((ibuf->rect_float) ? 1 : 0), 0, 0);
- if (BKE_brush_painter_paint(painter, project_paint_op, pos, time, pressure, ps, 0)) {
+ if (brush_painter_2d_paint(painter, project_paint_op, pos, time, pressure, ps, 0)) {
return 1;
}
else return 0;
@@ -4373,12 +4376,12 @@ static int project_paint_stroke(ProjPaintState *ps, BrushPainter *painter, const
/* Imagepaint Partial Redraw & Dirty Region */
-static void imapaint_clear_partial_redraw(void)
+void imapaint_clear_partial_redraw(void)
{
memset(&imapaintpartial, 0, sizeof(imapaintpartial));
}
-static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h)
+void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h)
{
ImBuf *tmpibuf = NULL;
int srcx = 0, srcy = 0, origx;
@@ -4417,7 +4420,7 @@ static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w,
IMB_freeImBuf(tmpibuf);
}
-static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint)
+void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint)
{
if (imapaintpartial.x1 != imapaintpartial.x2 &&
imapaintpartial.y1 != imapaintpartial.y2)
@@ -4717,7 +4720,7 @@ static int texpaint_break_stroke(float *prevuv, float *fwuv, float *bkuv, float
static int imapaint_canvas_set(ImagePaintState *s, Image *ima)
{
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL);
-
+
/* verify that we can paint and set canvas */
if (ima == NULL) {
return 0;
@@ -4740,7 +4743,7 @@ static int imapaint_canvas_set(ImagePaintState *s, Image *ima)
if (s->tool == PAINT_TOOL_CLONE) {
ima = s->brush->clone.image;
ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL);
-
+
if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) {
BKE_image_release_ibuf(ima, ibuf, NULL);
BKE_image_release_ibuf(s->image, s->canvas, NULL);
@@ -4780,12 +4783,12 @@ static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter,
pos[0] = uv[0] * ibuf->x;
pos[1] = uv[1] * ibuf->y;
- BKE_brush_painter_require_imbuf(painter, ((ibuf->rect_float) ? 1 : 0), 0, 0);
+ brush_painter_2d_require_imbuf(painter, ((ibuf->rect_float) ? 1 : 0), 0, 0);
/* OCIO_TODO: float buffers are now always linear, so always use color correction
* this should probably be changed when texture painting color space is supported
*/
- if (BKE_brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, is_data == FALSE)) {
+ if (brush_painter_2d_paint(painter, imapaint_paint_op, pos, time, pressure, s, is_data == FALSE)) {
if (update)
imapaint_image_update(s->sima, image, ibuf, texpaint);
BKE_image_release_ibuf(image, ibuf, NULL);
@@ -4844,7 +4847,7 @@ static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPaint
redraw |= imapaint_paint_sub_stroke(s, painter, s->image, texpaint,
fwuv, time, 1, pressure);
imapaint_clear_partial_redraw();
- BKE_brush_painter_break_stroke(painter);
+ brush_painter_2d_break_stroke(painter);
}
/* set new canvas */
@@ -5044,7 +5047,7 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps)
ps->do_mask_normal = FALSE; /* no need to do blending */
}
-static void paint_brush_init_tex(Brush *brush)
+void paint_brush_init_tex(Brush *brush)
{
/* init mtex nodes */
if (brush) {
@@ -5167,7 +5170,7 @@ static int texture_paint_init(bContext *C, wmOperator *op)
image_undo_restore, image_undo_free);
/* create painter */
- pop->painter = BKE_brush_painter_new(scene, pop->s.brush);
+ pop->painter = brush_painter_2d_new(scene, pop->s.brush);
{
UnifiedPaintSettings *ups = &settings->unified_paint_settings;
@@ -5214,7 +5217,7 @@ static void paint_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
pop->first = 0;
}
-static void paint_brush_exit_tex(Brush *brush)
+void paint_brush_exit_tex(Brush *brush)
{
if (brush) {
MTex *mtex = &brush->mtex;
@@ -5234,7 +5237,7 @@ static void paint_exit(bContext *C, wmOperator *op)
settings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
imapaint_canvas_free(&pop->s);
- BKE_brush_painter_free(pop->painter);
+ brush_painter_2d_free(pop->painter);
if (pop->mode == PAINT_MODE_3D_PROJECT) {
BKE_brush_size_set(scene, pop->ps.brush, pop->orig_brush_size);
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 84250853f38..194b36ac099 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -35,17 +35,84 @@
#include "DNA_brush_types.h"
#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_object_types.h"
+#include "BKE_context.h"
#include "BKE_brush.h"
+#include "BKE_main.h"
+#include "BKE_image.h"
+#include "BKE_paint.h"
+#include "BKE_report.h"
+
+#include "ED_screen.h"
#include "BLI_math.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "IMB_colormanagement.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_view2d.h"
#include "RE_shader_ext.h"
- /* Brush Painting for 2D image editor */
+#include "GPU_draw.h"
+
+#include "paint_intern.h"
+
+/* Brush Painting for 2D image editor */
+
+/* Defines and Structs */
+/* FTOCHAR as inline function */
+BLI_INLINE unsigned char f_to_char(const float val)
+{
+ return FTOCHAR(val);
+}
+#define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f) { \
+ (c)[0] = f_to_char((f)[0]); \
+ (c)[1] = f_to_char((f)[1]); \
+ (c)[2] = f_to_char((f)[2]); \
+} (void)0
+
+#define IMAPAINT_CHAR_RGB_TO_FLOAT(f, c) { \
+ (f)[0] = IMAPAINT_CHAR_TO_FLOAT((c)[0]); \
+ (f)[1] = IMAPAINT_CHAR_TO_FLOAT((c)[1]); \
+ (f)[2] = IMAPAINT_CHAR_TO_FLOAT((c)[2]); \
+} (void)0
+
+#define IMAPAINT_FLOAT_RGB_COPY(a, b) copy_v3_v3(a, b)
+
+typedef struct ImagePaintRegion {
+ int destx, desty;
+ int srcx, srcy;
+ int width, height;
+} ImagePaintRegion;
+
+typedef struct ImagePaintState {
+ BrushPainter *painter;
+ SpaceImage *sima;
+ View2D *v2d;
+ Scene *scene;
+ bScreen *screen;
+
+ Brush *brush;
+ short tool, blend;
+ Image *image;
+ ImBuf *canvas;
+ ImBuf *clonecanvas;
+ char *warnpackedfile;
+ char *warnmultifile;
+
+ /* viewport texture paint only, but _not_ project paint */
+ Object *ob;
+ int faceindex;
+ float uv[2];
+ int do_facesel;
+} ImagePaintState;
typedef struct BrushPainterCache {
short enabled;
@@ -88,7 +155,7 @@ struct BrushPainter {
BrushPainterCache cache;
};
-BrushPainter *BKE_brush_painter_new(Scene *scene, Brush *brush)
+BrushPainter *brush_painter_2d_new(Scene *scene, Brush *brush)
{
BrushPainter *painter = MEM_callocN(sizeof(BrushPainter), "BrushPainter");
@@ -119,7 +186,7 @@ static void brush_pressure_apply(BrushPainter *painter, Brush *brush, float pres
}
-void BKE_brush_painter_require_imbuf(BrushPainter *painter, short flt, short texonly, int size)
+void brush_painter_2d_require_imbuf(BrushPainter *painter, short flt, short texonly, int size)
{
if ((painter->cache.flt != flt) || (painter->cache.size != size) ||
((painter->cache.texonly != texonly) && texonly))
@@ -142,7 +209,7 @@ void BKE_brush_painter_require_imbuf(BrushPainter *painter, short flt, short tex
painter->cache.enabled = 1;
}
-void BKE_brush_painter_free(BrushPainter *painter)
+void brush_painter_2d_free(BrushPainter *painter)
{
Brush *brush = painter->brush;
@@ -157,7 +224,7 @@ void BKE_brush_painter_free(BrushPainter *painter)
MEM_freeN(painter);
}
-static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf,
+static void brush_painter_2d_do_partial(BrushPainter *painter, ImBuf *oldtexibuf,
int x, int y, int w, int h, int xt, int yt,
const float pos[2])
{
@@ -248,7 +315,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf,
}
}
-static void brush_painter_tiled_tex_partial_update(BrushPainter *painter, const float pos[2])
+static void brush_painter_2d_tiled_tex_partial_update(BrushPainter *painter, const float pos[2])
{
const Scene *scene = painter->scene;
Brush *brush = painter->brush;
@@ -286,23 +353,23 @@ static void brush_painter_tiled_tex_partial_update(BrushPainter *painter, const
/* blend existing texture in new position */
if ((x1 < x2) && (y1 < y2))
- brush_painter_do_partial(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy, pos);
+ brush_painter_2d_do_partial(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy, pos);
if (oldtexibuf)
IMB_freeImBuf(oldtexibuf);
/* sample texture in new areas */
if ((0 < x1) && (0 < ibuf->y))
- brush_painter_do_partial(painter, NULL, 0, 0, x1, ibuf->y, 0, 0, pos);
+ brush_painter_2d_do_partial(painter, NULL, 0, 0, x1, ibuf->y, 0, 0, pos);
if ((x2 < ibuf->x) && (0 < ibuf->y))
- brush_painter_do_partial(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0, pos);
+ brush_painter_2d_do_partial(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0, pos);
if ((x1 < x2) && (0 < y1))
- brush_painter_do_partial(painter, NULL, x1, 0, x2, y1, 0, 0, pos);
+ brush_painter_2d_do_partial(painter, NULL, x1, 0, x2, y1, 0, 0, pos);
if ((x1 < x2) && (y2 < ibuf->y))
- brush_painter_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos);
+ brush_painter_2d_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos);
}
-static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2], int use_color_correction)
+static void brush_painter_2d_refresh_cache(BrushPainter *painter, const float pos[2], int use_color_correction)
{
const Scene *scene = painter->scene;
Brush *brush = painter->brush;
@@ -332,7 +399,7 @@ static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2
if (do_tiled) {
BKE_brush_imbuf_new(scene, brush, flt, 3, size, &cache->maskibuf, use_color_correction);
- brush_painter_tiled_tex_partial_update(painter, pos);
+ brush_painter_2d_tiled_tex_partial_update(painter, pos);
}
else
BKE_brush_imbuf_new(scene, brush, flt, 2, size, &cache->ibuf, use_color_correction);
@@ -346,17 +413,17 @@ static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2
int dy = (int)painter->lastpaintpos[1] - (int)pos[1];
if ((dx != 0) || (dy != 0))
- brush_painter_tiled_tex_partial_update(painter, pos);
+ brush_painter_2d_tiled_tex_partial_update(painter, pos);
}
}
-void BKE_brush_painter_break_stroke(BrushPainter *painter)
+void brush_painter_2d_break_stroke(BrushPainter *painter)
{
painter->firsttouch = 1;
}
-int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float pos[2], double time, float pressure,
+int brush_painter_2d_paint(BrushPainter *painter, BrushFunc func, const float pos[2], double time, float pressure,
void *user, int use_color_correction)
{
Scene *scene = painter->scene;
@@ -376,7 +443,7 @@ int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float p
brush_pressure_apply(painter, brush, pressure);
if (painter->cache.enabled)
- brush_painter_refresh_cache(painter, pos, use_color_correction);
+ brush_painter_2d_refresh_cache(painter, pos, use_color_correction);
totpaintops += func(user, painter->cache.ibuf, pos, pos);
painter->lasttime = time;
@@ -449,7 +516,7 @@ int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float p
BKE_brush_jitter_pos(scene, brush, paintpos, finalpos);
if (painter->cache.enabled)
- brush_painter_refresh_cache(painter, finalpos, use_color_correction);
+ brush_painter_2d_refresh_cache(painter, finalpos, use_color_correction);
totpaintops +=
func(user, painter->cache.ibuf, painter->lastpaintpos, finalpos);
@@ -464,7 +531,7 @@ int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float p
BKE_brush_jitter_pos(scene, brush, pos, finalpos);
if (painter->cache.enabled)
- brush_painter_refresh_cache(painter, finalpos, use_color_correction);
+ brush_painter_2d_refresh_cache(painter, finalpos, use_color_correction);
totpaintops += func(user, painter->cache.ibuf, pos, finalpos);
@@ -492,7 +559,7 @@ int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float p
BKE_brush_jitter_pos(scene, brush, pos, finalpos);
if (painter->cache.enabled)
- brush_painter_refresh_cache(painter, finalpos, use_color_correction);
+ brush_painter_2d_refresh_cache(painter, finalpos, use_color_correction);
totpaintops +=
func(user, painter->cache.ibuf, painter->lastmousepos, finalpos);
@@ -515,46 +582,428 @@ int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float p
return totpaintops;
}
+/* Image Paint Operations */
-/* TODO: should probably be unified with BrushPainter stuff? */
-unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side)
+/* keep these functions in sync */
+static void paint_2d_ibuf_rgb_get(ImBuf *ibuf, int x, int y, const short is_torus, float r_rgb[3])
{
- unsigned int *texcache = NULL;
- MTex *mtex = &br->mtex;
- TexResult texres = {0};
- int hasrgb, ix, iy;
- int side = half_side * 2;
-
- if (mtex->tex) {
- float x, y, step = 2.0 / side, co[3];
-
- texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache");
-
- /*do normalized cannonical view coords for texture*/
- for (y = -1.0, iy = 0; iy < side; iy++, y += step) {
- for (x = -1.0, ix = 0; ix < side; ix++, x += step) {
- co[0] = x;
- co[1] = y;
- co[2] = 0.0f;
-
- /* This is copied from displace modifier code */
- hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres, NULL);
-
- /* if the texture gave an RGB value, we assume it didn't give a valid
- * intensity, so calculate one (formula from do_material_tex).
- * if the texture didn't give an RGB value, copy the intensity across
- */
- if (hasrgb & TEX_RGB)
- texres.tin = rgb_to_grayscale(&texres.tr);
-
- ((char *)texcache)[(iy * side + ix) * 4] =
- ((char *)texcache)[(iy * side + ix) * 4 + 1] =
- ((char *)texcache)[(iy * side + ix) * 4 + 2] =
- ((char *)texcache)[(iy * side + ix) * 4 + 3] = (char)(texres.tin * 255.0f);
- }
+ if (is_torus) {
+ x %= ibuf->x;
+ if (x < 0) x += ibuf->x;
+ y %= ibuf->y;
+ if (y < 0) y += ibuf->y;
+ }
+
+ if (ibuf->rect_float) {
+ float *rrgbf = ibuf->rect_float + (ibuf->x * y + x) * 4;
+ IMAPAINT_FLOAT_RGB_COPY(r_rgb, rrgbf);
+ }
+ else {
+ char *rrgb = (char *)ibuf->rect + (ibuf->x * y + x) * 4;
+ IMAPAINT_CHAR_RGB_TO_FLOAT(r_rgb, rrgb);
+ }
+}
+static void paint_2d_ibuf_rgb_set(ImBuf *ibuf, int x, int y, const short is_torus, const float rgb[3])
+{
+ if (is_torus) {
+ x %= ibuf->x;
+ if (x < 0) x += ibuf->x;
+ y %= ibuf->y;
+ if (y < 0) y += ibuf->y;
+ }
+
+ if (ibuf->rect_float) {
+ float *rrgbf = ibuf->rect_float + (ibuf->x * y + x) * 4;
+ IMAPAINT_FLOAT_RGB_COPY(rrgbf, rgb);
+ }
+ else {
+ char *rrgb = (char *)ibuf->rect + (ibuf->x * y + x) * 4;
+ IMAPAINT_FLOAT_RGB_TO_CHAR(rrgb, rgb);
+ }
+}
+
+static int paint_2d_ibuf_add_if(ImBuf *ibuf, unsigned int x, unsigned int y, float *outrgb, short torus)
+{
+ float inrgb[3];
+
+ // XXX: signed unsigned mismatch
+ if ((x >= (unsigned int)(ibuf->x)) || (y >= (unsigned int)(ibuf->y))) {
+ if (torus) paint_2d_ibuf_rgb_get(ibuf, x, y, 1, inrgb);
+ else return 0;
+ }
+ else {
+ paint_2d_ibuf_rgb_get(ibuf, x, y, 0, inrgb);
+ }
+
+ outrgb[0] += inrgb[0];
+ outrgb[1] += inrgb[1];
+ outrgb[2] += inrgb[2];
+
+ return 1;
+}
+
+static void paint_2d_lift_soften(ImBuf *ibuf, ImBuf *ibufb, int *pos, const short is_torus)
+{
+ int x, y, count, xi, yi, xo, yo;
+ int out_off[2], in_off[2], dim[2];
+ float outrgb[3];
+
+ dim[0] = ibufb->x;
+ dim[1] = ibufb->y;
+ in_off[0] = pos[0];
+ in_off[1] = pos[1];
+ out_off[0] = out_off[1] = 0;
+
+ if (!is_torus) {
+ IMB_rectclip(ibuf, ibufb, &in_off[0], &in_off[1], &out_off[0],
+ &out_off[1], &dim[0], &dim[1]);
+
+ if ((dim[0] == 0) || (dim[1] == 0))
+ return;
+ }
+
+ for (y = 0; y < dim[1]; y++) {
+ for (x = 0; x < dim[0]; x++) {
+ /* get input pixel */
+ xi = in_off[0] + x;
+ yi = in_off[1] + y;
+
+ count = 1;
+ paint_2d_ibuf_rgb_get(ibuf, xi, yi, is_torus, outrgb);
+
+ count += paint_2d_ibuf_add_if(ibuf, xi - 1, yi - 1, outrgb, is_torus);
+ count += paint_2d_ibuf_add_if(ibuf, xi - 1, yi, outrgb, is_torus);
+ count += paint_2d_ibuf_add_if(ibuf, xi - 1, yi + 1, outrgb, is_torus);
+
+ count += paint_2d_ibuf_add_if(ibuf, xi, yi - 1, outrgb, is_torus);
+ count += paint_2d_ibuf_add_if(ibuf, xi, yi + 1, outrgb, is_torus);
+
+ count += paint_2d_ibuf_add_if(ibuf, xi + 1, yi - 1, outrgb, is_torus);
+ count += paint_2d_ibuf_add_if(ibuf, xi + 1, yi, outrgb, is_torus);
+ count += paint_2d_ibuf_add_if(ibuf, xi + 1, yi + 1, outrgb, is_torus);
+
+ mul_v3_fl(outrgb, 1.0f / (float)count);
+
+ /* write into brush buffer */
+ xo = out_off[0] + x;
+ yo = out_off[1] + y;
+ paint_2d_ibuf_rgb_set(ibufb, xo, yo, 0, outrgb);
+ }
+ }
+}
+
+static void paint_2d_set_region(ImagePaintRegion *region, int destx, int desty, int srcx, int srcy, int width, int height)
+{
+ region->destx = destx;
+ region->desty = desty;
+ region->srcx = srcx;
+ region->srcy = srcy;
+ region->width = width;
+ region->height = height;
+}
+
+static int paint_2d_torus_split_region(ImagePaintRegion region[4], ImBuf *dbuf, ImBuf *sbuf)
+{
+ int destx = region->destx;
+ int desty = region->desty;
+ int srcx = region->srcx;
+ int srcy = region->srcy;
+ int width = region->width;
+ int height = region->height;
+ int origw, origh, w, h, tot = 0;
+
+ /* convert destination and source coordinates to be within image */
+ destx = destx % dbuf->x;
+ if (destx < 0) destx += dbuf->x;
+ desty = desty % dbuf->y;
+ if (desty < 0) desty += dbuf->y;
+ srcx = srcx % sbuf->x;
+ if (srcx < 0) srcx += sbuf->x;
+ srcy = srcy % sbuf->y;
+ if (srcy < 0) srcy += sbuf->y;
+
+ /* clip width of blending area to destination imbuf, to avoid writing the
+ * same pixel twice */
+ origw = w = (width > dbuf->x) ? dbuf->x : width;
+ origh = h = (height > dbuf->y) ? dbuf->y : height;
+
+ /* clip within image */
+ IMB_rectclip(dbuf, sbuf, &destx, &desty, &srcx, &srcy, &w, &h);
+ paint_2d_set_region(&region[tot++], destx, desty, srcx, srcy, w, h);
+
+ /* do 3 other rects if needed */
+ if (w < origw)
+ paint_2d_set_region(&region[tot++], (destx + w) % dbuf->x, desty, (srcx + w) % sbuf->x, srcy, origw - w, h);
+ if (h < origh)
+ paint_2d_set_region(&region[tot++], destx, (desty + h) % dbuf->y, srcx, (srcy + h) % sbuf->y, w, origh - h);
+ if ((w < origw) && (h < origh))
+ paint_2d_set_region(&region[tot++], (destx + w) % dbuf->x, (desty + h) % dbuf->y, (srcx + w) % sbuf->x, (srcy + h) % sbuf->y, origw - w, origh - h);
+
+ return tot;
+}
+
+static void paint_2d_lift_smear(ImBuf *ibuf, ImBuf *ibufb, int *pos)
+{
+ ImagePaintRegion region[4];
+ int a, tot;
+
+ paint_2d_set_region(region, 0, 0, pos[0], pos[1], ibufb->x, ibufb->y);
+ tot = paint_2d_torus_split_region(region, ibufb, ibuf);
+
+ for (a = 0; a < tot; a++)
+ IMB_rectblend(ibufb, ibuf, region[a].destx, region[a].desty,
+ region[a].srcx, region[a].srcy,
+ region[a].width, region[a].height, IMB_BLEND_COPY_RGB);
+}
+
+static ImBuf *paint_2d_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos)
+{
+ /* note: allocImbuf returns zero'd memory, so regions outside image will
+ * have zero alpha, and hence not be blended onto the image */
+ int w = ibufb->x, h = ibufb->y, destx = 0, desty = 0, srcx = pos[0], srcy = pos[1];
+ ImBuf *clonebuf = IMB_allocImBuf(w, h, ibufb->planes, ibufb->flags);
+
+ IMB_rectclip(clonebuf, ibuf, &destx, &desty, &srcx, &srcy, &w, &h);
+ IMB_rectblend(clonebuf, ibuf, destx, desty, srcx, srcy, w, h,
+ IMB_BLEND_COPY_RGB);
+ IMB_rectblend(clonebuf, ibufb, destx, desty, destx, desty, w, h,
+ IMB_BLEND_COPY_ALPHA);
+
+ return clonebuf;
+}
+
+static void paint_2d_convert_brushco(ImBuf *ibufb, const float pos[2], int ipos[2])
+{
+ ipos[0] = (int)floorf((pos[0] - ibufb->x / 2) + 1.0f);
+ ipos[1] = (int)floorf((pos[1] - ibufb->y / 2) + 1.0f);
+}
+
+static int paint_2d_op(void *state, ImBuf *ibufb, const float lastpos[2], const float pos[2])
+{
+ ImagePaintState *s = ((ImagePaintState *)state);
+ ImBuf *clonebuf = NULL, *frombuf;
+ ImagePaintRegion region[4];
+ short torus = s->brush->flag & BRUSH_TORUS;
+ short blend = s->blend;
+ float *offset = s->brush->clone.offset;
+ float liftpos[2];
+ int bpos[2], blastpos[2], bliftpos[2];
+ int a, tot;
+
+ paint_2d_convert_brushco(ibufb, pos, bpos);
+
+ /* lift from canvas */
+ if (s->tool == PAINT_TOOL_SOFTEN) {
+ paint_2d_lift_soften(s->canvas, ibufb, bpos, torus);
+ }
+ else if (s->tool == PAINT_TOOL_SMEAR) {
+ if (lastpos[0] == pos[0] && lastpos[1] == pos[1])
+ return 0;
+
+ paint_2d_convert_brushco(ibufb, lastpos, blastpos);
+ paint_2d_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;
+
+ paint_2d_convert_brushco(ibufb, liftpos, bliftpos);
+ clonebuf = paint_2d_lift_clone(s->clonecanvas, ibufb, bliftpos);
+ }
+
+ frombuf = (clonebuf) ? clonebuf : ibufb;
+
+ if (torus) {
+ paint_2d_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y);
+ tot = paint_2d_torus_split_region(region, s->canvas, frombuf);
+ }
+ else {
+ paint_2d_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y);
+ tot = 1;
+ }
+
+ /* blend into canvas */
+ for (a = 0; a < tot; a++) {
+ imapaint_dirty_region(s->image, s->canvas,
+ region[a].destx, region[a].desty,
+ region[a].width, region[a].height);
+
+ IMB_rectblend(s->canvas, frombuf,
+ region[a].destx, region[a].desty,
+ region[a].srcx, region[a].srcy,
+ region[a].width, region[a].height, blend);
+ }
+
+ if (clonebuf) IMB_freeImBuf(clonebuf);
+
+ return 1;
+}
+
+
+static int paint_2d_canvas_set(ImagePaintState *s, Image *ima)
+{
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL);
+
+ /* verify that we can paint and set canvas */
+ if (ima == NULL) {
+ return 0;
+ }
+ else if (ima->packedfile && ima->rr) {
+ s->warnpackedfile = ima->id.name + 2;
+ return 0;
+ }
+ else if (ibuf && ibuf->channels != 4) {
+ s->warnmultifile = ima->id.name + 2;
+ return 0;
+ }
+ else if (!ibuf || !(ibuf->rect || ibuf->rect_float))
+ return 0;
+
+ s->image = ima;
+ s->canvas = ibuf;
+
+ /* set clone canvas */
+ if (s->tool == PAINT_TOOL_CLONE) {
+ ima = s->brush->clone.image;
+ ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL);
+
+ if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_release_ibuf(s->image, s->canvas, NULL);
+ return 0;
}
+
+ s->clonecanvas = ibuf;
+
+ /* temporarily add float rect for cloning */
+ if (s->canvas->rect_float && !s->clonecanvas->rect_float) {
+ IMB_float_from_rect(s->clonecanvas);
+ }
+ else if (!s->canvas->rect_float && !s->clonecanvas->rect)
+ IMB_rect_from_float(s->clonecanvas);
+ }
+
+ return 1;
+}
+
+static void paint_2d_canvas_free(ImagePaintState *s)
+{
+ BKE_image_release_ibuf(s->image, s->canvas, NULL);
+ BKE_image_release_ibuf(s->brush->clone.image, s->clonecanvas, NULL);
+}
+
+static int paint_2d_sub_stroke(ImagePaintState *s, BrushPainter *painter, Image *image, float *uv, int update, float pressure)
+{
+ ImBuf *ibuf = BKE_image_acquire_ibuf(image, s->sima ? &s->sima->iuser : NULL, NULL);
+ float pos[2];
+ int is_data;
+
+ if (!ibuf)
+ return 0;
+
+ is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA;
+
+ pos[0] = uv[0] * ibuf->x;
+ pos[1] = uv[1] * ibuf->y;
+
+ brush_painter_2d_require_imbuf(painter, ((ibuf->rect_float) ? 1 : 0), 0, 0);
+
+ /* OCIO_TODO: float buffers are now always linear, so always use color correction
+ * this should probably be changed when texture painting color space is supported
+ */
+ if (brush_painter_2d_paint(painter, paint_2d_op, pos, 0, pressure, s, is_data == FALSE)) {
+ if (update)
+ imapaint_image_update(s->sima, image, ibuf, false);
+ BKE_image_release_ibuf(image, ibuf, NULL);
+ return 1;
}
+ else {
+ BKE_image_release_ibuf(image, ibuf, NULL);
+ return 0;
+ }
+}
+
+int paint_2d_stroke(void *ps, const int mval[2], float pressure, int eraser)
+{
+ float newuv[2];
+ int redraw = 0;
+ ImagePaintState *s = ps;
+ BrushPainter *painter = s->painter;
- return texcache;
+ s->blend = s->brush->blend;
+ if (eraser)
+ s->blend = IMB_BLEND_ERASE_ALPHA;
+
+ UI_view2d_region_to_view(s->v2d, mval[0], mval[1], &newuv[0], &newuv[1]);
+ redraw |= paint_2d_sub_stroke(s, painter, s->image, newuv,
+ 1, pressure);
+
+ if (redraw)
+ imapaint_clear_partial_redraw();
+
+ return redraw;
}
+void *paint_2d_new_stroke(bContext *C, wmOperator *op) {
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *settings = scene->toolsettings;
+ Brush *brush = paint_brush(&settings->imapaint.paint);
+
+ ImagePaintState *s = MEM_callocN(sizeof(ImagePaintState), "ImagePaintState");
+
+ s->sima = CTX_wm_space_image(C);
+ s->v2d = &CTX_wm_region(C)->v2d;
+ s->scene = scene;
+ s->screen = CTX_wm_screen(C);
+
+ s->brush = brush;
+ s->tool = brush->imagepaint_tool;
+ s->blend = brush->blend;
+
+ s->image = s->sima->image;
+
+ if (!paint_2d_canvas_set(s, s->image)) {
+ if (s->warnmultifile)
+ BKE_report(op->reports, RPT_WARNING, "Image requires 4 color channels to paint");
+ if (s->warnpackedfile)
+ BKE_report(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted");
+
+ MEM_freeN(s);
+ return NULL;
+ }
+
+ paint_brush_init_tex(s->brush);
+
+ /* create painter */
+ s->painter = brush_painter_2d_new(scene, s->brush);
+
+ return s;
+}
+
+void paint_2d_redraw (const bContext *C, void *ps, int final) {
+ ImagePaintState *s = ps;
+
+ if (final) {
+ if (s->image && !(s->sima && s->sima->lock))
+ GPU_free_image(s->image);
+
+ /* compositor listener deals with updating */
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, s->image);
+ }
+ else {
+ if (!s->sima || !s->sima->lock)
+ ED_region_tag_redraw(CTX_wm_region(C));
+ else
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, s->image);
+ }
+}
+
+void paint_2d_stroke_done(void *ps) {
+ ImagePaintState *s = ps;
+
+ paint_2d_canvas_free(s);
+ brush_painter_2d_free(s->painter);
+ paint_brush_exit_tex(s->brush);
+
+ MEM_freeN(s);
+}
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 69383d78614..e594bf25d0c 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -108,25 +108,13 @@ BLI_INLINE unsigned char f_to_char(const float val)
return FTOCHAR(val);
}
-
-#define IMAPAINT_CHAR_TO_FLOAT(c) ((c) / 255.0f)
-
-#define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f) { \
- (c)[0] = f_to_char((f)[0]); \
- (c)[1] = f_to_char((f)[1]); \
- (c)[2] = f_to_char((f)[2]); \
-} (void)0
#define IMAPAINT_FLOAT_RGBA_TO_CHAR(c, f) { \
(c)[0] = f_to_char((f)[0]); \
(c)[1] = f_to_char((f)[1]); \
(c)[2] = f_to_char((f)[2]); \
(c)[3] = f_to_char((f)[3]); \
} (void)0
-#define IMAPAINT_CHAR_RGB_TO_FLOAT(f, c) { \
- (f)[0] = IMAPAINT_CHAR_TO_FLOAT((c)[0]); \
- (f)[1] = IMAPAINT_CHAR_TO_FLOAT((c)[1]); \
- (f)[2] = IMAPAINT_CHAR_TO_FLOAT((c)[2]); \
-} (void)0
+
#define IMAPAINT_CHAR_RGBA_TO_FLOAT(f, c) { \
(f)[0] = IMAPAINT_CHAR_TO_FLOAT((c)[0]); \
(f)[1] = IMAPAINT_CHAR_TO_FLOAT((c)[1]); \
@@ -134,53 +122,11 @@ BLI_INLINE unsigned char f_to_char(const float val)
(f)[3] = IMAPAINT_CHAR_TO_FLOAT((c)[3]); \
} (void)0
-#define IMAPAINT_FLOAT_RGB_COPY(a, b) copy_v3_v3(a, b)
-
-#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)
-
-static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint);
-
-
-typedef struct ImagePaintState {
- SpaceImage *sima;
- View2D *v2d;
- Scene *scene;
- bScreen *screen;
-
- Brush *brush;
- short tool, blend;
- Image *image;
- ImBuf *canvas;
- ImBuf *clonecanvas;
- char *warnpackedfile;
- char *warnmultifile;
-
- /* viewport texture paint only, but _not_ project paint */
- Object *ob;
- int faceindex;
- float uv[2];
- int do_facesel;
-
- DerivedMesh *dm;
- int dm_totface;
- int dm_release;
-
- MFace *dm_mface;
- MTFace *dm_mtface;
-} ImagePaintState;
-
-typedef struct ImagePaintPartialRedraw {
- int x1, y1, x2, y2; /* XXX, could use 'rcti' */
- int enabled;
-} ImagePaintPartialRedraw;
-
-typedef struct ImagePaintRegion {
- int destx, desty;
- int srcx, srcy;
- int width, height;
-} ImagePaintRegion;
+#define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f) { \
+ (c)[0] = f_to_char((f)[0]); \
+ (c)[1] = f_to_char((f)[1]); \
+ (c)[2] = f_to_char((f)[2]); \
+} (void)0
/* ProjectionPaint defines */
@@ -411,8 +357,6 @@ typedef struct UndoImageTile {
char gen_type;
} UndoImageTile;
-static ImagePaintPartialRedraw imapaintpartial = {0, 0, 0, 0, 0};
-
/* UNDO */
static void undo_copy_tile(UndoImageTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, int restore)
@@ -433,45 +377,6 @@ static void undo_copy_tile(UndoImageTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, int
tile->y * IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
}
-static void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile)
-{
- ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
- UndoImageTile *tile;
- int allocsize;
- short use_float = ibuf->rect_float ? 1 : 0;
-
- for (tile = lb->first; tile; tile = tile->next)
- if (tile->x == x_tile && tile->y == y_tile && ima->gen_type == tile->gen_type && ima->source == tile->source)
- if (tile->use_float == use_float)
- if (strcmp(tile->idname, ima->id.name) == 0 && strcmp(tile->ibufname, ibuf->name) == 0)
- return tile->rect.pt;
-
- if (*tmpibuf == NULL)
- *tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat | IB_rect);
-
- tile = MEM_callocN(sizeof(UndoImageTile), "UndoImageTile");
- BLI_strncpy(tile->idname, ima->id.name, sizeof(tile->idname));
- tile->x = x_tile;
- tile->y = y_tile;
-
- allocsize = IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE * 4;
- allocsize *= (ibuf->rect_float) ? sizeof(float) : sizeof(char);
- tile->rect.pt = MEM_mapallocN(allocsize, "UndeImageTile.rect");
-
- BLI_strncpy(tile->ibufname, ibuf->name, sizeof(tile->ibufname));
-
- tile->gen_type = ima->gen_type;
- tile->source = ima->source;
- tile->use_float = use_float;
-
- undo_copy_tile(tile, *tmpibuf, ibuf, 0);
- undo_paint_push_count_alloc(UNDO_PAINT_IMAGE, allocsize);
-
- BLI_addtail(lb, tile);
-
- return tile->rect.pt;
-}
-
static void image_undo_restore(bContext *C, ListBase *lb)
{
Main *bmain = CTX_data_main(C);
@@ -3637,7 +3542,7 @@ static int project_image_refresh_tagged(ProjPaintState *ps)
for (i = 0; i < PROJ_BOUNDBOX_SQUARED; i++) {
pr = &(projIma->partRedrawRect[i]);
if (pr->x2 != -1) { /* TODO - use 'enabled' ? */
- imapaintpartial = *pr;
+ set_imapaintpartial(pr);
imapaint_image_update(NULL, projIma->ima, projIma->ibuf, true);
redraw = 1;
}
@@ -4319,7 +4224,7 @@ static int project_paint_op(void *state, const float lastpos[2], const float pos
}
-static int project_paint_stroke(ProjPaintState *ps, const int prevmval_i[2], const int mval_i[2], float UNUSED(pressure))
+static int project_paint_stroke(ProjPaintState *ps, const int prevmval_i[2], const int mval_i[2])
{
int a, redraw;
float pos[2], prev_pos[2];
@@ -4343,428 +4248,6 @@ static int project_paint_stroke(ProjPaintState *ps, const int prevmval_i[2], con
/* Imagepaint Partial Redraw & Dirty Region */
-static void imapaint_clear_partial_redraw(void)
-{
- memset(&imapaintpartial, 0, sizeof(imapaintpartial));
-}
-
-static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h)
-{
- ImBuf *tmpibuf = NULL;
- int srcx = 0, srcy = 0, origx;
-
- IMB_rectclip(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 = min_ii(imapaintpartial.x1, x);
- imapaintpartial.y1 = min_ii(imapaintpartial.y1, y);
- imapaintpartial.x2 = max_ii(imapaintpartial.x2, x + w);
- imapaintpartial.y2 = max_ii(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++)
- image_undo_push_tile(ima, ibuf, &tmpibuf, x, y);
-
- ibuf->userflags |= IB_BITMAPDIRTY;
-
- if (tmpibuf)
- IMB_freeImBuf(tmpibuf);
-}
-
-static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint)
-{
- if (imapaintpartial.x1 != imapaintpartial.x2 &&
- imapaintpartial.y1 != imapaintpartial.y2)
- {
- IMB_partial_display_buffer_update_delayed(ibuf, imapaintpartial.x1, imapaintpartial.y1,
- imapaintpartial.x2, imapaintpartial.y2);
- }
-
- if (ibuf->mipmap[0])
- ibuf->userflags |= IB_MIPMAP_INVALID;
-
- /* todo: should set_tpage create ->rect? */
- if (texpaint || (sima && sima->lock)) {
- int w = imapaintpartial.x2 - imapaintpartial.x1;
- int h = imapaintpartial.y2 - imapaintpartial.y1;
- /* Testing with partial update in uv editor too */
- GPU_paint_update_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h); //!texpaint);
- }
-}
-
-/* Image Paint Operations */
-
-/* keep these functions in sync */
-static void imapaint_ibuf_rgb_get(ImBuf *ibuf, int x, int y, const short is_torus, float r_rgb[3])
-{
- if (is_torus) {
- x %= ibuf->x;
- if (x < 0) x += ibuf->x;
- y %= ibuf->y;
- if (y < 0) y += ibuf->y;
- }
-
- if (ibuf->rect_float) {
- float *rrgbf = ibuf->rect_float + (ibuf->x * y + x) * 4;
- IMAPAINT_FLOAT_RGB_COPY(r_rgb, rrgbf);
- }
- else {
- char *rrgb = (char *)ibuf->rect + (ibuf->x * y + x) * 4;
- IMAPAINT_CHAR_RGB_TO_FLOAT(r_rgb, rrgb);
- }
-}
-static void imapaint_ibuf_rgb_set(ImBuf *ibuf, int x, int y, const short is_torus, const float rgb[3])
-{
- if (is_torus) {
- x %= ibuf->x;
- if (x < 0) x += ibuf->x;
- y %= ibuf->y;
- if (y < 0) y += ibuf->y;
- }
-
- if (ibuf->rect_float) {
- float *rrgbf = ibuf->rect_float + (ibuf->x * y + x) * 4;
- IMAPAINT_FLOAT_RGB_COPY(rrgbf, rgb);
- }
- else {
- char *rrgb = (char *)ibuf->rect + (ibuf->x * y + x) * 4;
- IMAPAINT_FLOAT_RGB_TO_CHAR(rrgb, rgb);
- }
-}
-
-static int imapaint_ibuf_add_if(ImBuf *ibuf, unsigned int x, unsigned int y, float *outrgb, short torus)
-{
- float inrgb[3];
-
- // XXX: signed unsigned mismatch
- if ((x >= (unsigned int)(ibuf->x)) || (y >= (unsigned int)(ibuf->y))) {
- if (torus) imapaint_ibuf_rgb_get(ibuf, x, y, 1, inrgb);
- else return 0;
- }
- else {
- imapaint_ibuf_rgb_get(ibuf, x, y, 0, inrgb);
- }
-
- outrgb[0] += inrgb[0];
- outrgb[1] += inrgb[1];
- outrgb[2] += inrgb[2];
-
- return 1;
-}
-
-static void imapaint_lift_soften(ImBuf *ibuf, ImBuf *ibufb, int *pos, const short is_torus)
-{
- int x, y, count, xi, yi, xo, yo;
- int out_off[2], in_off[2], dim[2];
- float outrgb[3];
-
- dim[0] = ibufb->x;
- dim[1] = ibufb->y;
- in_off[0] = pos[0];
- in_off[1] = pos[1];
- out_off[0] = out_off[1] = 0;
-
- if (!is_torus) {
- IMB_rectclip(ibuf, ibufb, &in_off[0], &in_off[1], &out_off[0],
- &out_off[1], &dim[0], &dim[1]);
-
- if ((dim[0] == 0) || (dim[1] == 0))
- return;
- }
-
- for (y = 0; y < dim[1]; y++) {
- for (x = 0; x < dim[0]; x++) {
- /* get input pixel */
- xi = in_off[0] + x;
- yi = in_off[1] + y;
-
- count = 1;
- imapaint_ibuf_rgb_get(ibuf, xi, yi, is_torus, outrgb);
-
- count += imapaint_ibuf_add_if(ibuf, xi - 1, yi - 1, outrgb, is_torus);
- count += imapaint_ibuf_add_if(ibuf, xi - 1, yi, outrgb, is_torus);
- count += imapaint_ibuf_add_if(ibuf, xi - 1, yi + 1, outrgb, is_torus);
-
- count += imapaint_ibuf_add_if(ibuf, xi, yi - 1, outrgb, is_torus);
- count += imapaint_ibuf_add_if(ibuf, xi, yi + 1, outrgb, is_torus);
-
- count += imapaint_ibuf_add_if(ibuf, xi + 1, yi - 1, outrgb, is_torus);
- count += imapaint_ibuf_add_if(ibuf, xi + 1, yi, outrgb, is_torus);
- count += imapaint_ibuf_add_if(ibuf, xi + 1, yi + 1, outrgb, is_torus);
-
- mul_v3_fl(outrgb, 1.0f / (float)count);
-
- /* write into brush buffer */
- xo = out_off[0] + x;
- yo = out_off[1] + y;
- imapaint_ibuf_rgb_set(ibufb, xo, yo, 0, outrgb);
- }
- }
-}
-
-static void imapaint_set_region(ImagePaintRegion *region, int destx, int desty, int srcx, int srcy, int width, int height)
-{
- region->destx = destx;
- region->desty = desty;
- region->srcx = srcx;
- region->srcy = srcy;
- region->width = width;
- region->height = height;
-}
-
-static int imapaint_torus_split_region(ImagePaintRegion region[4], ImBuf *dbuf, ImBuf *sbuf)
-{
- int destx = region->destx;
- int desty = region->desty;
- int srcx = region->srcx;
- int srcy = region->srcy;
- int width = region->width;
- int height = region->height;
- int origw, origh, w, h, tot = 0;
-
- /* convert destination and source coordinates to be within image */
- destx = destx % dbuf->x;
- if (destx < 0) destx += dbuf->x;
- desty = desty % dbuf->y;
- if (desty < 0) desty += dbuf->y;
- srcx = srcx % sbuf->x;
- if (srcx < 0) srcx += sbuf->x;
- srcy = srcy % sbuf->y;
- if (srcy < 0) srcy += sbuf->y;
-
- /* clip width of blending area to destination imbuf, to avoid writing the
- * same pixel twice */
- origw = w = (width > dbuf->x) ? dbuf->x : width;
- origh = h = (height > dbuf->y) ? dbuf->y : height;
-
- /* clip within image */
- IMB_rectclip(dbuf, sbuf, &destx, &desty, &srcx, &srcy, &w, &h);
- imapaint_set_region(&region[tot++], destx, desty, srcx, srcy, w, h);
-
- /* do 3 other rects if needed */
- if (w < origw)
- imapaint_set_region(&region[tot++], (destx + w) % dbuf->x, desty, (srcx + w) % sbuf->x, srcy, origw - w, h);
- if (h < origh)
- imapaint_set_region(&region[tot++], destx, (desty + h) % dbuf->y, srcx, (srcy + h) % sbuf->y, w, origh - h);
- if ((w < origw) && (h < origh))
- imapaint_set_region(&region[tot++], (destx + w) % dbuf->x, (desty + h) % dbuf->y, (srcx + w) % sbuf->x, (srcy + h) % sbuf->y, origw - w, origh - h);
-
- return tot;
-}
-
-static void imapaint_lift_smear(ImBuf *ibuf, ImBuf *ibufb, int *pos)
-{
- ImagePaintRegion region[4];
- int a, tot;
-
- imapaint_set_region(region, 0, 0, pos[0], pos[1], ibufb->x, ibufb->y);
- tot = imapaint_torus_split_region(region, ibufb, ibuf);
-
- for (a = 0; a < tot; a++)
- IMB_rectblend(ibufb, ibuf, region[a].destx, region[a].desty,
- region[a].srcx, region[a].srcy,
- region[a].width, region[a].height, IMB_BLEND_COPY_RGB);
-}
-
-static ImBuf *imapaint_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos)
-{
- /* note: allocImbuf returns zero'd memory, so regions outside image will
- * have zero alpha, and hence not be blended onto the image */
- int w = ibufb->x, h = ibufb->y, destx = 0, desty = 0, srcx = pos[0], srcy = pos[1];
- ImBuf *clonebuf = IMB_allocImBuf(w, h, ibufb->planes, ibufb->flags);
-
- IMB_rectclip(clonebuf, ibuf, &destx, &desty, &srcx, &srcy, &w, &h);
- IMB_rectblend(clonebuf, ibuf, destx, desty, srcx, srcy, w, h,
- IMB_BLEND_COPY_RGB);
- IMB_rectblend(clonebuf, ibufb, destx, desty, destx, desty, w, h,
- IMB_BLEND_COPY_ALPHA);
-
- return clonebuf;
-}
-
-static void imapaint_convert_brushco(ImBuf *ibufb, const float pos[2], int ipos[2])
-{
- ipos[0] = (int)floorf((pos[0] - ibufb->x / 2) + 1.0f);
- ipos[1] = (int)floorf((pos[1] - ibufb->y / 2) + 1.0f);
-}
-
-/* dosnt run for projection painting
- * only the old style painting in the 3d view */
-static int imapaint_paint_op(void *state, ImBuf *ibufb, const float lastpos[2], const float pos[2])
-{
- ImagePaintState *s = ((ImagePaintState *)state);
- ImBuf *clonebuf = NULL, *frombuf;
- ImagePaintRegion region[4];
- short torus = s->brush->flag & BRUSH_TORUS;
- short blend = s->blend;
- float *offset = s->brush->clone.offset;
- float liftpos[2];
- int bpos[2], blastpos[2], bliftpos[2];
- int a, tot;
-
- imapaint_convert_brushco(ibufb, pos, bpos);
-
- /* lift from canvas */
- if (s->tool == PAINT_TOOL_SOFTEN) {
- imapaint_lift_soften(s->canvas, ibufb, bpos, torus);
- }
- 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);
- }
- 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);
- }
-
- frombuf = (clonebuf) ? clonebuf : ibufb;
-
- if (torus) {
- imapaint_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y);
- tot = imapaint_torus_split_region(region, s->canvas, frombuf);
- }
- else {
- imapaint_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y);
- tot = 1;
- }
-
- /* blend into canvas */
- for (a = 0; a < tot; a++) {
- imapaint_dirty_region(s->image, s->canvas,
- region[a].destx, region[a].desty,
- region[a].width, region[a].height);
-
- IMB_rectblend(s->canvas, frombuf,
- region[a].destx, region[a].desty,
- region[a].srcx, region[a].srcy,
- region[a].width, region[a].height, blend);
- }
-
- if (clonebuf) IMB_freeImBuf(clonebuf);
-
- return 1;
-}
-
-
-static int imapaint_canvas_set(ImagePaintState *s, Image *ima)
-{
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL);
-
- /* verify that we can paint and set canvas */
- if (ima == NULL) {
- return 0;
- }
- else if (ima->packedfile && ima->rr) {
- s->warnpackedfile = ima->id.name + 2;
- return 0;
- }
- else if (ibuf && ibuf->channels != 4) {
- s->warnmultifile = ima->id.name + 2;
- return 0;
- }
- else if (!ibuf || !(ibuf->rect || ibuf->rect_float))
- return 0;
-
- s->image = ima;
- s->canvas = ibuf;
-
- /* set clone canvas */
- if (s->tool == PAINT_TOOL_CLONE) {
- ima = s->brush->clone.image;
- ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL);
-
- if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- BKE_image_release_ibuf(s->image, s->canvas, NULL);
- return 0;
- }
-
- s->clonecanvas = ibuf;
-
- /* temporarily add float rect for cloning */
- if (s->canvas->rect_float && !s->clonecanvas->rect_float) {
- IMB_float_from_rect(s->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)
-{
- BKE_image_release_ibuf(s->image, s->canvas, NULL);
- BKE_image_release_ibuf(s->brush->clone.image, s->clonecanvas, NULL);
-}
-
-static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, Image *image, float *uv, int update, float pressure)
-{
- ImBuf *ibuf = BKE_image_acquire_ibuf(image, s->sima ? &s->sima->iuser : NULL, NULL);
- float pos[2];
- int is_data;
-
- if (!ibuf)
- return 0;
-
- is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA;
-
- pos[0] = uv[0] * ibuf->x;
- pos[1] = uv[1] * ibuf->y;
-
- BKE_brush_painter_require_imbuf(painter, ((ibuf->rect_float) ? 1 : 0), 0, 0);
-
- /* OCIO_TODO: float buffers are now always linear, so always use color correction
- * this should probably be changed when texture painting color space is supported
- */
- if (BKE_brush_painter_paint(painter, imapaint_paint_op, pos, 0, pressure, s, is_data == FALSE)) {
- if (update)
- imapaint_image_update(s->sima, image, ibuf, false);
- BKE_image_release_ibuf(image, ibuf, NULL);
- return 1;
- }
- else {
- BKE_image_release_ibuf(image, ibuf, NULL);
- return 0;
- }
-}
-
-static int imapaint_paint_stroke(ImagePaintState *s, BrushPainter *painter, const int mval[2], float pressure)
-{
- float newuv[2];
- int redraw = 0;
-
- UI_view2d_region_to_view(s->v2d, mval[0], mval[1], &newuv[0], &newuv[1]);
- redraw |= imapaint_paint_sub_stroke(s, painter, s->image, newuv,
- 1, pressure);
-
- if (redraw)
- imapaint_clear_partial_redraw();
-
- return redraw;
-}
/************************ image paint poll ************************/
@@ -4811,8 +4294,7 @@ typedef enum TexPaintMode {
typedef struct PaintOperation {
TexPaintMode mode;
- BrushPainter *painter;
- ImagePaintState s;
+ void *custom_paint;
ProjPaintState ps;
int first;
@@ -4824,20 +4306,18 @@ typedef struct PaintOperation {
wmTimer *timer;
} PaintOperation;
-static void paint_redraw(const bContext *C, ImagePaintState *s, int final)
+static void paint_redraw(const bContext *C, PaintOperation *pop, int final)
{
- if (final) {
- if (s->image && !(s->sima && s->sima->lock))
- GPU_free_image(s->image);
-
- /* compositor listener deals with updating */
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, s->image);
- }
- else {
- if (!s->sima || !s->sima->lock)
+ if (pop->mode == PAINT_MODE_2D) {
+ paint_2d_redraw(C, pop->custom_paint, final);
+ } else {
+ if (final) {
+ /* compositor listener deals with updating */
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, NULL);
+ }
+ else {
ED_region_tag_redraw(CTX_wm_region(C));
- else
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, s->image);
+ }
}
}
@@ -4910,17 +4390,6 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps)
ps->do_mask_normal = FALSE; /* no need to do blending */
}
-static void paint_brush_init_tex(Brush *brush)
-{
- /* init mtex nodes */
- if (brush) {
- MTex *mtex = &brush->mtex;
- if (mtex->tex && mtex->tex->nodetree)
- ntreeTexBeginExecTree(mtex->tex->nodetree, 1); /* has internal flag to detect it only does it once */
- }
-
-}
-
static PaintOperation * texture_paint_init(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -4937,67 +4406,15 @@ static PaintOperation * texture_paint_init(bContext *C, wmOperator *op)
pop->mode = PAINT_MODE_3D_PROJECT;
}
else {
- pop->s.sima = CTX_wm_space_image(C);
- pop->s.v2d = &CTX_wm_region(C)->v2d;
- }
-
- pop->s.scene = scene;
- pop->s.screen = CTX_wm_screen(C);
-
- pop->s.brush = brush;
- pop->s.tool = brush->imagepaint_tool;
- pop->s.blend = brush->blend;
- pop->orig_brush_size = BKE_brush_size_get(scene, brush);
-
- if (pop->mode != PAINT_MODE_2D) {
- Object *ob = OBACT;
- Mesh *me = BKE_mesh_from_object(ob);
-
- if (!me) {
- return 0;
- }
-
- pop->s.ob = ob;
- pop->s.do_facesel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
-
- /* for non prohect paint we need */
- /* fill in derived mesh */
- if (ob->derivedFinal && CustomData_has_layer(&ob->derivedFinal->faceData, CD_MTFACE)) {
- pop->s.dm = ob->derivedFinal;
- pop->s.dm_release = FALSE;
- }
- else {
- pop->s.dm = mesh_get_derived_final(pop->s.scene, ob, pop->s.scene->customdata_mask | CD_MASK_MTFACE);
- pop->s.dm_release = TRUE;
- }
-
- if (!CustomData_has_layer(&pop->s.dm->faceData, CD_MTFACE)) {
-
- if (pop->s.dm_release)
- pop->s.dm->release(pop->s.dm);
-
- pop->s.dm = NULL;
+ pop->mode = PAINT_MODE_2D;
+ pop->custom_paint = paint_2d_new_stroke(C, op);
+ if (!pop->custom_paint) {
MEM_freeN(pop);
return NULL;
}
-
- pop->s.dm_mface = pop->s.dm->getTessFaceArray(pop->s.dm);
- pop->s.dm_mtface = pop->s.dm->getTessFaceDataArray(pop->s.dm, CD_MTFACE);
- pop->s.dm_totface = pop->s.dm->getNumTessFaces(pop->s.dm);
}
- else {
- pop->s.image = pop->s.sima->image;
- if (!imapaint_canvas_set(&pop->s, pop->s.image)) {
- if (pop->s.warnmultifile)
- BKE_report(op->reports, RPT_WARNING, "Image requires 4 color channels to paint");
- if (pop->s.warnpackedfile)
- BKE_report(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted");
-
- MEM_freeN(pop);
- return NULL;
- }
- }
+ pop->orig_brush_size = BKE_brush_size_get(scene, brush);
/* note, if we have no UVs on the derived mesh, then we must return here */
if (pop->mode == PAINT_MODE_3D_PROJECT) {
@@ -5029,17 +4446,11 @@ static PaintOperation * texture_paint_init(bContext *C, wmOperator *op)
return NULL;
}
}
- else {
- paint_brush_init_tex(pop->s.brush);
- }
settings->imapaint.flag |= IMAGEPAINT_DRAWING;
undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
image_undo_restore, image_undo_free);
- /* create painter */
- pop->painter = BKE_brush_painter_new(scene, pop->s.brush);
-
{
UnifiedPaintSettings *ups = &settings->unified_paint_settings;
ups->draw_pressure = true;
@@ -5053,43 +4464,35 @@ static void paint_stroke_update_step(bContext *C, struct PaintStroke *stroke, Po
PaintOperation *pop = paint_stroke_mode_data(stroke);
float mousef[2];
float pressure;
- int mouse[2], redraw;
+ int mouse[2], redraw, eraser;
RNA_float_get_array(itemptr, "mouse", mousef);
mouse[0] = (int)(mousef[0]);
mouse[1] = (int)(mousef[1]);
pressure = RNA_float_get(itemptr, "pressure");
+ eraser = RNA_boolean_get(itemptr, "pen_flip");
if (pop->mode == PAINT_MODE_3D_PROJECT) {
if (pop->first)
project_paint_begin_clone(&pop->ps, mouse);
- redraw = project_paint_stroke(&pop->ps, pop->prevmouse, mouse, pressure);
+ redraw = project_paint_stroke(&pop->ps, pop->prevmouse, mouse);
pop->prevmouse[0] = mouse[0];
pop->prevmouse[1] = mouse[1];
}
else {
- redraw = imapaint_paint_stroke(&pop->s, pop->painter, mouse, pressure);
+ redraw = paint_2d_stroke(pop->custom_paint, mouse, pressure, eraser);
pop->prevmouse[0] = mouse[0];
pop->prevmouse[1] = mouse[1];
}
if (redraw)
- paint_redraw(C, &pop->s, 0);
+ paint_redraw(C, pop, 0);
pop->first = 0;
}
-static void paint_brush_exit_tex(Brush *brush)
-{
- if (brush) {
- MTex *mtex = &brush->mtex;
- if (mtex->tex && mtex->tex->nodetree)
- ntreeTexEndExecTree(mtex->tex->nodetree->execdata, 1);
- }
-}
-
static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke)
{
Scene *scene = CTX_data_scene(C);
@@ -5100,24 +4503,16 @@ static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke)
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), pop->timer);
settings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
- imapaint_canvas_free(&pop->s);
- BKE_brush_painter_free(pop->painter);
if (pop->mode == PAINT_MODE_3D_PROJECT) {
BKE_brush_size_set(scene, pop->ps.brush, pop->orig_brush_size);
paint_brush_exit_tex(pop->ps.brush);
project_paint_end(&pop->ps);
- }
- else {
- paint_brush_exit_tex(pop->s.brush);
-
- /* non projection 3d paint, could move into own function of more needs adding */
- if (pop->s.dm_release)
- pop->s.dm->release(pop->s.dm);
- }
+ } else
+ paint_2d_stroke_done(pop->custom_paint);
- paint_redraw(C, &pop->s, 1);
+ paint_redraw(C, pop, 1);
undo_paint_push_end(UNDO_PAINT_IMAGE);
/* duplicate warning, see texpaint_init
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 36b1e56557f..91ef6b83b36 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -50,6 +50,8 @@ struct ViewContext;
struct wmEvent;
struct wmOperator;
struct wmOperatorType;
+struct ImagePaintState;
+enum PaintMode;
/* paint_stroke.c */
typedef int (*StrokeGetLocation)(struct bContext *C, float location[3], const float mouse[2]);
@@ -64,6 +66,7 @@ void paint_stroke_data_free(struct wmOperator *op);
bool paint_space_stroke_enabled(struct Brush *br);
bool paint_supports_dynamic_size(struct Brush *br);
+bool paint_supports_jitter(enum PaintMode mode);
struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf);
int paint_stroke_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
@@ -103,7 +106,30 @@ void PAINT_OT_vertex_paint(struct wmOperatorType *ot);
unsigned int vpaint_get_current_col(struct VPaint *vp);
/* paint_image.c */
+typedef struct ImagePaintPartialRedraw {
+ int x1, y1, x2, y2; /* XXX, could use 'rcti' */
+ int enabled;
+} ImagePaintPartialRedraw;
+
+#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)
+
+#define IMAPAINT_CHAR_TO_FLOAT(c) ((c) / 255.0f)
+
int image_texture_paint_poll(struct bContext *C);
+void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile);
+void imapaint_image_update(struct SpaceImage *sima, struct Image *image, struct ImBuf *ibuf, short texpaint);
+struct ImagePaintPartialRedraw *get_imapaintpartial(void);
+void set_imapaintpartial(struct ImagePaintPartialRedraw * ippr);
+void imapaint_clear_partial_redraw(void);
+void imapaint_dirty_region(struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h);
+void *paint_2d_new_stroke(struct bContext *, struct wmOperator *);
+void paint_2d_redraw(const bContext *C, void *ps, int final);
+void paint_2d_stroke_done(void *ps);
+int paint_2d_stroke(void *ps, const int mval[2], float pressure, int eraser);
+void paint_brush_init_tex(struct Brush *brush);
+void paint_brush_exit_tex(struct Brush *brush);
void PAINT_OT_image_paint(struct wmOperatorType *ot);
void PAINT_OT_grab_clone(struct wmOperatorType *ot);
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 287bd723534..2146c74fb6d 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -157,7 +157,7 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *ev
/* TODO: as sculpt and other paint modes are unified, this
* separation will go away */
- if (ELEM(mode, PAINT_SCULPT, PAINT_TEXTURE_PROJECTIVE)) {
+ if (paint_supports_jitter(mode)) {
float delta[2];
BKE_brush_jitter_pos(scene, brush, mouse_in, mouse_out);
@@ -338,6 +338,10 @@ bool paint_supports_dynamic_size(Brush *br)
!ELEM4(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_SNAKE_HOOK);
}
+bool paint_supports_jitter(PaintMode mode) {
+ return ELEM(mode, PAINT_SCULPT, PAINT_TEXTURE_PROJECTIVE);
+}
+
#define PAINT_STROKE_MODAL_CANCEL 1
/* called in paint_ops.c, on each regeneration of keymaps */