Drivers: fix Variable Copy & Paste in the edit popover.

Without these buttons the functionality of the popover is
incomplete compared to the Graph Editor panel. To support
this the operators have to read the active F-Curve from
the context, instead of directly scanning animation data.

Expanding the context would also help Python operators.
This commit is contained in:
Alexander Gavrilov 2019-06-16 13:32:50 +03:00
parent 985f33719c
commit 3e086af79c
Notes: blender-bot 2023-02-14 05:51:17 +01:00
Referenced by issue #55145, Implement Driver Workflow Changes
5 changed files with 98 additions and 99 deletions

View File

@ -104,7 +104,11 @@ const char *screen_context_dir[] = {
"active_gpencil_layer",
"active_gpencil_frame",
"active_operator",
"visible_fcurves",
"editable_fcurves",
"selected_visible_fcurves",
"selected_editable_fcurves",
"active_editable_fcurve",
NULL,
};
@ -654,23 +658,31 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
}
else if (CTX_data_equals(member, "selected_editable_fcurves")) {
else if (CTX_data_equals(member, "editable_fcurves") ||
CTX_data_equals(member, "visible_fcurves") ||
CTX_data_equals(member, "selected_editable_fcurves") ||
CTX_data_equals(member, "selected_visible_fcurves")) {
bAnimContext ac;
if (ANIM_animdata_get_context(C, &ac) && ELEM(ac.spacetype, SPACE_ACTION, SPACE_GRAPH)) {
bAnimListElem *ale;
ListBase anim_data = {NULL, NULL};
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS |
ANIMFILTER_SEL) |
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS) |
(ac.spacetype == SPACE_GRAPH ? ANIMFILTER_CURVE_VISIBLE :
ANIMFILTER_LIST_VISIBLE);
if (strstr(member, "editable_")) {
filter |= ANIMFILTER_FOREDIT;
}
if (STRPREFIX(member, "selected_")) {
filter |= ANIMFILTER_SEL;
}
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
for (ale = anim_data.first; ale; ale = ale->next) {
if (ale->type == ANIMTYPE_FCURVE) {
CTX_data_list_add(result, ale->id, &RNA_FCurve, ale->data);
for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next) {
if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
CTX_data_list_add(result, ale->fcurve_owner_id, &RNA_FCurve, ale->data);
}
}
@ -680,6 +692,28 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
}
else if (CTX_data_equals(member, "active_editable_fcurve")) {
bAnimContext ac;
if (ANIM_animdata_get_context(C, &ac) && ELEM(ac.spacetype, SPACE_GRAPH)) {
ListBase anim_data = {NULL, NULL};
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_FOREDIT |
ANIMFILTER_CURVE_VISIBLE);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next) {
if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
CTX_data_pointer_set(result, ale->fcurve_owner_id, &RNA_FCurve, ale->data);
break;
}
}
ANIM_animdata_freelist(&anim_data);
return 1;
}
}
else {
return 0; /* not found */
}

View File

