doxygen: prevent GPL license block from being parsed as doxygen comment.
[blender.git] / source / blender / blenkernel / intern / brush.c
index ec761c27c64b12f1cf801028ee6176b2380246a5..15404acc10539d95a930ea4ea5b4a01f06faf177 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
@@ -15,7 +15,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
 
 #include "DNA_brush_types.h"
 #include "DNA_color_types.h"
 
 #include "DNA_brush_types.h"
 #include "DNA_color_types.h"
-#include "DNA_image_types.h"
-#include "DNA_object_types.h"
-#include "DNA_texture_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_object_types.h"
 #include "DNA_windowmanager_types.h"
 
 #include "WM_types.h"
 #include "DNA_windowmanager_types.h"
 
 #include "WM_types.h"
@@ -47,6 +45,7 @@
 #include "BLI_math.h"
 #include "BLI_blenlib.h"
 #include "BLI_rand.h"
 #include "BLI_math.h"
 #include "BLI_blenlib.h"
 #include "BLI_rand.h"
+#include "BLI_utildefines.h"
 
 #include "BKE_brush.h"
 #include "BKE_colortools.h"
 
 #include "BKE_brush.h"
 #include "BKE_colortools.h"
@@ -56,9 +55,7 @@
 #include "BKE_main.h"
 #include "BKE_paint.h"
 #include "BKE_texture.h"
 #include "BKE_main.h"
 #include "BKE_paint.h"
 #include "BKE_texture.h"
-#include "BKE_utildefines.h"
-
-
+#include "BKE_icons.h"
 
 #include "IMB_imbuf.h"
 #include "IMB_imbuf_types.h"
 
 #include "IMB_imbuf.h"
 #include "IMB_imbuf_types.h"
 #include "RE_render_ext.h" /* externtex */
 #include "RE_shader_ext.h"
 
 #include "RE_render_ext.h" /* externtex */
 #include "RE_shader_ext.h"
 
+static void brush_set_defaults(Brush *brush)
+{
+       brush->blend = 0;
+       brush->flag = 0;
+
+       brush->ob_mode = OB_MODE_ALL_PAINT;
+
+       /* BRUSH SCULPT TOOL SETTINGS */
+       brush->size= 35; /* radius of the brush in pixels */
+       brush->alpha= 0.5f; /* brush strength/intensity probably variable should be renamed? */
+       brush->autosmooth_factor= 0.0f;
+       brush->crease_pinch_factor= 0.5f;
+       brush->sculpt_plane = SCULPT_DISP_DIR_AREA;
+       brush->plane_offset= 0.0f; /* how far above or below the plane that is found by averaging the faces */
+       brush->plane_trim= 0.5f;
+       brush->clone.alpha= 0.5f;
+       brush->normal_weight= 0.0f;
+       brush->flag |= BRUSH_ALPHA_PRESSURE;
+
+       /* BRUSH PAINT TOOL SETTINGS */
+       brush->rgb[0]= 1.0f; /* default rgb color of the brush when painting - white */
+       brush->rgb[1]= 1.0f;
+       brush->rgb[2]= 1.0f;
+
+       /* BRUSH STROKE SETTINGS */
+       brush->flag |= (BRUSH_SPACE|BRUSH_SPACE_ATTEN);
+       brush->spacing= 10; /* how far each brush dot should be spaced as a percentage of brush diameter */
+
+       brush->smooth_stroke_radius= 75;
+       brush->smooth_stroke_factor= 0.9f;
+
+       brush->rate= 0.1f; /* time delay between dots of paint or sculpting when doing airbrush mode */
+
+       brush->jitter= 0.0f;
+
+       /* BRUSH TEXTURE SETTINGS */
+       default_mtex(&brush->mtex);
+
+       brush->texture_sample_bias= 0; /* value to added to texture samples */
+       brush->texture_overlay_alpha= 33;
+
+       /* brush appearance  */
+
+       brush->add_col[0]= 1.00; /* add mode color is light red */
+       brush->add_col[1]= 0.39;
+       brush->add_col[2]= 0.39;
+
+       brush->sub_col[0]= 0.39; /* subtract mode color is light blue */
+       brush->sub_col[1]= 0.39;
+       brush->sub_col[2]= 1.00;
+}
+
 /* Datablock add/copy/free/make_local */
 
 Brush *add_brush(const char *name)
 /* Datablock add/copy/free/make_local */
 
 Brush *add_brush(const char *name)
@@ -74,27 +123,17 @@ Brush *add_brush(const char *name)
 
        brush= alloc_libblock(&G.main->brush, ID_BR, name);
 
 
        brush= alloc_libblock(&G.main->brush, ID_BR, name);
 
-       brush->rgb[0]= 1.0f;
-       brush->rgb[1]= 1.0f;
-       brush->rgb[2]= 1.0f;
-       brush->alpha= 0.2f;
-       brush->size= 25;
-       brush->spacing= 7.5f;
-       brush->smooth_stroke_radius= 75;
-       brush->smooth_stroke_factor= 0.9;
-       brush->rate= 0.1f;
-       brush->jitter= 0.0f;
-       brush->clone.alpha= 0.5;
-       brush->sculpt_tool = SCULPT_TOOL_DRAW;
-       brush->flag |= BRUSH_SPACE;
+       /* enable fake user by default */
+       brush->id.flag |= LIB_FAKEUSER;
 
 
+       brush_set_defaults(brush);
+
+       brush->sculpt_tool = SCULPT_TOOL_DRAW; /* sculpting defaults to the draw tool for new brushes */
+
+        /* the default alpha falloff curve */
        brush_curve_preset(brush, CURVE_PRESET_SMOOTH);
 
        brush_curve_preset(brush, CURVE_PRESET_SMOOTH);
 
-       /* enable fake user by default */
-       brush->id.flag |= LIB_FAKEUSER;
-       brush_toggled_fake_user(brush);
-       
-       return brush;   
+       return brush;
 }
 
 Brush *copy_brush(Brush *brush)
 }
 
 Brush *copy_brush(Brush *brush)
@@ -103,14 +142,20 @@ Brush *copy_brush(Brush *brush)
        
        brushn= copy_libblock(brush);
 
        
        brushn= copy_libblock(brush);
 
-       if(brush->mtex.tex) id_us_plus((ID*)brush->mtex.tex);
-       
+       if (brush->mtex.tex)
+               id_us_plus((ID*)brush->mtex.tex);
+
+       if (brush->icon_imbuf)
+               brushn->icon_imbuf= IMB_dupImBuf(brush->icon_imbuf);
+
+       brushn->preview = NULL;
+
        brushn->curve= curvemapping_copy(brush->curve);
 
        /* enable fake user by default */
        if (!(brushn->id.flag & LIB_FAKEUSER)) {
                brushn->id.flag |= LIB_FAKEUSER;
        brushn->curve= curvemapping_copy(brush->curve);
 
        /* enable fake user by default */
        if (!(brushn->id.flag & LIB_FAKEUSER)) {
                brushn->id.flag |= LIB_FAKEUSER;
-               brush_toggled_fake_user(brushn);
+               brushn->id.us++;
        }
        
        return brushn;
        }
        
        return brushn;
