Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonioya <blendergit@gmail.com>2016-09-15 14:29:26 +0300
committerAntonioya <blendergit@gmail.com>2016-09-16 11:32:39 +0300
commitac7ff55f110e9c0b9e6cef2557d8cd06348c45fa (patch)
tree32eefdfad9497e42003573ba705daf06a9a90302
parent6f92604e539b2114763150fb1ace60d28e59a889 (diff)
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.
-rw-r--r--release/scripts/startup/bl_ui/properties_grease_pencil_common.py1
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c119
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h1
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c4
4 files changed, 125 insertions, 0 deletions
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 4299cf6035d..9432be39d1d 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 cce22ba9e17..7175ec3e83d 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 c1ed603273a..e2e5fc28710 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 e5d5bdbc831..26fcfdcead7 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);