Commit: ac7ff55f110e9c0b9e6cef2557d8cd06348c45fa
Author: Antonioya
Date:   Thu Sep 15 13:29:26 2016 +0200
Branches: master
https://developer.blender.org/rBac7ff55f110e9c0b9e6cef2557d8cd06348c45fa

GPencil: New subdivide stroke operator

In some situations the artist needs to subdivide a stroke created with
few points before, specially for sculpting.

The subdivision is done for any pair of continuous selected points in
the same stroke.

The operator can be activated in edit mode with W key and has a
parameter for number of cuts.

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

M       release/scripts/startup/bl_ui/properties_grease_pencil_common.py
M       source/blender/editors/gpencil/gpencil_edit.c
M       source/blender/editors/gpencil/gpencil_intern.h
M       source/blender/editors/gpencil/gpencil_ops.c

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

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 4299cf6..9432be3 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -227,6 +227,7 @@ class GreasePencilStrokeEditPanel:
 
         layout.separator()
         col = layout.column(align=True)
+        col.operator("gpencil.stroke_subdivide", text="Subdivide")
         col.operator("gpencil.stroke_join", text="Join").type = 'JOIN'
         col.operator("gpencil.stroke_join", text="Join & Copy").type = 
'JOINCOPY'
         col.operator("gpencil.stroke_flip", text="Flip Direction")
diff --git a/source/blender/editors/gpencil/gpencil_edit.c 
b/source/blender/editors/gpencil/gpencil_edit.c
index cce22ba..7175ec3 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -1970,6 +1970,125 @@ void GPENCIL_OT_reproject(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
+/* ******************* Stroke subdivide ************************** */
+/* helper: Count how many points need to be inserted */
+static int gp_count_subdivision_cuts(bGPDstroke *gps)
+{
+       bGPDspoint *pt;
+       int i;
+       int totnewpoints = 0;
+       for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) {
+               if (pt->flag & GP_SPOINT_SELECT) {
+                       if (i + 1 < gps->totpoints){
+                               if (gps->points[i + 1].flag & GP_SPOINT_SELECT) 
{
+                                       ++totnewpoints;
+                               };
+                       }
+               }
+       }
+
+       return totnewpoints;
+}
+static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
+{
+       bGPdata *gpd = ED_gpencil_data_get_active(C);
+       bGPDspoint *temp_points;
+       const int cuts = RNA_int_get(op->ptr, "number_cuts");
+
+       int totnewpoints, oldtotpoints;
+       int i2;
+
+       /* sanity checks */
+       if (ELEM(NULL, gpd))
+               return OPERATOR_CANCELLED;
+
+       /* Go through each editable + selected stroke */
+       GP_EDITABLE_STROKES_BEGIN(C, gpl, gps)
+       {
+               if (gps->flag & GP_STROKE_SELECT) {
+                       /* loop as many times as cuts */
+                       for (int s = 0; s < cuts; s++) {
+                               totnewpoints = gp_count_subdivision_cuts(gps);
+                               if (totnewpoints == 0) {
+                                       continue;
+                               }
+                               /* duplicate points in a temp area */
+                               temp_points = MEM_dupallocN(gps->points);
+                               oldtotpoints = gps->totpoints;
+
+                               /* resize the points arrys */
+                               gps->totpoints += totnewpoints;
+                               gps->points = MEM_recallocN(gps->points, 
sizeof(*gps->points) * gps->totpoints);
+                               gps->flag |= GP_STROKE_RECALC_CACHES;
+
+                               /* loop and interpolate */
+                               i2 = 0;
+                               for (int i = 0; i < oldtotpoints; i++) {
+                                       bGPDspoint *pt = &temp_points[i];
+                                       bGPDspoint *pt_final = &gps->points[i2];
+
+                                       /* copy current point */
+                                       copy_v3_v3(&pt_final->x, &pt->x);
+                                       pt_final->pressure = pt->pressure;
+                                       pt_final->strength = pt->strength;
+                                       pt_final->time = pt->time;
+                                       pt_final->flag = pt->flag;
+                                       ++i2;
+
+                                       /* if next point is selected add a half 
way point */
+                                       if (pt->flag & GP_SPOINT_SELECT) {
+                                               if (i + 1 < oldtotpoints){
+                                                       if (temp_points[i + 
1].flag & GP_SPOINT_SELECT) {
+                                                               pt_final = 
&gps->points[i2];
+                                                               /* Interpolate 
all values */
+                                                               bGPDspoint 
*next = &temp_points[i + 1];
+                                                               
interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
+                                                               
pt_final->pressure = interpf(pt->pressure, next->pressure, 0.5f);
+                                                               
pt_final->strength = interpf(pt->strength, next->strength, 0.5f);
+                                                               
CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
+                                                               pt_final->time 
= interpf(pt->time, next->time, 0.5f);
+                                                               pt_final->flag 
|= GP_SPOINT_SELECT;
+                                                               ++i2;
+                                                       };
+                                               }
+                                       }
+                               }
+                               /* free temp memory */
+                               MEM_freeN(temp_points);
+                       }
+               }
+       }
+       GP_EDITABLE_STROKES_END;
+
+       /* notifiers */
+       WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+       return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_stroke_subdivide(wmOperatorType *ot)
+{
+       PropertyRNA *prop;
+
+       /* identifiers */
+       ot->name = "Subdivide Stroke";
+       ot->idname = "GPENCIL_OT_stroke_subdivide";
+       ot->description = "Subdivide between continuous selected points of the 
stroke adding a point half way between them";
+
+       /* api callbacks */
+       ot->exec = gp_stroke_subdivide_exec;
+       ot->poll = gp_active_layer_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+       /* properties */
+       prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 10, "Number of Cuts", 
"", 1, 5);
+       /* avoid re-using last var because it can cause _very_ high value and 
annoy users */
+       RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+}
+
 /* =========  Interpolation operators ========================== */
 /* Helper: Update point with interpolation */
 static void gp_interpolate_update_points(bGPDstroke *gps_from, bGPDstroke 
*gps_to, bGPDstroke *new_stroke, float factor)
diff --git a/source/blender/editors/gpencil/gpencil_intern.h 
b/source/blender/editors/gpencil/gpencil_intern.h
index c1ed603..e2e5fc2 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -304,6 +304,7 @@ void GPENCIL_OT_stroke_apply_thickness(struct 
wmOperatorType *ot);
 void GPENCIL_OT_stroke_cyclical_set(struct wmOperatorType *ot);
 void GPENCIL_OT_stroke_join(struct wmOperatorType *ot);
 void GPENCIL_OT_stroke_flip(struct wmOperatorType *ot);
