[Bf-blender-cvs] [3503b71fcc0] greasepencil-object: Merge branch 'master' into greasepencil-object

Antonio Vazquez noreply at git.blender.org
Wed Nov 18 21:45:34 CET 2020


Commit: 3503b71fcc069c525551a489988aa312251e529f
Author: Antonio Vazquez
Date:   Wed Nov 18 21:43:13 2020 +0100
Branches: greasepencil-object
https://developer.blender.org/rB3503b71fcc069c525551a489988aa312251e529f

Merge branch 'master' into greasepencil-object

 Conflicts:
	source/blender/blenkernel/intern/gpencil_geom.c
	source/blender/editors/gpencil/gpencil_utils.c
	source/blender/editors/include/ED_gpencil.h

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



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

diff --cc source/blender/blenkernel/intern/gpencil_geom.c
index eaad8e4a1b3,fc74439fd76..1554bb0fb41
--- a/source/blender/blenkernel/intern/gpencil_geom.c
+++ b/source/blender/blenkernel/intern/gpencil_geom.c
@@@ -2643,602 -2669,559 +2671,1159 @@@ void BKE_gpencil_stroke_set_random_colo
    }
  }
  
+ /* Flip stroke. */
+ void BKE_gpencil_stroke_flip(bGPDstroke *gps)
+ {
+   int end = gps->totpoints - 1;
+ 
+   for (int i = 0; i < gps->totpoints / 2; i++) {
+     bGPDspoint *point, *point2;
+     bGPDspoint pt;
+ 
+     /* save first point */
+     point = &gps->points[i];
+     pt.x = point->x;
+     pt.y = point->y;
+     pt.z = point->z;
+     pt.flag = point->flag;
+     pt.pressure = point->pressure;
+     pt.strength = point->strength;
+     pt.time = point->time;
+     copy_v4_v4(pt.vert_color, point->vert_color);
+ 
+     /* replace first point with last point */
+     point2 = &gps->points[end];
+     point->x = point2->x;
+     point->y = point2->y;
+     point->z = point2->z;
+     point->flag = point2->flag;
+     point->pressure = point2->pressure;
+     point->strength = point2->strength;
+     point->time = point2->time;
+     copy_v4_v4(point->vert_color, point2->vert_color);
+ 
+     /* replace last point with first saved before */
+     point = &gps->points[end];
+     point->x = pt.x;
+     point->y = pt.y;
+     point->z = pt.z;
+     point->flag = pt.flag;
+     point->pressure = pt.pressure;
+     point->strength = pt.strength;
+     point->time = pt.time;
+     copy_v4_v4(point->vert_color, pt.vert_color);
+ 
+     end--;
+   }
+ }
+ 
+ /* Temp data for storing information about an "island" of points
+  * that should be kept when splitting up a stroke. Used in:
+  * gpencil_stroke_delete_tagged_points()
+  */
+ typedef struct tGPDeleteIsland {
+   int start_idx;
+   int end_idx;
+ } tGPDeleteIsland;
+ 
+ static void gpencil_stroke_join_islands(bGPdata *gpd,
+                                         bGPDframe *gpf,
+                                         bGPDstroke *gps_first,
+                                         bGPDstroke *gps_last)
+ {
+   bGPDspoint *pt = NULL;
+   bGPDspoint *pt_final = NULL;
+   const int totpoints = gps_first->totpoints + gps_last->totpoints;
+ 
+   /* create new stroke */
+   bGPDstroke *join_stroke = BKE_gpencil_stroke_duplicate(gps_first, false, true);
+ 
+   join_stroke->points = MEM_callocN(sizeof(bGPDspoint) * totpoints, __func__);
+   join_stroke->totpoints = totpoints;
+   join_stroke->flag &= ~GP_STROKE_CYCLIC;
+ 
+   /* copy points (last before) */
+   int e1 = 0;
+   int e2 = 0;
+   float delta = 0.0f;
+ 
+   for (int i = 0; i < totpoints; i++) {
+     pt_final = &join_stroke->points[i];
+     if (i < gps_last->totpoints) {
+       pt = &gps_last->points[e1];
+       e1++;
+     }
+     else {
+       pt = &gps_first->points[e2];
+       e2++;
+     }
+ 
+     /* copy current point */
+     copy_v3_v3(&pt_final->x, &pt->x);
+     pt_final->pressure = pt->pressure;
+     pt_final->strength = pt->strength;
+     pt_final->time = delta;
+     pt_final->flag = pt->flag;
+     copy_v4_v4(pt_final->vert_color, pt->vert_color);
+ 
+     /* retiming with fixed time interval (we cannot determine real time) */
+     delta += 0.01f;
+   }
+ 
+   /* Copy over vertex weight data (if available) */
+   if ((gps_first->dvert != NULL) || (gps_last->dvert != NULL)) {
+     join_stroke->dvert = MEM_callocN(sizeof(MDeformVert) * totpoints, __func__);
+     MDeformVert *dvert_src = NULL;
+     MDeformVert *dvert_dst = NULL;
+ 
+     /* Copy weights (last before)*/
+     e1 = 0;
+     e2 = 0;
+     for (int i = 0; i < totpoints; i++) {
+       dvert_dst = &join_stroke->dvert[i];
+       dvert_src = NULL;
+       if (i < gps_last->totpoints) {
+         if (gps_last->dvert) {
+           dvert_src = &gps_last->dvert[e1];
+           e1++;
+         }
+       }
+       else {
+         if (gps_first->dvert) {
+           dvert_src = &gps_first->dvert[e2];
+           e2++;
+         }
+       }
+ 
+       if ((dvert_src) && (dvert_src->dw)) {
+         dvert_dst->dw = MEM_dupallocN(dvert_src->dw);
+       }
+     }
+   }
+ 
+   /* add new stroke at head */
+   BLI_addhead(&gpf->strokes, join_stroke);
+   /* Calc geometry data. */
+   BKE_gpencil_stroke_geometry_update(gpd, join_stroke);
+ 
+   /* remove first stroke */
+   BLI_remlink(&gpf->strokes, gps_first);
+   BKE_gpencil_free_stroke(gps_first);
+ 
+   /* remove last stroke */
+   BLI_remlink(&gpf->strokes, gps_last);
+   BKE_gpencil_free_stroke(gps_last);
+ }
+ 
+ /* Split the given stroke into several new strokes, partitioning
+  * it based on whether the stroke points have a particular flag
+  * is set (e.g. "GP_SPOINT_SELECT" in most cases, but not always)
+  *
+  * The algorithm used here is as follows:
+  * 1) We firstly identify the number of "islands" of non-tagged points
+  *    which will all end up being in new strokes.
+  *    - In the most extreme case (i.e. every other vert is a 1-vert island),
+  *      we have at most n / 2 islands
+  *    - Once we start having larger islands than that, the number required
+  *      becomes much less
+  * 2) Each island gets converted to a new stroke
+  * If the number of points is <= limit, the stroke is deleted
+  */
+ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd,
+                                                     bGPDframe *gpf,
+                                                     bGPDstroke *gps,
+                                                     bGPDstroke *next_stroke,
+                                                     int tag_flags,
+                                                     bool select,
+                                                     int limit)
+ {
+   tGPDeleteIsland *islands = MEM_callocN(sizeof(tGPDeleteIsland) * (gps->totpoints + 1) / 2,
+                                          "gp_point_islands");
+   bool in_island = false;
+   int num_islands = 0;
+ 
+   bGPDstroke *new_stroke = NULL;
+   bGPDstroke *gps_first = NULL;
+   const bool is_cyclic = (bool)(gps->flag & GP_STROKE_CYCLIC);
+ 
+   /* First Pass: Identify start/end of islands */
+   bGPDspoint *pt = gps->points;
+   for (int i = 0; i < gps->totpoints; i++, pt++) {
+     if (pt->flag & tag_flags) {
+       /* selected - stop accumulating to island */
+       in_island = false;
+     }
+     else {
+       /* unselected - start of a new island? */
+       int idx;
+ 
+       if (in_island) {
+         /* extend existing island */
+         idx = num_islands - 1;
+         islands[idx].end_idx = i;
+       }
+       else {
+         /* start of new island */
+         in_island = true;
+         num_islands++;
+ 
+         idx = num_islands - 1;
+         islands[idx].start_idx = islands[idx].end_idx = i;
+       }
+     }
+   }
+ 
+   /* Watch out for special case where No islands = All points selected = Delete Stroke only */
+   if (num_islands) {
+     /* There are islands, so create a series of new strokes,
+      * adding them before the "next" stroke. */
+     int idx;
+ 
+     /* Create each new stroke... */
+     for (idx = 0; idx < num_islands; idx++) {
+       tGPDeleteIsland *island = &islands[idx];
+       new_stroke = BKE_gpencil_stroke_duplicate(gps, false, true);
+ 
+       /* if cyclic and first stroke, save to join later */
+       if ((is_cyclic) && (gps_first == NULL)) {
+         gps_first = new_stroke;
+       }
+ 
+       new_stroke->flag &= ~GP_STROKE_CYCLIC;
+ 
+       /* Compute new buffer size (+ 1 needed as the endpoint index is "inclusive") */
+       new_stroke->totpoints = island->end_idx - island->start_idx + 1;
+ 
+       /* Copy over the relevant point data */
+       new_stroke->points = MEM_callocN(sizeof(bGPDspoint) * new_stroke->totpoints,
+                                        "gp delete stroke fragment");
+       memcpy(new_stroke->points,
+              gps->points + island->start_idx,
+              sizeof(bGPDspoint) * new_stroke->totpoints);
+ 
+       /* Copy over vertex weight data (if available) */
+       if (gps->dvert != NULL) {
+         /* Copy over the relevant vertex-weight points */
+         new_stroke->dvert = MEM_callocN(sizeof(MDeformVert) * new_stroke->totpoints,
+                                         "gp delete stroke fragment weight");
+         memcpy(new_stroke->dvert,
+                gps->dvert + island->start_idx,
+                sizeof(MDeformVert) * new_stroke->totpoints);
+ 
+         /* Copy weights */
+         int e = island->start_idx;
+         for (int i = 0; i < new_stroke->totpoints; i++) {
+           MDeformVert *dvert_src = &gps->dvert[e];
+           MDeformVert *dvert_dst = &new_stroke->dvert[i];
+           if (dvert_src->dw) {
+             dvert_dst->dw = MEM_dupallocN(dvert_src->dw);
+           }
+           e++;
+         }
+       }
+       /* Each island corresponds to a new stroke.
+        * We must adjust the timings of these new strokes:
+        *
+        * Each point's timing data is a delta from stroke's inittime, so as we erase some points
+        * from the start of the stroke, we have to offset this inittime and all remaining points'
+        * delta values. This way we get a new stroke with exactly the same timing as if user had
+        * started drawing from the first non-removed point.
+        */
+       {
+         bGPDspoint *pts;
+         float delta = gps->points[island->start_idx].time;
+         int j;
+ 
+         new_stroke->inittime += (double)delta;
+ 
+         pts = new_stroke->points;
+         for (j = 0; j < new_stroke->totpoints; j++, pts++) {
+           pts->time -= delta;
+           /* set flag for select again later */
+           if (select == true) {
+             pts->flag &= ~GP_SPOINT_SELECT;
+             pts->flag |= GP_SPOINT_TAG;
+           }
+         }
+       }
+ 
+       /* Add new stroke to the frame or delete if below limit */
+       if ((limit > 0) && (new_stroke->totpoints <= limit)) {
+         BKE_gpencil_free_stroke(new_stroke);
+       }
+       else {
+         /* Calc geometry data. */
+         BKE_gpencil_stroke_geometry_update(gpd, new_stroke);
+ 
+         if (next_stroke) {
+           BLI_insertlinkbefore(&gpf->strokes, 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list