Commit: f6c25ed3baad7c2e96fedce8f3e960d64f2324f6
Author: Charlie Jolly
Date:   Thu Jan 24 15:57:02 2019 +0000
Branches: greasepencil-object
https://developer.blender.org/rBf6c25ed3baad7c2e96fedce8f3e960d64f2324f6

GP: Draw: Stroke Trim

+ New 'Trim' 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/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 49f857492f3..b1743861202 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -214,6 +214,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 f0bbc1d39dc..14af4fbf0c7 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -3943,6 +3943,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()
 
@@ -5595,6 +5596,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 95f97ee454f..513df3dc155 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -1573,6 +1573,9 @@ class 
VIEW3D_PT_tools_grease_pencil_brush_settings(View3DPanel, Panel):
         gp_settings = brush.gpencil_settings
         layout.active = gp_settings.use_settings_postprocess
 
+        col = layout.column(align=True)
+        col.prop(gp_settings, "trim")
+        
         col = layout.column(align=True)
         col.prop(gp_settings, "pen_smooth_factor")
         col.prop(gp_settings, "pen_smooth_steps")
diff --git a/source/blender/blenkernel/BKE_gpencil.h 
b/source/blender/blenkernel/BKE_gpencil.h
index 8c680feb04c..5925072235b 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -167,6 +167,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);
+void 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/editors/gpencil/gpencil_edit.c 
b/source/blender/editors/gpencil/gpencil_edit.c
index 05bd5dd3c1b..9b3c3e8a000 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -3454,6 +3454,154 @@ void GPENCIL_OT_stroke_simplify_fixed(wmOperatorType 
*ot)
 
 }
 
+/* ******************* Stroke trim ************************** */
+
+/**
+ * Trim stroke to the first intersection or loop
+ * \param gps: Stroke data
+ */
+bool 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; 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;
+
+               print_v3_id(point);
+               printf("\tstart: %i, end: %i\n", start, end);
+               printf("\told: %i\n", gps->totpoints);
+               printf("\tnewtot: %i\n", newtot);
+
+               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;
+}
+
+/* Trim stroke to first loop or intersection */
+void BKE_gpencil_trim_stroke(bGPDstroke *gps)
+{
+       gpencil_trim_stroke(gps);
+}
+
+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 */
+       GP_EDITABLE_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
+       {
+               if (gps->flag & GP_STROKE_SELECT) {
+                       /* simplify stroke using Ramer-Douglas-Peucker 
algorithm */
+                       BKE_gpencil_trim_stroke(gps);
+               }
+       }
+       GP_EDITABLE_STROKES_END(gpstroke_iter);
+
+       /* 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 6f71505de68..4f4f677a1b9 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -475,6 +475,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 8493244998d..e6e33b4c5fe 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -316,6 +316,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 e025dd9b261..654cf639af8 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -1255,6 +1255,12 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
                }
        }
 
+       /* post process stroke */
+       if ((p->brush->gpencil_settings->flag & GP_BRUSH_GROUP_SETTINGS) &&
+               p->brush->gpencil_settings->flag & GP_BRUSH_TRIM_STROKE) {
+               BKE_gpencil_trim_stroke(gps);
+       }
+
        gp_stroke_added_enable(p);
 }
 
diff --git a/source/blender/makesdna/DNA_brush_types.h 
b/source/blender/makesdna/DNA_brush_types.h
index 17e683c76d5..1c859709b25 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -79,8 +79,7 @@ typedef struct BrushGpencilSettings {
        short draw_smoothlvl;
        /** Number of times to subdivide new strokes. */
        short draw_subdivide;
-       /** Internal grease pencil drawing flags. */
-       short flag;
+       short _pad;
 
        /** Number of times to apply thickness smoo

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to