[Bf-blender-cvs] [65de468396a] master: GP: Draw: Stroke Trim

Charlie Jolly noreply at git.blender.org
Tue Feb 26 17:04:53 CET 2019


Commit: 65de468396aaf5f43fffdc6d42e304412f75fcb8
Author: Charlie Jolly
Date:   Tue Feb 26 16:04:27 2019 +0000
Branches: master
https://developer.blender.org/rB65de468396aaf5f43fffdc6d42e304412f75fcb8

GP: Draw: Stroke Trim

New edit mode operator and post-processing brush option.

Trim works on a single GP stroke. It removes trailing points before and after the first intersection (or loop) nearest to the start of the stroke.

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

M	release/scripts/startup/bl_operators/presets.py
M	release/scripts/startup/bl_ui/properties_grease_pencil_common.py
M	release/scripts/startup/bl_ui/space_view3d.py
M	release/scripts/startup/bl_ui/space_view3d_toolbar.py
M	source/blender/blenkernel/BKE_gpencil.h
M	source/blender/blenkernel/intern/gpencil.c
M	source/blender/editors/gpencil/gpencil_edit.c
M	source/blender/editors/gpencil/gpencil_intern.h
M	source/blender/editors/gpencil/gpencil_ops.c
M	source/blender/editors/gpencil/gpencil_paint.c
M	source/blender/makesdna/DNA_brush_types.h
M	source/blender/makesrna/intern/rna_brush.c

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

diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py
index 1351dbbd42e..663de209c15 100644
--- a/release/scripts/startup/bl_operators/presets.py
+++ b/release/scripts/startup/bl_operators/presets.py
@@ -673,6 +673,7 @@ class AddPresetGpencilBrush(AddPresetBase, Operator):
         "settings.uv_random",
         "settings.pen_jitter",
         "settings.use_jitter_pressure",
+        "settings.trim",
     ]
 
     preset_subdir = "gpencil_brush"
diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
index b5937388634..2a4c4e94b0c 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -215,6 +215,7 @@ class GreasePencilStrokeEditPanel:
         row = col.row(align=True)
         row.operator("gpencil.stroke_simplify_fixed", text="Simplify")
         row.operator("gpencil.stroke_simplify", text="Adaptive")
+        row.operator("gpencil.stroke_trim", text="Trim")
 
         col.separator()
 
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 6a0ba6a713d..e73b2538bee 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -4007,6 +4007,7 @@ class VIEW3D_MT_edit_gpencil(Menu):
         layout.operator("gpencil.stroke_smooth", text="Smooth")
         layout.operator("gpencil.stroke_subdivide", text="Subdivide")
         layout.menu("VIEW3D_MT_gpencil_simplify")
+        layout.operator("gpencil.stroke_trim", text="Trim")
 
         layout.separator()
 
@@ -5674,6 +5675,7 @@ class VIEW3D_MT_gpencil_edit_specials(Menu):
         layout.operator("gpencil.stroke_subdivide", text="Subdivide")
         layout.operator("gpencil.stroke_simplify_fixed", text="Simplify")
         layout.operator("gpencil.stroke_simplify", text="Simplify Adaptive")
+        layout.operator("gpencil.stroke_trim", text="Trim")
 
         layout.separator()
         layout.menu("GPENCIL_MT_separate", text="Separate")
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 2ba84ac166e..254a893be52 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -1599,6 +1599,9 @@ class VIEW3D_PT_tools_grease_pencil_brush_settings(View3DPanel, Panel):
         col.prop(gp_settings, "pen_subdivision_steps")
         col.prop(gp_settings, "random_subdiv", text="Randomness", slider=True)
 
+        col = layout.column(align=True)
+        col.prop(gp_settings, "trim")
+
 
 class VIEW3D_PT_tools_grease_pencil_brush_random(View3DPanel, Panel):
     bl_context = ".greasepencil_paint"
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index a33f172b961..eb4101fa2f7 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -160,6 +160,7 @@ void BKE_gpencil_stroke_normal(const struct bGPDstroke *gps, float r_normal[3]);
 void BKE_gpencil_simplify_stroke(struct bGPDstroke *gps, float factor);
 void BKE_gpencil_simplify_fixed(struct bGPDstroke *gps);
 void BKE_gpencil_subdivide(struct bGPDstroke *gps, int level, int flag);
+bool BKE_gpencil_trim_stroke(struct bGPDstroke *gps);
 
 void BKE_gpencil_stroke_2d_flat(
 	const struct bGPDspoint *points, int totpoints, float(*points2d)[2], int *r_direction);
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index ad41382f854..108192c5be9 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -1700,3 +1700,98 @@ void BKE_gpencil_stroke_2d_flat_ref(
 	/* Concave (-1), Convex (1), or Autodetect (0)? */
 	*r_direction = (int)locy[2];
 }
