diff options
5 files changed, 88 insertions, 6 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 336e4acfd8f..7101b855c58 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -599,10 +599,6 @@ class GPENCIL_MT_gpencil_draw_specials(Menu): layout.operator("gpencil.primitive", text="Rectangle", icon='UV_FACESEL').type = 'BOX' layout.operator("gpencil.primitive", text="Circle", icon='ANTIALIASED').type = 'CIRCLE' - # Colors. - layout.separator() - layout.operator("gpencil.colorpick", text="Colors", icon="GROUP_VCOL") - class GPENCIL_MT_gpencil_draw_delete(Menu): bl_label = "GPencil Draw Delete" @@ -616,6 +612,21 @@ class GPENCIL_MT_gpencil_draw_delete(Menu): layout.operator("gpencil.active_frames_delete_all", text="Delete Frame") +class GPENCIL_MT_cleanup(Menu): + bl_label = "Clean Up" + + def draw(self, context): + layout = self.layout + layout.operator("gpencil.frame_clean_loose", text="Loose Points") + layout.separator() + + layout.operator("gpencil.frame_clean_fill", text="Boundary Strokes").mode = 'ACTIVE' + layout.operator("gpencil.frame_clean_fill", text="Boundary Strokes all Frames").mode = 'ALL' + layout.separator() + + layout.operator("gpencil.reproject") + + class GPENCIL_UL_annotation_layer(UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): # assert(isinstance(item, bpy.types.GPencilLayer) @@ -805,6 +816,7 @@ classes = ( GPENCIL_MT_snap, GPENCIL_MT_separate, + GPENCIL_MT_cleanup, GPENCIL_MT_gpencil_draw_specials, GPENCIL_MT_gpencil_draw_delete, diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index a26d99e9ae9..2edd1815c08 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -3633,7 +3633,7 @@ class VIEW3D_MT_edit_gpencil(Menu): layout.separator() - layout.operator_menu_enum("gpencil.frame_clean_fill", text="Clean Boundary Strokes...", property="mode") + layout.menu("GPENCIL_MT_cleanup") class VIEW3D_MT_sculpt_gpencil(Menu): @@ -4959,7 +4959,7 @@ class VIEW3D_MT_gpencil_edit_specials(Menu): if is_3d_view: layout.separator() - layout.operator("gpencil.reproject") + layout.menu("GPENCIL_MT_cleanup") class VIEW3D_MT_gpencil_sculpt_specials(Menu): diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index 752839e8dfa..45e5634eedb 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -565,6 +565,74 @@ void GPENCIL_OT_frame_clean_fill(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "mode", duplicate_mode, GP_FRAME_DUP_ACTIVE, "Mode", ""); } +/* ********************* Clean Loose Boundaries on Frame ************************** */ +static int gp_frame_clean_loose_exec(bContext *C, wmOperator *op) +{ + bool changed = false; + bGPdata *gpd = ED_gpencil_data_get_active(C); + int limit = RNA_int_get(op->ptr, "limit"); + + CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) + { + bGPDframe *gpf = gpl->actframe; + bGPDstroke *gps, *gpsn; + + if (gpf == NULL) + continue; + + /* simply delete strokes which are no loose */ + 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; + + /* free stroke */ + if (gps->totpoints <= limit) { + /* free stroke memory arrays, then stroke itself */ + if (gps->points) { + MEM_freeN(gps->points); + } + if (gps->dvert) { + BKE_gpencil_free_stroke_weights(gps); + MEM_freeN(gps->dvert); + } + MEM_SAFE_FREE(gps->triangles); + BLI_freelinkN(&gpf->strokes, gps); + + changed = true; + } + } + } + CTX_DATA_END; + + /* notifiers */ + if (changed) { + DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + } + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_frame_clean_loose(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Clean Loose points"; + ot->idname = "GPENCIL_OT_frame_clean_loose"; + ot->description = "Remove loose points"; + + /* callbacks */ + ot->exec = gp_frame_clean_loose_exec; + ot->poll = gp_active_layer_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_int(ot->srna, "limit", 1, 1, INT_MAX, "Limit", "Number of points to consider stroke as loose", 1, INT_MAX); +} + /* *********************** Hide Layers ******************************** */ static int gp_hide_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index 52e7d1e1f30..9d9fede91af 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -351,6 +351,7 @@ void GPENCIL_OT_active_frame_delete(struct wmOperatorType *ot); void GPENCIL_OT_active_frames_delete_all(struct wmOperatorType *ot); void GPENCIL_OT_frame_duplicate(struct wmOperatorType *ot); void GPENCIL_OT_frame_clean_fill(struct wmOperatorType *ot); +void GPENCIL_OT_frame_clean_loose(struct wmOperatorType *ot); void GPENCIL_OT_convert(struct wmOperatorType *ot); diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c index 1f238fccdc4..67e3d484596 100644 --- a/source/blender/editors/gpencil/gpencil_ops.c +++ b/source/blender/editors/gpencil/gpencil_ops.c @@ -729,6 +729,7 @@ void ED_operatortypes_gpencil(void) WM_operatortype_append(GPENCIL_OT_active_frames_delete_all); WM_operatortype_append(GPENCIL_OT_frame_duplicate); WM_operatortype_append(GPENCIL_OT_frame_clean_fill); + WM_operatortype_append(GPENCIL_OT_frame_clean_loose); WM_operatortype_append(GPENCIL_OT_convert); |