Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / space_graph / graph_buttons.c
index d5586a5..706beb9 100644 (file)
 
 #include "BKE_context.h"
 #include "BKE_curve.h"
-#include "BKE_depsgraph.h"
 #include "BKE_fcurve.h"
 #include "BKE_main.h"
 #include "BKE_global.h"
 #include "BKE_screen.h"
 #include "BKE_unit.h"
 
+#include "DEG_depsgraph_build.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
@@ -154,17 +154,12 @@ static void graph_panel_properties(const bContext *C, Panel *pa)
        PointerRNA fcu_ptr;
        uiLayout *layout = pa->layout;
        uiLayout *col, *row, *sub;
-       // uiBlock *block;  // UNUSED
        char name[256];
        int icon = 0;
 
        if (!graph_panel_context(C, &ale, &fcu))
                return;
 
-       // UNUSED
-       // block = uiLayoutGetBlock(layout);
-       // UI_block_func_handle_set(block, do_graph_region_buttons, NULL);
-
        /* F-Curve pointer */
        RNA_pointer_create(ale->id, &RNA_FCurve, fcu, &fcu_ptr);
 
@@ -472,7 +467,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *pa)
 
 #define B_IPO_DEPCHANGE     10
 
-static void do_graph_region_driver_buttons(bContext *C, void *UNUSED(arg), int event)
+static void do_graph_region_driver_buttons(bContext *C, void *fcu_v, int event)
 {
        Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
@@ -480,8 +475,18 @@ static void do_graph_region_driver_buttons(bContext *C, void *UNUSED(arg), int e
        switch (event) {
                case B_IPO_DEPCHANGE:
                {
+                       /* force F-Curve & Driver to get re-evaluated (same as the old Update Dependencies) */
+                       FCurve *fcu = (FCurve *)fcu_v;
+                       ChannelDriver *driver = (fcu) ? fcu->driver : NULL;
+
+                       /* clear invalid flags */
+                       if (fcu) {
+                               fcu->flag &= ~FCURVE_DISABLED;
+                               driver->flag &= ~DRIVER_FLAG_INVALID;
+                       }
+
                        /* rebuild depsgraph for the new deps */
-                       DAG_relations_tag_update(bmain);
+                       DEG_relations_tag_update(bmain);
                        break;
                }
        }
@@ -490,23 +495,6 @@ static void do_graph_region_driver_buttons(bContext *C, void *UNUSED(arg), int e
        WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); // XXX could use better notifier
 }
 
-/* callback to remove the active driver */
-static void driver_remove_cb(bContext *C, void *ale_v, void *UNUSED(arg))
-{
-       bAnimListElem *ale = (bAnimListElem *)ale_v;
-       ID *id = ale->id;
-       FCurve *fcu = ale->data;
-       ReportList *reports = CTX_wm_reports(C);
-
-       /* try to get F-Curve that driver lives on, and ID block which has this AnimData */
-       if (ELEM(NULL, id, fcu))
-               return;
-
-       /* call API method to remove this driver  */
-       ANIM_remove_driver(reports, id, fcu->rna_path, fcu->array_index, 0);
-       ED_undo_push(C, "Remove Driver");
-}
-
 /* callback to add a target variable to the active driver */
 static void driver_add_var_cb(bContext *C, void *driver_v, void *UNUSED(arg))
 {
@@ -728,60 +716,88 @@ static void graph_panel_driverVar__transChan(uiLayout *layout, ID *id, DriverVar
        uiItemR(sub, &dtar_ptr, "transform_space", 0, IFACE_("Space"), ICON_NONE);
 }
 
-/* driver settings for active F-Curve (only for 'Drivers' mode) */
-static void graph_panel_drivers(const bContext *C, Panel *pa)
+/* ----------------------------------------------------------------- */
+
+
+/* property driven by the driver - duplicates Active FCurve, but useful for clarity */
+static void graph_draw_driven_property_panel(uiLayout *layout, ID *id, FCurve *fcu)
 {
-       bAnimListElem *ale;
-       FCurve *fcu;
-       ChannelDriver *driver;
+       PointerRNA fcu_ptr;
+       uiLayout *row;
+       char name[256];
+       int icon = 0;
+
+       /* F-Curve pointer */
+       RNA_pointer_create(id, &RNA_FCurve, fcu, &fcu_ptr);
+
+       /* get user-friendly 'name' for F-Curve */
+       icon = getname_anim_fcurve(name, id, fcu);
+
+       /* panel layout... */
+       row = uiLayoutRow(layout, true);
+       uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
+
+       /* -> user friendly 'name' for datablock that owns F-Curve */
+       /* XXX: Actually, we may need the datablock icons only... (e.g. right now will show bone for bone props) */
+       uiItemL(row, id->name + 2, icon);
+
+       /* -> user friendly 'name' for F-Curve/driver target */
+       uiItemL(row, "", VICO_SMALL_TRI_RIGHT_VEC);
+       uiItemL(row, name, ICON_RNA);
+}
+
+/* UI properties panel layout for driver settings - shared for Drivers Editor and for */
+static void graph_draw_driver_settings_panel(uiLayout *layout, ID *id, FCurve *fcu)
+{
+       ChannelDriver *driver = fcu->driver;
        DriverVar *dvar;
 
        PointerRNA driver_ptr;
-       uiLayout *col;
+       uiLayout *col, *row;
        uiBlock *block;
        uiBut *but;
 
-       /* Get settings from context */
-       if (!graph_panel_context(C, &ale, &fcu))
-               return;
-       driver = fcu->driver;
-
        /* set event handler for panel */
-       block = uiLayoutGetBlock(pa->layout); // xxx?
+       block = uiLayoutGetBlock(layout);
        UI_block_func_handle_set(block, do_graph_region_driver_buttons, NULL);
 
-       /* general actions - management */
-       col = uiLayoutColumn(pa->layout, false);
-       block = uiLayoutGetBlock(col);
-       but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_FILE_REFRESH, IFACE_("Update Dependencies"),
-                      0, 0, 10 * UI_UNIT_X, UI_UNIT_Y,
-                      NULL, 0.0, 0.0, 0, 0,
-                      TIP_("Force updates of dependencies"));
-       UI_but_func_set(but, driver_update_flags_cb, fcu, NULL);
-
-       but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ZOOMOUT, IFACE_("Remove Driver"),
-                      0, 0, 10 * UI_UNIT_X, UI_UNIT_Y,
-                      NULL, 0.0, 0.0, 0, 0,
-                      TIP_("Remove this driver"));
-       UI_but_funcN_set(but, driver_remove_cb, MEM_dupallocN(ale), NULL);
-
        /* driver-level settings - type, expressions, and errors */
-       RNA_pointer_create(ale->id, &RNA_Driver, driver, &driver_ptr);
+       RNA_pointer_create(id, &RNA_Driver, driver, &driver_ptr);
 
-       col = uiLayoutColumn(pa->layout, true);
+       col = uiLayoutColumn(layout, true);
        block = uiLayoutGetBlock(col);
        uiItemR(col, &driver_ptr, "type", 0, NULL, ICON_NONE);
 
+       {
+               char valBuf[32];
+
+               /* value of driver */
+               row = uiLayoutRow(col, true);
+               uiItemL(row, IFACE_("Driver Value:"), ICON_NONE);
+               BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", driver->curval);
+               uiItemL(row, valBuf, ICON_NONE);
+       }
+
        /* show expression box if doing scripted drivers, and/or error messages when invalid drivers exist */
        if (driver->type == DRIVER_TYPE_PYTHON) {
                bool bpy_data_expr_error = (strstr(driver->expression, "bpy.data.") != NULL);
                bool bpy_ctx_expr_error  = (strstr(driver->expression, "bpy.context.") != NULL);
 
                /* expression */
-               uiItemR(col, &driver_ptr, "expression", 0, IFACE_("Expr"), ICON_NONE);
+               /* TODO: "Show syntax hints" button */
+               col = uiLayoutColumn(layout, true);
+               block = uiLayoutGetBlock(col);
+
+               uiItemL(col, IFACE_("Expression:"), ICON_NONE);
+               uiItemR(col, &driver_ptr, "expression", 0, "", ICON_NONE);
+               uiItemR(col, &driver_ptr, "use_self", 0, NULL, ICON_NONE);
 
                /* errors? */
+               col = uiLayoutColumn(layout, true);
+               block = uiLayoutGetBlock(col);
+
                if ((G.f & G_SCRIPT_AUTOEXEC) == 0) {
+                       /* TODO: Add button to enable? */
                        uiItemL(col, IFACE_("ERROR: Python auto-execution disabled"), ICON_CANCEL);
                }
                else if (driver->flag & DRIVER_FLAG_INVALID) {
@@ -803,6 +819,9 @@ static void graph_panel_drivers(const bContext *C, Panel *pa)
        }
        else {
                /* errors? */
+               col = uiLayoutColumn(layout, true);
+               block = uiLayoutGetBlock(col);
+
                if (driver->flag & DRIVER_FLAG_INVALID)
                        uiItemL(col, IFACE_("ERROR: Invalid target channel(s)"), ICON_ERROR);
 
@@ -822,37 +841,15 @@ static void graph_panel_drivers(const bContext *C, Panel *pa)
                }
        }
 
-       col = uiLayoutColumn(pa->layout, true);
-
-       if (driver->type == DRIVER_TYPE_PYTHON) {
-               uiItemR(col, &driver_ptr, "use_self", 0, NULL, ICON_NONE);
-       }
-
-       /* debug setting */
-       uiItemR(col, &driver_ptr, "show_debug_info", 0, NULL, ICON_NONE);
-
-       /* value of driver */
-       if (driver->flag & DRIVER_FLAG_SHOWDEBUG) {
-               uiLayout *row = uiLayoutRow(col, true);
-               char valBuf[32];
-
-               uiItemL(row, IFACE_("Driver Value:"), ICON_NONE);
-
-               BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", driver->curval);
-               uiItemL(row, valBuf, ICON_NONE);
-       }
-
        /* add/copy/paste driver variables */
        {
-               uiLayout *row;
-
                /* add driver variable */
-               row = uiLayoutRow(pa->layout, false);
+               row = uiLayoutRow(layout, false);
                block = uiLayoutGetBlock(row);
-               but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ZOOMIN, IFACE_("Add Variable"),
+               but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ZOOMIN, 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 and that drivers will update correctly"));
+                                  TIP_("Driver variables ensure that all dependencies will be accounted for, eusuring that drivers will update correctly"));
                UI_but_func_set(but, driver_add_var_cb, driver, NULL);
 
                /* copy/paste (as sub-row) */
@@ -866,15 +863,15 @@ static void graph_panel_drivers(const bContext *C, Panel *pa)
        /* loop over targets, drawing them */
        for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
                PointerRNA dvar_ptr;
-               uiLayout *box, *row;
+               uiLayout *box;
                uiLayout *subrow, *sub;
 
                /* sub-layout column for this variable's settings */
-               col = uiLayoutColumn(pa->layout, true);
+               col = uiLayoutColumn(layout, true);
 
                /* 1) header panel */
                box = uiLayoutBox(col);
-               RNA_pointer_create(ale->id, &RNA_DriverVariable, dvar, &dvar_ptr);
+               RNA_pointer_create(id, &RNA_DriverVariable, dvar, &dvar_ptr);
 
                row = uiLayoutRow(box, false);
                block = uiLayoutGetBlock(row);
@@ -915,21 +912,21 @@ static void graph_panel_drivers(const bContext *C, Panel *pa)
                /* controls to draw depends on the type of variable */
                switch (dvar->type) {
                        case DVAR_TYPE_SINGLE_PROP:     /* single property */
-                               graph_panel_driverVar__singleProp(box, ale->id, dvar);
+                               graph_panel_driverVar__singleProp(box, id, dvar);
                                break;
                        case DVAR_TYPE_ROT_DIFF:     /* rotational difference */
-                               graph_panel_driverVar__rotDiff(box, ale->id, dvar);
+                               graph_panel_driverVar__rotDiff(box, id, dvar);
                                break;
                        case DVAR_TYPE_LOC_DIFF:     /* location difference */
-                               graph_panel_driverVar__locDiff(box, ale->id, dvar);
+                               graph_panel_driverVar__locDiff(box, id, dvar);
                                break;
                        case DVAR_TYPE_TRANSFORM_CHAN:     /* transform channel */
-                               graph_panel_driverVar__transChan(box, ale->id, dvar);
+                               graph_panel_driverVar__transChan(box, id, dvar);
                                break;
                }
 
                /* 3) value of variable */
-               if (driver->flag & DRIVER_FLAG_SHOWDEBUG) {
+               {
                        char valBuf[32];
 
                        box = uiLayoutBox(col);
@@ -951,10 +948,99 @@ static void graph_panel_drivers(const bContext *C, Panel *pa)
                }
        }
 
+       /* XXX: This should become redundant. But sometimes the flushing fails, so keep this around for a while longer as a "last resort" */
+       row = uiLayoutRow(layout, true);
+       block = uiLayoutGetBlock(row);
+       but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_FILE_REFRESH, IFACE_("Update Dependencies"),
+                      0, 0, 10 * UI_UNIT_X, UI_UNIT_Y,
+                      NULL, 0.0, 0.0, 0, 0,
+                      TIP_("Force updates of dependencies - Only use this if drivers are not updating correctly"));
+       UI_but_func_set(but, driver_update_flags_cb, fcu, NULL);
+}
+
+/* ----------------------------------------------------------------- */
+
+
+/* panel to show property driven by the driver (in Drivers Editor) - duplicates Active FCurve, but useful for clarity */
+static void graph_panel_driven_property(const bContext *C, Panel *pa)
+{
+       bAnimListElem *ale;
+       FCurve *fcu;
+
+       if (!graph_panel_context(C, &ale, &fcu))
+               return;
+
+       graph_draw_driven_property_panel(pa->layout, ale->id, fcu);
+
+       MEM_freeN(ale);
+}
+
+/* driver settings for active F-Curve (only for 'Drivers' mode in Graph Editor, i.e. the full "Drivers Editor") */
+static void graph_panel_drivers(const bContext *C, Panel *pa)
+{
+       bAnimListElem *ale;
+       FCurve *fcu;
+
+       /* Get settings from context */
+       if (!graph_panel_context(C, &ale, &fcu))
+               return;
+
+       graph_draw_driver_settings_panel(pa->layout, ale->id, fcu);
+
        /* cleanup */
        MEM_freeN(ale);
 }
 