+
+/**
+ * Trim stroke to the first intersection or loop
+ * \param gps: Stroke data
+ */
+bool BKE_gpencil_trim_stroke(bGPDstroke *gps)
+{
+	if (gps->totpoints < 4) {
+		return false;
+	}
+	bool intersect = false;
+	int start, end;
+	float point[3];
+	/* loop segments from start until we have an intersection */
+	for (int i = 0; i < gps->totpoints - 2; i++) {
+		start = i;
+		bGPDspoint *a = &gps->points[start];
+		bGPDspoint *b = &gps->points[start + 1];
+		for (int j = start + 2; j < gps->totpoints - 1; j++) {
+			end = j + 1;
+			bGPDspoint *c = &gps->points[j];
+			bGPDspoint *d = &gps->points[end];
+			float pointb[3];
+			/* get intersection */
+			if (isect_line_line_v3(&a->x, &b->x, &c->x, &d->x, point, pointb)) {
+				if (len_v3(point) > 0.0f) {
+					float closest[3];
+					/* check intersection is on both lines */
+					float lambda = closest_to_line_v3(closest, point, &a->x, &b->x);
+					if ((lambda <= 0.0f) || (lambda >= 1.0f)) {
+						continue;
+					}
+					lambda = closest_to_line_v3(closest, point, &c->x, &d->x);
+					if ((lambda <= 0.0f) || (lambda >= 1.0f)) {
+						continue;
+					}
+					else {
+						intersect = true;
+						break;
+					}
+				}
+			}
+		}
+		if (intersect) {
+			break;
+		}
+	}
+
+	/* trim unwanted points */
+	if (intersect) {
+
+		/* save points */
+		bGPDspoint *old_points = MEM_dupallocN(gps->points);
+		MDeformVert *old_dvert = NULL;
+		MDeformVert *dvert_src = NULL;
+
+		if (gps->dvert != NULL) {
+			old_dvert = MEM_dupallocN(gps->dvert);
+		}
+
+		/* resize gps */
+		int newtot = end - start + 1;
+
+		gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * newtot);
+		if (gps->dvert != NULL) {
+			gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot);
+		}
+
+		for (int i = 0; i < newtot; i++) {
+			int idx = start + i;
+			bGPDspoint *pt_src = &old_points[idx];
+			bGPDspoint *pt_new = &gps->points[i];
+			memcpy(pt_new, pt_src, sizeof(bGPDspoint));
+			if (gps->dvert != NULL) {
+				dvert_src = &old_dvert[idx];
+				MDeformVert *dvert = &gps->dvert[i];
+				memcpy(dvert, dvert_src, sizeof(MDeformVert));
+				if (dvert_src->dw) {
+					memcpy(dvert->dw, dvert_src->dw, sizeof(MDeformWeight));
+				}
+			}
+			if (idx == start || idx == end) {
+				copy_v3_v3(&pt_new->x, point);
+			}
+		}
+
+		gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+		gps->tot_triangles = 0;
+		gps->totpoints = newtot;
+
+		MEM_SAFE_FREE(old_points);
+		MEM_SAFE_FREE(old_dvert);
+	}
+	return intersect;
+}
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index ebf2ca8c304..cfb32c5b5ef 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -3562,6 +3562,74 @@ void GPENCIL_OT_stroke_simplify_fixed(wmOperatorType *ot)
 
 }
 
+/* ******************* Stroke trim ************************** */
+static int gp_stroke_trim_exec(bContext *C, wmOperator *op)
+{
+	bGPdata *gpd = ED_gpencil_data_get_active(C);
+
+	/* sanity checks */
+	if (ELEM(NULL, gpd))
+		return OPERATOR_CANCELLED;
+
+	/* Go through each editable + selected stroke */
+	const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+
+	CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+	{
+		bGPDframe *init_gpf = gpl->actframe;
+		if (is_multiedit) {
+			init_gpf = gpl->frames.first;
+		}
+
+		for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+			if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+				bGPDstroke *gps, *gpsn;
+
+				if (gpf == NULL)
+					continue;
+
+				for (gps = gpf->strokes.first; gps; gps = gpsn) {
+					gpsn = gps->next;
+
+					/* skip strokes that are invalid for current view */
+					if (ED_gpencil_stroke_can_use(C, gps) == false)
+						continue;
+
+					if (gps->flag & GP_STROKE_SELECT) {
+						BKE_gpencil_trim_stroke(gps);
+					}
+				}
+				/* if not multiedit, exit loop*/
+				if (!is_multiedit) {
+					break;
+				}
+			}
+		}
+	}
+	CTX_DATA_END;
+
+	/* notifiers */
+	DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+	WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+	return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_stroke_trim(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Trim Stroke";
+	ot->idname = "GPENCIL_OT_stroke_trim";
+	ot->description = "Trim selected stroke to first loop or intersection";
+
+	/* api callbacks */
+	ot->exec = gp_stroke_trim_exec;
+	ot->poll = gp_active_layer_poll;
+
+	/* flags */
+	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
 /* ***************** Separate Strokes ********************** */
 typedef enum eGP_SeparateModes {
 	/* Points */
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 971cc9e98be..9341133d520 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -467,6 +467,7 @@ void GPENCIL_OT_stroke_split(struct wmOperatorType *ot);
 void GPENCIL_OT_stroke_smooth(struct wmOperatorType *ot);
 void GPENCIL_OT_stroke_merge(struct wmOperatorType *ot);
 void GPENCIL_OT_stroke_cutter(struct wmOperatorType *ot);
+void GPENCIL_OT_stroke_trim(struct wmOperatorType *ot);
 
 void GPENCIL_OT_brush_presets_create(struct wmOperatorType *ot);
 
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 67957e64e8f..60b2fb5d64e 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -310,6 +310,7 @@ void ED_operatortypes_gpencil(void)
 	WM_operatortype_append(GPENCIL_OT_stroke_smooth);
 	WM_operatortype_append(GPENCIL_OT_stroke_merge);
 	WM_operatortype_append(GPENCIL_OT_stroke_cutter);
+	WM_operatortype_append(GPENCIL_OT_stroke_trim);
 
 	WM_operatortype_append(GPENCIL_OT_brush_presets_create);
 
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 731f85d1bea..63f1e495e6b 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -1242,6 +1242,12 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
 		}
 	}
 
+	/* post process

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list