[Bf-blender-cvs] [abeda01ac6d] master: GPencil: Improve Vertex Paint in filled areas

Antonio Vazquez noreply at git.blender.org
Fri Jun 5 15:11:14 CEST 2020


Commit: abeda01ac6da28564ad1b37d8ac09af75da96eba
Author: Antonio Vazquez
Date:   Fri Jun 5 10:52:21 2020 +0200
Branches: master
https://developer.blender.org/rBabeda01ac6da28564ad1b37d8ac09af75da96eba

GPencil: Improve Vertex Paint in filled areas

When use the Tint tool, it was very difficult to tint the filled areas if the strokes had very few points or the area was big.

Differential Revision: https://developer.blender.org/D7936

===================================================================

M	source/blender/editors/gpencil/gpencil_select.c
M	source/blender/editors/gpencil/gpencil_utils.c
M	source/blender/editors/gpencil/gpencil_vertex_paint.c
M	source/blender/editors/include/ED_gpencil.h

===================================================================

diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index 7accf48832a..c41b2993a80 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -68,45 +68,6 @@
 /** \name Shared Utilities
  * \{ */
 
-/* Check if mouse inside stroke. */
-static bool gpencil_point_inside_stroke(bGPDstroke *gps,
-                                        GP_SpaceConversion *gsc,
-                                        int mouse[2],
-                                        const float diff_mat[4][4])
-{
-  bool hit = false;
-  if (gps->totpoints == 0) {
-    return hit;
-  }
-
-  int(*mcoords)[2] = NULL;
-  int len = gps->totpoints;
-  mcoords = MEM_mallocN(sizeof(int) * 2 * len, __func__);
-
-  /* Convert stroke to 2D array of points. */
-  bGPDspoint *pt;
-  int i;
-  for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
-    bGPDspoint pt2;
-    gp_point_to_parent_space(pt, diff_mat, &pt2);
-    gp_point_to_xy(gsc, gps, &pt2, &mcoords[i][0], &mcoords[i][1]);
-  }
-
-  /* Compute boundbox of lasso (for faster testing later). */
-  rcti rect;
-  BLI_lasso_boundbox(&rect, mcoords, len);
-
-  /* Test if point inside stroke. */
-  hit = ((!ELEM(V2D_IS_CLIPPED, mouse[0], mouse[1])) &&
-         BLI_rcti_isect_pt(&rect, mouse[0], mouse[1]) &&
-         BLI_lasso_is_point_inside(mcoords, len, mouse[0], mouse[1], INT_MAX));
-
-  /* Free memory. */
-  MEM_SAFE_FREE(mcoords);
-
-  return hit;
-}
-
 /* Convert sculpt mask mode to Select mode */
 static int gpencil_select_mode_from_sculpt(eGP_Sculpt_SelectMaskFlag mode)
 {
@@ -1264,7 +1225,7 @@ static int gpencil_generic_select_exec(
       mval[0] = (box.xmax + box.xmin) / 2;
       mval[1] = (box.ymax + box.ymin) / 2;
 
-      whole = gpencil_point_inside_stroke(gps_active, &gsc, mval, gpstroke_iter.diff_mat);
+      whole = ED_gpencil_stroke_point_is_inside(gps_active, &gsc, mval, gpstroke_iter.diff_mat);
     }
 
     /* if stroke mode expand selection. */
@@ -1565,7 +1526,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
       if ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0) {
         continue;
       }
-      bool hit_fill = gpencil_point_inside_stroke(gps, &gsc, mval, gpstroke_iter.diff_mat);
+      bool hit_fill = ED_gpencil_stroke_point_is_inside(gps, &gsc, mval, gpstroke_iter.diff_mat);
       if (hit_fill) {
         hit_stroke = gps_active;
         hit_point = &gps_active->points[0];
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 1962eba5017..876fa7c9874 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -31,6 +31,7 @@
 #include "BLI_blenlib.h"
 #include "BLI_ghash.h"
 #include "BLI_hash.h"
+#include "BLI_lasso_2d.h"
 #include "BLI_math.h"
 #include "BLI_rand.h"
 #include "BLI_utildefines.h"
@@ -2799,3 +2800,49 @@ bool ED_gpencil_stroke_check_collision(GP_SpaceConversion *gsc,
   /* Check collision between both rectangles. */
   return BLI_rcti_isect(&rect_stroke, &rect_mouse, NULL);
 }
+
+/**
+ * Check if a point is inside of the stroke
+ * \param gps: Stroke to check
+ * \param gsc: SpaceConversion data
+ * \param mouse:  Mouse position
+ * \param diff_mat:  View matrix
+ * \return  True if the point is inside
+ */
+bool ED_gpencil_stroke_point_is_inside(bGPDstroke *gps,
+                                       GP_SpaceConversion *gsc,
+                                       int mouse[2],
+                                       const float diff_mat[4][4])
+{
+  bool hit = false;
+  if (gps->totpoints == 0) {
+    return hit;
+  }
+
+  int(*mcoords)[2] = NULL;
+  int len = gps->totpoints;
+  mcoords = MEM_mallocN(sizeof(int) * 2 * len, __func__);
+
+  /* Convert stroke to 2D array of points. */
+  bGPDspoint *pt;
+  int i;
+  for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+    bGPDspoint pt2;
+    gp_point_to_parent_space(pt, diff_mat, &pt2);
+    gp_point_to_xy(gsc, gps, &pt2, &mcoords[i][0], &mcoords[i][1]);
+  }
+
+  /* Compute boundbox of lasso (for faster testing later). */
+  rcti rect;
+  BLI_lasso_boundbox(&rect, mcoords, len);
+
+  /* Test if point inside stroke. */
+  hit = ((!ELEM(V2D_IS_CLIPPED, mouse[0], mouse[1])) &&
+         BLI_rcti_isect_pt(&rect, mouse[0], mouse[1]) &&
+         BLI_lasso_is_point_inside(mcoords, len, mouse[0], mouse[1], INT_MAX));
+
+  /* Free memory. */
+  MEM_SAFE_FREE(mcoords);
+
+  return hit;
+}
diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c
index 10867bd1e0d..581a5d977c2 100644
--- a/source/blender/editors/gpencil/gpencil_vertex_paint.c
+++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c
@@ -36,6 +36,7 @@
 #include "BKE_colortools.h"
 #include "BKE_context.h"
 #include "BKE_gpencil.h"