@@ -119,8 +164,14 @@ Brush *copy_brush(Brush *brush)
 /* not brush itself */
 void free_brush(Brush *brush)
 {
 /* not brush itself */
 void free_brush(Brush *brush)
 {
-       if(brush->mtex.tex) brush->mtex.tex->id.us--;
-       
+       if (brush->mtex.tex)
+               brush->mtex.tex->id.us--;
+
+       if (brush->icon_imbuf)
+               IMB_freeImBuf(brush->icon_imbuf);
+
+       BKE_previewimg_free(&(brush->preview));
+
        curvemapping_free(brush->curve);
 }
 
        curvemapping_free(brush->curve);
 }
 
@@ -135,13 +186,13 @@ void make_local_brush(Brush *brush)
        Scene *scene;
        int local= 0, lib= 0;
 
        Scene *scene;
        int local= 0, lib= 0;
 
-       if(brush->id.lib==0) return;
+       if(brush->id.lib==NULL) return;
 
        if(brush->clone.image) {
                /* special case: ima always local immediately */
 
        if(brush->clone.image) {
                /* special case: ima always local immediately */
-               brush->clone.image->id.lib= 0;
+               brush->clone.image->id.lib= NULL;
                brush->clone.image->id.flag= LIB_LOCAL;
                brush->clone.image->id.flag= LIB_LOCAL;
-               new_id(0, (ID *)brush->clone.image, 0);
+               new_id(NULL, (ID *)brush->clone.image, NULL);
        }
 
        for(scene= G.main->scene.first; scene; scene=scene->id.next)
        }
 
        for(scene= G.main->scene.first; scene; scene=scene->id.next)
@@ -149,16 +200,16 @@ void make_local_brush(Brush *brush)
                        if(scene->id.lib) lib= 1;
                        else local= 1;
                }
                        if(scene->id.lib) lib= 1;
                        else local= 1;
                }
-       
+
        if(local && lib==0) {
        if(local && lib==0) {
-               brush->id.lib= 0;
+               brush->id.lib= NULL;
                brush->id.flag= LIB_LOCAL;
                brush->id.flag= LIB_LOCAL;
-               new_id(0, (ID *)brush, 0);
+               new_id(NULL, (ID *)brush, NULL);
 
                /* enable fake user by default */
                if (!(brush->id.flag & LIB_FAKEUSER)) {
                        brush->id.flag |= LIB_FAKEUSER;
 
                /* enable fake user by default */
                if (!(brush->id.flag & LIB_FAKEUSER)) {
                        brush->id.flag |= LIB_FAKEUSER;
-                       brush_toggled_fake_user(brush);
+                       brush->id.us++;
                }
        }
        else if(local && lib) {
                }
        }
        else if(local && lib) {
@@ -168,7 +219,7 @@ void make_local_brush(Brush *brush)
                
                for(scene= G.main->scene.first; scene; scene=scene->id.next)
                        if(paint_brush(&scene->toolsettings->imapaint.paint)==brush)
                
                for(scene= G.main->scene.first; scene; scene=scene->id.next)
                        if(paint_brush(&scene->toolsettings->imapaint.paint)==brush)
-                               if(scene->id.lib==0) {
+                               if(scene->id.lib==NULL) {
                                        paint_brush_set(&scene->toolsettings->imapaint.paint, brushn);
                                        brushn->id.us++;
                                        brush->id.us--;
                                        paint_brush_set(&scene->toolsettings->imapaint.paint, brushn);
                                        brushn->id.us++;
                                        brush->id.us--;
@@ -176,56 +227,175 @@ void make_local_brush(Brush *brush)
        }
 }
 
        }
 }
 
