[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