+#include "BKE_material.h"
 #include "BKE_report.h"
 
 #include "WM_api.h"
@@ -433,10 +434,9 @@ static bool brush_tint_apply(tGP_BrushVertexpaintData *gso,
   CLAMP(inf, 0.0f, 1.0f);
   CLAMP(inf_fill, 0.0f, 1.0f);
 
-  bGPDspoint *pt = &gps->points[pt_index];
-
   /* Apply color to Stroke point. */
-  if (GPENCIL_TINT_VERTEX_COLOR_STROKE(brush)) {
+  if (GPENCIL_TINT_VERTEX_COLOR_STROKE(brush) && (pt_index > -1)) {
+    bGPDspoint *pt = &gps->points[pt_index];
     if (brush_invert_check(gso)) {
       pt->vert_color[3] -= inf;
       CLAMP_MIN(pt->vert_color[3], 0.0f);
@@ -813,15 +813,18 @@ static void gp_save_selected_point(tGP_BrushVertexpaintData *gso,
   selected = &gso->pbuffer[gso->pbuffer_used];
   selected->gps = gps;
   selected->pt_index = index;
-  copy_v2_v2_int(selected->pc, pc);
-  copy_v4_v4(selected->color, pt->vert_color);
-
+  /* Check the index is not a special case for fill. */
+  if (index > -1) {
+    copy_v2_v2_int(selected->pc, pc);
+    copy_v4_v4(selected->color, pt->vert_color);
+  }
   gso->pbuffer_used++;
 }
 
 /* Select points in this stroke and add to an array to be used later. */
 static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
                                          bGPDstroke *gps,
+                                         const char tool,
                                          const float diff_mat[4][4])
 {
   GP_SpaceConversion *gsc = &gso->gsc;
@@ -869,6 +872,7 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
     /* Loop over the points in the stroke, checking for intersections
      * - an intersection means that we touched the stroke
      */
+    bool hit = false;
     for (i = 0; (i + 1) < gps->totpoints; i++) {
       /* Get points to work with */
       pt1 = gps->points + i;
@@ -904,6 +908,7 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
           pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
           index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i;
           if (pt_active != NULL) {
+            hit = true;
             gp_save_selected_point(gso, gps_active, index, pc1);
           }
 
@@ -920,6 +925,7 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
             pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
             index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i + 1;
             if (pt_active != NULL) {
+              hit = true;
               gp_save_selected_point(gso, gps_active, index, pc2);
               include_last = false;
             }
@@ -938,6 +944,7 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
           pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
           index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i;
           if (pt_active != NULL) {
+            hit = true;
             gp_save_selected_point(gso, gps_active, index, pc1);
 
             include_last = false;
@@ -945,6 +952,24 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
         }
       }
     }
+
+    /* If nothing hit, check if the mouse is inside any filled stroke. */
+    if ((!hit) && (ELEM(tool, GPAINT_TOOL_TINT, GPVERTEX_TOOL_DRAW))) {
+      MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(gso->object,
+                                                                     gps_active->mat_nr + 1);
+      if (gp_style->flag & GP_MATERIAL_FILL_SHOW) {
+        int mval[2];
+        round_v2i_v2fl(mval, gso->mval);
+        bool hit_fill = ED_gpencil_stroke_point_is_inside(gps_active, gsc, mval, diff_mat);
+        if (hit_fill) {
+          /* Need repeat the effect because if we don't do that the tint process
+           * is very slow. */
+          for (int repeat = 0; repeat < 50; repeat++) {
+            gp_save_selected_point(gso, gps_active, -1, NULL);
+          }
+        }
+      }
+    }
   }
 }
 
@@ -956,8 +981,8 @@ static bool gp_vertexpaint_brush_do_frame(bContext *C,
                                           const float diff_mat[4][4])
 {
   Object *ob = CTX_data_active_object(C);
-  char tool = ob->mode == OB_MODE_VERTEX_GPENCIL ? gso->brush->gpencil_vertex_tool :
-                                                   gso->brush->gpencil_tool;
+  const char tool = ob->mode == OB_MODE_VERTEX_GPENCIL ? gso->brush->gpencil_vertex_tool :
+                                                         gso->brush->gpencil_tool;
   const int radius = (gso->brush->flag & GP_BRUSH_USE_PRESSURE) ?
                          gso->brush->size * gso->pressure :
                          gso->brush->size;
@@ -980,7 +1005,7 @@ static bool gp_vertexpaint_brush_do_frame(bContext *C,
     }
 
     /* Check points below the brush. */
-    gp_vertexpaint_select_stroke(gso, gps, diff_mat);
+    gp_vertexpaint_select_stroke(gso, gps, tool, diff_mat);
   }
 
   /* For Average tool, need calculate the average resulting color from all colors
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index 58364e69679..0c228fc962b 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -317,6 +317,10 @@ bool ED_gpencil_stroke_check_collision(struct G

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list