@ -904,7 +904,7 @@ static void graph_draw_driver_settings_panel(uiLayout *layout,
DriverVar *dvar;
PointerRNA driver_ptr;
uiLayout *col, *row;
uiLayout *col, *row, *row_outer;
uiBlock *block;
uiBut *but;
@ -1005,61 +1005,41 @@ static void graph_draw_driver_settings_panel(uiLayout *layout,
uiItemS(layout);
/* add/copy/paste driver variables */
if (is_popover) {
/* add driver variable - add blank */
row = uiLayoutRow(layout, true);
block = uiLayoutGetBlock(row);
but = uiDefIconTextBut(
block,
UI_BTYPE_BUT,
B_IPO_DEPCHANGE,
ICON_ADD,
IFACE_("Add Input Variable"),
0,
0,
10 * UI_UNIT_X,
UI_UNIT_Y,
NULL,
0.0,
0.0,
0,
0,
TIP_("Add a Driver Variable to keep track an input used by the driver"));
UI_but_func_set(but, driver_add_var_cb, driver, NULL);
row_outer = uiLayoutRow(layout, false);
/* add driver variable - add blank */
row = uiLayoutRow(row_outer, true);
block = uiLayoutGetBlock(row);
but = uiDefIconTextBut(
block,
UI_BTYPE_BUT,
B_IPO_DEPCHANGE,
ICON_ADD,
IFACE_("Add Input Variable"),
0,
0,
10 * UI_UNIT_X,
UI_UNIT_Y,
NULL,
0.0,
0.0,
0,
0,
TIP_("Add a Driver Variable to keep track of an input used by the driver"));
UI_but_func_set(but, driver_add_var_cb, driver, NULL);
if (is_popover) {
/* add driver variable - add using eyedropper */
/* XXX: will this operator work like this? */
uiItemO(row, "", ICON_EYEDROPPER, "UI_OT_eyedropper_driver");
}
else {
/* add driver variable */
row = uiLayoutRow(layout, false);
block = uiLayoutGetBlock(row);
but = uiDefIconTextBut(block,
UI_BTYPE_BUT,
B_IPO_DEPCHANGE,
ICON_ADD,
IFACE_("Add Input Variable"),
0,
0,
10 * UI_UNIT_X,
UI_UNIT_Y,
NULL,
0.0,
0.0,
0,
0,
TIP_("Driver variables ensure that all dependencies will be accounted "
"for, ensuring that drivers will update correctly"));
UI_but_func_set(but, driver_add_var_cb, driver, NULL);
/* copy/paste (as sub-row) */
row = uiLayoutRow(row, true);
block = uiLayoutGetBlock(row);
/* copy/paste (as sub-row) */
row = uiLayoutRow(row_outer, true);
block = uiLayoutGetBlock(row);
uiItemO(row, "", ICON_COPYDOWN, "GRAPH_OT_driver_variables_copy");
uiItemO(row, "", ICON_PASTEDOWN, "GRAPH_OT_driver_variables_paste");
}
uiItemO(row, "", ICON_COPYDOWN, "GRAPH_OT_driver_variables_copy");
uiItemO(row, "", ICON_PASTEDOWN, "GRAPH_OT_driver_variables_paste");
/* loop over targets, drawing them */
for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
@ -1280,6 +1260,10 @@ static void graph_panel_drivers_popover(const bContext *C, Panel *pa)
if (fcu && fcu->driver) {
ID *id = ptr.id.data;
PointerRNA ptr_fcurve;
RNA_pointer_create(id, &RNA_FCurve, fcu, &ptr_fcurve);
uiLayoutSetContextPointer(layout, "active_editable_fcurve", &ptr_fcurve);
/* Driven Property Settings */
uiItemL(layout, IFACE_("Driven Property:"), ICON_NONE);
graph_draw_driven_property_panel(pa->layout, id, fcu);

View File

@ -2995,29 +2995,15 @@ void GRAPH_OT_fmodifier_paste(wmOperatorType *ot)
static int graph_driver_vars_copy_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
bAnimListElem *ale;
bool ok = false;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0) {
return OPERATOR_CANCELLED;
}
/* clear buffer first */
ANIM_driver_vars_copybuf_free();
/* get the active F-Curve */
ale = get_active_fcurve_channel(&ac);
PointerRNA ptr = CTX_data_pointer_get_type(C, "active_editable_fcurve", &RNA_FCurve);
/* if this exists, call the copy driver vars API function */
if (ale && ale->data) {
FCurve *fcu = (FCurve *)ale->data;
FCurve *fcu = (FCurve *)ptr.data;
if (fcu) {
ok = ANIM_driver_vars_copy(op->reports, fcu);
/* free temp data now */
MEM_freeN(ale);
}
/* successful or not? */
@ -3034,11 +3020,11 @@ void GRAPH_OT_driver_variables_copy(wmOperatorType *ot)
/* identifiers */
ot->name = "Copy Driver Variables";
ot->idname = "GRAPH_OT_driver_variables_copy";
ot->description = "Copy the driver variables of the active F-Curve";
ot->description = "Copy the driver variables of the active driver";
/* api callbacks */
ot->exec = graph_driver_vars_copy_exec;
ot->poll = graphop_active_fcurve_poll;
ot->poll = graphop_active_editable_fcurve_ctx_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@ -3048,34 +3034,18 @@ void GRAPH_OT_driver_variables_copy(wmOperatorType *ot)
static int graph_driver_vars_paste_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
const bool replace = RNA_boolean_get(op->ptr, "replace");
bool ok = false;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0) {
return OPERATOR_CANCELLED;
PointerRNA ptr = CTX_data_pointer_get_type(C, "active_editable_fcurve", &RNA_FCurve);
/* if this exists, call the paste driver vars API function */
FCurve *fcu = (FCurve *)ptr.data;
if (fcu) {
ok = ANIM_driver_vars_paste(op->reports, fcu, replace);
}
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* paste variables */
for (ale = anim_data.first; ale; ale = ale->next) {
FCurve *fcu = (FCurve *)ale->data;
ok |= ANIM_driver_vars_paste(op->reports, fcu, replace);
}
/* cleanup */
ANIM_animdata_freelist(&anim_data);
/* successful or not? */
if (ok) {
/* rebuild depsgraph, now that there are extra deps here */
@ -3100,7 +3070,7 @@ void GRAPH_OT_driver_variables_paste(wmOperatorType *ot)
/* api callbacks */
ot->exec = graph_driver_vars_paste_exec;
ot->poll = graphop_active_fcurve_poll;
ot->poll = graphop_active_editable_fcurve_ctx_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;

View File

@ -168,6 +168,7 @@ struct bAnimListElem *get_active_fcurve_channel(struct bAnimContext *ac);
bool graphop_visible_keyframes_poll(struct bContext *C);
bool graphop_editable_keyframes_poll(struct bContext *C);
bool graphop_active_fcurve_poll(struct bContext *C);
bool graphop_active_editable_fcurve_ctx_poll(struct bContext *C);
bool graphop_selected_fcurve_poll(struct bContext *C);
/* ***************************************** */

View File

@ -44,6 +44,8 @@
#include "ED_screen.h"
#include "UI_interface.h"
#include "RNA_access.h"
#include "graph_intern.h" // own include
/* ************************************************************** */
@ -278,6 +280,14 @@ bool graphop_active_fcurve_poll(bContext *C)
return has_fcurve;
}
/* has active F-Curve in the context that's editable */
bool graphop_active_editable_fcurve_ctx_poll(bContext *C)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "active_editable_fcurve", &RNA_FCurve);
return ptr.data != NULL;
}
/* has selected F-Curve that's editable */
bool graphop_selected_fcurve_poll(bContext *C)
{