From a5dae7ee1914a648c85f07f22c8daa5506924cdc Mon Sep 17 00:00:00 2001 From: pullusb Date: Tue, 17 Jun 2025 17:17:29 +0200 Subject: [PATCH] Fix redundant checker and add operator "Remove Redundant GP Stroke" (search) --- CHANGELOG.md | 1 + OP_file_checker.py | 36 ++++++++++++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fdc70f0..6b0712a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ 4.1.3 - fixed: error in "remove stroke duplication" using file checker +- added: `Remove Redundant GP Stroke` Operator (Not exposed, avaialbe in search with developer extras enabled). Allow to use directly without going using file checker 4.1.2 diff --git a/OP_file_checker.py b/OP_file_checker.py index 669bb7c..ae56c91 100755 --- a/OP_file_checker.py +++ b/OP_file_checker.py @@ -10,17 +10,19 @@ from bpy.props import (BoolProperty, CollectionProperty, StringProperty) -def remove_stroke_exact_duplications(apply=True): +def remove_stroke_exact_duplications(apply=True, verbose=True): '''Remove accidental stroke duplication (points exactly in the same place) :apply: Remove the duplication instead of just listing dupes return number of duplication found/deleted ''' # TODO: Add additional check of material (even if unlikely to happen, better to avoid false positive) ct = 0 + if verbose: + print('\nRemove redundant strokdes in GP frames:') gp_datas = [gp for gp in bpy.data.grease_pencils_v3] for gp in gp_datas: for l in gp.layers: - for f in l.frames: + for f_id, f in enumerate(l.frames): stroke_list = [] idx_to_delete = [] @@ -32,10 +34,35 @@ def remove_stroke_exact_duplications(apply=True): else: stroke_list.append(point_list) - if apply: - # Remove redundancy + if apply and idx_to_delete: + # Remove redundancy (carefull, passing an empty list delete all strokes) + print(f"{gp.name} > {l.name} > {f_id}: {len(idx_to_delete)} strokes") f.drawing.remove_strokes(indices=idx_to_delete) return ct + +class GPTB_OT_remove_stroke_duplication(bpy.types.Operator): + bl_idname = "gp.remove_stroke_duplication" + bl_label = "Remove Redundant GP Stroke" + bl_description = "Within every frame, remove every strokes that are exactly superposed with a previous one" + bl_options = {"REGISTER", "UNDO"} + + apply : bpy.props.BoolProperty(name="Apply Fixes", default=True, + description="Remove the duplication", + options={'SKIP_SAVE'}) + + def execute(self, context): + ct = remove_stroke_exact_duplications(apply=self.apply) + if ct > 0: + if self.apply: + self.report({'INFO'}, f'Removed {ct} strokes duplications') + else: + self.report({'INFO'}, f'Found {ct} strokes duplications') + else: + self.report({'INFO'}, 'No stroke duplication found') + + return {'FINISHED'} + + class GPTB_OT_file_checker(bpy.types.Operator): bl_idname = "gp.file_checker" bl_label = "Check File" @@ -798,6 +825,7 @@ GPTB_OT_copy_string_to_clipboard, GPTB_OT_copy_multipath_clipboard, GPTB_OT_file_checker, GPTB_OT_links_checker, +GPTB_OT_remove_stroke_duplication, ) def register():