Context: implement an active_action property that returns a single action.

Although e.g. in the dopesheet there is no specific concept of
active action, displaying panels requires singling out one action
reference. It is more efficient and clearer to implement this
natively in the context rather than using selected_visible_actions[0].

- In the Action Editor the action is taken from the header.
- In the Dope Sheet the first selected action is chosen, because
  there is no concept of an active channel or keyframe.
- In the Graph Editor the action associated with the active curve
  is used, which should also be associated with the active vertex.
  This case may be different from selected_visible_actions[0].

Differential Revision: https://developer.blender.org/D15412
This commit is contained in:
Alexander Gavrilov 2022-07-10 12:28:44 +03:00
parent 935b7a6f65
commit cd21022b78
Notes: blender-bot 2023-02-14 09:48:25 +01:00
Referenced by commit 37ad72ab23, Fix T99966: Python API docs fail to generate
2 changed files with 40 additions and 18 deletions

View File

@ -567,10 +567,10 @@ class DOPESHEET_PT_action(DopesheetActionPanelBase, Panel):
@classmethod
def poll(cls, context):
return bool(context.selected_visible_actions)
return bool(context.active_action)
def draw(self, context):
action = context.selected_visible_actions[0]
action = context.active_action
self.draw_generic_panel(context, self.layout, action)

View File

@ -100,6 +100,7 @@ const char *screen_context_dir[] = {
"active_gpencil_frame",
"active_annotation_layer",
"active_operator",
"active_action",
"selected_visible_actions",
"selected_editable_actions",
"visible_fcurves",
@ -969,6 +970,7 @@ static eContextResult screen_ctx_active_operator(const bContext *C, bContextData
}
static eContextResult screen_ctx_sel_actions_impl(const bContext *C,
bContextDataResult *result,
bool active_only,
bool editable)
{
bAnimContext ac;
@ -978,11 +980,17 @@ static eContextResult screen_ctx_sel_actions_impl(const bContext *C,
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);
if (active_only) {
CTX_data_id_pointer_set(result, (ID *)saction->action);
}
else {
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);
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return CTX_RESULT_OK;
}
}
@ -995,7 +1003,8 @@ static eContextResult screen_ctx_sel_actions_impl(const bContext *C,
switch (ac.spacetype) {
case SPACE_GRAPH:
filter |= ANIMFILTER_FCURVESONLY | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL;
filter |= ANIMFILTER_FCURVESONLY | ANIMFILTER_CURVE_VISIBLE |
(active_only ? ANIMFILTER_ACTIVE : ANIMFILTER_SEL);
break;
case SPACE_ACTION:
@ -1006,7 +1015,7 @@ static eContextResult screen_ctx_sel_actions_impl(const bContext *C,
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
GSet *seen_set = BLI_gset_ptr_new("seen actions");
GSet *seen_set = active_only ? NULL : BLI_gset_ptr_new("seen actions");
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
/* In dopesheet check selection status of individual items, skipping
@ -1019,36 +1028,48 @@ static eContextResult screen_ctx_sel_actions_impl(const bContext *C,
bAction *action = ANIM_channel_action_get(ale);
if (action) {
if (editable && ID_IS_LINKED(action)) {
continue;
if (active_only) {
CTX_data_id_pointer_set(result, (ID *)action);
break;
}
else {
if (editable && ID_IS_LINKED(action)) {
continue;
}
/* Add the action to the output list if not already added. */
if (BLI_gset_add(seen_set, action)) {
CTX_data_id_list_add(result, &action->id);
/* Add the action to the output list if not already added. */
if (BLI_gset_add(seen_set, action)) {
CTX_data_id_list_add(result, &action->id);
}
}
}
}
BLI_gset_free(seen_set, NULL);
ANIM_animdata_freelist(&anim_data);
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
if (!active_only) {
BLI_gset_free(seen_set, NULL);
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
}
return CTX_RESULT_OK;
}
return CTX_RESULT_NO_DATA;
}
static eContextResult screen_ctx_active_action(const bContext *C, bContextDataResult *result)
{
return screen_ctx_sel_actions_impl(C, result, true, false);
}
static eContextResult screen_ctx_selected_visible_actions(const bContext *C,
bContextDataResult *result)
{
return screen_ctx_sel_actions_impl(C, result, false);
return screen_ctx_sel_actions_impl(C, result, false, false);
}
static eContextResult screen_ctx_selected_editable_actions(const bContext *C,
bContextDataResult *result)
{
return screen_ctx_sel_actions_impl(C, result, true);
return screen_ctx_sel_actions_impl(C, result, false, true);
}
static eContextResult screen_ctx_sel_edit_fcurves_(const bContext *C,
bContextDataResult *result,
@ -1262,6 +1283,7 @@ 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("active_action", screen_ctx_active_action);
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);