Fix: Grease Pencil: Missing operator to delete breakdown keyframes

Operation to delete keys generated from interpolate sequence.

Resolves #134081

Pull Request: https://projects.blender.org/blender/blender/pulls/134091
This commit is contained in:
Pratik Borhade
2025-02-07 13:36:38 +01:00
committed by Falk David
parent 3baac1992a
commit 2d18046bbc
2 changed files with 83 additions and 0 deletions

View File

@@ -582,6 +582,7 @@ class DOPESHEET_MT_key(Menu):
def draw(self, _context):
layout = self.layout
ob = _context.active_object
layout.menu("DOPESHEET_MT_key_transform", text="Transform")
@@ -600,6 +601,8 @@ class DOPESHEET_MT_key(Menu):
layout.operator("action.paste", text="Paste Flipped").flipped = True
layout.operator("action.duplicate_move")
layout.operator("action.delete")
if ob and ob.type == 'GREASEPENCIL':
layout.operator("grease_pencil.delete_breakdown")
layout.separator()
layout.operator_menu_enum("action.keyframe_type", "type", text="Keyframe Type")
@@ -785,6 +788,7 @@ class DOPESHEET_MT_context_menu(Menu):
if st.mode == 'GPENCIL':
layout.separator()
layout.operator("grease_pencil.delete_breakdown")
layout.operator_context = 'EXEC_REGION_WIN'
layout.operator("action.delete")

View File

@@ -906,6 +906,84 @@ static void GREASE_PENCIL_OT_active_frame_delete(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "all", false, "Delete all", "Delete active keyframes of all layers");
}
bool grease_pencil_active_breakdown_frame_poll(bContext *C)
{
if (!active_grease_pencil_poll(C)) {
return false;
}
const Object &ob = *CTX_data_active_object(C);
const Scene &scene = *CTX_data_scene(C);
/* Ensure that there is a breakdown keyframe visible at the current frame. */
const GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob.data);
if (const bke::greasepencil::Layer *active_layer = grease_pencil.get_active_layer()) {
const GreasePencilFrame *frame = active_layer->frame_at(scene.r.cfra);
if (frame && frame->type == BEZT_KEYTYPE_BREAKDOWN) {
return true;
}
}
return false;
}
static int grease_pencil_delete_breakdown_frames_exec(bContext *C, wmOperator * /*op*/)
{
const Object &ob = *CTX_data_active_object(C);
const Scene &scene = *CTX_data_scene(C);
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob.data);
bke::greasepencil::Layer *active_layer = grease_pencil.get_active_layer();
const int current_frame = active_layer->start_frame_at(scene.r.cfra).value();
const Span<int> sorted_keys = active_layer->sorted_keys();
const int curr_frame_index = sorted_keys.first_index(current_frame);
Vector<int> frame_numbers_to_remove;
for (int i = curr_frame_index; i <= sorted_keys.size(); i++) {
int frame_number = sorted_keys[i];
GreasePencilFrame *frame = active_layer->frame_at(frame_number);
if (frame && frame->type == BEZT_KEYTYPE_BREAKDOWN) {
frame_numbers_to_remove.append(frame_number);
continue;
}
break;
}
for (int i = curr_frame_index - 1; i >= 0; i--) {
int frame_number = sorted_keys[i];
GreasePencilFrame *frame = active_layer->frame_at(frame_number);
if (frame && frame->type == BEZT_KEYTYPE_BREAKDOWN) {
frame_numbers_to_remove.append(frame_number);
continue;
}
break;
}
if (frame_numbers_to_remove.is_empty()) {
return OPERATOR_CANCELLED;
}
grease_pencil.remove_frames(*active_layer, frame_numbers_to_remove);
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, nullptr);
return OPERATOR_FINISHED;
}
static void GREASE_PENCIL_OT_delete_breakdown(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Delete Breakdown Frames";
ot->idname = "GREASE_PENCIL_OT_delete_breakdown";
ot->description =
"Remove breakdown frames generated by interpolating between two Grease Pencil frames";
/* callback */
ot->exec = grease_pencil_delete_breakdown_frames_exec;
ot->poll = grease_pencil_active_breakdown_frame_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
} // namespace blender::ed::greasepencil
void ED_operatortypes_grease_pencil_frames()
@@ -915,4 +993,5 @@ void ED_operatortypes_grease_pencil_frames()
WM_operatortype_append(GREASE_PENCIL_OT_frame_clean_duplicate);
WM_operatortype_append(GREASE_PENCIL_OT_frame_duplicate);
WM_operatortype_append(GREASE_PENCIL_OT_active_frame_delete);
WM_operatortype_append(GREASE_PENCIL_OT_delete_breakdown);
}