code cleanup: move file string defines into BLI_path_utils.h, BKE_utildefines is...
[blender.git] / source / blender / editors / animation / drivers.c
index ababa25917aaa1e3c460041ccea8027c947f58c7..672e11ac61363e99c34cd893071cdf12c670eb46 100644 (file)
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  *
  * ***** END GPL LICENSE BLOCK *****
  */
+
+/** \file blender/editors/animation/drivers.c
+ *  \ingroup edanimation
+ */
+
  
 #include <stdio.h>
-#include <stddef.h>
 #include <string.h>
-#include <math.h>
-#include <float.h>
 
 #include "MEM_guardedalloc.h"
 
 #include "BLI_blenlib.h"
-#include "BLI_math.h"
-#include "BLI_dynstr.h"
+#include "BLI_utildefines.h"
 
 #include "DNA_anim_types.h"
-#include "DNA_action_types.h"
-#include "DNA_armature_types.h"
-#include "DNA_constraint_types.h"
-#include "DNA_key_types.h"
 #include "DNA_object_types.h"
 #include "DNA_material_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_userdef_types.h"
-#include "DNA_windowmanager_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
 
 #include "BKE_animsys.h"
-#include "BKE_action.h"
-#include "BKE_constraint.h"
 #include "BKE_depsgraph.h"
 #include "BKE_fcurve.h"
-#include "BKE_utildefines.h"
 #include "BKE_context.h"
 #include "BKE_report.h"
-#include "BKE_key.h"
 #include "BKE_material.h"
+#include "BKE_texture.h"
 
-#include "ED_anim_api.h"
 #include "ED_keyframing.h"
-#include "ED_keyframes_edit.h"
-#include "ED_screen.h"
-#include "ED_util.h"
 
 #include "UI_interface.h"
 
 
 #include "RNA_access.h"
 #include "RNA_define.h"
-#include "RNA_types.h"
+
+#include "anim_intern.h"
+
+/* called by WM */
+void free_anim_drivers_copybuf(void);
 
 /* ************************************************** */
 /* Animation Data Validation */
  *                     1 - add new Driver FCurve, 
  *                     -1 - add new Driver FCurve without driver stuff (for pasting)
  */
-FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_index, short add)
+FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_index, short add)
 {
        AnimData *adt;
        FCurve *fcu;
        
        /* sanity checks */
-       if ELEM(NULL, id, rna_path)
+       if (ELEM(NULL, id, rna_path))
                return NULL;
        
        /* init animdata if none available yet */
-       adt= BKE_animdata_from_id(id);
+       adt = BKE_animdata_from_id(id);
        if ((adt == NULL) && (add))
-               adt= BKE_id_add_animdata(id);
+               adt = BKE_id_add_animdata(id);
        if (adt == NULL) { 
                /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
                return NULL;
@@ -108,22 +100,22 @@ FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_ind
         *      - add if not found and allowed to add one
         *              TODO: add auto-grouping support? how this works will need to be resolved
         */
-       fcu= list_find_fcurve(&adt->drivers, rna_path, array_index);
+       fcu = list_find_fcurve(&adt->drivers, rna_path, array_index);
        
        if ((fcu == NULL) && (add)) {
                /* use default settings to make a F-Curve */
-               fcu= MEM_callocN(sizeof(FCurve), "FCurve");
+               fcu = MEM_callocN(sizeof(FCurve), "FCurve");
                
-               fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
+               fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
                
                /* store path - make copy, and store that */
-               fcu->rna_path= BLI_strdupn(rna_path, strlen(rna_path));
-               fcu->array_index= array_index;
+               fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
+               fcu->array_index = array_index;
                
                /* if add is negative, don't init this data yet, since it will be filled in by the pasted driver */
                if (add > 0) {
                        /* add some new driver data */
-                       fcu->driver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
+                       fcu->driver = MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
                        
                        /* add simple generator modifier for driver so that there is some visible representation */
                        add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR);
@@ -141,30 +133,32 @@ FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_ind
 /* Driver Management API */
 
 /* Main Driver Management API calls:
- *     Add a new driver for the specified property on the given ID block
+ *  Add a new driver for the specified property on the given ID block
  */
-short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short flag, int type)
+short ANIM_add_driver(ReportList *reports, ID *id, const char rna_path[], int array_index, short flag, int type)
 {      
        PointerRNA id_ptr, ptr;
        PropertyRNA *prop;
        FCurve *fcu;
        int array_index_max;
-       int done = 0;
+       int done = FALSE;
        
        /* validate pointer first - exit if failure */
        RNA_id_pointer_create(id, &id_ptr);
        if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) {
-               printf("Add Driver: Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path);
+               BKE_reportf(reports, RPT_ERROR, 
+                           "Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)",
+                           id->name, rna_path);
                return 0;
        }
        
        /* key entire array convenience method */
        if (array_index == -1) {
-               array_index_max= RNA_property_array_length(&ptr, prop);
-               array_index= 0;
+               array_index_max = RNA_property_array_length(&ptr, prop);
+               array_index = 0;
        }
        else
-               array_index_max= array_index;
+               array_index_max = array_index;
        
        /* maximum index should be greater than the start index */
        if (array_index == array_index_max)
@@ -173,41 +167,55 @@ short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short fla
        /* will only loop once unless the array index was -1 */
        for (; array_index < array_index_max; array_index++) {
                /* create F-Curve with Driver */
-               fcu= verify_driver_fcurve(id, rna_path, array_index, 1);
+               fcu = verify_driver_fcurve(id, rna_path, array_index, 1);
                
                if (fcu && fcu->driver) {
-                       ChannelDriver *driver= fcu->driver;
+                       ChannelDriver *driver = fcu->driver;
                        
                        /* set the type of the driver */
-                       driver->type= type;
+                       driver->type = type;
                        
-                       /* fill in current value for python */
+                       /* creating drivers for buttons will create the driver(s) with type 
+                        * "scripted expression" so that their values won't be lost immediately,
+                        * so here we copy those values over to the driver's expression
+                        */
                        if (type == DRIVER_TYPE_PYTHON) {
-                               PropertyType proptype= RNA_property_type(prop);
-                               int array= RNA_property_array_length(&ptr, prop);
-                               char *expression= driver->expression;
-                               int val, maxlen= sizeof(driver->expression);
+                               PropertyType proptype = RNA_property_type(prop);
+                               int array = RNA_property_array_length(&ptr, prop);
+                               char *expression = driver->expression;
+                               int val, maxlen = sizeof(driver->expression);
                                float fval;
                                
                                if (proptype == PROP_BOOLEAN) {
-                                       if (!array) val= RNA_property_boolean_get(&ptr, prop);
-                                       else val= RNA_property_boolean_get_index(&ptr, prop, array_index);
+                                       if (!array) val = RNA_property_boolean_get(&ptr, prop);
+                                       else val = RNA_property_boolean_get_index(&ptr, prop, array_index);
                                        
-                                       BLI_strncpy(expression, (val)? "True": "False", maxlen);
+                                       BLI_strncpy(expression, (val) ? "True" : "False", maxlen);
                                }
                                else if (proptype == PROP_INT) {
-                                       if (!array) val= RNA_property_int_get(&ptr, prop);
-                                       else val= RNA_property_int_get_index(&ptr, prop, array_index);
+                                       if (!array) val = RNA_property_int_get(&ptr, prop);
+                                       else val = RNA_property_int_get_index(&ptr, prop, array_index);
                                        
                                        BLI_snprintf(expression, maxlen, "%d", val);
                                }
                                else if (proptype == PROP_FLOAT) {
-                                       if (!array) fval= RNA_property_float_get(&ptr, prop);
-                                       else fval= RNA_property_float_get_index(&ptr, prop, array_index);
+                                       if (!array) fval = RNA_property_float_get(&ptr, prop);
+                                       else fval = RNA_property_float_get_index(&ptr, prop, array_index);
                                        
                                        BLI_snprintf(expression, maxlen, "%.3f", fval);
                                }
                        }
+                       
+                       /* for easier setup of drivers from UI, a driver variable should be 
+                        * added if flag is set (UI calls only)
+                        */
+                       if (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) {
+                               /* assume that users will mostly want this to be of type "Transform Channel" too,
+                                * since this allows the easiest setting up of common rig components
+                                */
+                               DriverVar *dvar = driver_add_new_variable(driver);
+                               driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN);
+                       }
                }
                
                /* set the done status */
@@ -219,33 +227,50 @@ short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short fla
 }
 
 /* Main Driver Management API calls:
- *     Remove the driver for the specified property on the given ID block (if available)
+ *  Remove the driver for the specified property on the given ID block (if available)
  */
-short ANIM_remove_driver (struct ID *id, const char rna_path[], int array_index, short flag)
+short ANIM_remove_driver(ReportList *UNUSED(reports), ID *id, const char rna_path[], int array_index, short UNUSED(flag))
 {
        AnimData *adt;
        FCurve *fcu;
+       int success = 0;
        
-       /* get F-Curve
-        * Note: here is one of the places where we don't want new F-Curve + Driver added!
-        *              so 'add' var must be 0
-        */
        /* we don't check the validity of the path here yet, but it should be ok... */
-       fcu= verify_driver_fcurve(id, rna_path, array_index, 0);
-       adt= BKE_animdata_from_id(id);
-       
-       /* only continue if we have an driver to remove */
-       if (adt && fcu) {
-               /* remove F-Curve from driver stack, then free it */
-               BLI_remlink(&adt->drivers, fcu);
-               free_fcurve(fcu);
-               
-               /* done successfully */
-               return 1;
-       }
+       adt = BKE_animdata_from_id(id);
        
-       /* failed */
-       return 0;
+       if (adt) {
+               if (array_index == -1) {
+                       /* step through all drivers, removing all of those with the same base path */
+                       FCurve *fcu_iter = adt->drivers.first;
+                       
+                       while ((fcu = iter_step_fcurve(fcu_iter, rna_path)) != NULL) {
+                               /* store the next fcurve for looping  */
+                               fcu_iter = fcu->next;
+                               
+                               /* remove F-Curve from driver stack, then free it */
+                               BLI_remlink(&adt->drivers, fcu);
+                               free_fcurve(fcu);
+                               
+                               /* done successfully */
+                               success |= 1;
+                       }
+               }
+               else {
+                       /* find the matching driver and remove it only 
+                        * Note: here is one of the places where we don't want new F-Curve + Driver added!
+                        *      so 'add' var must be 0
+                        */
+                       fcu = verify_driver_fcurve(id, rna_path, array_index, 0);
+                       if (fcu) {
+                               BLI_remlink(&adt->drivers, fcu);
+                               free_fcurve(fcu);
+                               
+                               success = 1;
+                       }
+               }
+       }
+
+       return success;
 }
 
 /* ************************************************** */
@@ -256,16 +281,16 @@ static FCurve *channeldriver_copypaste_buf = NULL;
 
 /* This function frees any MEM_calloc'ed copy/paste buffer data */
 // XXX find some header to put this in!
-void free_anim_drivers_copybuf (void)
+void free_anim_drivers_copybuf(void)
 {
        /* free the buffer F-Curve if it exists, as if it were just another F-Curve */
        if (channeldriver_copypaste_buf)
                free_fcurve(channeldriver_copypaste_buf);
-       channeldriver_copypaste_buf= NULL;
+       channeldriver_copypaste_buf = NULL;
 }
 
 /* Checks if there is a driver in the copy/paste buffer */
-short ANIM_driver_can_paste (void)
+short ANIM_driver_can_paste(void)
 {
        return (channeldriver_copypaste_buf != NULL);
 }
@@ -273,9 +298,9 @@ short ANIM_driver_can_paste (void)
 /* ------------------- */
 
 /* Main Driver Management API calls:
- *     Make a copy of the driver for the specified property on the given ID block
+ *  Make a copy of the driver for the specified property on the given ID block
  */
-short ANIM_copy_driver (ID *id, const char rna_path[], int array_index, short flag)
+short ANIM_copy_driver(ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag))
 {
        PointerRNA id_ptr, ptr;
        PropertyRNA *prop;
@@ -284,12 +309,14 @@ short ANIM_copy_driver (ID *id, const char rna_path[], int array_index, short fl
        /* validate pointer first - exit if failure */
        RNA_id_pointer_create(id, &id_ptr);
        if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) {
-               printf("Copy Driver: Could not find Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path);
+               BKE_reportf(reports, RPT_ERROR,
+                           "Could not find Driver to copy, as RNA Path is invalid for the given ID (ID = %s, Path = %s)",
+                           id->name, rna_path);
                return 0;
        }
        
        /* try to get F-Curve with Driver */
-       fcu= verify_driver_fcurve(id, rna_path, array_index, 0);
+       fcu = verify_driver_fcurve(id, rna_path, array_index, 0);
        
        /* clear copy/paste buffer first (for consistency with other copy/paste buffers) */
        free_anim_drivers_copybuf();
@@ -300,13 +327,13 @@ short ANIM_copy_driver (ID *id, const char rna_path[], int array_index, short fl
                 * so that we don't end up wasting memory storing the path which won't get used ever...
                 */
                char *tmp_path = fcu->rna_path;
-               fcu->rna_path= NULL;
+               fcu->rna_path = NULL;
                
                /* make a copy of the F-Curve with */
-               channeldriver_copypaste_buf= copy_fcurve(fcu);
+               channeldriver_copypaste_buf = copy_fcurve(fcu);
                
                /* restore the path */
-               fcu->rna_path= tmp_path;
+               fcu->rna_path = tmp_path;
                
                /* copied... */
                return 1;
@@ -317,10 +344,10 @@ short ANIM_copy_driver (ID *id, const char rna_path[], int array_index, short fl
 }
 
 /* Main Driver Management API calls:
- *     Add a new driver for the specified property on the given ID block or replace an existing one
+ *  Add a new driver for the specified property on the given ID block or replace an existing one
  *     with the driver + driver-curve data from the buffer 
  */
-short ANIM_paste_driver (ID *id, const char rna_path[], int array_index, short flag)
+short ANIM_paste_driver(ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag))
 {      
        PointerRNA id_ptr, ptr;
        PropertyRNA *prop;
@@ -329,41 +356,38 @@ short ANIM_paste_driver (ID *id, const char rna_path[], int array_index, short f
        /* validate pointer first - exit if failure */
        RNA_id_pointer_create(id, &id_ptr);
        if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) {
-               printf("Paste Driver: Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path);
+               BKE_reportf(reports, RPT_ERROR,
+                           "Could not paste Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)",
+                           id->name, rna_path);
                return 0;
        }
        
        /* if the buffer is empty, cannot paste... */
        if (channeldriver_copypaste_buf == NULL) {
-               printf("Paste Driver: No Driver to paste. \n");
+               BKE_report(reports, RPT_ERROR, "Paste Driver: No Driver to paste");
                return 0;
        }
        
        /* create Driver F-Curve, but without data which will be copied across... */
-       fcu= verify_driver_fcurve(id, rna_path, array_index, -1);
+       fcu = verify_driver_fcurve(id, rna_path, array_index, -1);
 
        if (fcu) {
                /* copy across the curve data from the buffer curve 
                 * NOTE: this step needs care to not miss new settings
                 */
-                       /* keyframes/samples */
-               fcu->bezt= MEM_dupallocN(channeldriver_copypaste_buf->bezt);
-               fcu->fpt= MEM_dupallocN(channeldriver_copypaste_buf->fpt);
-               fcu->totvert= channeldriver_copypaste_buf->totvert;
+               /* keyframes/samples */
+               fcu->bezt = MEM_dupallocN(channeldriver_copypaste_buf->bezt);
+               fcu->fpt = MEM_dupallocN(channeldriver_copypaste_buf->fpt);
+               fcu->totvert = channeldriver_copypaste_buf->totvert;
                
-                       /* modifiers */
+               /* modifiers */
                copy_fmodifiers(&fcu->modifiers, &channeldriver_copypaste_buf->modifiers);
                
-                       /* flags - on a per-relevant-flag basis */
-               if (channeldriver_copypaste_buf->flag & FCURVE_AUTO_HANDLES)
-                       fcu->flag |= FCURVE_AUTO_HANDLES;
-               else
-                       fcu->flag &= ~FCURVE_AUTO_HANDLES;
-                       /* extrapolation mode */
-               fcu->extend= channeldriver_copypaste_buf->extend;
+               /* extrapolation mode */
+               fcu->extend = channeldriver_copypaste_buf->extend;
                        
-                       /* the 'juicy' stuff - the driver */
-               fcu->driver= fcurve_copy_driver(channeldriver_copypaste_buf->driver);
+               /* the 'juicy' stuff - the driver */
+               fcu->driver = fcurve_copy_driver(channeldriver_copypaste_buf->driver);
        }
        
        /* done */
@@ -373,28 +397,89 @@ short ANIM_paste_driver (ID *id, const char rna_path[], int array_index, short f
 /* ************************************************** */
 /* UI-Button Interface */
 
+/* Temporary wrapper for driver operators for buttons to make it easier to create
+ * such drivers by rerouting all paths through the active object instead so that
+ * they will get picked up by the dependency system.
+ *
+ * < C: context pointer - for getting active data 
+ * <> ptr: RNA pointer for property's datablock. May be modified as result of path remapping.
+ * < prop: RNA definition of property to add for
+ *
+ * > returns: MEM_alloc'd string representing the path to the property from the given PointerRNA
+ */
+static char *get_driver_path_hack(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
+{
+       ID *id = (ID *)ptr->id.data;
+       ScrArea *sa = CTX_wm_area(C);
+       
+       /* get standard path which may be extended */
+       char *basepath = RNA_path_from_ID_to_property(ptr, prop);
+       char *path = basepath; /* in case no remapping is needed */
+       
+       
+       /* Remapping will only be performed in the Properties Editor, as only this 
+        * restricts the subspace of options to the 'active' data (a manageable state)
+        */
+       // TODO: watch out for pinned context?
+       if ((sa) && (sa->spacetype == SPACE_BUTS)) {
+               Object *ob = CTX_data_active_object(C);
+               
+               if (ob && id) {
+                       /* only id-types which can be remapped to go through objects should be considered */
+                       switch (GS(id->name)) {
+                               case ID_TE: /* textures */
+                               {
+                                       Material *ma = give_current_material(ob, ob->actcol);
+                                       Tex *tex = give_current_material_texture(ma);
+                                       
+                                       /* assumes: texture will only be shown if it is active material's active texture it's ok */
+                                       if ((ID *)tex == id) {
+                                               /* create new path */
+                                               // TODO: use RNA path functions to construct step by step instead?
+                                               // FIXME: maybe this isn't even needed anymore...
+                                               path = BLI_sprintfN("material_slots[\"%s\"].material.texture_slots[\"%s\"].texture.%s", 
+                                                                   ma->id.name + 2, tex->id.name + 2, basepath);
+                                                       
+                                               /* free old one */
+                                               MEM_freeN(basepath);
+                                       }
+                               }
+                               break;
+                       }
+                       
+                       /* fix RNA pointer, as we've now changed the ID root by changing the paths */
+                       if (basepath != path) {
+                               /* rebase provided pointer so that it starts from object... */
+                               RNA_pointer_create(&ob->id, ptr->type, ptr->data, ptr);
+                       }
+               }
+       }
+       
+       /* the path should now have been corrected for use */
+       return path;
+}
+
 /* Add Driver Button Operator ------------------------ */
 
-static int add_driver_button_exec (bContext *C, wmOperator *op)
+static int add_driver_button_exec(bContext *C, wmOperator *op)
 {
-       PointerRNA ptr;
-       PropertyRNA *prop= NULL;
-       char *path;
-       short success= 0;
-       int index, all= RNA_boolean_get(op->ptr, "all");
+       PointerRNA ptr = {{NULL}};
+       PropertyRNA *prop = NULL;
+       short success = 0;
+       int index, all = RNA_boolean_get(op->ptr, "all");
        
        /* try to create driver using property retrieved from UI */
-       memset(&ptr, 0, sizeof(PointerRNA));
-       uiAnimContextProperty(C, &ptr, &prop, &index);
-
+       uiContextActiveProperty(C, &ptr, &prop, &index);
+       
        if (all)
-               index= -1;
-
-       if (ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
-               path= RNA_path_from_ID_to_property(&ptr, prop);
+               index = -1;
+       
+       if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
+               char *path = get_driver_path_hack(C, &ptr, prop);
+               short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
                
                if (path) {                     
-                       success+= ANIM_add_driver(ptr.id.data, path, index, 0, DRIVER_TYPE_PYTHON);
+                       success += ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON);
                        
                        MEM_freeN(path);
                }
@@ -402,181 +487,172 @@ static int add_driver_button_exec (bContext *C, wmOperator *op)
        
        if (success) {
                /* send updates */
-               DAG_ids_flush_update(0);
+               uiContextAnimUpdate(C);
+               
+               DAG_ids_flush_update(CTX_data_main(C), 0);
                
-               WM_event_add_notifier(C, NC_ANIMATION|ND_FCURVES_ORDER, NULL); // XXX
+               WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX
        }
        
-       return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
+       return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
 }
 
-void ANIM_OT_driver_button_add (wmOperatorType *ot)
+void ANIM_OT_driver_button_add(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Add Driver";
-       ot->idname= "ANIM_OT_driver_button_add";
-       ot->description= "Add driver(s) for the property(s) connected represented by the highlighted button";
+       ot->name = "Add Driver";
+       ot->idname = "ANIM_OT_driver_button_add";
+       ot->description = "Add driver(s) for the property(s) connected represented by the highlighted button";
        
        /* callbacks */
-       ot->exec= add_driver_button_exec; 
-       //op->poll= ??? // TODO: need to have some animateable property to do this
+       ot->exec = add_driver_button_exec; 
+       //op->poll = ??? // TODO: need to have some animatable property to do this
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
-       RNA_def_boolean(ot->srna, "all", 1, "All", "Create drivers for all elements of the array.");
+       RNA_def_boolean(ot->srna, "all", 1, "All", "Create drivers for all elements of the array");
 }
 
 /* Remove Driver Button Operator ------------------------ */
 
-static int remove_driver_button_exec (bContext *C, wmOperator *op)
+static int remove_driver_button_exec(bContext *C, wmOperator *op)
 {
-       PointerRNA ptr;
-       PropertyRNA *prop= NULL;
-       char *path;
-       short success= 0;
-       int a, index, length, all= RNA_boolean_get(op->ptr, "all");
+       PointerRNA ptr = {{NULL}};
+       PropertyRNA *prop = NULL;
+       short success = 0;
+       int index, all = RNA_boolean_get(op->ptr, "all");
        
        /* try to find driver using property retrieved from UI */
-       memset(&ptr, 0, sizeof(PointerRNA));
-       uiAnimContextProperty(C, &ptr, &prop, &index);
-
-       if (ptr.data && prop) {
-               path= RNA_path_from_ID_to_property(&ptr, prop);
+       uiContextActiveProperty(C, &ptr, &prop, &index);
+       
+       if (all)
+               index = -1;
+       
+       if (ptr.id.data && ptr.data && prop) {
+               char *path = get_driver_path_hack(C, &ptr, prop);
                
-               if (path) {
-                       if (all) {
-                               length= RNA_property_array_length(&ptr, prop);
-                               
-                               if(length) index= 0;
-                               else length= 1;
-                       }
-                       else
-                               length= 1;
-                       
-                       for (a=0; a<length; a++)
-                               success+= ANIM_remove_driver(ptr.id.data, path, index+a, 0);
-                       
-                       MEM_freeN(path);
-               }
+               success = ANIM_remove_driver(op->reports, ptr.id.data, path, index, 0);
+               MEM_freeN(path);
        }
        
-       
        if (success) {
                /* send updates */
-               DAG_ids_flush_update(0);
+               uiContextAnimUpdate(C);
                
-               WM_event_add_notifier(C, NC_ANIMATION|ND_FCURVES_ORDER, NULL);  // XXX
+               DAG_ids_flush_update(CTX_data_main(C), 0);
+               
+               WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL);  // XXX
        }
        
-       return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
+       return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
 }
 
-void ANIM_OT_driver_button_remove (wmOperatorType *ot)
+void ANIM_OT_driver_button_remove(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Remove Driver";
-       ot->idname= "ANIM_OT_driver_button_remove";
-       ot->description= "Remove the driver(s) for the property(s) connected represented by the highlighted button";
+       ot->name = "Remove Driver";
+       ot->idname = "ANIM_OT_driver_button_remove";
+       ot->description = "Remove the driver(s) for the property(s) connected represented by the highlighted button";
        
        /* callbacks */
-       ot->exec= remove_driver_button_exec; 
-       //op->poll= ??? // TODO: need to have some driver to be able to do this...
+       ot->exec = remove_driver_button_exec; 
+       //op->poll = ??? // TODO: need to have some driver to be able to do this...
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
-       RNA_def_boolean(ot->srna, "all", 1, "All", "Delete drivers for all elements of the array.");
+       RNA_def_boolean(ot->srna, "all", 1, "All", "Delete drivers for all elements of the array");
 }
 
 /* Copy Driver Button Operator ------------------------ */
 
-static int copy_driver_button_exec (bContext *C, wmOperator *op)
+static int copy_driver_button_exec(bContext *C, wmOperator *op)
 {
-       PointerRNA ptr;
-       PropertyRNA *prop= NULL;
-       char *path;
-       short success= 0;
+       PointerRNA ptr = {{NULL}};
+       PropertyRNA *prop = NULL;
+       short success = 0;
        int index;
        
        /* try to create driver using property retrieved from UI */
-       memset(&ptr, 0, sizeof(PointerRNA));
-       uiAnimContextProperty(C, &ptr, &prop, &index);
+       uiContextActiveProperty(C, &ptr, &prop, &index);
        
-       if (ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
-               path= RNA_path_from_ID_to_property(&ptr, prop);
+       if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
+               char *path = get_driver_path_hack(C, &ptr, prop);
                
                if (path) {
                        /* only copy the driver for the button that this was involved for */
-                       success= ANIM_copy_driver(ptr.id.data, path, index, 0);
+                       success = ANIM_copy_driver(op->reports, ptr.id.data, path, index, 0);
+                       
+                       uiContextAnimUpdate(C);
                        
                        MEM_freeN(path);
                }
        }
        
        /* since we're just copying, we don't really need to do anything else...*/
-       return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
+       return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
 }
 
-void ANIM_OT_copy_driver_button (wmOperatorType *ot)
+void ANIM_OT_copy_driver_button(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Copy Driver";
-       ot->idname= "ANIM_OT_copy_driver_button";
-       ot->description= "Copy the driver for the highlighted button";
+       ot->name = "Copy Driver";
+       ot->idname = "ANIM_OT_copy_driver_button";
+       ot->description = "Copy the driver for the highlighted button";
        
        /* callbacks */
-       ot->exec= copy_driver_button_exec; 
-       //op->poll= ??? // TODO: need to have some driver to be able to do this...
+       ot->exec = copy_driver_button_exec; 
+       //op->poll = ??? // TODO: need to have some driver to be able to do this...
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /* Paste Driver Button Operator ------------------------ */
 
-static int paste_driver_button_exec (bContext *C, wmOperator *op)
+static int paste_driver_button_exec(bContext *C, wmOperator *op)
 {
-       PointerRNA ptr;
-       PropertyRNA *prop= NULL;
-       char *path;
-       short success= 0;
+       PointerRNA ptr = {{NULL}};
+       PropertyRNA *prop = NULL;
+       short success = 0;
        int index;
        
        /* try to create driver using property retrieved from UI */
-       memset(&ptr, 0, sizeof(PointerRNA));
-       uiAnimContextProperty(C, &ptr, &prop, &index);
+       uiContextActiveProperty(C, &ptr, &prop, &index);
        
-       if (ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
-               path= RNA_path_from_ID_to_property(&ptr, prop);
+       if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
+               char *path = get_driver_path_hack(C, &ptr, prop);
                
                if (path) {
                        /* only copy the driver for the button that this was involved for */
-                       success= ANIM_paste_driver(ptr.id.data, path, index, 0);
+                       success = ANIM_paste_driver(op->reports, ptr.id.data, path, index, 0);
+                       
+                       uiContextAnimUpdate(C);
                        
                        MEM_freeN(path);
                }
        }
        
        /* since we're just copying, we don't really need to do anything else...*/
-       return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
+       return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
 }
 
-void ANIM_OT_paste_driver_button (wmOperatorType *ot)
+void ANIM_OT_paste_driver_button(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Paste Driver";
-       ot->idname= "ANIM_OT_paste_driver_button";
-       ot->description= "Paste the driver in the copy/paste buffer for the highlighted button";
+       ot->name = "Paste Driver";
+       ot->idname = "ANIM_OT_paste_driver_button";
+       ot->description = "Paste the driver in the copy/paste buffer for the highlighted button";
        
        /* callbacks */
-       ot->exec= paste_driver_button_exec; 
-       //op->poll= ??? // TODO: need to have some driver to be able to do this...
+       ot->exec = paste_driver_button_exec; 
+       //op->poll = ??? // TODO: need to have some driver to be able to do this...
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /* ************************************************** */