Style changes to refactor commit.
[blender.git] / source / blender / editors / sculpt_paint / paint_cursor.c
index 49863621b044ce4b250610bb8ac3c7ef27c499b5..8f4454eb2da828f6bb7a7d4282d8d93957be6c7d 100644 (file)
@@ -35,6 +35,7 @@
 #include "BLI_utildefines.h"
 
 #include "DNA_brush_types.h"
+#include "DNA_customdata_types.h"
 #include "DNA_color_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
@@ -72,17 +73,37 @@ typedef struct TexSnapshot {
        GLuint overlay_texture;
        int winx;
        int winy;
-       bool init;
        int old_size;
-       int old_zoom;
+       float old_zoom;
        bool old_col;
 } TexSnapshot;
 
-typedef struct CurveSnapshot {
-       int BKE_brush_size_get;
-       int curve_changed_timestamp;
-       bool init;
-} CurveSnapshot;
+typedef struct CursorSnapshot {
+       GLuint overlay_texture;
+       int size;
+       int zoom;
+} CursorSnapshot;
+
+static TexSnapshot primary_snap = {0};
+static TexSnapshot secondary_snap  = {0};
+static CursorSnapshot cursor_snap  = {0};
+
+/* delete overlay cursor textures to preserve memory and invalidate all overlay flags */
+void paint_cursor_delete_textures(void)
+{
+       if (primary_snap.overlay_texture)
+               glDeleteTextures(1, &primary_snap.overlay_texture);
+       if (secondary_snap.overlay_texture)
+               glDeleteTextures(1, &secondary_snap.overlay_texture);
+       if (cursor_snap.overlay_texture)
+               glDeleteTextures(1, &cursor_snap.overlay_texture);
+
+       memset(&primary_snap, 0, sizeof(TexSnapshot));
+       memset(&secondary_snap, 0, sizeof(TexSnapshot));
+       memset(&cursor_snap, 0, sizeof(CursorSnapshot));
+
+       BKE_paint_invalidate_overlay_all();
+}
 
 static int same_tex_snap(TexSnapshot *snap, MTex *mtex, ViewContext *vc, bool col, float zoom)
 {
@@ -91,10 +112,11 @@ static int same_tex_snap(TexSnapshot *snap, MTex *mtex, ViewContext *vc, bool co
                //(BKE_brush_size_get(vc->scene, brush) <= snap->BKE_brush_size_get)) &&
 
                (mtex->brush_map_mode != MTEX_MAP_MODE_TILED ||
-               (vc->ar->winx == snap->winx &&
-               vc->ar->winy == snap->winy)) &&
-               snap->old_zoom == zoom &&
-                       snap->old_col == col
+                (vc->ar->winx == snap->winx &&
+                 vc->ar->winy == snap->winy)) &&
+               (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL ||
+               snap->old_zoom == zoom) &&
+               snap->old_col == col
                );
 }
 
@@ -107,9 +129,7 @@ static void make_tex_snap(TexSnapshot *snap, ViewContext *vc, float zoom)
 
 static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool primary)
 {
-       static int init = 0;
-       static TexSnapshot primary_snap = {0};
-       static TexSnapshot secondary_snap  = {0};
+       bool init;
        TexSnapshot *target;
 
        MTex *mtex = (primary) ? &br->mtex : &br->mask_mtex;
@@ -124,14 +144,14 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
                                   (overlay_flags & PAINT_INVALID_OVERLAY_TEXTURE_SECONDARY);
 
        target = (primary) ? &primary_snap : &secondary_snap;
-       
-       if (mtex->brush_map_mode != MTEX_MAP_MODE_VIEW && !mtex->tex) return 0;
-       
+
        refresh = 
            !target->overlay_texture ||
            (invalid != 0) ||
            !same_tex_snap(target, mtex, vc, col, zoom);
 
+       init = (target->overlay_texture != 0);
+
        if (refresh) {
                struct ImagePool *pool = NULL;
                /* stencil is rotated later */
@@ -166,7 +186,7 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
                                target->overlay_texture = 0;
                        }
 
-                       init = 0;
+                       init = false;
 
                        target->old_size = size;
                }
@@ -175,8 +195,7 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
                else
                        buffer = MEM_mallocN(sizeof(GLubyte) * size * size, "load_tex");
 