-/* Library Operations */
-
-int brush_set_nr(Brush **current_brush, int nr, const char *name)
+void brush_debug_print_state(Brush *br)
 {
 {
-       ID *idtest, *id;
+       /* create a fake brush and set it to the defaults */
+       Brush def= {{NULL}};
+       brush_set_defaults(&def);
        
        
-       id= (ID*)(*current_brush);
-       idtest= (ID*)BLI_findlink(&G.main->brush, nr-1);
+#define BR_TEST(field, t)                                      \
+       if(br->field != def.field)                              \
+               printf("br->" #field " = %" #t ";\n", br->field)
+
+#define BR_TEST_FLAG(_f)                               \
+       if((br->flag & _f) && !(def.flag & _f))         \
+               printf("br->flag |= " #_f ";\n");       \
+       else if(!(br->flag & _f) && (def.flag & _f))    \
+               printf("br->flag &= ~" #_f ";\n")
        
        
-       if(idtest==0) { /* new brush */
-               if(id) idtest= (ID *)copy_brush((Brush *)id);
-               else idtest= (ID *)add_brush(name);
-               idtest->us--;
-       }
-       if(idtest!=id) {
-               brush_delete(current_brush);
-               *current_brush= (Brush *)idtest;
-               id_us_plus(idtest);
-
-               return 1;
-       }
 
 
-       return 0;
-}
-
-int brush_delete(Brush **current_brush)
-{
-       if (*current_brush) {
-               (*current_brush)->id.us--;
-               *current_brush= NULL;
-
-               return 1;
-       }
-
-       return 0;
+       /* print out any non-default brush state */
+       BR_TEST(normal_weight, f);
+
+       BR_TEST(blend, d);
+       BR_TEST(size, d);
+
+       /* br->flag */
+       BR_TEST_FLAG(BRUSH_AIRBRUSH);
+       BR_TEST_FLAG(BRUSH_TORUS);
+       BR_TEST_FLAG(BRUSH_ALPHA_PRESSURE);
+       BR_TEST_FLAG(BRUSH_SIZE_PRESSURE);
+       BR_TEST_FLAG(BRUSH_JITTER_PRESSURE);
+       BR_TEST_FLAG(BRUSH_SPACING_PRESSURE);
+       BR_TEST_FLAG(BRUSH_FIXED_TEX);
+       BR_TEST_FLAG(BRUSH_RAKE);
+       BR_TEST_FLAG(BRUSH_ANCHORED);
+       BR_TEST_FLAG(BRUSH_DIR_IN);
+       BR_TEST_FLAG(BRUSH_SPACE);
+       BR_TEST_FLAG(BRUSH_SMOOTH_STROKE);
+       BR_TEST_FLAG(BRUSH_PERSISTENT);
+       BR_TEST_FLAG(BRUSH_ACCUMULATE);
+       BR_TEST_FLAG(BRUSH_LOCK_ALPHA);
+       BR_TEST_FLAG(BRUSH_ORIGINAL_NORMAL);
+       BR_TEST_FLAG(BRUSH_OFFSET_PRESSURE);
+       BR_TEST_FLAG(BRUSH_SPACE_ATTEN);
+       BR_TEST_FLAG(BRUSH_ADAPTIVE_SPACE);
+       BR_TEST_FLAG(BRUSH_LOCK_SIZE);
+       BR_TEST_FLAG(BRUSH_TEXTURE_OVERLAY);
+       BR_TEST_FLAG(BRUSH_EDGE_TO_EDGE);
+       BR_TEST_FLAG(BRUSH_RESTORE_MESH);
+       BR_TEST_FLAG(BRUSH_INVERSE_SMOOTH_PRESSURE);
+       BR_TEST_FLAG(BRUSH_RANDOM_ROTATION);
+       BR_TEST_FLAG(BRUSH_PLANE_TRIM);
+       BR_TEST_FLAG(BRUSH_FRONTFACE);
+       BR_TEST_FLAG(BRUSH_CUSTOM_ICON);
+
+       BR_TEST(jitter, f);
+       BR_TEST(spacing, d);
+       BR_TEST(smooth_stroke_radius, d);
+       BR_TEST(smooth_stroke_factor, f);
+       BR_TEST(rate, f);
+
+       BR_TEST(alpha, f);
+
+       BR_TEST(sculpt_plane, d);
+
+       BR_TEST(plane_offset, f);
+
+       BR_TEST(autosmooth_factor, f);
+
+       BR_TEST(crease_pinch_factor, f);
+
+       BR_TEST(plane_trim, f);
+
+       BR_TEST(texture_sample_bias, f);
+       BR_TEST(texture_overlay_alpha, d);
+
+       BR_TEST(add_col[0], f);
+       BR_TEST(add_col[1], f);
+       BR_TEST(add_col[2], f);
+       BR_TEST(sub_col[0], f);
+       BR_TEST(sub_col[1], f);
+       BR_TEST(sub_col[2], f);
+
+       printf("\n");
+       
+#undef BR_TEST
+#undef BR_TEST_FLAG
 }
 
 }
 
-void brush_toggled_fake_user(Brush *brush)
+void brush_reset_sculpt(Brush *br)
 {
 {
-       ID *id= (ID*)brush;
-       if(id) {
-               if(id->flag & LIB_FAKEUSER) {
-                       id_us_plus(id);
-               } else {
-                       id->us--;
-               }
+       /* enable this to see any non-default
+          settings used by a brush:
+
+          brush_debug_print_state(br);
+       */
+
+       brush_set_defaults(br);
+       brush_curve_preset(br, CURVE_PRESET_SMOOTH);
+
+       switch(br->sculpt_tool) {
+       case SCULPT_TOOL_CLAY:
+               br->flag |= BRUSH_FRONTFACE;
+               break;
+       case SCULPT_TOOL_CREASE:
+               br->flag |= BRUSH_DIR_IN;
+               br->alpha = 0.25;
+               break;
+       case SCULPT_TOOL_FILL:
+               br->add_col[1] = 1;
+               br->sub_col[0] = 0.25;
+               br->sub_col[1] = 1;
+               break;
+       case SCULPT_TOOL_FLATTEN:
+               br->add_col[1] = 1;
+               br->sub_col[0] = 0.25;
+               br->sub_col[1] = 1;
+               break;
+       case SCULPT_TOOL_INFLATE:
+               br->add_col[0] = 0.750000;
+               br->add_col[1] = 0.750000;
+               br->add_col[2] = 0.750000;
+               br->sub_col[0] = 0.250000;
+               br->sub_col[1] = 0.250000;
+               br->sub_col[2] = 0.250000;
+               break;
+       case SCULPT_TOOL_NUDGE:
+               br->add_col[0] = 0.250000;
+               br->add_col[1] = 1.000000;
+               br->add_col[2] = 0.250000;
+               break;
+       case SCULPT_TOOL_PINCH:
+               br->add_col[0] = 0.750000;
+               br->add_col[1] = 0.750000;
+               br->add_col[2] = 0.750000;
+               br->sub_col[0] = 0.250000;
+               br->sub_col[1] = 0.250000;
+               br->sub_col[2] = 0.250000;
+               break;
+       case SCULPT_TOOL_SCRAPE:
+               br->add_col[1] = 1.000000;
+               br->sub_col[0] = 0.250000;
+               br->sub_col[1] = 1.000000;
+               break;
+       case SCULPT_TOOL_ROTATE:
+               break;
+       case SCULPT_TOOL_SMOOTH:
+               br->flag &= ~BRUSH_SPACE_ATTEN;
+               br->spacing = 5;
+               br->add_col[0] = 0.750000;
+               br->add_col[1] = 0.750000;
+               br->add_col[2] = 0.750000;
+               break;
+       case SCULPT_TOOL_GRAB:
+       case SCULPT_TOOL_SNAKE_HOOK:
+       case SCULPT_TOOL_THUMB:
+               br->size = 75;
+               br->flag &= ~BRUSH_ALPHA_PRESSURE;
+               br->flag &= ~BRUSH_SPACE;
+               br->flag &= ~BRUSH_SPACE_ATTEN;
+               br->add_col[0] = 0.250000;
+               br->add_col[1] = 1.000000;
+               br->add_col[2] = 0.250000;
+               break;
+       default:
+               break;
        }
 }
 
        }
 }
 
-void brush_curve_preset(Brush *b, CurveMappingPreset preset)
+/* Library Operations */
+void brush_curve_preset(Brush *b, /*CurveMappingPreset*/int preset)
 {
        CurveMap *cm = NULL;
 
 {
        CurveMap *cm = NULL;
 
@@ -235,7 +405,8 @@ void brush_curve_preset(Brush *b, CurveMappingPreset preset)
        cm = b->curve->cm;
        cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
 
        cm = b->curve->cm;
        cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
 
-       curvemap_reset(cm, &b->curve->clipr, preset);
+       b->curve->preset = preset;
+       curvemap_reset(cm, &b->curve->clipr, b->curve->preset, CURVEMAP_SLOPE_NEGATIVE);
        curvemapping_changed(b->curve, 0);
 }
 
        curvemapping_changed(b->curve, 0);
 }
 
@@ -253,7 +424,7 @@ int brush_texture_set_nr(Brush *brush, int nr)
        id= (ID *)brush->mtex.tex;
 
        idtest= (ID*)BLI_findlink(&G.main->tex, nr-1);
        id= (ID *)brush->mtex.tex;
 
        idtest= (ID*)BLI_findlink(&G.main->tex, nr-1);
-       if(idtest==0) { /* new tex */
+       if(idtest==NULL) { /* new tex */
                if(id) idtest= (ID *)copy_texture((Tex *)id);
                else idtest= (ID *)add_texture("Tex");
                idtest->us--;
                if(id) idtest= (ID *)copy_texture((Tex *)id);
                else idtest= (ID *)add_texture("Tex");
                idtest->us--;
@@ -307,26 +478,21 @@ int brush_clone_image_delete(Brush *brush)
        return 0;
 }
 
        return 0;
 }
 
-void brush_check_exists(Brush **brush, const char *name)
-{
-       if(*brush==NULL)
-               brush_set_nr(brush, 1, name);
-}
-
 /* Brush Sampling */
 /* Brush Sampling */
-void brush_sample_tex(Brush *brush, float *xy, float *rgba)
+void brush_sample_tex(Brush *brush, float *xy, float *rgba, const int thread)
 {
        MTex *mtex= &brush->mtex;
 
        if (mtex && mtex->tex) {
                float co[3], tin, tr, tg, tb, ta;
                int hasrgb;
 {
        MTex *mtex= &brush->mtex;
 
        if (mtex && mtex->tex) {
                float co[3], tin, tr, tg, tb, ta;
                int hasrgb;
-               
-               co[0]= xy[0]/(brush->size >> 1);
-               co[1]= xy[1]/(brush->size >> 1);
+               const int radius= brush_size(brush);
+
+               co[0]= xy[0]/radius;
+               co[1]= xy[1]/radius;
                co[2]= 0.0f;
 
                co[2]= 0.0f;
 
-               hasrgb= externtex(mtex, co, &tin, &tr, &tg, &tb, &ta);
+               hasrgb= externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread);
 
                if (hasrgb) {
                        rgba[0]= tr;
 
                if (hasrgb) {
                        rgba[0]= tr;
@@ -346,23 +512,24 @@ void brush_sample_tex(Brush *brush, float *xy, float *rgba)
 }
 
 
 }
 
 
-void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **outbuf)
+void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf **outbuf)
 {
        ImBuf *ibuf;
        float xy[2], dist, rgba[4], *dstf;
        int x, y, rowbytes, xoff, yoff, imbflag;
 {
        ImBuf *ibuf;
        float xy[2], dist, rgba[4], *dstf;
        int x, y, rowbytes, xoff, yoff, imbflag;
-       int maxsize = brush->size >> 1;
+       const int radius= brush_size(brush);
        char *dst, crgb[3];
        char *dst, crgb[3];
+       const float alpha= brush_alpha(brush);
 
        imbflag= (flt)? IB_rectfloat: IB_rect;
 
        imbflag= (flt)? IB_rectfloat: IB_rect;
-       xoff = -size/2.0f + 0.5f;
-       yoff = -size/2.0f + 0.5f;
-       rowbytes= size*4;
+       xoff = -bufsize/2.0f + 0.5f;
+       yoff = -bufsize/2.0f + 0.5f;
+       rowbytes= bufsize*4;
 
        if (*outbuf)
                ibuf= *outbuf;
        else
 
        if (*outbuf)
                ibuf= *outbuf;
        else
-               ibuf= IMB_allocImBuf(size, size, 32, imbflag, 0);
+               ibuf= IMB_allocImBuf(bufsize, bufsize, 32, imbflag);
 
        if (flt) {
                for (y=0; y < ibuf->y; y++) {
 
        if (flt) {
                for (y=0; y < ibuf->y; y++) {
@@ -376,20 +543,20 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **o
                                        dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
 
                                        VECCOPY(dstf, brush->rgb);
                                        dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
 
                                        VECCOPY(dstf, brush->rgb);
-                                       dstf[3]= brush->alpha*brush_curve_strength_clamp(brush, dist, maxsize);
+                                       dstf[3]= alpha*brush_curve_strength_clamp(brush, dist, radius);
                                }
                                else if (texfall == 1) {
                                }
                                else if (texfall == 1) {
-                                       brush_sample_tex(brush, xy, dstf);
+                                       brush_sample_tex(brush, xy, dstf, 0);
                                }
                                else {
                                        dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
 
                                }
                                else {
                                        dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
 
-                                       brush_sample_tex(brush, xy, rgba);
+                                       brush_sample_tex(brush, xy, rgba, 0);
 
                                        dstf[0] = rgba[0]*brush->rgb[0];
                                        dstf[1] = rgba[1]*brush->rgb[1];
                                        dstf[2] = rgba[2]*brush->rgb[2];
 
                                        dstf[0] = rgba[0]*brush->rgb[0];
                                        dstf[1] = rgba[1]*brush->rgb[1];
                                        dstf[2] = rgba[2]*brush->rgb[2];
-                                       dstf[3] = rgba[3]*brush->alpha*brush_curve_strength_clamp(brush, dist, maxsize);
+                                       dstf[3] = rgba[3]*alpha*brush_curve_strength_clamp(brush, dist, radius);
                                }
                        }
                }
                                }
                        }
                }
@@ -412,10 +579,10 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **o
                                        dst[0]= crgb[0];
                                        dst[1]= crgb[1];
                                        dst[2]= crgb[2];
                                        dst[0]= crgb[0];
                                        dst[1]= crgb[1];
                                        dst[2]= crgb[2];
-                                       dst[3]= FTOCHAR(brush->alpha*brush_curve_strength(brush, dist, maxsize));
+                                       dst[3]= FTOCHAR(alpha*brush_curve_strength(brush, dist, radius));
                                }
                                else if (texfall == 1) {
                                }
                                else if (texfall == 1) {
-                                       brush_sample_tex(brush, xy, rgba);
+                                       brush_sample_tex(brush, xy, rgba, 0);
                                        dst[0]= FTOCHAR(rgba[0]);
                                        dst[1]= FTOCHAR(rgba[1]);
                                        dst[2]= FTOCHAR(rgba[2]);
                                        dst[0]= FTOCHAR(rgba[0]);
                                        dst[1]= FTOCHAR(rgba[1]);
                                        dst[2]= FTOCHAR(rgba[2]);
@@ -424,11 +591,11 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **o
                                else {
                                        dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
 
                                else {
                                        dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
 
-                                       brush_sample_tex(brush, xy, rgba);
+                                       brush_sample_tex(brush, xy, rgba, 0);
                                        dst[0] = FTOCHAR(rgba[0]*brush->rgb[0]);
                                        dst[1] = FTOCHAR(rgba[1]*brush->rgb[1]);
                                        dst[2] = FTOCHAR(rgba[2]*brush->rgb[2]);
                                        dst[0] = FTOCHAR(rgba[0]*brush->rgb[0]);
                                        dst[1] = FTOCHAR(rgba[1]*brush->rgb[1]);
                                        dst[2] = FTOCHAR(rgba[2]*brush->rgb[2]);
-                                       dst[3] = FTOCHAR(rgba[3]*brush->alpha*brush_curve_strength_clamp(brush, dist, maxsize));
+                                       dst[3] = FTOCHAR(rgba[3]*alpha*brush_curve_strength_clamp(brush, dist, radius));
                                }
                        }
                }
                                }
                        }
                }
