[Bf-blender-cvs] [0b3df9561da] greasepencil-object: GPencil: Use an array to select Vertex Paint points

Antonio Vazquez noreply at git.blender.org
Fri Nov 8 19:47:39 CET 2019


Commit: 0b3df9561daeadb16d90960b0684a4dc77771a98
Author: Antonio Vazquez
Date:   Fri Nov 8 19:47:32 2019 +0100
Branches: greasepencil-object
https://developer.blender.org/rB0b3df9561daeadb16d90960b0684a4dc77771a98

GPencil: Use an array to select Vertex Paint points

This is required for new brushes that need to have all points selected before applying the effect

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

M	source/blender/editors/gpencil/gpencil_vertex_paint.c

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

diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c
index 12ee20e2846..c97351e9e27 100644
--- a/source/blender/editors/gpencil/gpencil_vertex_paint.c
+++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c
@@ -58,6 +58,7 @@
 
 /* ************************************************ */
 /* General Brush Editing Context */
+#define GP_SELECT_BUFFER_CHUNK 256
 
 /* Temp Flags while Painting. */
 typedef enum eGPDvertex_brush_Flag {
@@ -67,6 +68,16 @@ typedef enum eGPDvertex_brush_Flag {
   GP_VERTEX_FLAG_TMP_INVERT = (1 << 1),
 } eGPDvertex_brush_Flag;
 
+/* List of points affected by brush. */
+typedef struct tGP_selected {
+  /** Referenced stroke. */
+  bGPDstroke *gps;
+  /** Point index in points array. */
+  int pt_index;
+  /** Position */
+  int pc[2];
+} tGP_selected;
+
 /* Context for brush operators */
 typedef struct tGP_BrushVertexpaintData {
   struct Main *bmain;
@@ -116,8 +127,55 @@ typedef struct tGP_BrushVertexpaintData {
   /* Object invert matrix */
   float inv_mat[4][4];
 
+  /* Temp data to save selected points */
+  /** Stroke buffer. */
+  tGP_selected *pbuffer;
+  /** Number of elements currently used in cache. */
+  int pbuffer_used;
+  /** Number of total elements available in cache. */
+  int pbuffer_size;
+
 } tGP_BrushVertexpaintData;
 
+/* Ensure the buffer to hold temp selwcted point size is enough to save all points selected. */
+static tGP_selected *gpencil_select_buffer_ensure(tGP_selected *buffer_array,
+                                                  int *buffer_size,
+                                                  int *buffer_used,
+                                                  const bool clear)
+{
+  tGP_selected *p = NULL;
+
+  /* By default a buffer is created with one block with a predefined number of free slots,
+   * if the size is not enough, the cache is reallocated adding a new block of free slots.
+   * This is done in order to keep cache small and improve speed. */
+  if (*buffer_used + 1 > *buffer_size) {
+    if ((*buffer_size == 0) || (buffer_array == NULL)) {
+      p = MEM_callocN(sizeof(struct tGP_selected) * GP_SELECT_BUFFER_CHUNK, __func__);
+      *buffer_size = GP_SELECT_BUFFER_CHUNK;
+    }
+    else {
+      *buffer_size += GP_SELECT_BUFFER_CHUNK;
+      p = MEM_recallocN(buffer_array, sizeof(struct tGP_selected) * *buffer_size);
+    }
+
+    if (p == NULL) {
+      *buffer_size = *buffer_used = 0;
+    }
+
+    buffer_array = p;
+  }
+
+  /* clear old data */
+  if (clear) {
+    *buffer_used = 0;
+    if (buffer_array != NULL) {
+      memset(buffer_array, 0, sizeof(tGP_selected) * *buffer_size);
+    }
+  }
+
+  return buffer_array;
+}
+
 /* Callback for performing some brush operation on a single point */
 typedef bool (*GP_VertexpaintApplyCb)(tGP_BrushVertexpaintData *gso,
                                       bGPDstroke *gps,
@@ -300,6 +358,10 @@ static bool gp_vertexpaint_brush_init(bContext *C, wmOperator *op)
   gso->is_painting = false;
   gso->first = true;
 
+  gso->pbuffer = NULL;
+  gso->pbuffer_size = 0;
+  gso->pbuffer_used = 0;
+
   gso->gpd = ED_gpencil_data_get_active(C);
   gso->scene = scene;
   gso->object = ob;
@@ -352,6 +414,7 @@ static void gp_vertexpaint_brush_exit(bContext *C, wmOperator *op)
   gso->brush->flag &= ~GP_VERTEX_FLAG_TMP_INVERT;
 
   /* free operator data */
+  MEM_freeN(gso->pbuffer);
   MEM_freeN(gso);
   op->customdata = NULL;
 }
@@ -363,13 +426,29 @@ static bool gp_vertexpaint_brush_poll(bContext *C)
   return CTX_DATA_COUNT(C, editable_gpencil_strokes) != 0;
 }
 
-/* Apply ----------------------------------------------- */
+/* Helper to save the points selected by the brush. */
+static void gp_save_selected_point(tGP_BrushVertexpaintData *gso,
+                                   bGPDstroke *gps,
+                                   int index,
+                                   int pc[2])
+{
+  tGP_selected *selected;
+  /* Ensure the array to save the list of selected points is big enough. */
+  gso->pbuffer = gpencil_select_buffer_ensure(
+      gso->pbuffer, &gso->pbuffer_size, &gso->pbuffer_used, false);
+
+  selected = &gso->pbuffer[gso->pbuffer_used];
+  selected->gps = gps;
+  selected->pt_index = index;
+  copy_v2_v2_int(selected->pc, pc);
+
+  gso->pbuffer_used++;
+}
 
-/* Apply brush operation to points in this stroke */
-static bool gp_vertexpaint_brush_do_stroke(tGP_BrushVertexpaintData *gso,
-                                           bGPDstroke *gps,
-                                           const float diff_mat[4][4],
-                                           GP_VertexpaintApplyCb apply)
+/* Select points in this stroke */
+static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
+                                         bGPDstroke *gps,
+                                         const float diff_mat[4][4])
 {
   GP_SpaceConversion *gsc = &gso->gsc;
   rcti *rect = &gso->brush_rect;
@@ -387,7 +466,7 @@ static bool gp_vertexpaint_brush_do_stroke(tGP_BrushVertexpaintData *gso,
   int i;
   int index;
   bool include_last = false;
-  bool changed = false;
+
   if (gps->totpoints == 1) {
     bGPDspoint pt_temp;
     pt = &gps->points[0];
@@ -403,7 +482,7 @@ static bool gp_vertexpaint_brush_do_stroke(tGP_BrushVertexpaintData *gso,
       if (len_v2v2_int(mval_i, pc1) <= radius) {
         /* apply operation to this point */
         if (pt_active != NULL) {
-          changed = apply(gso, gps_active, 0, radius, pc1);
+          gp_save_selected_point(gso, gps_active, 0, pc1);
         }
       }
     }
@@ -443,15 +522,12 @@ static bool gp_vertexpaint_brush_do_stroke(tGP_BrushVertexpaintData *gso,
         if (gp_stroke_inside_circle(
                 gso->mval, gso->mval_prev, radius, pc1[0], pc1[1], pc2[0], pc2[1])) {
 
-          /* Apply operation to these points */
-          bool ok = false;
-
           /* To each point individually... */
           pt = &gps->points[i];
           pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
           index = (!is_multiedit) ? pt->runtime.idx_orig : i;
           if (pt_active != NULL) {
-            ok = apply(gso, gps_active, index, radius, pc1);
+            gp_save_selected_point(gso, gps_active, index, pc1);
           }
 
           /* Only do the second point if this is the last segment,
@@ -467,15 +543,13 @@ static bool gp_vertexpaint_brush_do_stroke(tGP_BrushVertexpaintData *gso,
             pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
             index = (!is_multiedit) ? pt->runtime.idx_orig : i + 1;
             if (pt_active != NULL) {
-              ok |= apply(gso, gps_active, index, radius, pc2);
+              gp_save_selected_point(gso, gps_active, index, pc2);
               include_last = false;
             }
           }
           else {
             include_last = true;
           }
-
-          changed |= ok;
         }
         else if (include_last) {
           /* This case is for cases where for whatever reason the second vert (1st here)
@@ -487,56 +561,80 @@ static bool gp_vertexpaint_brush_do_stroke(tGP_BrushVertexpaintData *gso,
           pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
           index = (!is_multiedit) ? pt->runtime.idx_orig : i;
           if (pt_active != NULL) {
-            changed |= apply(gso, gps_active, index, radius, pc1);
+            gp_save_selected_point(gso, gps_active, index, pc1);
+
             include_last = false;
           }
         }
       }
     }
   }
-
-  return changed;
 }
 
-/* Apply sculpt brushes to strokes in the given frame */
+/* Apply sculpt brushes to strokes in the given frame. */
 static bool gp_vertexpaint_brush_do_frame(bContext *C,
                                           tGP_BrushVertexpaintData *gso,
                                           bGPDlayer *gpl,
                                           bGPDframe *gpf,
                                           const float diff_mat[4][4])
 {
-  bool changed = false;
   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 int radius = (gso->brush->flag & GP_BRUSH_USE_PRESSURE) ?
+                         gso->brush->size * gso->pressure :
+                         gso->brush->size;
+
+  /*---------------------------------------------------------------------
+   * First step: select the points affected. This step is required to have
+   * all selected points before apply the effect, because it could be
+   * required to average data.
+   *--------------------------------------------------------------------- */
   for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
-    /* skip strokes that are invalid for current view */
+    /* Skip strokes that are invalid for current view. */
     if (ED_gpencil_stroke_can_use(C, gps) == false) {
       continue;
     }
-    /* check if the color is editable */
+    /* Check if the color is editable. */
     if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
       continue;
     }
 
+    /* Check points below the brush. */
+    gp_vertexpaint_select_stroke(gso, gps, diff_mat);
+  }
+
+  /*---------------------------------------------------------------------
+   * Second step: Apply effect.
+   *--------------------------------------------------------------------- */
+  bool changed = false;
+  tGP_selected *selected = NULL;
+  for (int i = 0; i < gso->pbuffer_used; i++) {
+    changed = true;
+    selected = &gso->pbuffer[i];
+
     switch (tool) {
       case GPAINT_TOOL_TINT:
       case GPVERTEX_TOOL_DRAW: {
-        changed |= gp_vertexpaint_brush_do_stroke(gso, gps, diff_mat, brush_tint_apply);
+        brush_tint_apply(gso, selected->gps, selected->pt_index, radius, selected->pc);
+        changed |= true;
         break;
       }
 
       default:
-        printf("ERROR: Unknown type of GPencil Vertex paint brush\n");
+        printf("ERROR: Unknown type of GPencil Vertex Paint brush\n");
         break;
     }
   }
+  /* Clear the selected array, but keep the memory allocation.*/
+  gso->pbuffer = 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list