[Bf-blender-cvs] [8d4b31ce03] master: GP Interpolation: "Remove Breakdowns" operator

Joshua Leung noreply at git.blender.org
Wed Jan 18 07:43:22 CET 2017


Commit: 8d4b31ce03523b80c82a2de43cd53120a3089c46
Author: Joshua Leung
Date:   Wed Jan 18 19:40:48 2017 +1300
Branches: master
https://developer.blender.org/rB8d4b31ce03523b80c82a2de43cd53120a3089c46

GP Interpolation: "Remove Breakdowns" operator

To make it faster to try different interpolation curves, there's a new operator
"Remove Breakdowns" which will delete all breakdowns sandwiched by normal
keyframes (i.e. all the ones that the previous run of the Interpolation op created)

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

M	release/scripts/startup/bl_ui/properties_grease_pencil_common.py
M	source/blender/editors/gpencil/gpencil_intern.h
M	source/blender/editors/gpencil/gpencil_interpolate.c
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 1f06b202ad..3d68930e63 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -247,7 +247,7 @@ class GreasePencilStrokeEditPanel:
 
 class GreasePencilInterpolatePanel:
     bl_space_type = 'VIEW_3D'
-    bl_label = "Interpolate..."
+    bl_label = "Interpolate"
     bl_category = "Grease Pencil"
     bl_region_type = 'TOOLS'
     bl_options = {'DEFAULT_CLOSED'}
@@ -270,6 +270,10 @@ class GreasePencilInterpolatePanel:
         col = layout.column(align=True)
         col.operator("gpencil.interpolate", text="Interpolate")
         col.operator("gpencil.interpolate_sequence", text="Sequence")
+        col.operator("gpencil.interpolate_reverse", text="Remove Breakdowns")
+
+        col = layout.column(align=True)
+        col.label(text="Options:")
         col.prop(settings, "interpolate_all_layers")
         col.prop(settings, "interpolate_selected_only")
 
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index e2e5fc2871..cb293dda1e 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -340,6 +340,7 @@ void gpencil_undo_finish(void);
 
 void GPENCIL_OT_interpolate(struct wmOperatorType *ot);
 void GPENCIL_OT_interpolate_sequence(struct wmOperatorType *ot);
+void GPENCIL_OT_interpolate_reverse(struct wmOperatorType *ot);
 
 /* ****************************************************** */
 /* FILTERED ACTION DATA - TYPES  ---> XXX DEPRECEATED OLD ANIM SYSTEM CODE! */
diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c
index 287a6f214c..22aa92e6d7 100644
--- a/source/blender/editors/gpencil/gpencil_interpolate.c
+++ b/source/blender/editors/gpencil/gpencil_interpolate.c
@@ -1023,4 +1023,123 @@ void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot)
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
+/* ******************** Remove Breakdowns ************************ */
+
+/* Same as gpencil_interpolate_poll(), 
+ * except we ALSO need to have an active frame that is a breakdown
+ */
+static int gpencil_interpolate_reverse_poll(bContext *C)
+{
+	bGPdata *gpd = CTX_data_gpencil_data(C);
+	bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+	
+	/* only 3D view */
+	if (CTX_wm_area(C)->spacetype != SPACE_VIEW3D) {
+		return 0;
+	}
+	
+	/* need data to interpolate */
+	if (ELEM(NULL, gpd, gpl)) {
+		return 0;
+	}
+	
+	/* need to be on a breakdown frame */
+	if ((gpl->actframe == NULL) || (gpl->actframe->key_type != BEZT_KEYTYPE_BREAKDOWN)) {
+		CTX_wm_operator_poll_msg_set(C, "Expected current frame to be a breakdown");
+		return 0;
+	}
+	
+	return 1;
+}
+
+static int gpencil_interpolate_reverse_exec(bContext *C, wmOperator *op)
+{
+	/* Go through each layer, deleting the breakdowns around the current frame,
+	 * but only if there is a keyframe nearby to stop at
+	 */
+	CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+	{
+		bGPDframe *start_key = NULL;
+		bGPDframe *end_key = NULL;
+		bGPDframe *gpf, *gpfn;
+		
+		/* Only continue if we're currently on a breakdown keyframe */
+		if ((gpl->actframe == NULL) || (gpl->actframe->key_type != BEZT_KEYTYPE_BREAKDOWN))
+			continue;
+		
+		/* Search left for "start_key" (i.e. the first breakdown to remove) */
+		gpf = gpl->actframe;
+		while (gpf) {
+			if (gpf->key_type == BEZT_KEYTYPE_BREAKDOWN) {
+				/* A breakdown... keep going left */
+				start_key = gpf;
+				gpf = gpf->prev;
+			}
+			else {
+				/* Not a breakdown (may be a key, or an extreme, or something else that wasn't generated)... stop */
+				break;
+			}
+		}
+		
+		/* Search right for "end_key" (i.e. the last breakdown to remove) */
+		gpf = gpl->actframe;
+		while (gpf) {
+			if (gpf->key_type == BEZT_KEYTYPE_BREAKDOWN) {
+				/* A breakdown... keep going right */
+				end_key = gpf;
+				gpf = gpf->next;
+			}
+			else {
+				/* Not a breakdown... stop */
+				break;
+			}
+		}
+		
+		/* Did we find anything? */
+		/* NOTE: We should only proceed if there's something before/after these extents...
+		 * Otherwise, there's just an extent of breakdowns with no keys to interpolate between
+		 */
+		if ((start_key && end_key) && 
+		    ELEM(NULL, start_key->prev, end_key->next) == false)
+		{
+			/* Set actframe to the key before start_key, since the keys have been removed now */
+			gpl->actframe = start_key->prev;
+			
+			/* Free each frame we're removing (except the last one) */
+			for (gpf = start_key; gpf && gpf != end_key; gpf = gpfn) {
+				gpfn = gpf->next;
+				
+				/* free strokes and their associated memory */
+				BKE_gpencil_free_strokes(gpf);
+				BLI_freelinkN(&gpl->frames, gpf);
+			}
+			
+			/* Now free the last one... */
+			BKE_gpencil_free_strokes(end_key);
+			BLI_freelinkN(&gpl->frames, end_key);
+		}
+	}
+	CTX_DATA_END;
+	
+	/* notifiers */
+	WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+	
+	return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_interpolate_reverse(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Remove Breakdowns";
+	ot->idname = "GPENCIL_OT_interpolate_reverse";
+	ot->description = "Remove breakdown frames generated by interpolating between two Grease Pencil frames";
+	
+	/* callbacks */
+	ot->exec = gpencil_interpolate_reverse_exec;
+	ot->poll = gpencil_interpolate_reverse_poll;
+	
+	/* flags */
+	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
 /* *************************************************************** */
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 057d53ea45..82bbc476c2 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -443,6 +443,7 @@ void ED_operatortypes_gpencil(void)
 	/* Interpolation */
 	WM_operatortype_append(GPENCIL_OT_interpolate);
 	WM_operatortype_append(GPENCIL_OT_interpolate_sequence);
+	WM_operatortype_append(GPENCIL_OT_interpolate_reverse);
 }
 
 void ED_operatormacros_gpencil(void)




More information about the Bf-blender-cvs mailing list