-               if (mtex->tex)
-                       pool = BKE_image_pool_new();
+               pool = BKE_image_pool_new();
 
                #pragma omp parallel for schedule(static)
                for (j = 0; j < size; j++) {
@@ -228,8 +247,7 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
                                        if (col) {
                                                float rgba[4];
 
-                                               if (mtex->tex)
-                                                       paint_get_tex_pixel_col(mtex, x, y, rgba, pool);
+                                               paint_get_tex_pixel_col(mtex, x, y, rgba, pool);
 
                                                buffer[index * 4]     = rgba[0] * 255;
                                                buffer[index * 4 + 1] = rgba[1] * 255;
@@ -237,7 +255,7 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
                                                buffer[index * 4 + 3] = rgba[3] * 255;
                                        }
                                        else {
-                                               float avg = mtex->tex ? paint_get_tex_pixel(mtex, x, y, pool) : 1;
+                                               float avg = paint_get_tex_pixel(mtex, x, y, pool);
 
                                                avg += br->texture_sample_bias;
 
@@ -275,7 +293,6 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
        if (refresh) {
                if (!init || (target->old_col != col)) {
                        glTexImage2D(GL_TEXTURE_2D, 0, format, size, size, 0, format, GL_UNSIGNED_BYTE, buffer);
-                       init = 1;
                }
                else {
                        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, format, GL_UNSIGNED_BYTE, buffer);
@@ -305,10 +322,7 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
 
 static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
 {
-       static GLuint overlay_texture = 0;
-       static int init = 0;
-       static int old_size = -1;
-       static int old_zoom = -1;
+       bool init;
 
        OverlayControlFlags overlay_flags = BKE_paint_get_overlay_flags();
        GLubyte *buffer = NULL;
@@ -318,14 +332,16 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
        int refresh;
 
        refresh =
-           !overlay_texture ||
+           !cursor_snap.overlay_texture ||
            (overlay_flags & PAINT_INVALID_OVERLAY_CURVE) ||
-           old_zoom != zoom;
+           cursor_snap.zoom != zoom;
+
+       init = (cursor_snap.overlay_texture != 0);
 
        if (refresh) {
                int s, r;
 
-               old_zoom = zoom;
+               cursor_snap.zoom = zoom;
 
                s = BKE_brush_size_get(vc->scene, br);
                r = 1;
@@ -338,18 +354,18 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
                if (size < 256)
                        size = 256;
 
-               if (size < old_size)
-                       size = old_size;
+               if (size < cursor_snap.size)
+                       size = cursor_snap.size;
 
-               if (old_size != size) {
-                       if (overlay_texture) {
-                               glDeleteTextures(1, &overlay_texture);
-                               overlay_texture = 0;
+               if (cursor_snap.size != size) {
+                       if (cursor_snap.overlay_texture) {
+                               glDeleteTextures(1, &cursor_snap.overlay_texture);
+                               cursor_snap.overlay_texture = 0;
                        }
 
-                       init = 0;
+                       init = false;
 
-                       old_size = size;
+                       cursor_snap.size = size;
                }
                buffer = MEM_mallocN(sizeof(GLubyte) * size * size, "load_tex");
 
@@ -380,11 +396,9 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
                                len = sqrtf(x * x + y * y);
 
                                if (len <= 1) {
-                                               float avg = BKE_brush_curve_strength(br, len, 1.0f);  /* Falloff curve */
+                                       float avg = BKE_brush_curve_strength_clamp(br, len, 1.0f);  /* Falloff curve */
 
-                                               /* clamp to avoid precision overflow */
-                                               CLAMP(avg, 0.0f, 1.0f);
-                                               buffer[index] = 255 - (GLubyte)(255 * avg);
+                                       buffer[index] = 255 - (GLubyte)(255 * avg);
 
                                }
                                else {
@@ -393,19 +407,18 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
                        }
                }
 
-               if (!overlay_texture)
-                       glGenTextures(1, &overlay_texture);
+               if (!cursor_snap.overlay_texture)
+                       glGenTextures(1, &cursor_snap.overlay_texture);
        }
        else {
-               size = old_size;
+               size = cursor_snap.size;
        }
 
-       glBindTexture(GL_TEXTURE_2D, overlay_texture);
+       glBindTexture(GL_TEXTURE_2D, cursor_snap.overlay_texture);
 
        if (refresh) {
                if (!init) {
                        glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, size, size, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buffer);
-                       init = 1;
                }
                else {
                        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, GL_ALPHA, GL_UNSIGNED_BYTE, buffer);
@@ -530,9 +543,9 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush,
                                 (brush->overlay_flags & BRUSH_OVERLAY_SECONDARY) != 0;
        int overlay_alpha = (primary) ? brush->texture_overlay_alpha : brush->mask_overlay_alpha;
 
-       if (!((mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL && mtex->tex) ||
+       if (!(mtex->tex) || !((mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) ||
            (valid &&
-           ELEM(mtex->brush_map_mode, MTEX_MAP_MODE_VIEW, MTEX_MAP_MODE_TILED))))
+               ELEM(mtex->brush_map_mode, MTEX_MAP_MODE_VIEW, MTEX_MAP_MODE_TILED))))
        {
                return;
        }
@@ -556,7 +569,7 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush,
                        glTranslatef(-0.5f, -0.5f, 0);
 
                        /* scale based on tablet pressure */
-                       if (primary && ups->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush)) {
+                       if (primary && ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) {
                                glTranslatef(0.5f, 0.5f, 0);
                                glScalef(1.0f / ups->pressure_value, 1.0f / ups->pressure_value, 1);
                                glTranslatef(-0.5f, -0.5f, 0);
@@ -585,14 +598,24 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush,
                }
                /* Stencil code goes here */
                else {
-                       quad.xmin = -brush->stencil_dimension[0];
-                       quad.ymin = -brush->stencil_dimension[1];
-                       quad.xmax = brush->stencil_dimension[0];
-                       quad.ymax = brush->stencil_dimension[1];
-
+                       if (primary) {
+                               quad.xmin = -brush->stencil_dimension[0];
+                               quad.ymin = -brush->stencil_dimension[1];
+                               quad.xmax = brush->stencil_dimension[0];
+                               quad.ymax = brush->stencil_dimension[1];
+                       }
+                       else {
+                               quad.xmin = -brush->mask_stencil_dimension[0];
+                               quad.ymin = -brush->mask_stencil_dimension[1];
+                               quad.xmax = brush->mask_stencil_dimension[0];
+                               quad.ymax = brush->mask_stencil_dimension[1];
+                       }
                        glMatrixMode(GL_MODELVIEW);
                        glPushMatrix();
-                       glTranslatef(brush->stencil_pos[0], brush->stencil_pos[1], 0);
+                       if (primary)
+                               glTranslatef(brush->stencil_pos[0], brush->stencil_pos[1], 0);
+                       else
+                               glTranslatef(brush->mask_stencil_pos[0], brush->mask_stencil_pos[1], 0);
                        glRotatef(RAD2DEGF(mtex->rot), 0, 0, 1);
                        glMatrixMode(GL_TEXTURE);
                }
@@ -633,32 +656,27 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush,
 /* Draw an overlay that shows what effect the brush's texture will
  * have on brush strength */
 static void paint_draw_cursor_overlay(UnifiedPaintSettings *ups, Brush *brush,
-                                     ViewContext *vc, int x, int y, float zoom)
+                                      ViewContext *vc, int x, int y, float zoom)
 {
        rctf quad;
        /* check for overlay mode */
 
-       if (!(brush->overlay_flags & BRUSH_OVERLAY_CURSOR))
-       {
+       if (!(brush->overlay_flags & BRUSH_OVERLAY_CURSOR)) {
                return;
        }
 
        if (load_tex_cursor(brush, vc, zoom)) {
+               bool do_pop = false;
+               float center[2];
                glEnable(GL_BLEND);
 
                glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
                glDepthMask(GL_FALSE);
                glDepthFunc(GL_ALWAYS);
 
-               /* scale based on tablet pressure */
-               if (ups->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush)) {
-                       glTranslatef(0.5f, 0.5f, 0);
-                       glScalef(1.0f / ups->pressure_value, 1.0f / ups->pressure_value, 1);
-                       glTranslatef(-0.5f, -0.5f, 0);
-               }
-
                if (ups->draw_anchored) {
                        const float *aim = ups->anchored_initial_mouse;
+                       copy_v2_v2(center, aim);
                        quad.xmin = aim[0] - ups->anchored_size;
                        quad.ymin = aim[1] - ups->anchored_size;
                        quad.xmax = aim[0] + ups->anchored_size;
@@ -666,12 +684,25 @@ static void paint_draw_cursor_overlay(UnifiedPaintSettings *ups, Brush *brush,
                }
                else {
                        const int radius = BKE_brush_size_get(vc->scene, brush) * zoom;
+                       center[0] = x;
+                       center[1] = y;
+
                        quad.xmin = x - radius;
                        quad.ymin = y - radius;
                        quad.xmax = x + radius;
                        quad.ymax = y + radius;
                }
 
+               /* scale based on tablet pressure */
+               if (ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) {
+                       do_pop = true;
+                       glPushMatrix();
+                       glLoadIdentity();
+                       glTranslatef(center[0], center[1], 0);
+                       glScalef(ups->pressure_value, ups->pressure_value, 1);
+                       glTranslatef(-center[0], -center[1], 0);
+               }
+
                glColor4f(U.sculpt_paint_overlay_col[0],
                        U.sculpt_paint_overlay_col[1],
                        U.sculpt_paint_overlay_col[2],
@@ -688,6 +719,9 @@ static void paint_draw_cursor_overlay(UnifiedPaintSettings *ups, Brush *brush,
                glTexCoord2f(0, 1);
                glVertex2f(quad.xmin, quad.ymax);
                glEnd();
+
+               if (do_pop)
+                       glPopMatrix();
        }
 }
 
@@ -696,7 +730,7 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
 {
        /* color means that primary brush texture is colured and secondary is used for alpha/mask control */
        bool col = ELEM3(mode, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D, PAINT_VERTEX) ? true: false;
-
+       OverlayControlFlags flags = BKE_paint_get_overlay_flags();
        /* save lots of GL state
         * TODO: check on whether all of these are needed? */
        glPushAttrib(GL_COLOR_BUFFER_BIT |
@@ -713,12 +747,18 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
 
        /* coloured overlay should be drawn separately */
        if (col) {
-               paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, true, true);
-               paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, false);
-               paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
-       } else {
-               paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, true);
-               paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
+               if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY))
+                       paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, true, true);
+               if (!(flags & PAINT_OVERLAY_OVERRIDE_SECONDARY))
+                       paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, false);
+               if (!(flags & PAINT_OVERLAY_OVERRIDE_CURSOR))
+                       paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
+       }
+       else {
+               if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY))
+                       paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, true);
+               if (!(flags & PAINT_OVERLAY_OVERRIDE_CURSOR))
+                       paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
        }
 
        glPopAttrib();
