doxygen: prevent GPL license block from being parsed as doxygen comment.
[blender.git] / source / blender / blenkernel / intern / brush.c
index a8a53e3..15404ac 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
 #include "DNA_brush_types.h"
 #include "DNA_color_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_object_types.h"
 #include "DNA_windowmanager_types.h"
 
 #include "WM_types.h"
-#include "WM_api.h"
 
 #include "RNA_access.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 "RE_render_ext.h" /* externtex */
 #include "RE_shader_ext.h"
 
-/* Datablock add/copy/free/make_local */
-
-Brush *add_brush(const char *name)
+static void brush_set_defaults(Brush *brush)
 {
-       Brush *brush;
+       brush->blend = 0;
+       brush->flag = 0;
 
-       brush= alloc_libblock(&G.main->brush, ID_BR, name);
+       brush->ob_mode = OB_MODE_ALL_PAINT;
 
        /* BRUSH SCULPT TOOL SETTINGS */
-       brush->sculpt_tool = SCULPT_TOOL_DRAW; /* sculpting defaults to the draw tool for new brushes */
        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_VIEW;
+       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 */
@@ -102,6 +102,7 @@ Brush *add_brush(const char *name)
        default_mtex(&brush->mtex);
 
        brush->texture_sample_bias= 0; /* value to added to texture samples */
+       brush->texture_overlay_alpha= 33;
 
        /* brush appearance  */
 
@@ -112,13 +113,25 @@ Brush *add_brush(const char *name)
        brush->sub_col[0]= 0.39; /* subtract mode color is light blue */
        brush->sub_col[1]= 0.39;
        brush->sub_col[2]= 1.00;
+}
 
-        /* the default alpha falloff curve */
-       brush_curve_preset(brush, CURVE_PRESET_SMOOTH);
+/* Datablock add/copy/free/make_local */
+
+Brush *add_brush(const char *name)
+{
+       Brush *brush;
+
+       brush= alloc_libblock(&G.main->brush, ID_BR, name);
 
        /* enable fake user by default */
        brush->id.flag |= LIB_FAKEUSER;
-       brush_toggled_fake_user(brush);
+
+       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);
 
        return brush;
 }
@@ -135,12 +148,14 @@ Brush *copy_brush(Brush *brush)
        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;
-               brush_toggled_fake_user(brushn);
+               brushn->id.us++;
        }
        
        return brushn;
@@ -171,13 +186,13 @@ void make_local_brush(Brush *brush)
        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 */
-               brush->clone.image->id.lib= 0;
+               brush->clone.image->id.lib= NULL;
                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)
@@ -187,14 +202,14 @@ void make_local_brush(Brush *brush)
                }
 
        if(local && lib==0) {
-               brush->id.lib= 0;
+               brush->id.lib= NULL;
                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;
-                       brush_toggled_fake_user(brush);
+                       brush->id.us++;
                }
        }
        else if(local && lib) {
@@ -204,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)
-                               if(scene->id.lib==0) {
+                               if(scene->id.lib==NULL) {
                                        paint_brush_set(&scene->toolsettings->imapaint.paint, brushn);
                                        brushn->id.us++;
                                        brush->id.us--;
@@ -212,55 +227,174 @@ 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;
        }
 }
 
+/* Library Operations */
 void brush_curve_preset(Brush *b, /*CurveMappingPreset*/int preset)
 {
        CurveMap *cm = NULL;
@@ -272,7 +406,7 @@ void brush_curve_preset(Brush *b, /*CurveMappingPreset*/int preset)
        cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
 
        b->curve->preset = preset;
-       curvemap_reset(cm, &b->curve->clipr, b->curve->preset);
+       curvemap_reset(cm, &b->curve->clipr, b->curve->preset, CURVEMAP_SLOPE_NEGATIVE);
        curvemapping_changed(b->curve, 0);
 }
 
@@ -290,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);
-       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--;
@@ -344,14 +478,8 @@ int brush_clone_image_delete(Brush *brush)
        return 0;
 }
 
-void brush_check_exists(Brush **brush, const char *name)
-{
-       if(*brush==NULL)
-               brush_set_nr(brush, 1, name);
-}
-
 /* 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;
 
@@ -364,7 +492,7 @@ void brush_sample_tex(Brush *brush, float *xy, float *rgba)
                co[1]= xy[1]/radius;
                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;
@@ -401,7 +529,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf
        if (*outbuf)
                ibuf= *outbuf;
        else
-               ibuf= IMB_allocImBuf(bufsize, bufsize, 32, imbflag, 0);
+               ibuf= IMB_allocImBuf(bufsize, bufsize, 32, imbflag);
 
        if (flt) {
                for (y=0; y < ibuf->y; y++) {
@@ -418,12 +546,12 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf
                                        dstf[3]= alpha*brush_curve_strength_clamp(brush, dist, radius);
                                }
                                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]);
 
-                                       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];
@@ -454,7 +582,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf
                                        dst[3]= FTOCHAR(alpha*brush_curve_strength(brush, dist, radius));
                                }
                                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]);
@@ -463,7 +591,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf
                                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]);
@@ -610,7 +738,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i
                                        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];
@@ -641,7 +769,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i
                                        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]);
@@ -667,11 +795,11 @@ static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, float
 
        imbflag= (cache->flt)? IB_rectfloat: IB_rect;
        if (!cache->ibuf)
-               cache->ibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag, 0);
+               cache->ibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag);
        ibuf= cache->ibuf;
 
        oldtexibuf= cache->texibuf;
-       cache->texibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag, 0);
+       cache->texibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag);
 
        if (oldtexibuf) {
                srcx= srcy= 0;
@@ -779,7 +907,13 @@ static void brush_apply_pressure(BrushPainter *painter, Brush *brush, float pres
 
 void brush_jitter_pos(Brush *brush, float *pos, float *jitterpos)
 {
-       if(brush->jitter){
+       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;
@@ -969,11 +1103,9 @@ unsigned int *brush_gen_texture_cache(Brush *br, int half_side)
 {
        unsigned int *texcache = NULL;
        MTex *mtex = &br->mtex;
-       TexResult texres;
+       TexResult texres= {0};
        int hasrgb, ix, iy;
        int side = half_side * 2;
-
-       memset(&texres, 0, sizeof(TexResult));
        
        if(mtex->tex) {
                float x, y, step = 2.0 / side, co[3];