- UNUSED macro wasn't throwing an error with GCC if a var become used.
[blender.git] / source / blender / editors / sculpt_paint / paint_image.c
index ef8c33007a254858831f66047a211240d32bf47a..cd498c274cf3eea382f0da5134ef45705c2d66ca 100644 (file)
 #include "DNA_meshdata_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_brush_types.h"
 
 #include "BKE_context.h"
 #include "BKE_idprop.h"
 #include "BKE_object.h"
 #include "BKE_brush.h"
-#include "BKE_global.h"
 #include "BKE_image.h"
 #include "BKE_main.h"
 #include "BKE_mesh.h"
-#include "BKE_node.h"
 #include "BKE_paint.h"
-#include "BKE_utildefines.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_report.h"
 #include "BKE_depsgraph.h"
@@ -475,8 +473,6 @@ static int project_bucket_offset_safe(const ProjPaintState *ps, const float proj
        }
 }
 
-#define SIDE_OF_LINE(pa, pb, pp)       ((pa[0]-pp[0])*(pb[1]-pp[1]))-((pb[0]-pp[0])*(pa[1]-pp[1]))
-
 /* still use 2D X,Y space but this works for verts transformed by a perspective matrix, using their 4th component as a weight */
 static void barycentric_weights_v2_persp(float v1[4], float v2[4], float v3[4], float co[2], float w[3])
 {
@@ -1334,7 +1330,7 @@ float project_paint_uvpixel_mask(
        
        // This only works when the opacity dosnt change while painting, stylus pressure messes with this
        // so dont use it.
-       // if (ps->is_airbrush==0) mask *= ps->brush->alpha;
+       // if (ps->is_airbrush==0) mask *= brush_alpha(ps->brush);
        
        return mask;
 }
@@ -1691,7 +1687,7 @@ static float Vec2Lenf_nosqrt_other(const float *v1, const float v2_1, const floa
 /* note, use a squared value so we can use Vec2Lenf_nosqrt
  * be sure that you have done a bounds check first or this may fail */
 /* only give bucket_bounds as an arg because we need it elsewhere */
-static int project_bucket_isect_circle(const int bucket_x, const int bucket_y, const float cent[2], const float radius_squared, rctf *bucket_bounds)
+static int project_bucket_isect_circle(const float cent[2], const float radius_squared, rctf *bucket_bounds)
 {
         
        /* Would normally to a simple intersection test, however we know the bounds of these 2 already intersect 
@@ -1854,7 +1850,7 @@ static void project_bucket_clip_face(
 {
        int inside_bucket_flag = 0;
        int inside_face_flag = 0;
-       const int flip = ((SIDE_OF_LINE(v1coSS, v2coSS, v3coSS) > 0.0f) != (SIDE_OF_LINE(uv1co, uv2co, uv3co) > 0.0f));
+       const int flip = ((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) != (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f));
        
        float bucket_bounds_ss[4][2];
 
@@ -2136,15 +2132,15 @@ if __name__ == '__main__':
 
        
 /* checks if pt is inside a convex 2D polyline, the polyline must be ordered rotating clockwise
- * otherwise it would have to test for mixed (SIDE_OF_LINE > 0.0f) cases */
+ * otherwise it would have to test for mixed (line_point_side_v2 > 0.0f) cases */
 int IsectPoly2Df(const float pt[2], float uv[][2], const int tot)
 {
        int i;
-       if (SIDE_OF_LINE(uv[tot-1], uv[0], pt) < 0.0f)
+       if (line_point_side_v2(uv[tot-1], uv[0], pt) < 0.0f)
                return 0;
        
        for (i=1; i<tot; i++) {
-               if (SIDE_OF_LINE(uv[i-1], uv[i], pt) < 0.0f)
+               if (line_point_side_v2(uv[i-1], uv[i], pt) < 0.0f)
                        return 0;
                
        }
@@ -2154,10 +2150,10 @@ int IsectPoly2Df(const float pt[2], float uv[][2], const int tot)
 static int IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot)
 {
        int i;
-       int side = (SIDE_OF_LINE(uv[tot-1], uv[0], pt) > 0.0f);
+       int side = (line_point_side_v2(uv[tot-1], uv[0], pt) > 0.0f);
        
        for (i=1; i<tot; i++) {
-               if ((SIDE_OF_LINE(uv[i-1], uv[i], pt) > 0.0f) != side)
+               if ((line_point_side_v2(uv[i-1], uv[i], pt) > 0.0f) != side)
                        return 0;
                
        }
@@ -2654,7 +2650,7 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index
  * calculated when it might not be needed later, (at the moment at least)
  * obviously it shouldn't have bugs though */
 
-static int project_bucket_face_isect(ProjPaintState *ps, float min[2], float max[2], int bucket_x, int bucket_y, int bucket_index, const MFace *mf)
+static int project_bucket_face_isect(ProjPaintState *ps, int bucket_x, int bucket_y, const MFace *mf)
 {
        /* TODO - replace this with a tricker method that uses sideofline for all screenCoords's edges against the closest bucket corner */
        rctf bucket_bounds;
@@ -2714,11 +2710,11 @@ static int project_bucket_face_isect(ProjPaintState *ps, float min[2], float max
 
 /* Add faces to the bucket but dont initialize its pixels
  * TODO - when painting occluded, sort the faces on their min-Z and only add faces that faces that are not occluded */
-static void project_paint_delayed_face_init(ProjPaintState *ps, const MFace *mf, const MTFace *tf, const int face_index)
+static void project_paint_delayed_face_init(ProjPaintState *ps, const MFace *mf, const int face_index)
 {
        float min[2], max[2], *vCoSS;
        int bucketMin[2], bucketMax[2]; /* for  ps->bucketRect indexing */
-       int fidx, bucket_x, bucket_y, bucket_index;
+       int fidx, bucket_x, bucket_y;
        int has_x_isect = -1, has_isect = 0; /* for early loop exit */
        MemArena *arena = ps->arena_mt[0]; /* just use the first thread arena since threading has not started yet */
        
@@ -2735,10 +2731,8 @@ static void project_paint_delayed_face_init(ProjPaintState *ps, const MFace *mf,
        for (bucket_y = bucketMin[1]; bucket_y < bucketMax[1]; bucket_y++) {
                has_x_isect = 0;
                for (bucket_x = bucketMin[0]; bucket_x < bucketMax[0]; bucket_x++) {
-                       
-                       bucket_index = bucket_x + (bucket_y * ps->buckets_x);
-                       
-                       if (project_bucket_face_isect(ps, min, max, bucket_x, bucket_y, bucket_index, mf)) {
+                       if (project_bucket_face_isect(ps, bucket_x, bucket_y, mf)) {
+                               int bucket_index= bucket_x + (bucket_y * ps->buckets_x);
                                BLI_linklist_prepend_arena(
                                        &ps->bucketFaces[ bucket_index ],
                                        SET_INT_IN_POINTER(face_index), /* cast to a pointer to shut up the compiler */
@@ -2809,6 +2803,8 @@ static void project_paint_begin(ProjPaintState *ps)
        MVert *mv;
        
        MemArena *arena; /* at the moment this is just ps->arena_mt[0], but use this to show were not multithreading */
+
+       const int diameter= 2*brush_size(ps->brush);
        
        /* ---- end defines ---- */
        
@@ -3030,11 +3026,11 @@ static void project_paint_begin(ProjPaintState *ps)
        
        if(ps->source==PROJ_SRC_VIEW) {
 #ifdef PROJ_DEBUG_WINCLIP
-               CLAMP(ps->screenMin[0], (float)(-ps->brush->size), (float)(ps->winx + ps->brush->size));
-               CLAMP(ps->screenMax[0], (float)(-ps->brush->size), (float)(ps->winx + ps->brush->size));
+               CLAMP(ps->screenMin[0], (float)(-diameter), (float)(ps->winx + diameter));
+               CLAMP(ps->screenMax[0], (float)(-diameter), (float)(ps->winx + diameter));
 
-               CLAMP(ps->screenMin[1], (float)(-ps->brush->size), (float)(ps->winy + ps->brush->size));
-               CLAMP(ps->screenMax[1], (float)(-ps->brush->size), (float)(ps->winy + ps->brush->size));
+               CLAMP(ps->screenMin[1], (float)(-diameter), (float)(ps->winy + diameter));
+               CLAMP(ps->screenMax[1], (float)(-diameter), (float)(ps->winy + diameter));
 #endif
        }
        else { /* reprojection, use bounds */
@@ -3049,8 +3045,8 @@ static void project_paint_begin(ProjPaintState *ps)
        ps->screen_width  = ps->screenMax[0] - ps->screenMin[0];
        ps->screen_height = ps->screenMax[1] - ps->screenMin[1];
        
-       ps->buckets_x = (int)(ps->screen_width / (((float)ps->brush->size) / PROJ_BUCKET_BRUSH_DIV));
-       ps->buckets_y = (int)(ps->screen_height / (((float)ps->brush->size) / PROJ_BUCKET_BRUSH_DIV));
+       ps->buckets_x = (int)(ps->screen_width / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV));
+       ps->buckets_y = (int)(ps->screen_height / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV));
        
        /* printf("\tscreenspace bucket division x:%d y:%d\n", ps->buckets_x, ps->buckets_y); */
        
@@ -3194,7 +3190,7 @@ static void project_paint_begin(ProjPaintState *ps)
                                        }
                                }
                                else {
-                                       if (SIDE_OF_LINE(v1coSS, v2coSS, v3coSS) < 0.0f) {
+                                       if (line_point_side_v2(v1coSS, v2coSS, v3coSS) < 0.0f) {
                                                continue;
                                        }
                                        
@@ -3217,7 +3213,7 @@ static void project_paint_begin(ProjPaintState *ps)
                        if (image_index != -1) {
                                /* Initialize the faces screen pixels */
                                /* Add this to a list to initialize later */
-                               project_paint_delayed_face_init(ps, mf, tf, face_index);
+                               project_paint_delayed_face_init(ps, mf, face_index);
                        }
                }
        }
@@ -3448,16 +3444,16 @@ static int project_bucket_iter_init(ProjPaintState *ps, const float mval_f[2])
 {
        if(ps->source==PROJ_SRC_VIEW) {
                float min_brush[2], max_brush[2];
-               float size_half = ((float)ps->brush->size) * 0.5f;
+               const float radius = (float)brush_size(ps->brush);
 
                /* so we dont have a bucket bounds that is way too small to paint into */
-               // if (size_half < 1.0f) size_half = 1.0f; // this dosnt work yet :/
+               // if (radius < 1.0f) radius = 1.0f; // this doesn't work yet :/
 
-               min_brush[0] = mval_f[0] - size_half;
-               min_brush[1] = mval_f[1] - size_half;
+               min_brush[0] = mval_f[0] - radius;
+               min_brush[1] = mval_f[1] - radius;
 
-               max_brush[0] = mval_f[0] + size_half;
-               max_brush[1] = mval_f[1] + size_half;
+               max_brush[0] = mval_f[0] + radius;
+               max_brush[1] = mval_f[1] + radius;
 
                /* offset to make this a valid bucket index */
                project_paint_bucket_bounds(ps, min_brush, max_brush, ps->bucketMin, ps->bucketMax);
@@ -3486,6 +3482,8 @@ static int project_bucket_iter_init(ProjPaintState *ps, const float mval_f[2])
 
 static int project_bucket_iter_next(ProjPaintState *ps, int *bucket_index, rctf *bucket_bounds, const float mval[2])
 {
+       const int diameter= 2*brush_size(ps->brush);
+
        if (ps->thread_tot > 1)
                BLI_lock_thread(LOCK_CUSTOM1);
        
@@ -3498,7 +3496,7 @@ static int project_bucket_iter_next(ProjPaintState *ps, int *bucket_index, rctf
                        project_bucket_bounds(ps, ps->context_bucket_x, ps->context_bucket_y, bucket_bounds);
                        
                        if (    (ps->source != PROJ_SRC_VIEW) ||
-                                       project_bucket_isect_circle(ps->context_bucket_x, ps->context_bucket_y, mval, (float)(ps->brush->size * ps->brush->size), bucket_bounds)
+                                       project_bucket_isect_circle(mval, (float)(diameter*diameter), bucket_bounds)
                        ) {
                                *bucket_index = ps->context_bucket_x + (ps->context_bucket_y * ps->buckets_x);
                                ps->context_bucket_x++;
@@ -3567,7 +3565,7 @@ static void blend_color_mix_accum(unsigned char *cp, const unsigned char *cp1, c
        cp[3]= alpha > 255 ? 255 : alpha;
 }
 
-static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask)
+static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask)
 {
        if (ps->is_airbrush==0 && mask < 1.0f) {
                projPixel->newColor.uint = IMB_blend_color(projPixel->newColor.uint, ((ProjPixelClone*)projPixel)->clonepx.uint, (int)(alpha*255), ps->blend);
@@ -3578,7 +3576,7 @@ static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, floa
        }
 }
 
-static void do_projectpaint_clone_f(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask)
+static void do_projectpaint_clone_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask)
 {
        if (ps->is_airbrush==0 && mask < 1.0f) {
                IMB_blend_color_float(projPixel->newColor.f, projPixel->newColor.f, ((ProjPixelClone *)projPixel)->clonepx.f, alpha, ps->blend);
@@ -3595,7 +3593,7 @@ static void do_projectpaint_clone_f(ProjPaintState *ps, ProjPixel *projPixel, fl
  * accumulation of color greater then 'projPixel->mask' however in the case of smear its not 
  * really that important to be correct as it is with clone and painting 
  */
-static void do_projectpaint_smear(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask, MemArena *smearArena, LinkNode **smearPixels, float co[2])
+static void do_projectpaint_smear(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, MemArena *smearArena, LinkNode **smearPixels, float co[2])
 {
        unsigned char rgba_ub[4];
        
@@ -3606,7 +3604,7 @@ static void do_projectpaint_smear(ProjPaintState *ps, ProjPixel *projPixel, floa
        BLI_linklist_prepend_arena(smearPixels, (void *)projPixel, smearArena);
 } 
 
-static void do_projectpaint_smear_f(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask, MemArena *smearArena, LinkNode **smearPixels_f, float co[2])
+static void do_projectpaint_smear_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, MemArena *smearArena, LinkNode **smearPixels_f, float co[2])
 {
        unsigned char rgba_ub[4];
        unsigned char rgba_smear[4];
@@ -3685,7 +3683,6 @@ static void *do_projectpaint_thread(void *ph_v)
        
        float rgba[4], alpha, dist_nosqrt, dist;
        
-       float brush_size_sqared;
        float falloff;
        int bucket_index;
        int is_floatbuf = 0;
@@ -3697,14 +3694,15 @@ static void *do_projectpaint_thread(void *ph_v)
        float co[2];
        float mask = 1.0f; /* airbrush wont use mask */
        unsigned short mask_short;
-       float size_half = ((float)ps->brush->size) * 0.5f;
+       const float radius= (float)brush_size(ps->brush);
+       const float radius_squared= radius*radius; /* avoid a square root with every dist comparison */
+       
        short lock_alpha= ELEM(ps->brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ? 0 : ps->brush->flag & BRUSH_LOCK_ALPHA;
        
        LinkNode *smearPixels = NULL;
        LinkNode *smearPixels_f = NULL;
        MemArena *smearArena = NULL; /* mem arena for this brush projection only */
        
-       
        if (tool==PAINT_TOOL_SMEAR) {
                pos_ofs[0] = pos[0] - lastpos[0];
                pos_ofs[1] = pos[1] - lastpos[1];
@@ -3712,9 +3710,6 @@ static void *do_projectpaint_thread(void *ph_v)
                smearArena = BLI_memarena_new(1<<16, "paint smear arena");
        }
        
-       /* avoid a square root with every dist comparison */
-       brush_size_sqared = (float)(ps->brush->size * ps->brush->size);
-       
        /* printf("brush bounds %d %d %d %d\n", bucketMin[0], bucketMin[1], bucketMax[0], bucketMax[1]); */
        
        while (project_bucket_iter_next(ps, &bucket_index, &bucket_bounds, pos)) {                              
@@ -3735,7 +3730,7 @@ static void *do_projectpaint_thread(void *ph_v)
                                bicubic_interpolation_color(ps->reproject_ibuf, projPixel->newColor.ch, NULL, projPixel->projCoSS[0], projPixel->projCoSS[1]);
                                if(projPixel->newColor.ch[3]) {
                                        mask = ((float)projPixel->mask)/65535.0f;
-                                       blend_color_mix_accum(projPixel->pixel.ch_pt,  projPixel->origColor.ch, projPixel->newColor.ch, (mask*projPixel->newColor.ch[3]));
+                                       blend_color_mix_accum(projPixel->pixel.ch_pt,  projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask*projPixel->newColor.ch[3]));
 
                                }
                        }
@@ -3750,13 +3745,16 @@ static void *do_projectpaint_thread(void *ph_v)
                                /*dist = len_v2v2(projPixel->projCoSS, pos);*/ /* correct but uses a sqrtf */
                                dist_nosqrt = Vec2Lenf_nosqrt(projPixel->projCoSS, pos);
 
-                               /*if (dist < s->brush->size) {*/ /* correct but uses a sqrtf */
-                               if (dist_nosqrt < brush_size_sqared && (dist=sqrtf(dist_nosqrt)) < size_half) {
-                                       falloff = brush_curve_strength_clamp(ps->brush, dist, size_half);
+                               /*if (dist < radius) {*/ /* correct but uses a sqrtf */
+                               if (dist_nosqrt <= radius_squared) {
+                                       dist=sqrtf(dist_nosqrt);
+
+                                       falloff = brush_curve_strength_clamp(ps->brush, dist, radius);
 
                                        if (falloff > 0.0f) {
                                                if (ps->is_texbrush) {
-                                                       brush_sample_tex(ps->brush, projPixel->projCoSS, rgba);
+                                                       /* note, for clone and smear, we only use the alpha, could be a special function */
+                                                       brush_sample_tex(ps->brush, projPixel->projCoSS, rgba, thread_index);
                                                        alpha = rgba[3];
                                                } else {
                                                        alpha = 1.0f;
@@ -3764,7 +3762,7 @@ static void *do_projectpaint_thread(void *ph_v)
                                                
                                                if (ps->is_airbrush) {
                                                        /* for an aurbrush there is no real mask, so just multiply the alpha by it */
-                                                       alpha *= falloff * ps->brush->alpha;
+                                                       alpha *= falloff * brush_alpha(ps->brush);
                                                        mask = ((float)projPixel->mask)/65535.0f;
                                                }
                                                else {
@@ -3772,7 +3770,7 @@ static void *do_projectpaint_thread(void *ph_v)
                                                        falloff = 1.0f - falloff;
                                                        falloff = 1.0f - (falloff * falloff);
                                                        
-                                                       mask_short = (unsigned short)(projPixel->mask * (ps->brush->alpha * falloff));
+                                                       mask_short = (unsigned short)(projPixel->mask * (brush_alpha(ps->brush) * falloff));
                                                        if (mask_short > projPixel->mask_max) {
                                                                mask = ((float)mask_short)/65535.0f;
                                                                projPixel->mask_max = mask_short;
@@ -3807,20 +3805,20 @@ static void *do_projectpaint_thread(void *ph_v)
                                                        case PAINT_TOOL_CLONE:
                                                                if (is_floatbuf) {
                                                                        if (((ProjPixelClone *)projPixel)->clonepx.f[3]) {
-                                                                               do_projectpaint_clone_f(ps, projPixel, rgba, alpha, mask);
+                                                                               do_projectpaint_clone_f(ps, projPixel, alpha, mask); /* rgba isnt used for cloning, only alpha */
                                                                        }
                                                                }
                                                                else {
                                                                        if (((ProjPixelClone*)projPixel)->clonepx.ch[3]) {
-                                                                               do_projectpaint_clone(ps, projPixel, rgba, alpha, mask);
+                                                                               do_projectpaint_clone(ps, projPixel, alpha, mask); /* rgba isnt used for cloning, only alpha */
                                                                        }
                                                                }
                                                                break;
                                                        case PAINT_TOOL_SMEAR:
                                                                sub_v2_v2v2(co, projPixel->projCoSS, pos_ofs);
 
-                                                               if (is_floatbuf)        do_projectpaint_smear_f(ps, projPixel, rgba, alpha, mask, smearArena, &smearPixels_f, co);
-                                                               else                            do_projectpaint_smear(ps, projPixel, rgba, alpha, mask, smearArena, &smearPixels, co);
+                                                               if (is_floatbuf)        do_projectpaint_smear_f(ps, projPixel, alpha, mask, smearArena, &smearPixels_f, co);
+                                                               else                            do_projectpaint_smear(ps, projPixel, alpha, mask, smearArena, &smearPixels, co);
                                                                break;
                                                        default:
                                                                if (is_floatbuf)        do_projectpaint_draw_f(ps, projPixel, rgba, alpha, mask);
@@ -3860,7 +3858,7 @@ static void *do_projectpaint_thread(void *ph_v)
        return NULL;
 }
 
-static int project_paint_op(void *state, ImBuf *ibufb, float *lastpos, float *pos)
+static int project_paint_op(void *state, ImBuf *UNUSED(ibufb), float *lastpos, float *pos)
 {
        /* First unpack args from the struct */
        ProjPaintState *ps = (ProjPaintState *)state;
@@ -3927,7 +3925,7 @@ static int project_paint_op(void *state, ImBuf *ibufb, float *lastpos, float *po
 }
 
 
-static int project_paint_sub_stroke(ProjPaintState *ps, BrushPainter *painter, int *prevmval_i, int *mval_i, double time, float pressure)
+static int project_paint_sub_stroke(ProjPaintState *ps, BrushPainter *painter, int *UNUSED(prevmval_i), int *mval_i, double time, float pressure)
 {
        
        /* Use mouse coords as floats for projection painting */
@@ -4386,7 +4384,7 @@ static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPaint
                        ibuf= BKE_image_get_ibuf(newimage, s->sima? &s->sima->iuser: NULL);
 
                        if(ibuf && ibuf->rect)
-                               imapaint_pick_uv(s->scene, s->ob, s->me, newfaceindex, mval, newuv);
+                               imapaint_pick_uv(s->scene, s->ob, newfaceindex, mval, newuv);
                        else {
                                newimage = NULL;
                                newuv[0] = newuv[1] = 0.0f;
@@ -4397,8 +4395,8 @@ static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPaint
 
                /* see if stroke is broken, and if so finish painting in old position */
                if (s->image) {
-                       imapaint_pick_uv(s->scene, s->ob, s->me, s->faceindex, mval, fwuv);
-                       imapaint_pick_uv(s->scene, s->ob, s->me, newfaceindex, prevmval, bkuv);
+                       imapaint_pick_uv(s->scene, s->ob, s->faceindex, mval, fwuv);
+                       imapaint_pick_uv(s->scene, s->ob, newfaceindex, prevmval, bkuv);
 
                        if (newimage == s->image)
                                breakstroke= texpaint_break_stroke(s->uv, fwuv, bkuv, newuv);
@@ -4409,7 +4407,7 @@ static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPaint
                        fwuv[0]= fwuv[1]= 0.0f;
 
                if (breakstroke) {
-                       imapaint_pick_uv(s->scene, s->ob, s->me, s->faceindex, mval, fwuv);
+                       imapaint_pick_uv(s->scene, s->ob, s->faceindex, mval, fwuv);
                        redraw |= imapaint_paint_sub_stroke(s, painter, s->image, texpaint,
                                fwuv, time, 1, pressure);
                        imapaint_clear_partial_redraw();
@@ -4520,7 +4518,7 @@ typedef struct PaintOperation {
        int first;
        int prevmouse[2];
        float prev_pressure; /* need this since we dont get tablet events for pressure change */
-       int brush_size_orig;
+       int orig_brush_size;
        double starttime;
 
        ViewContext vc;
@@ -4533,29 +4531,8 @@ static void paint_redraw(bContext *C, ImagePaintState *s, int final)
                if(s->image)
                        GPU_free_image(s->image);
 
+               /* compositor listener deals with updating */
                WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, s->image);
-
-               // XXX node update
-#if 0
-               if(!s->sima && s->image) {
-                       /* after paint, tag Image or RenderResult nodes changed */
-                       if(s->scene->nodetree) {
-                               imagepaint_composite_tags(s->scene->nodetree, image, &s->sima->iuser);
-                       }
-                       /* signal composite (hurmf, need an allqueue?) */
-                       if(s->sima->lock) {
-                               ScrArea *sa;
-                               for(sa=s->screen->areabase.first; sa; sa= sa->next) {
-                                       if(sa->spacetype==SPACE_NODE) {
-                                               if(((SpaceNode *)sa->spacedata.first)->treetype==NTREE_COMPOSIT) {
-                                                       addqueue(sa->win, UI_BUT_EVENT, B_NODE_TREE_EXEC);
-                                                       break;
-                                               }
-                                       }
-                               }
-                       }
-               }               
-#endif
        }
        else {
                if(!s->sima || !s->sima->lock)
@@ -4653,7 +4630,7 @@ static int texture_paint_init(bContext *C, wmOperator *op)
        if(pop->mode == PAINT_MODE_3D && (pop->s.tool == PAINT_TOOL_CLONE))
                pop->s.tool = PAINT_TOOL_DRAW;
        pop->s.blend = brush->blend;
-       pop->brush_size_orig= brush->size;
+       pop->orig_brush_size= brush_size(brush);
 
        if(pop->mode != PAINT_MODE_2D) {
                pop->s.ob = OBACT;
@@ -4685,8 +4662,8 @@ static int texture_paint_init(bContext *C, wmOperator *op)
                        return 0;
 
                /* Dont allow brush size below 2 */
-               if (brush->size <= 1)
-                       brush->size = 2;
+               if (brush_size(brush) < 2)
+                       brush_set_size(brush, 2);
 
                /* allocate and initialize spacial data structures */
                project_paint_begin(&pop->ps);
@@ -4696,7 +4673,7 @@ static int texture_paint_init(bContext *C, wmOperator *op)
        }
        
        settings->imapaint.flag |= IMAGEPAINT_DRAWING;
-       undo_paint_push_begin(UNDO_PAINT_IMAGE, "Image Paint",
+       undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
                image_undo_restore, image_undo_free);
 
        /* create painter */
@@ -4756,7 +4733,7 @@ static void paint_exit(bContext *C, wmOperator *op)
        brush_painter_free(pop->painter);
 
        if(pop->mode == PAINT_MODE_3D_PROJECT) {
-               pop->ps.brush->size = pop->brush_size_orig;
+               brush_set_size(pop->ps.brush, pop->orig_brush_size);
                project_paint_end(&pop->ps);
        }
        
@@ -4827,8 +4804,15 @@ static void paint_apply_event(bContext *C, wmOperator *op, wmEvent *event)
 
                /* special exception here for too high pressure values on first touch in
                   windows for some tablets, then we just skip first touch ..  */
-               if ((pop->s.brush->flag & (BRUSH_ALPHA_PRESSURE|BRUSH_SIZE_PRESSURE|BRUSH_SPACING_PRESSURE)) && tablet && (pressure >= 0.99f))
+               if (tablet && (pressure >= 0.99f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || brush_use_alpha_pressure(pop->s.brush) || brush_use_size_pressure(pop->s.brush)))
                        return;
+
+               /* This can be removed once fixed properly in
+                brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, float pressure, void *user) 
+                at zero pressure we should do nothing 1/2^12 is .0002 which is the sensitivity of the most sensitive pen tablet available*/
+               if (tablet && (pressure < .0002f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || brush_use_alpha_pressure(pop->s.brush) || brush_use_size_pressure(pop->s.brush)))
+                       return;
+       
        }
 
        /* fill in stroke */
@@ -4936,12 +4920,17 @@ static int get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy)
 
 /************************ cursor drawing *******************************/
 
-static void brush_drawcursor(bContext *C, int x, int y, void *customdata)
+static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata))
 {
        Brush *brush= image_paint_brush(C);
+       Paint *paint= paint_get_active(CTX_data_scene(C));
 
-       if(brush) {
+       if(paint && brush) {
                float zoomx, zoomy;
+
+               if(!(paint->flags & PAINT_SHOW_BRUSH))
+                       return;
+
                glPushMatrix();
 
                glTranslatef((float)x, (float)y, 0.0f);
@@ -4949,13 +4938,13 @@ static void brush_drawcursor(bContext *C, int x, int y, void *customdata)
                if(get_imapaint_zoom(C, &zoomx, &zoomy))
                        glScalef(zoomx, zoomy, 1.0f);
 
-               glColor4ub(255, 255, 255, 128);
+               glColor4f(brush->add_col[0], brush->add_col[1], brush->add_col[2], 0.5f);
                glEnable( GL_LINE_SMOOTH );
                glEnable(GL_BLEND);
-               glutil_draw_lined_arc(0, (float)(M_PI*2.0), brush->size*0.5f, 40);
+               glutil_draw_lined_arc(0, (float)(M_PI*2.0), (float)brush_size(brush), 40);
                glDisable(GL_BLEND);
                glDisable( GL_LINE_SMOOTH );
-               
+
                glPopMatrix();
        }
 }
@@ -4979,7 +4968,7 @@ static int paint_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *eve
        ToolSettings *ts = CTX_data_scene(C)->toolsettings;
        get_imapaint_zoom(C, &zoom, &zoom);
        toggle_paint_cursor(C, !ts->imapaint.paintcursor);
-       brush_radial_control_invoke(op, paint_brush(&ts->imapaint.paint), 0.5f * zoom);
+       brush_radial_control_invoke(op, paint_brush(&ts->imapaint.paint), zoom);
        return WM_radial_control_invoke(C, op, event);
 }
 
@@ -4997,10 +4986,10 @@ static int paint_radial_control_exec(bContext *C, wmOperator *op)
        Brush *brush = paint_brush(&CTX_data_scene(C)->toolsettings->imapaint.paint);
        float zoom;
        int ret;
-       char str[256];
+       char str[64];
        get_imapaint_zoom(C, &zoom, &zoom);
-       ret = brush_radial_control_exec(op, brush, 2.0f / zoom);
-       WM_radial_control_string(op, str, 256);
+       ret = brush_radial_control_exec(op, brush, 1.0f / zoom);
+       WM_radial_control_string(op, str, sizeof(str));
        
        WM_event_add_notifier(C, NC_BRUSH|NA_EDITED, brush);
 
@@ -5095,7 +5084,7 @@ static int grab_clone_modal(bContext *C, wmOperator *op, wmEvent *event)
        return OPERATOR_RUNNING_MODAL;
 }
 
-static int grab_clone_cancel(bContext *C, wmOperator *op)
+static int grab_clone_cancel(bContext *UNUSED(C), wmOperator *op)
 {
        MEM_freeN(op->customdata);
        return OPERATOR_CANCELLED;
@@ -5143,11 +5132,40 @@ static int sample_color_invoke(bContext *C, wmOperator *op, wmEvent *event)
        ARegion *ar= CTX_wm_region(C);
        int location[2];
 
-       location[0]= event->x - ar->winrct.xmin;
-       location[1]= event->y - ar->winrct.ymin;
-       RNA_int_set_array(op->ptr, "location", location);
+       if(ar) {
+               location[0]= event->x - ar->winrct.xmin;
+               location[1]= event->y - ar->winrct.ymin;
+               RNA_int_set_array(op->ptr, "location", location);
 
-       return sample_color_exec(C, op);
+               sample_color_exec(C, op);
+       }
+
+       WM_event_add_modal_handler(C, op);
+
+       return OPERATOR_RUNNING_MODAL;
+}
+
+static int sample_color_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+       ARegion *ar= CTX_wm_region(C);
+       int location[2];
+
+       switch(event->type) {
+               case LEFTMOUSE:
+               case RIGHTMOUSE: // XXX hardcoded
+                       return OPERATOR_FINISHED;
+               case MOUSEMOVE:
+                       if(ar) {
+                               location[0]= event->x - ar->winrct.xmin;
+                               location[1]= event->y - ar->winrct.ymin;
+                               RNA_int_set_array(op->ptr, "location", location);
+
+                               sample_color_exec(C, op);
+                       }
+                       break;
+       }
+
+       return OPERATOR_RUNNING_MODAL;
 }
 
 void PAINT_OT_sample_color(wmOperatorType *ot)
@@ -5159,6 +5177,7 @@ void PAINT_OT_sample_color(wmOperatorType *ot)
        /* api callbacks */
        ot->exec= sample_color_exec;
        ot->invoke= sample_color_invoke;
+       ot->modal= sample_color_modal;
        ot->poll= image_paint_poll;
 
        /* flags */
@@ -5306,16 +5325,16 @@ static int texture_paint_radial_control_invoke(bContext *C, wmOperator *op, wmEv
 {
        ToolSettings *ts = CTX_data_scene(C)->toolsettings;
        toggle_paint_cursor(C, !ts->imapaint.paintcursor);
-       brush_radial_control_invoke(op, paint_brush(&ts->imapaint.paint), 0.5);
+       brush_radial_control_invoke(op, paint_brush(&ts->imapaint.paint), 1);
        return WM_radial_control_invoke(C, op, event);
 }
 
 static int texture_paint_radial_control_exec(bContext *C, wmOperator *op)
 {
        Brush *brush = paint_brush(&CTX_data_scene(C)->toolsettings->imapaint.paint);
-       int ret = brush_radial_control_exec(op, brush, 2);
-       char str[256];
-       WM_radial_control_string(op, str, 256);
+       int ret = brush_radial_control_exec(op, brush, 1);
+       char str[64];
+       WM_radial_control_string(op, str, sizeof(str));
 
        WM_event_add_notifier(C, NC_BRUSH|NA_EDITED, brush);
 
@@ -5349,7 +5368,7 @@ void PAINT_OT_texture_paint_radial_control(wmOperatorType *ot)
        ot->poll= texture_paint_poll;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
 }
 
 
@@ -5418,21 +5437,21 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
        /* override */
        ps.is_texbrush= 0;
        ps.is_airbrush= 1;
-       orig_brush_size= ps.brush->size;
-       ps.brush->size= 32; /* cover the whole image */
+       orig_brush_size= brush_size(ps.brush);
+       brush_set_size(ps.brush, 32); /* cover the whole image */
 
        ps.tool= PAINT_TOOL_DRAW; /* so pixels are initialized with minimal info */
 
        scene->toolsettings->imapaint.flag |= IMAGEPAINT_DRAWING;
 
-       undo_paint_push_begin(UNDO_PAINT_IMAGE, "Image Paint",
+       undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
                image_undo_restore, image_undo_free);
 
        /* allocate and initialize spacial data structures */
        project_paint_begin(&ps);
 
        if(ps.dm==NULL) {
-               ps.brush->size= orig_brush_size;
+               brush_set_size(ps.brush, orig_brush_size);
                return OPERATOR_CANCELLED;
        }
        else {
@@ -5456,7 +5475,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
        project_paint_end(&ps);
 
        scene->toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
-       ps.brush->size= orig_brush_size;
+       brush_set_size(ps.brush, orig_brush_size);
 
        return OPERATOR_FINISHED;
 }
@@ -5501,7 +5520,14 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
        if(w > maxsize) w= maxsize;
        if(h > maxsize) h= maxsize;
 
-       ibuf= ED_view3d_draw_offscreen_imbuf(CTX_data_scene(C), CTX_wm_view3d(C), CTX_wm_region(C), w, h);
+       ibuf= ED_view3d_draw_offscreen_imbuf(CTX_data_scene(C), CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect);
+       if(!ibuf) {
+               /* Mostly happens when OpenGL offscreen buffer was failed to create, */
+               /* but could be other reasons. Should be handled in the future. nazgul */
+               BKE_report(op->reports, RPT_ERROR, "Failed to create OpenGL offscreen buffer.");
+               return OPERATOR_CANCELLED;
+       }
+
        image= BKE_add_image_imbuf(ibuf);
 
        if(image) {