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)
This commit is contained in:
Joshua Leung
2017-01-18 19:40:48 +13:00
parent 65ec429d11
commit 8d4b31ce03
4 changed files with 126 additions and 1 deletions

View File

@@ -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")

View File

@@ -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! */

View File

@@ -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;
}
/* *************************************************************** */

View File

@@ -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)