@@ -442,7 +609,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **o
 typedef struct BrushPainterCache {
        short enabled;
 
 typedef struct BrushPainterCache {
        short enabled;
 
-       int size;                       /* size override, if 0 uses brush->size */
+       int size;                       /* size override, if 0 uses 2*brush_size(brush) */
        short flt;                      /* need float imbuf? */
        short texonly;          /* no alpha, color or fallof, only texture in imbuf */
 
        short flt;                      /* need float imbuf? */
        short texonly;          /* no alpha, color or fallof, only texture in imbuf */
 
@@ -487,8 +654,8 @@ BrushPainter *brush_painter_new(Brush *brush)
        painter->firsttouch= 1;
        painter->cache.lastsize= -1; /* force ibuf create in refresh */
 
        painter->firsttouch= 1;
        painter->cache.lastsize= -1; /* force ibuf create in refresh */
 
-       painter->startsize = brush->size;
-       painter->startalpha = brush->alpha;
+       painter->startsize = brush_size(brush);
+       painter->startalpha = brush_alpha(brush);
        painter->startjitter = brush->jitter;
        painter->startspacing = brush->spacing;
 
        painter->startjitter = brush->jitter;
        painter->startspacing = brush->spacing;
 
@@ -521,8 +688,8 @@ void brush_painter_free(BrushPainter *painter)
 {
        Brush *brush = painter->brush;
 
 {
        Brush *brush = painter->brush;
 
-       brush->size = painter->startsize;
-       brush->alpha = painter->startalpha;
+       brush_set_size(brush, painter->startsize);
+       brush_set_alpha(brush, painter->startalpha);
        brush->jitter = painter->startjitter;
        brush->spacing = painter->startspacing;
 
        brush->jitter = painter->startjitter;
        brush->spacing = painter->startspacing;
 
@@ -539,9 +706,10 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i
        float *bf, *mf, *tf, *otf=NULL, xoff, yoff, xy[2], rgba[4];
        char *b, *m, *t, *ot= NULL;
        int dotexold, origx= x, origy= y;
        float *bf, *mf, *tf, *otf=NULL, xoff, yoff, xy[2], rgba[4];
        char *b, *m, *t, *ot= NULL;
        int dotexold, origx= x, origy= y;
+       const int radius= brush_size(brush);
 
 
-       xoff = -brush->size/2.0f + 0.5f;
-       yoff = -brush->size/2.0f + 0.5f;
+       xoff = -radius + 0.5f;
+       yoff = -radius + 0.5f;
        xoff += (int)pos[0] - (int)painter->startpaintpos[0];
        yoff += (int)pos[1] - (int)painter->startpaintpos[1];
 
        xoff += (int)pos[0] - (int)painter->startpaintpos[0];
        yoff += (int)pos[1] - (int)painter->startpaintpos[1];
 
@@ -570,7 +738,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i
                                        xy[0] = x + xoff;
                                        xy[1] = y + yoff;
 
                                        xy[0] = x + xoff;
                                        xy[1] = y + yoff;
 
-                                       brush_sample_tex(brush, xy, tf);
+                                       brush_sample_tex(brush, xy, tf, 0);
                                }
 
                                bf[0] = tf[0]*mf[0];
                                }
 
                                bf[0] = tf[0]*mf[0];
@@ -601,7 +769,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i
                                        xy[0] = x + xoff;
                                        xy[1] = y + yoff;
 
                                        xy[0] = x + xoff;
                                        xy[1] = y + yoff;
 
-                                       brush_sample_tex(brush, xy, rgba);
+                                       brush_sample_tex(brush, xy, rgba, 0);
                                        t[0]= FTOCHAR(rgba[0]);
                                        t[1]= FTOCHAR(rgba[1]);
                                        t[2]= FTOCHAR(rgba[2]);
                                        t[0]= FTOCHAR(rgba[0]);
                                        t[1]= FTOCHAR(rgba[1]);
                                        t[2]= FTOCHAR(rgba[2]);
@@ -623,14 +791,15 @@ static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, float
        BrushPainterCache *cache= &painter->cache;
        ImBuf *oldtexibuf, *ibuf;
        int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
        BrushPainterCache *cache= &painter->cache;
        ImBuf *oldtexibuf, *ibuf;
        int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
+       const int diameter= 2*brush_size(brush);
 
        imbflag= (cache->flt)? IB_rectfloat: IB_rect;
        if (!cache->ibuf)
 
        imbflag= (cache->flt)? IB_rectfloat: IB_rect;
        if (!cache->ibuf)
-               cache->ibuf= IMB_allocImBuf(brush->size, brush->size, 32, imbflag, 0);
+               cache->ibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag);
        ibuf= cache->ibuf;
 
        oldtexibuf= cache->texibuf;
        ibuf= cache->ibuf;
 
        oldtexibuf= cache->texibuf;
-       cache->texibuf= IMB_allocImBuf(brush->size, brush->size, 32, imbflag, 0);
+       cache->texibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag);
 
        if (oldtexibuf) {
                srcx= srcy= 0;
 
        if (oldtexibuf) {
                srcx= srcy= 0;
@@ -677,9 +846,13 @@ static void brush_painter_refresh_cache(BrushPainter *painter, float *pos)
        MTex *mtex= &brush->mtex;
        int size;
        short flt;
        MTex *mtex= &brush->mtex;
        int size;
        short flt;
+       const int diameter= 2*brush_size(brush);
+       const float alpha= brush_alpha(brush);
 
 
-       if ((brush->size != cache->lastsize) || (brush->alpha != cache->lastalpha)
-           || (brush->jitter != cache->lastjitter)) {
+       if (diameter != cache->lastsize ||
+               alpha != cache->lastalpha ||
+               brush->jitter != cache->lastjitter)
+       {
                if (cache->ibuf) {
                        IMB_freeImBuf(cache->ibuf);
                        cache->ibuf= NULL;
                if (cache->ibuf) {
                        IMB_freeImBuf(cache->ibuf);
                        cache->ibuf= NULL;
@@ -690,7 +863,7 @@ static void brush_painter_refresh_cache(BrushPainter *painter, float *pos)
                }
 
                flt= cache->flt;
                }
 
                flt= cache->flt;
-               size= (cache->size)? cache->size: brush->size;
+               size= (cache->size)? cache->size: diameter;
 
                if (!(mtex && mtex->tex) || (mtex->tex->type==0)) {
                        brush_imbuf_new(brush, flt, 0, size, &cache->ibuf);
 
                if (!(mtex && mtex->tex) || (mtex->tex->type==0)) {
                        brush_imbuf_new(brush, flt, 0, size, &cache->ibuf);
@@ -702,8 +875,8 @@ static void brush_painter_refresh_cache(BrushPainter *painter, float *pos)
                else
                        brush_imbuf_new(brush, flt, 2, size, &cache->ibuf);
 
                else
                        brush_imbuf_new(brush, flt, 2, size, &cache->ibuf);
 
-               cache->lastsize= brush->size;
-               cache->lastalpha= brush->alpha;
+               cache->lastsize= diameter;
+               cache->lastalpha= alpha;
                cache->lastjitter= brush->jitter;
        }
        else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) {
                cache->lastjitter= brush->jitter;
        }
        else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) {
@@ -722,21 +895,37 @@ void brush_painter_break_stroke(BrushPainter *painter)
 
 static void brush_apply_pressure(BrushPainter *painter, Brush *brush, float pressure)
 {
 
 static void brush_apply_pressure(BrushPainter *painter, Brush *brush, float pressure)
 {
-       if (brush->flag & BRUSH_ALPHA_PRESSURE
-               brush->alpha = MAX2(0.0, painter->startalpha*pressure);
-       if (brush->flag & BRUSH_SIZE_PRESSURE)
-               brush->size = MAX2(1.0, painter->startsize*pressure);
+       if (brush_use_alpha_pressure(brush)
+               brush_set_alpha(brush, MAX2(0.0, painter->startalpha*pressure));
+       if (brush_use_size_pressure(brush))
+               brush_set_size(brush, MAX2(1.0, painter->startsize*pressure));
        if (brush->flag & BRUSH_JITTER_PRESSURE)
                brush->jitter = MAX2(0.0, painter->startjitter*pressure);
        if (brush->flag & BRUSH_SPACING_PRESSURE)
                brush->spacing = MAX2(1.0, painter->startspacing*(1.5f-pressure));
 }
 
        if (brush->flag & BRUSH_JITTER_PRESSURE)
                brush->jitter = MAX2(0.0, painter->startjitter*pressure);
        if (brush->flag & BRUSH_SPACING_PRESSURE)
                brush->spacing = MAX2(1.0, painter->startspacing*(1.5f-pressure));
 }
 
-static void brush_jitter_pos(Brush *brush, float *pos, float *jitterpos)
+void brush_jitter_pos(Brush *brush, float *pos, float *jitterpos)
 {
 {
-       if(brush->jitter){
-               jitterpos[0] = pos[0] + ((BLI_frand()-0.5f) * brush->size * brush->jitter * 2);
-               jitterpos[1] = pos[1] + ((BLI_frand()-0.5f) * brush->size * brush->jitter * 2);
+       int use_jitter= brush->jitter != 0;
+
+       /* jitter-ed brush gives wierd and unpredictable result for this
+          kinds of stroke, so manyally disable jitter usage (sergey) */
+       use_jitter&= (brush->flag & (BRUSH_RESTORE_MESH|BRUSH_ANCHORED)) == 0;
+
+       if(use_jitter){
+               float rand_pos[2];
+               const int radius= brush_size(brush);
+               const int diameter= 2*radius;
+
+               // find random position within a circle of diameter 1
+               do {
+                       rand_pos[0] = BLI_frand()-0.5f;
+                       rand_pos[1] = BLI_frand()-0.5f;
+               } while (len_v2(rand_pos) > 0.5f);
+
+               jitterpos[0] = pos[0] + 2*rand_pos[0]*diameter*brush->jitter;
+               jitterpos[1] = pos[1] + 2*rand_pos[1]*diameter*brush->jitter;
        }
        else {
                VECCOPY2D(jitterpos, pos);
        }
        else {
                VECCOPY2D(jitterpos, pos);
@@ -775,7 +964,7 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl
                double starttime, curtime= time;
 
                /* compute brush spacing adapted to brush size */
                double starttime, curtime= time;
 
                /* compute brush spacing adapted to brush size */
-               spacing= brush->rate; //brush->size*brush->spacing*0.01f;
+               spacing= brush->rate; //radius*brush->spacing*0.01f;
 
                /* setup starting time, direction vector and accumulated time */
                starttime= painter->accumtime;
 
                /* setup starting time, direction vector and accumulated time */
                starttime= painter->accumtime;
@@ -806,11 +995,12 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl
        else {
                float startdistance, spacing, step, paintpos[2], dmousepos[2], finalpos[2];
                float t, len, press;
        else {
                float startdistance, spacing, step, paintpos[2], dmousepos[2], finalpos[2];
                float t, len, press;
+               const int radius= brush_size(brush);
 
 
-               /* compute brush spacing adapted to brush size, spacing may depend
+               /* compute brush spacing adapted to brush radius, spacing may depend
                   on pressure, so update it */
                brush_apply_pressure(painter, brush, painter->lastpressure);
                   on pressure, so update it */
                brush_apply_pressure(painter, brush, painter->lastpressure);
-               spacing= MAX2(1.0f, brush->size)*brush->spacing*0.01f;
+               spacing= MAX2(1.0f, radius)*brush->spacing*0.01f;
 
                /* setup starting distance, direction vector and accumulated distance */
                startdistance= painter->accumdistance;
 
                /* setup starting distance, direction vector and accumulated distance */
                startdistance= painter->accumdistance;
@@ -827,7 +1017,7 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl
                        t = step/len;
                        press= (1.0f-t)*painter->lastpressure + t*pressure;
                        brush_apply_pressure(painter, brush, press);
                        t = step/len;
                        press= (1.0f-t)*painter->lastpressure + t*pressure;
                        brush_apply_pressure(painter, brush, press);
-                       spacing= MAX2(1.0f, brush->size)*brush->spacing*0.01f;
+                       spacing= MAX2(1.0f, radius)*brush->spacing*0.01f;
 
                        brush_jitter_pos(brush, paintpos, finalpos);
 
 
                        brush_jitter_pos(brush, paintpos, finalpos);
 
@@ -877,8 +1067,8 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl
        painter->lastmousepos[1]= pos[1];
        painter->lastpressure= pressure;
 
        painter->lastmousepos[1]= pos[1];
        painter->lastpressure= pressure;
 
-       brush->alpha = painter->startalpha;
-       brush->size = painter->startsize;
+       brush_set_alpha(brush, painter->startalpha);
+       brush_set_size(brush, painter->startsize);
        brush->jitter = painter->startjitter;
        brush->spacing = painter->startspacing;
 
        brush->jitter = painter->startjitter;
        brush->spacing = painter->startspacing;
 
@@ -888,7 +1078,7 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl
 /* Uses the brush curve control to find a strength value between 0 and 1 */
 float brush_curve_strength_clamp(Brush *br, float p, const float len)
 {
 /* Uses the brush curve control to find a strength value between 0 and 1 */
 float brush_curve_strength_clamp(Brush *br, float p, const float len)
 {
-       if(p >= len)    p= 1.0f;
+       if(p >= len)    return 0;
        else                    p= p/len;
 
        p= curvemapping_evaluateF(br->curve, 0, p);
        else                    p= p/len;
 
        p= curvemapping_evaluateF(br->curve, 0, p);
@@ -900,9 +1090,12 @@ float brush_curve_strength_clamp(Brush *br, float p, const float len)
  * used for sculpt only */
 float brush_curve_strength(Brush *br, float p, const float len)
 {
  * used for sculpt only */
 float brush_curve_strength(Brush *br, float p, const float len)
 {
-       if(p >= len)    p= 1.0f;
-       else                    p= p/len;
-       return curvemapping_evaluateF(br->curve, 0, p);
+    if(p >= len)
+        p= 1.0f;
+    else
+        p= p/len;
+
+    return curvemapping_evaluateF(br->curve, 0, p);
 }
 
 /* TODO: should probably be unified with BrushPainter stuff? */
 }
 
 /* TODO: should probably be unified with BrushPainter stuff? */
@@ -910,13 +1103,11 @@ unsigned int *brush_gen_texture_cache(Brush *br, int half_side)
 {
        unsigned int *texcache = NULL;
        MTex *mtex = &br->mtex;
 {
        unsigned int *texcache = NULL;
        MTex *mtex = &br->mtex;
-       TexResult texres;
+       TexResult texres= {0};
        int hasrgb, ix, iy;
        int side = half_side * 2;
        int hasrgb, ix, iy;
        int side = half_side * 2;
-
-       memset(&texres, 0, sizeof(TexResult));
        
        
-       if(mtex && mtex->tex) {
+       if(mtex->tex) {
                float x, y, step = 2.0 / side, co[3];
 
                texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache");
                float x, y, step = 2.0 / side, co[3];
 
                texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache");
@@ -931,7 +1122,7 @@ unsigned int *brush_gen_texture_cache(Brush *br, int half_side)
                                co[2]= 0.0f;
                                
                                /* This is copied from displace modifier code */
                                co[2]= 0.0f;
                                
                                /* This is copied from displace modifier code */
-                               hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 1, &texres);
+                               hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres);
                        
                                /* 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 gave an RGB value, we assume it didn't give a valid
                                 * intensity, so calculate one (formula from do_material_tex).
@@ -939,7 +1130,7 @@ unsigned int *brush_gen_texture_cache(Brush *br, int half_side)
                                 */
                                if(hasrgb & TEX_RGB)
                                        texres.tin = (0.35 * texres.tr + 0.45 *
                                 */
                                if(hasrgb & TEX_RGB)
                                        texres.tin = (0.35 * texres.tr + 0.45 *
-                                                     texres.tg + 0.2 * texres.tb);
+                                                                 texres.tg + 0.2 * texres.tb);
 
                                texres.tin = texres.tin * 255.0;
                                ((char*)texcache)[(iy*side+ix)*4] = (char)texres.tin;
 
                                texres.tin = texres.tin * 255.0;
                                ((char*)texcache)[(iy*side+ix)*4] = (char)texres.tin;
@@ -994,9 +1185,9 @@ void brush_radial_control_invoke(wmOperator *op, Brush *br, float size_weight)
        float original_value= 0;
 
        if(mode == WM_RADIALCONTROL_SIZE)
        float original_value= 0;
 
        if(mode == WM_RADIALCONTROL_SIZE)
-               original_value = br->size * size_weight;
+               original_value = brush_size(br) * size_weight;
        else if(mode == WM_RADIALCONTROL_STRENGTH)
        else if(mode == WM_RADIALCONTROL_STRENGTH)
-               original_value = br->alpha;
+               original_value = brush_alpha(br);
        else if(mode == WM_RADIALCONTROL_ANGLE) {
                MTex *mtex = brush_active_texture(br);
                if(mtex)
        else if(mode == WM_RADIALCONTROL_ANGLE) {
                MTex *mtex = brush_active_texture(br);
                if(mtex)
@@ -1014,9 +1205,15 @@ int brush_radial_control_exec(wmOperator *op, Brush *br, float size_weight)
        const float conv = 0.017453293;
 
        if(mode == WM_RADIALCONTROL_SIZE)
        const float conv = 0.017453293;
 
        if(mode == WM_RADIALCONTROL_SIZE)
-               br->size = new_value * size_weight;
+               if (brush_use_locked_size(br)) {
+                       float initial_value = RNA_float_get(op->ptr, "initial_value");
+                       const float unprojected_radius = brush_unprojected_radius(br);
+                       brush_set_unprojected_radius(br, unprojected_radius * new_value/initial_value * size_weight);
+               }
+               else
+                       brush_set_size(br, new_value * size_weight);
        else if(mode == WM_RADIALCONTROL_STRENGTH)
        else if(mode == WM_RADIALCONTROL_STRENGTH)
-               br->alpha = new_value;
+               brush_set_alpha(br, new_value);
        else if(mode == WM_RADIALCONTROL_ANGLE) {
                MTex *mtex = brush_active_texture(br);
                if(mtex)
        else if(mode == WM_RADIALCONTROL_ANGLE) {
                MTex *mtex = brush_active_texture(br);
                if(mtex)
@@ -1025,3 +1222,248 @@ int brush_radial_control_exec(wmOperator *op, Brush *br, float size_weight)
 
        return OPERATOR_FINISHED;
 }
 
        return OPERATOR_FINISHED;
 }
+
+/* Unified Size and Strength */
+
+static void set_unified_settings(Brush *brush, short flag, int value)
+{
+       Scene *sce;
+       for (sce= G.main->scene.first; sce; sce= sce->id.next) {
+               if (sce->toolsettings && 
+                       ELEM4(brush,
+                           paint_brush(&(sce->toolsettings->imapaint.paint)),
+                           paint_brush(&(sce->toolsettings->vpaint->paint)),
+                           paint_brush(&(sce->toolsettings->wpaint->paint)),
+                           paint_brush(&(sce->toolsettings->sculpt->paint))))
+               {
+                       if (value)
+                               sce->toolsettings->sculpt_paint_settings |= flag;
+                       else
+                               sce->toolsettings->sculpt_paint_settings &= ~flag;
+               }
+       }
+}
+
+static short unified_settings(Brush *brush)
+{
+       Scene *sce;
+       for (sce= G.main->scene.first; sce; sce= sce->id.next) {
+               if (sce->toolsettings && 
+                       ELEM4(brush,
+                           paint_brush(&(sce->toolsettings->imapaint.paint)),
+                           paint_brush(&(sce->toolsettings->vpaint->paint)),
+                           paint_brush(&(sce->toolsettings->wpaint->paint)),
+                           paint_brush(&(sce->toolsettings->sculpt->paint))))
+               {
+                       return sce->toolsettings->sculpt_paint_settings;
+               }
+       }
+
+       return 0;
+}
+
+static void set_unified_size(Brush *brush, int value)
+{
+       Scene *sce;
+       for (sce= G.main->scene.first; sce; sce= sce->id.next) {
+               if (sce->toolsettings && 
+                       ELEM4(brush,
+                           paint_brush(&(sce->toolsettings->imapaint.paint)),
+                           paint_brush(&(sce->toolsettings->vpaint->paint)),
+                           paint_brush(&(sce->toolsettings->wpaint->paint)),
+                           paint_brush(&(sce->toolsettings->sculpt->paint))))
+               {
+                       sce->toolsettings->sculpt_paint_unified_size= value;
+               }
+       }
+}
+
+static int unified_size(Brush *brush)
+{
+       Scene *sce;
+       for (sce= G.main->scene.first; sce; sce= sce->id.next) {
+               if (sce->toolsettings && 
+                       ELEM4(brush,
+                           paint_brush(&(sce->toolsettings->imapaint.paint)),
+                           paint_brush(&(sce->toolsettings->vpaint->paint)),
+                           paint_brush(&(sce->toolsettings->wpaint->paint)),
+                           paint_brush(&(sce->toolsettings->sculpt->paint))))
+               {
+                       return sce->toolsettings->sculpt_paint_unified_size;
+               }
+       }
+
+       return 35; // XXX magic number
+}
+
+static void set_unified_alpha(Brush *brush, float value)
+{
+       Scene *sce;
+       for (sce= G.main->scene.first; sce; sce= sce->id.next) {
+               if (sce->toolsettings && 
+                       ELEM4(brush,
+                           paint_brush(&(sce->toolsettings->imapaint.paint)),
+                           paint_brush(&(sce->toolsettings->vpaint->paint)),
+                           paint_brush(&(sce->toolsettings->wpaint->paint)),
+                           paint_brush(&(sce->toolsettings->sculpt->paint))))
+               {
+                       sce->toolsettings->sculpt_paint_unified_alpha= value;
+               }
+       }
+}
+
+static float unified_alpha(Brush *brush)
+{
+       Scene *sce;
+       for (sce= G.main->scene.first; sce; sce= sce->id.next) {
+               if (sce->toolsettings && 
+                       ELEM4(brush,
+                           paint_brush(&(sce->toolsettings->imapaint.paint)),
+                           paint_brush(&(sce->toolsettings->vpaint->paint)),
+                           paint_brush(&(sce->toolsettings->wpaint->paint)),
+                           paint_brush(&(sce->toolsettings->sculpt->paint))))
+               {
+                       return sce->toolsettings->sculpt_paint_unified_alpha;
+               }
+       }
+
+       return 0.5f; // XXX magic number
+}
+
+static void set_unified_unprojected_radius(Brush *brush, float value)
+{
+       Scene *sce;
+       for (sce= G.main->scene.first; sce; sce= sce->id.next) {
+               if (sce->toolsettings && 
+                       ELEM4(brush,
+                           paint_brush(&(sce->toolsettings->imapaint.paint)),
+                           paint_brush(&(sce->toolsettings->vpaint->paint)),
+                           paint_brush(&(sce->toolsettings->wpaint->paint)),
+                           paint_brush(&(sce->toolsettings->sculpt->paint))))
+               {
+                       sce->toolsettings->sculpt_paint_unified_unprojected_radius= value;
+               }
+       }
+}
+
+static float unified_unprojected_radius(Brush *brush)
+{
+       Scene *sce;
+       for (sce= G.main->scene.first; sce; sce= sce->id.next) {
+               if (sce->toolsettings && 
+                       ELEM4(brush,
+                           paint_brush(&(sce->toolsettings->imapaint.paint)),
+                           paint_brush(&(sce->toolsettings->vpaint->paint)),
+                           paint_brush(&(sce->toolsettings->wpaint->paint)),
+                           paint_brush(&(sce->toolsettings->sculpt->paint))))
+               {
+                       return sce->toolsettings->sculpt_paint_unified_unprojected_radius;
+               }
+       }
+
+       return 0.125f; // XXX magic number
+}
+void brush_set_size(Brush *brush, int size)
+{
+       if (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE)
+               set_unified_size(brush, size);
+       else
+               brush->size= size;
+
+       //WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush);
+}
+
+int brush_size(Brush *brush)
+{
+       return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) ? unified_size(brush) : brush->size;
+}
+
+void brush_set_use_locked_size(Brush *brush, int value)
+{
+       if (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) {
+               set_unified_settings(brush, SCULPT_PAINT_UNIFIED_LOCK_BRUSH_SIZE, value);
+       }
+       else {
+               if (value)
+                       brush->flag |= BRUSH_LOCK_SIZE;
+               else
+                       brush->flag &= ~BRUSH_LOCK_SIZE;
+       }
+
+       //WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush);
+}
+
+int brush_use_locked_size(Brush *brush)
+{
+       return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) ? (unified_settings(brush) & SCULPT_PAINT_UNIFIED_LOCK_BRUSH_SIZE) : (brush->flag & BRUSH_LOCK_SIZE);
+}
+
+void brush_set_use_size_pressure(Brush *brush, int value)
+{
+       if (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) {
+               set_unified_settings(brush, SCULPT_PAINT_UNIFIED_SIZE_PRESSURE, value);
+       }
+       else {
+               if (value)
+                       brush->flag |= BRUSH_SIZE_PRESSURE;
+               else
+                       brush->flag &= ~BRUSH_SIZE_PRESSURE;
+       }
+
+       //WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush);
+}
+
+int brush_use_size_pressure(Brush *brush)
+{
+       return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) ? (unified_settings(brush) & SCULPT_PAINT_UNIFIED_SIZE_PRESSURE) : (brush->flag & BRUSH_SIZE_PRESSURE);
+}
+
+void brush_set_use_alpha_pressure(Brush *brush, int value)
+{
+       if (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_ALPHA) {
+               set_unified_settings(brush, SCULPT_PAINT_UNIFIED_ALPHA_PRESSURE, value);
+       }
+       else {
+               if (value)
+                       brush->flag |= BRUSH_ALPHA_PRESSURE;
+               else
+                       brush->flag &= ~BRUSH_ALPHA_PRESSURE;
+       }
+
+       //WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush);
+}
+
+int brush_use_alpha_pressure(Brush *brush)
+{
+       return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_ALPHA) ? (unified_settings(brush) & SCULPT_PAINT_UNIFIED_ALPHA_PRESSURE) : (brush->flag & BRUSH_ALPHA_PRESSURE);
+}
+
+void brush_set_unprojected_radius(Brush *brush, float unprojected_radius)
+{
+       if (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE)
+               set_unified_unprojected_radius(brush, unprojected_radius);
+       else
+               brush->unprojected_radius= unprojected_radius;
+
+       //WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush);
+}
+
+float brush_unprojected_radius(Brush *brush)
+{
+       return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) ? unified_unprojected_radius(brush) : brush->unprojected_radius;
+}
+
+void brush_set_alpha(Brush *brush, float alpha)
+{
+       if (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_ALPHA) 
+               set_unified_alpha(brush, alpha);
+       else
+               brush->alpha= alpha;
+
+       //WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush);
+}
+
+float brush_alpha(Brush *brush)
+{
+       return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_ALPHA) ? unified_alpha(brush) : brush->alpha;
+}