Context: add accessors returning selected actions for animation editors.

Add a new 'selected_visible_actions' property to allow querying
actions that are selected in animation related editors for use in
UI and operators. The 'selected_editable_actions' variant excludes
linked actions (the only reason an action can be read-only).

In the Action and Shape Key editors there is only one action
that is specified by the field at the top of the editor.

In Dope Sheet it scans the channel rows and returns all actions
related to the selected items. This includes summary items for
actions and groups.

In Graph Editor, it lists actions associated with selected curves.

The new property is also used for Copy To Selected and Alt-Click.

Ref D11803
This commit is contained in:
Alexander Gavrilov 2021-07-16 12:36:57 +03:00
parent 65f547c3fc
commit 057cb7e5e7
5 changed files with 114 additions and 0 deletions

View File

@ -1103,6 +1103,7 @@ context_type_map = {
"selectable_objects": ("Object", True),
"selected_asset_files": ("FileSelectEntry", True),
"selected_bones": ("EditBone", True),
"selected_editable_actions": ("Action", True),
"selected_editable_bones": ("EditBone", True),
"selected_editable_fcurves": ("FCurve", True),
"selected_editable_keyframes": ("Keyframe", True),
@ -1118,6 +1119,7 @@ context_type_map = {
"selected_pose_bones": ("PoseBone", True),
"selected_pose_bones_from_active_object": ("PoseBone", True),
"selected_sequences": ("Sequence", True),
"selected_visible_actions": ("Action", True),
"selected_visible_fcurves": ("FCurve", True),
"sequences": ("Sequence", True),
"soft_body": ("SoftBodyModifier", False),

View File

@ -4212,6 +4212,24 @@ void ANIM_channel_debug_print_info(bAnimListElem *ale, short indent_level)
}
}
/* Retrieves the Action associated with this animation channel. */
bAction *ANIM_channel_action_get(const bAnimListElem *ale)
{
if (ale->datatype == ALE_ACT) {
return (bAction *)ale->key_data;
}
if (ELEM(ale->type, ANIMTYPE_GROUP, ANIMTYPE_FCURVE)) {
ID *owner = ale->fcurve_owner_id;
if (owner && GS(owner->name) == ID_AC) {
return (bAction *)owner;
}
}
return NULL;
}
/* --------------------------- */
/* Check if some setting for a channel is enabled

View File

@ -577,6 +577,9 @@ const bAnimChannelType *ANIM_channel_get_typeinfo(bAnimListElem *ale);
/* Print debugging info about a given channel */
void ANIM_channel_debug_print_info(bAnimListElem *ale, short indent_level);
/* Retrieves the Action associated with this animation channel. */
bAction *ANIM_channel_action_get(const bAnimListElem *ale);
/* Draw the given channel */
void ANIM_channel_draw(
bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc, size_t channel_index);

View File

@ -846,6 +846,9 @@ bool UI_context_copy_to_selected_list(bContext *C,
else if (RNA_struct_is_a(ptr->type, &RNA_Keyframe)) {
*r_lb = CTX_data_collection_get(C, "selected_editable_keyframes");
}
else if (RNA_struct_is_a(ptr->type, &RNA_Action)) {
*r_lb = CTX_data_collection_get(C, "selected_editable_actions");
}
else if (RNA_struct_is_a(ptr->type, &RNA_NlaStrip)) {
*r_lb = CTX_data_collection_get(C, "selected_nla_strips");
}

View File

@ -113,6 +113,8 @@ const char *screen_context_dir[] = {
"active_gpencil_frame",
"active_annotation_layer",
"active_operator",
"selected_visible_actions",
"selected_editable_actions",
"visible_fcurves",
"editable_fcurves",
"selected_visible_fcurves",
@ -975,6 +977,90 @@ static eContextResult screen_ctx_active_operator(const bContext *C, bContextData
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_sel_actions_impl(const bContext *C,
bContextDataResult *result,
bool editable)
{
bAnimContext ac;
if (ANIM_animdata_get_context(C, &ac) && ELEM(ac.spacetype, SPACE_ACTION, SPACE_GRAPH)) {
/* In the Action and Shape Key editor always use the action field at the top. */
if (ac.spacetype == SPACE_ACTION) {
SpaceAction *saction = (SpaceAction *)ac.sl;
if (ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY)) {
if (saction->action && !(editable && ID_IS_LINKED(saction->action))) {
CTX_data_id_list_add(result, &saction->action->id);
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
}
/* Search for selected animation data items. */
ListBase anim_data = {NULL, NULL};
int filter = ANIMFILTER_DATA_VISIBLE;
bool check_selected = false;
switch (ac.spacetype) {
case SPACE_GRAPH:
filter |= ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL;
break;
case SPACE_ACTION:
filter |= ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS;
check_selected = true;
break;
}
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
GSet *seen_set = BLI_gset_ptr_new("seen actions");
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
/* In dopesheet check selection status of individual items, skipping
* if not selected or has no selection flag. This is needed so that
* selecting action or group rows without any channels works. */
if (check_selected && ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_SELECT) <= 0) {
continue;
}
bAction *action = ANIM_channel_action_get(ale);
if (action) {
if (editable && ID_IS_LINKED(action)) {
continue;
}
/* Add the action to the output list if not already added. */
if (!BLI_gset_haskey(seen_set, action)) {
CTX_data_id_list_add(result, &action->id);
BLI_gset_add(seen_set, action);
}
}
}
BLI_gset_free(seen_set, NULL);
ANIM_animdata_freelist(&anim_data);
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_selected_visible_actions(const bContext *C,
bContextDataResult *result)
{
return screen_ctx_sel_actions_impl(C, result, false);
}
static eContextResult screen_ctx_selected_editable_actions(const bContext *C,
bContextDataResult *result)
{
return screen_ctx_sel_actions_impl(C, result, true);
}
static eContextResult screen_ctx_sel_edit_fcurves_(const bContext *C,
bContextDataResult *result,
const int extra_filter)
@ -1185,6 +1271,8 @@ static void ensure_ed_screen_context_functions(void)
register_context_function("editable_gpencil_layers", screen_ctx_editable_gpencil_layers);
register_context_function("editable_gpencil_strokes", screen_ctx_editable_gpencil_strokes);
register_context_function("active_operator", screen_ctx_active_operator);
register_context_function("selected_visible_actions", screen_ctx_selected_visible_actions);
register_context_function("selected_editable_actions", screen_ctx_selected_editable_actions);
register_context_function("editable_fcurves", screen_ctx_editable_fcurves);
register_context_function("visible_fcurves", screen_ctx_visible_fcurves);
register_context_function("selected_editable_fcurves", screen_ctx_selected_editable_fcurves);