+/* ----------------------------------------------------------------- */
+
+/* poll to make this not show up in the graph editor, as this is only to be used as a popup elsewhere */
+static int graph_panel_drivers_popover_poll(const bContext *C, PanelType *UNUSED(pt))
+{
+       return ED_operator_graphedit_active((bContext *)C) == false;
+}
+
+/* popover panel for driver editing anywhere in ui */
+static void graph_panel_drivers_popover(const bContext *C, Panel *pa)
+{
+       uiLayout *layout = pa->layout;
+
+       PointerRNA ptr = {{NULL}};
+       PropertyRNA *prop = NULL;
+       int index = -1;
+       uiBut *but = NULL;
+
+       /* Get active property to show driver properties for */
+       but = UI_context_active_but_prop_get((bContext *)C, &ptr, &prop, &index);
+       if (but) {
+               FCurve *fcu;
+               bool driven, special;
+
+               fcu = rna_get_fcurve_context_ui((bContext *)C,
+                                               &ptr, prop, index,
+                                               NULL, NULL, &driven, &special);
+
+               /* Populate Panel - With a combination of the contents of the Driven and Driver panels */
+               if (fcu) {
+                       ID *id = ptr.id.data;
+
+                       /* Driven Property Settings */
+                       uiItemL(layout, IFACE_("Driven Property:"), ICON_NONE);
+                       graph_draw_driven_property_panel(pa->layout, id, fcu);
+                       /* TODO: All vs Single */
+
+                       uiItemS(layout);
+                       uiItemS(layout);
+
+                       /* Drivers Settings */
+                       uiItemL(layout, IFACE_("Driver Settings:"), ICON_NONE);
+                       graph_draw_driver_settings_panel(pa->layout, id, fcu);
+               }
+       }
+
+       /* Show drivers editor is always visible */
+       uiItemO(layout, IFACE_("Show in Drivers Editor"), ICON_DRIVER, "SCREEN_OT_drivers_editor_show");
+}
+
 /* ******************* F-Modifiers ******************************** */
 /* All the drawing code is in editors/animation/fmodifier_ui.c */
 