@@ -748,7 +788,7 @@ static void paint_cursor_on_hit(UnifiedPaintSettings *ups, Brush *brush, ViewCon
                                                                    projected_radius);
 
                /* scale 3D brush radius by pressure */
-               if (ups->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush))
+               if (ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush))
                        unprojected_radius *= ups->pressure_value;
 
                /* set cached value in either Brush or UnifiedPaintSettings */
@@ -788,19 +828,17 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
        outline_col = brush->add_col;
        final_radius = BKE_brush_size_get(scene, brush) * zoomx;
 
-       if (brush->flag & BRUSH_RAKE)
-               /* here, translation contains the mouse coordinates. */
+       /* don't calculate rake angles while a stroke is active because the rake variables are global and
+        * we may get interference with the stroke itself. For line strokes, such interference is visible */
+       if (!ups->stroke_active && (brush->flag & BRUSH_RAKE))
                paint_calculate_rake_rotation(ups, translation);
-       else if (!(brush->flag & BRUSH_ANCHORED))
-               ups->brush_rotation = 0.0;
 
        /* draw overlay */
-       if (!BKE_paint_get_overlay_override())
-               paint_draw_alpha_overlay(ups, brush, &vc, x, y, zoomx, mode);
+       paint_draw_alpha_overlay(ups, brush, &vc, x, y, zoomx, mode);
 
        /* TODO: as sculpt and other paint modes are unified, this
         * special mode of drawing will go away */
-       if (vc.obact->sculpt) {
+       if ((mode == PAINT_SCULPT) && vc.obact->sculpt) {
                float location[3];
                int pixel_radius, hit;
 
@@ -844,7 +882,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
        glTranslatef(translation[0], translation[1], 0);
 
        /* draw an inner brush */
-       if (ups->draw_pressure && BKE_brush_use_size_pressure(scene, brush)) {
+       if (ups->stroke_active && BKE_brush_use_size_pressure(scene, brush)) {
                /* inner at full alpha */
                glutil_draw_lined_arc(0.0, M_PI * 2.0, final_radius * ups->pressure_value, 40);
                /* outer at half alpha */