Anim: Add operator to select keyframes by type

This adds an operator to the Dope Sheet that selects
all keyframes of a given type.

Idea based on the workflow by Wayne Dixon
Based on a discussion from an Animation & Rigging module meeting [1]

[1] https://devtalk.blender.org/t/2026-03-05-animation-rigging-module-meeting/44533#p-161088-patches-review-decision-time-7

Pull Request: https://projects.blender.org/blender/blender/pulls/157629
This commit is contained in:
Christoph Lendenfeld 2026-04-21 11:12:13 +02:00 • committed by Christoph Lendenfeld
parent baf05a1f16
commit 1447bfd22b
4 changed files with 74 additions and 0 deletions

View file

@ -552,6 +552,7 @@ class DOPESHEET_MT_select(Menu):
layout.separator()
layout.operator("action.select_linked")
layout.operator_menu_enum("action.select_by_type", "type")
layout.separator()
layout.operator("action.select_column", text="Columns on Selected Keys").mode = 'KEYS'

View file

@ -63,6 +63,7 @@ void ACTION_OT_select_more(wmOperatorType *ot);
void ACTION_OT_select_less(wmOperatorType *ot);
void ACTION_OT_select_leftright(wmOperatorType *ot);
void ACTION_OT_clickselect(wmOperatorType *ot);
void ACTION_OT_select_by_type(wmOperatorType *ot);
/* defines for left-right select tool */
enum eActKeys_LeftRightSelect_Mode {

View file

@ -38,6 +38,7 @@ void action_operatortypes()
WM_operatortype_append(ACTION_OT_select_more);
WM_operatortype_append(ACTION_OT_select_less);
WM_operatortype_append(ACTION_OT_select_leftright);
WM_operatortype_append(ACTION_OT_select_by_type);
/* editing */
WM_operatortype_append(ACTION_OT_snap);

View file

@ -25,6 +25,7 @@
#include "RNA_access.hh"
#include "RNA_define.hh"
#include "RNA_enum_types.hh"
#include "BKE_context.hh"
#include "BKE_fcurve.hh"
@ -2141,4 +2142,74 @@ void ACTION_OT_clickselect(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Select by Keyframe Type operator
* \{ */
static wmOperatorStatus select_by_type_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
if (ANIM_animdata_get_context(C, &ac) == 0) {
return OPERATOR_CANCELLED;
}
ListBaseT<bAnimListElem> anim_data = {nullptr, nullptr};
const eAnimFilter_Flags filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
ANIMFILTER_NODUPLIS | ANIMFILTER_FOREDIT |
ANIMFILTER_FCURVESONLY);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
const eBezTriple_KeyframeType key_type = eBezTriple_KeyframeType(RNA_enum_get(op->ptr, "type"));
const bool extend = RNA_boolean_get(op->ptr, "extend");
for (bAnimListElem &elem : anim_data) {
FCurve *fcurve = static_cast<FCurve *>(elem.data);
if (!fcurve->bezt) {
continue;
}
for (int i = 0; i < fcurve->totvert; i++) {
BezTriple &key = fcurve->bezt[i];
if (BEZKEYTYPE(&key) == key_type) {
BEZT_SEL_ALL(&key);
}
else if (!extend) {
BEZT_DESEL_ALL(&key);
}
}
}
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, nullptr);
ANIM_animdata_freelist(&anim_data);
return OPERATOR_FINISHED;
}
void ACTION_OT_select_by_type(wmOperatorType *ot)
{
ot->name = "Select by Type";
ot->idname = "ACTION_OT_select_by_type";
ot->description = "Select all keyframes of the given type";
ot->exec = select_by_type_exec;
ot->poll = ED_operator_action_active;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
PropertyRNA *prop = RNA_def_boolean(ot->srna,
"extend",
true,
"Extend Selection",
"Keeps the current selection and adds the given type to it. "
"If disabled, only keys of the type will be selected");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
RNA_def_enum(ot->srna,
"type",
rna_enum_beztriple_keyframe_type_items,
0,
"Type",
"The type of keyframe to select");
}
/** \} */
} // namespace blender