@@ -1035,16 +1121,33 @@ void graph_buttons_register(ARegionType *art)
        pt->poll = graph_panel_poll;
        BLI_addtail(&art->paneltypes, pt);
 
+       pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel drivers driven");
+       strcpy(pt->idname, "GRAPH_PT_driven_property");
+       strcpy(pt->label, N_("Driven Property"));
+       strcpy(pt->category, "Drivers");
+       strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+       pt->draw = graph_panel_driven_property;
+       pt->poll = graph_panel_drivers_poll;
+       BLI_addtail(&art->paneltypes, pt);
 
        pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel drivers");
        strcpy(pt->idname, "GRAPH_PT_drivers");
-       strcpy(pt->label, N_("Drivers"));
+       strcpy(pt->label, N_("Driver"));
        strcpy(pt->category, "Drivers");
        strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
        pt->draw = graph_panel_drivers;
        pt->poll = graph_panel_drivers_poll;
        BLI_addtail(&art->paneltypes, pt);
 
+       pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel drivers pover");
+       strcpy(pt->idname, "GRAPH_PT_drivers_popover");
+       strcpy(pt->label, N_("Add/Edit Driver"));
+       strcpy(pt->category, "Drivers");
+       strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+       pt->draw = graph_panel_drivers_popover;
+       pt->poll = graph_panel_drivers_popover_poll;
+       BLI_addtail(&art->paneltypes, pt);
+
        pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel modifiers");
        strcpy(pt->idname, "GRAPH_PT_modifiers");
        strcpy(pt->label, N_("Modifiers"));