From dc4c3ce592a7db9269b3f78dd6d5b2cdbb5a210c Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 9 May 2016 17:23:15 +1200 Subject: [PATCH] GPencil: Added operators to select first and last points of strokes These are useful for removing overshoots at the end of closed strokes (for fills) --- release/scripts/startup/bl_ui/space_view3d.py | 5 + .../blender/editors/gpencil/gpencil_intern.h | 2 + source/blender/editors/gpencil/gpencil_ops.c | 2 + .../blender/editors/gpencil/gpencil_select.c | 120 ++++++++++++++++++ 4 files changed, 129 insertions(+) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index b4525d4f498..2b92f20dcf6 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -992,6 +992,11 @@ class VIEW3D_MT_select_gpencil(Menu): layout.separator() + layout.operator("gpencil.select_first") + layout.operator("gpencil.select_last") + + layout.separator() + layout.operator("gpencil.select_more") layout.operator("gpencil.select_less") diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index 368da618a1d..dd28f6ac531 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -177,6 +177,8 @@ void GPENCIL_OT_select_linked(struct wmOperatorType *ot); void GPENCIL_OT_select_grouped(struct wmOperatorType *ot); void GPENCIL_OT_select_more(struct wmOperatorType *ot); void GPENCIL_OT_select_less(struct wmOperatorType *ot); +void GPENCIL_OT_select_first(struct wmOperatorType *ot); +void GPENCIL_OT_select_last(struct wmOperatorType *ot); void GPENCIL_OT_duplicate(struct wmOperatorType *ot); void GPENCIL_OT_delete(struct wmOperatorType *ot); diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c index d3520ef3e32..7241d4bb632 100644 --- a/source/blender/editors/gpencil/gpencil_ops.c +++ b/source/blender/editors/gpencil/gpencil_ops.c @@ -323,6 +323,8 @@ void ED_operatortypes_gpencil(void) WM_operatortype_append(GPENCIL_OT_select_grouped); WM_operatortype_append(GPENCIL_OT_select_more); WM_operatortype_append(GPENCIL_OT_select_less); + WM_operatortype_append(GPENCIL_OT_select_first); + WM_operatortype_append(GPENCIL_OT_select_last); WM_operatortype_append(GPENCIL_OT_duplicate); WM_operatortype_append(GPENCIL_OT_delete); diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index 0a36df471f1..b6482786b4f 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -348,6 +348,126 @@ void GPENCIL_OT_select_grouped(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, GP_SEL_SAME_LAYER, "Type", ""); } +/* ********************************************** */ +/* Select First */ + +static int gpencil_select_first_exec(bContext *C, wmOperator *op) +{ + const bool only_selected = RNA_boolean_get(op->ptr, "only_selected_strokes"); + const bool extend = RNA_boolean_get(op->ptr, "extend"); + + CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes) + { + /* skip stroke if we're only manipulating selected strokes */ + if (only_selected && !(gps->flag & GP_STROKE_SELECT)) { + continue; + } + + /* select first point */ + BLI_assert(gps->totpoints >= 1); + + gps->points->flag |= GP_SPOINT_SELECT; + gps->flag |= GP_STROKE_SELECT; + + /* deselect rest? */ + if ((extend == false) && (gps->totpoints > 1)) { + /* start from index 1, to skip the first point that we'd just selected... */ + bGPDspoint *pt = &gps->points[1]; + int i = 1; + + for (; i < gps->totpoints; i++, pt++) { + pt->flag &= ~GP_SPOINT_SELECT; + } + } + } + CTX_DATA_END; + + /* updates */ + WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL); + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_select_first(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select First"; + ot->idname = "GPENCIL_OT_select_first"; + ot->description = "Select first point in Grease Pencil strokes"; + + /* callbacks */ + ot->exec = gpencil_select_first_exec; + ot->poll = gpencil_select_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, "only_selected_strokes", false, "Selected Strokes Only", + "Only select the first point of strokes that already have points selected"); + + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting all other selected points"); +} + +/* ********************************************** */ +/* Select First */ + +static int gpencil_select_last_exec(bContext *C, wmOperator *op) +{ + const bool only_selected = RNA_boolean_get(op->ptr, "only_selected_strokes"); + const bool extend = RNA_boolean_get(op->ptr, "extend"); + + CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes) + { + /* skip stroke if we're only manipulating selected strokes */ + if (only_selected && !(gps->flag & GP_STROKE_SELECT)) { + continue; + } + + /* select last point */ + BLI_assert(gps->totpoints >= 1); + + gps->points[gps->totpoints - 1].flag |= GP_SPOINT_SELECT; + gps->flag |= GP_STROKE_SELECT; + + /* deselect rest? */ + if ((extend == false) && (gps->totpoints > 1)) { + /* don't include the last point... */ + bGPDspoint *pt = gps->points; + int i = 1; + + for (; i < gps->totpoints - 1; i++, pt++) { + pt->flag &= ~GP_SPOINT_SELECT; + } + } + } + CTX_DATA_END; + + /* updates */ + WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL); + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_select_last(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Last"; + ot->idname = "GPENCIL_OT_select_last"; + ot->description = "Select last point in Grease Pencil strokes"; + + /* callbacks */ + ot->exec = gpencil_select_last_exec; + ot->poll = gpencil_select_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, "only_selected_strokes", false, "Selected Strokes Only", + "Only select the last point of strokes that already have points selected"); + + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting all other selected points"); +} + /* ********************************************** */ /* Select More */