+void GPENCIL_OT_stroke_subdivide(struct wmOperatorType *ot);
 
 void GPENCIL_OT_brush_add(struct wmOperatorType *ot);
 void GPENCIL_OT_brush_remove(struct wmOperatorType *ot);
diff --git a/source/blender/editors/gpencil/gpencil_ops.c 
b/source/blender/editors/gpencil/gpencil_ops.c
index e5d5bdb..26fcfdc 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -242,6 +242,9 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
        
        WM_keymap_add_item(keymap, "GPENCIL_OT_active_frames_delete_all", XKEY, 
KM_PRESS, KM_SHIFT, 0);
        
+       /* subdivide strokes */
+       WM_keymap_add_item(keymap, "GPENCIL_OT_stroke_subdivide", WKEY, 
KM_PRESS, 0, 0);
+
        /* join strokes */
        WM_keymap_add_item(keymap, "GPENCIL_OT_stroke_join", JKEY, KM_PRESS, 
KM_CTRL, 0);
        
@@ -410,6 +413,7 @@ void ED_operatortypes_gpencil(void)
        WM_operatortype_append(GPENCIL_OT_stroke_cyclical_set);
        WM_operatortype_append(GPENCIL_OT_stroke_join);
        WM_operatortype_append(GPENCIL_OT_stroke_flip);
+       WM_operatortype_append(GPENCIL_OT_stroke_subdivide);
 
        WM_operatortype_append(GPENCIL_OT_palette_add);
        WM_operatortype_append(GPENCIL_OT_palette_remove);

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to