Blender V2.61 - r43446

drivers.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): Joshua Leung (full recode)
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <stdio.h>
00034 #include <string.h>
00035 
00036 #include "MEM_guardedalloc.h"
00037 
00038 #include "BLI_blenlib.h"
00039 #include "BLI_utildefines.h"
00040 
00041 #include "DNA_anim_types.h"
00042 #include "DNA_object_types.h"
00043 #include "DNA_material_types.h"
00044 #include "DNA_texture_types.h"
00045 #include "DNA_screen_types.h"
00046 #include "DNA_space_types.h"
00047 
00048 #include "BKE_animsys.h"
00049 #include "BKE_depsgraph.h"
00050 #include "BKE_fcurve.h"
00051 #include "BKE_context.h"
00052 #include "BKE_report.h"
00053 #include "BKE_material.h"
00054 #include "BKE_texture.h"
00055 
00056 #include "ED_keyframing.h"
00057 
00058 #include "UI_interface.h"
00059 
00060 #include "WM_api.h"
00061 #include "WM_types.h"
00062 
00063 #include "RNA_access.h"
00064 #include "RNA_define.h"
00065 
00066 #include "anim_intern.h"
00067 
00068 /* called by WM */
00069 void free_anim_drivers_copybuf (void);
00070 
00071 /* ************************************************** */
00072 /* Animation Data Validation */
00073 
00074 /* Get (or add relevant data to be able to do so) F-Curve from the driver stack, 
00075  * for the given Animation Data block. This assumes that all the destinations are valid.
00076  *  
00077  *  - add:  0 - don't add anything if not found, 
00078  *          1 - add new Driver FCurve, 
00079  *          -1 - add new Driver FCurve without driver stuff (for pasting)
00080  */
00081 FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_index, short add)
00082 {
00083     AnimData *adt;
00084     FCurve *fcu;
00085     
00086     /* sanity checks */
00087     if ELEM(NULL, id, rna_path)
00088         return NULL;
00089     
00090     /* init animdata if none available yet */
00091     adt= BKE_animdata_from_id(id);
00092     if ((adt == NULL) && (add))
00093         adt= BKE_id_add_animdata(id);
00094     if (adt == NULL) { 
00095         /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
00096         return NULL;
00097     }
00098         
00099     /* try to find f-curve matching for this setting 
00100      *  - add if not found and allowed to add one
00101      *      TODO: add auto-grouping support? how this works will need to be resolved
00102      */
00103     fcu= list_find_fcurve(&adt->drivers, rna_path, array_index);
00104     
00105     if ((fcu == NULL) && (add)) {
00106         /* use default settings to make a F-Curve */
00107         fcu= MEM_callocN(sizeof(FCurve), "FCurve");
00108         
00109         fcu->flag = (FCURVE_VISIBLE|FCURVE_SELECTED);
00110         
00111         /* store path - make copy, and store that */
00112         fcu->rna_path= BLI_strdupn(rna_path, strlen(rna_path));
00113         fcu->array_index= array_index;
00114         
00115         /* if add is negative, don't init this data yet, since it will be filled in by the pasted driver */
00116         if (add > 0) {
00117             /* add some new driver data */
00118             fcu->driver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
00119             
00120             /* add simple generator modifier for driver so that there is some visible representation */
00121             add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR);
00122         }
00123         
00124         /* just add F-Curve to end of driver list */
00125         BLI_addtail(&adt->drivers, fcu);
00126     }
00127     
00128     /* return the F-Curve */
00129     return fcu;
00130 }
00131 
00132 /* ************************************************** */
00133 /* Driver Management API */
00134 
00135 /* Main Driver Management API calls:
00136  *  Add a new driver for the specified property on the given ID block
00137  */
00138 short ANIM_add_driver (ReportList *reports, ID *id, const char rna_path[], int array_index, short flag, int type)
00139 {   
00140     PointerRNA id_ptr, ptr;
00141     PropertyRNA *prop;
00142     FCurve *fcu;
00143     int array_index_max;
00144     int done = 0;
00145     
00146     /* validate pointer first - exit if failure */
00147     RNA_id_pointer_create(id, &id_ptr);
00148     if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) {
00149         BKE_reportf(reports, RPT_ERROR, 
00150             "Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", 
00151             id->name, rna_path);
00152         return 0;
00153     }
00154     
00155     /* key entire array convenience method */
00156     if (array_index == -1) {
00157         array_index_max= RNA_property_array_length(&ptr, prop);
00158         array_index= 0;
00159     }
00160     else
00161         array_index_max= array_index;
00162     
00163     /* maximum index should be greater than the start index */
00164     if (array_index == array_index_max)
00165         array_index_max += 1;
00166     
00167     /* will only loop once unless the array index was -1 */
00168     for (; array_index < array_index_max; array_index++) {
00169         /* create F-Curve with Driver */
00170         fcu= verify_driver_fcurve(id, rna_path, array_index, 1);
00171         
00172         if (fcu && fcu->driver) {
00173             ChannelDriver *driver= fcu->driver;
00174             
00175             /* set the type of the driver */
00176             driver->type= type;
00177             
00178             /* creating drivers for buttons will create the driver(s) with type 
00179              * "scripted expression" so that their values won't be lost immediately,
00180              * so here we copy those values over to the driver's expression
00181              */
00182             if (type == DRIVER_TYPE_PYTHON) {
00183                 PropertyType proptype= RNA_property_type(prop);
00184                 int array= RNA_property_array_length(&ptr, prop);
00185                 char *expression= driver->expression;
00186                 int val, maxlen= sizeof(driver->expression);
00187                 float fval;
00188                 
00189                 if (proptype == PROP_BOOLEAN) {
00190                     if (!array) val= RNA_property_boolean_get(&ptr, prop);
00191                     else val= RNA_property_boolean_get_index(&ptr, prop, array_index);
00192                     
00193                     BLI_strncpy(expression, (val)? "True": "False", maxlen);
00194                 }
00195                 else if (proptype == PROP_INT) {
00196                     if (!array) val= RNA_property_int_get(&ptr, prop);
00197                     else val= RNA_property_int_get_index(&ptr, prop, array_index);
00198                     
00199                     BLI_snprintf(expression, maxlen, "%d", val);
00200                 }
00201                 else if (proptype == PROP_FLOAT) {
00202                     if (!array) fval= RNA_property_float_get(&ptr, prop);
00203                     else fval= RNA_property_float_get_index(&ptr, prop, array_index);
00204                     
00205                     BLI_snprintf(expression, maxlen, "%.3f", fval);
00206                 }
00207             }
00208             
00209             /* for easier setup of drivers from UI, a driver variable should be 
00210              * added if flag is set (UI calls only)
00211              */
00212             if (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) {
00213                 /* assume that users will mostly want this to be of type "Transform Channel" too,
00214                  * since this allows the easiest setting up of common rig components
00215                  */
00216                 DriverVar *dvar = driver_add_new_variable(driver);
00217                 driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN);
00218             }
00219         }
00220         
00221         /* set the done status */
00222         done += (fcu != NULL);
00223     }
00224     
00225     /* done */
00226     return done;
00227 }
00228 
00229 /* Main Driver Management API calls:
00230  *  Remove the driver for the specified property on the given ID block (if available)
00231  */
00232 short ANIM_remove_driver (ReportList *UNUSED(reports), ID *id, const char rna_path[], int array_index, short UNUSED(flag))
00233 {
00234     AnimData *adt;
00235     FCurve *fcu;
00236     int success= 0;
00237     
00238     /* we don't check the validity of the path here yet, but it should be ok... */
00239     adt= BKE_animdata_from_id(id);
00240     
00241     if (adt) {
00242         if (array_index == -1) {
00243             /* step through all drivers, removing all of those with the same base path */
00244             FCurve *fcu_iter= adt->drivers.first;
00245             
00246             while ((fcu = iter_step_fcurve(fcu_iter, rna_path)) != NULL) {
00247                 /* store the next fcurve for looping  */
00248                 fcu_iter= fcu->next;
00249                 
00250                 /* remove F-Curve from driver stack, then free it */
00251                 BLI_remlink(&adt->drivers, fcu);
00252                 free_fcurve(fcu);
00253                 
00254                 /* done successfully */
00255                 success |= 1;
00256             }
00257         }
00258         else {
00259             /* find the matching driver and remove it only 
00260              * Note: here is one of the places where we don't want new F-Curve + Driver added!
00261              *      so 'add' var must be 0
00262              */
00263             fcu= verify_driver_fcurve(id, rna_path, array_index, 0);
00264             if (fcu) {
00265                 BLI_remlink(&adt->drivers, fcu);
00266                 free_fcurve(fcu);
00267                 
00268                 success = 1;
00269             }
00270         }
00271     }
00272 
00273     return success;
00274 }
00275 
00276 /* ************************************************** */
00277 /* Driver Management API - Copy/Paste Drivers */
00278 
00279 /* Copy/Paste Buffer for Driver Data... */
00280 static FCurve *channeldriver_copypaste_buf = NULL;
00281 
00282 /* This function frees any MEM_calloc'ed copy/paste buffer data */
00283 // XXX find some header to put this in!
00284 void free_anim_drivers_copybuf (void)
00285 {
00286     /* free the buffer F-Curve if it exists, as if it were just another F-Curve */
00287     if (channeldriver_copypaste_buf)
00288         free_fcurve(channeldriver_copypaste_buf);
00289     channeldriver_copypaste_buf= NULL;
00290 }
00291 
00292 /* Checks if there is a driver in the copy/paste buffer */
00293 short ANIM_driver_can_paste (void)
00294 {
00295     return (channeldriver_copypaste_buf != NULL);
00296 }
00297 
00298 /* ------------------- */
00299 
00300 /* Main Driver Management API calls:
00301  *  Make a copy of the driver for the specified property on the given ID block
00302  */
00303 short ANIM_copy_driver (ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag))
00304 {
00305     PointerRNA id_ptr, ptr;
00306     PropertyRNA *prop;
00307     FCurve *fcu;
00308     
00309     /* validate pointer first - exit if failure */
00310     RNA_id_pointer_create(id, &id_ptr);
00311     if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) {
00312         BKE_reportf(reports, RPT_ERROR,
00313             "Could not find Driver to copy, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", 
00314             id->name, rna_path);
00315         return 0;
00316     }
00317     
00318     /* try to get F-Curve with Driver */
00319     fcu= verify_driver_fcurve(id, rna_path, array_index, 0);
00320     
00321     /* clear copy/paste buffer first (for consistency with other copy/paste buffers) */
00322     free_anim_drivers_copybuf();
00323     
00324     /* copy this to the copy/paste buf if it exists */
00325     if (fcu && fcu->driver) {
00326         /* make copies of some info such as the rna_path, then clear this info from the F-Curve temporarily
00327          * so that we don't end up wasting memory storing the path which won't get used ever...
00328          */
00329         char *tmp_path = fcu->rna_path;
00330         fcu->rna_path= NULL;
00331         
00332         /* make a copy of the F-Curve with */
00333         channeldriver_copypaste_buf= copy_fcurve(fcu);
00334         
00335         /* restore the path */
00336         fcu->rna_path= tmp_path;
00337         
00338         /* copied... */
00339         return 1;
00340     }
00341     
00342     /* done */
00343     return 0;
00344 }
00345 
00346 /* Main Driver Management API calls:
00347  *  Add a new driver for the specified property on the given ID block or replace an existing one
00348  *  with the driver + driver-curve data from the buffer 
00349  */
00350 short ANIM_paste_driver (ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag))
00351 {   
00352     PointerRNA id_ptr, ptr;
00353     PropertyRNA *prop;
00354     FCurve *fcu;
00355     
00356     /* validate pointer first - exit if failure */
00357     RNA_id_pointer_create(id, &id_ptr);
00358     if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) {
00359         BKE_reportf(reports, RPT_ERROR,
00360             "Could not paste Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", 
00361             id->name, rna_path);
00362         return 0;
00363     }
00364     
00365     /* if the buffer is empty, cannot paste... */
00366     if (channeldriver_copypaste_buf == NULL) {
00367         BKE_report(reports, RPT_ERROR, "Paste Driver: No Driver to paste");
00368         return 0;
00369     }
00370     
00371     /* create Driver F-Curve, but without data which will be copied across... */
00372     fcu= verify_driver_fcurve(id, rna_path, array_index, -1);
00373 
00374     if (fcu) {
00375         /* copy across the curve data from the buffer curve 
00376          * NOTE: this step needs care to not miss new settings
00377          */
00378             /* keyframes/samples */
00379         fcu->bezt= MEM_dupallocN(channeldriver_copypaste_buf->bezt);
00380         fcu->fpt= MEM_dupallocN(channeldriver_copypaste_buf->fpt);
00381         fcu->totvert= channeldriver_copypaste_buf->totvert;
00382         
00383             /* modifiers */
00384         copy_fmodifiers(&fcu->modifiers, &channeldriver_copypaste_buf->modifiers);
00385         
00386             /* extrapolation mode */
00387         fcu->extend= channeldriver_copypaste_buf->extend;
00388             
00389             /* the 'juicy' stuff - the driver */
00390         fcu->driver= fcurve_copy_driver(channeldriver_copypaste_buf->driver);
00391     }
00392     
00393     /* done */
00394     return (fcu != NULL);
00395 }
00396 
00397 /* ************************************************** */
00398 /* UI-Button Interface */
00399 
00400 /* Temporary wrapper for driver operators for buttons to make it easier to create
00401  * such drivers by rerouting all paths through the active object instead so that
00402  * they will get picked up by the dependency system.
00403  *
00404  * < C: context pointer - for getting active data 
00405  * <> ptr: RNA pointer for property's datablock. May be modified as result of path remapping.
00406  * < prop: RNA definition of property to add for
00407  *
00408  * > returns: MEM_alloc'd string representing the path to the property from the given PointerRNA
00409  */
00410 static char *get_driver_path_hack (bContext *C, PointerRNA *ptr, PropertyRNA *prop)
00411 {
00412     ID *id = (ID *)ptr->id.data;
00413     ScrArea *sa = CTX_wm_area(C);
00414     
00415     /* get standard path which may be extended */
00416     char *basepath = RNA_path_from_ID_to_property(ptr, prop);
00417     char *path = basepath; /* in case no remapping is needed */
00418     
00419     /* Remapping will only be performed in the Properties Editor, as only this 
00420      * restricts the subspace of options to the 'active' data (a manageable state)
00421      */
00422     // TODO: watch out for pinned context?
00423     if ((sa) && (sa->spacetype == SPACE_BUTS)) {
00424         Object *ob = CTX_data_active_object(C);
00425         
00426         if (ob && id) {
00427             /* only id-types which can be remapped to go through objects should be considered */
00428             switch (GS(id->name)) {
00429                 case ID_MA: /* materials */
00430                 {
00431                     Material *ma = give_current_material(ob, ob->actcol);
00432                     
00433                     /* assumes: material will only be shown if it is active objects's active material it's ok */
00434                     if ((ID*)ma == id) {
00435                         /* create new path */
00436                         // TODO: use RNA path functions to construct instead?
00437                         path = BLI_sprintfN("material_slots[\"%s\"].material.%s",
00438                             ma->id.name+2, basepath);
00439                             
00440                         /* free old one */
00441                         MEM_freeN(basepath);
00442                     }
00443                 }
00444                     break;
00445                     
00446                 case ID_TE: /* textures */
00447                 {
00448                     Material *ma = give_current_material(ob, ob->actcol);
00449                     Tex *tex = give_current_material_texture(ma);
00450                     
00451                     /* assumes: texture will only be shown if it is active material's active texture it's ok */
00452                     if ((ID*)tex == id) {
00453                         /* create new path */
00454                         // TODO: use RNA path functions to construct step by step instead?
00455                         path = BLI_sprintfN("material_slots[\"%s\"].material.texture_slots[\"%s\"].texture.%s", 
00456                             ma->id.name+2, tex->id.name+2, basepath);
00457                             
00458                         /* free old one */
00459                         MEM_freeN(basepath);
00460                     }
00461                 }
00462                     break;
00463             }
00464             
00465             /* fix RNA pointer, as we've now changed the ID root by changing the paths */
00466             if (basepath != path) {
00467                 /* rebase provided pointer so that it starts from object... */
00468                 RNA_pointer_create(&ob->id, ptr->type, ptr->data, ptr);
00469             }
00470         }
00471     }
00472     
00473     /* the path should now have been corrected for use */
00474     return path;
00475 }
00476 
00477 /* Add Driver Button Operator ------------------------ */
00478 
00479 static int add_driver_button_exec (bContext *C, wmOperator *op)
00480 {
00481     PointerRNA ptr= {{NULL}};
00482     PropertyRNA *prop= NULL;
00483     short success= 0;
00484     int index, all= RNA_boolean_get(op->ptr, "all");
00485     
00486     /* try to create driver using property retrieved from UI */
00487     uiContextActiveProperty(C, &ptr, &prop, &index);
00488     
00489     if (all)
00490         index= -1;
00491     
00492     if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
00493         char *path= get_driver_path_hack(C, &ptr, prop);
00494         short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
00495         
00496         if (path) {         
00497             success+= ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON);
00498             
00499             MEM_freeN(path);
00500         }
00501     }
00502     
00503     if (success) {
00504         /* send updates */
00505         uiContextAnimUpdate(C);
00506         
00507         DAG_ids_flush_update(CTX_data_main(C), 0);
00508         
00509         WM_event_add_notifier(C, NC_ANIMATION|ND_FCURVES_ORDER, NULL); // XXX
00510     }
00511     
00512     return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
00513 }
00514 
00515 void ANIM_OT_driver_button_add (wmOperatorType *ot)
00516 {
00517     /* identifiers */
00518     ot->name= "Add Driver";
00519     ot->idname= "ANIM_OT_driver_button_add";
00520     ot->description= "Add driver(s) for the property(s) connected represented by the highlighted button";
00521     
00522     /* callbacks */
00523     ot->exec= add_driver_button_exec; 
00524     //op->poll= ??? // TODO: need to have some animateable property to do this
00525     
00526     /* flags */
00527     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00528 
00529     /* properties */
00530     RNA_def_boolean(ot->srna, "all", 1, "All", "Create drivers for all elements of the array");
00531 }
00532 
00533 /* Remove Driver Button Operator ------------------------ */
00534 
00535 static int remove_driver_button_exec (bContext *C, wmOperator *op)
00536 {
00537     PointerRNA ptr= {{NULL}};
00538     PropertyRNA *prop= NULL;
00539     short success= 0;
00540     int index, all= RNA_boolean_get(op->ptr, "all");
00541     
00542     /* try to find driver using property retrieved from UI */
00543     uiContextActiveProperty(C, &ptr, &prop, &index);
00544     
00545     if (all)
00546         index= -1;
00547     
00548     if (ptr.id.data && ptr.data && prop) {
00549         char *path= get_driver_path_hack(C, &ptr, prop);
00550         
00551         success= ANIM_remove_driver(op->reports, ptr.id.data, path, index, 0);
00552         MEM_freeN(path);
00553     }
00554     
00555     if (success) {
00556         /* send updates */
00557         uiContextAnimUpdate(C);
00558         
00559         DAG_ids_flush_update(CTX_data_main(C), 0);
00560         
00561         WM_event_add_notifier(C, NC_ANIMATION|ND_FCURVES_ORDER, NULL);  // XXX
00562     }
00563     
00564     return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
00565 }
00566 
00567 void ANIM_OT_driver_button_remove (wmOperatorType *ot)
00568 {
00569     /* identifiers */
00570     ot->name= "Remove Driver";
00571     ot->idname= "ANIM_OT_driver_button_remove";
00572     ot->description= "Remove the driver(s) for the property(s) connected represented by the highlighted button";
00573     
00574     /* callbacks */
00575     ot->exec= remove_driver_button_exec; 
00576     //op->poll= ??? // TODO: need to have some driver to be able to do this...
00577     
00578     /* flags */
00579     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00580 
00581     /* properties */
00582     RNA_def_boolean(ot->srna, "all", 1, "All", "Delete drivers for all elements of the array");
00583 }
00584 
00585 /* Copy Driver Button Operator ------------------------ */
00586 
00587 static int copy_driver_button_exec (bContext *C, wmOperator *op)
00588 {
00589     PointerRNA ptr= {{NULL}};
00590     PropertyRNA *prop= NULL;
00591     short success= 0;
00592     int index;
00593     
00594     /* try to create driver using property retrieved from UI */
00595     uiContextActiveProperty(C, &ptr, &prop, &index);
00596     
00597     if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
00598         char *path= get_driver_path_hack(C, &ptr, prop);
00599         
00600         if (path) {
00601             /* only copy the driver for the button that this was involved for */
00602             success= ANIM_copy_driver(op->reports, ptr.id.data, path, index, 0);
00603             
00604             uiContextAnimUpdate(C);
00605             
00606             MEM_freeN(path);
00607         }
00608     }
00609     
00610     /* since we're just copying, we don't really need to do anything else...*/
00611     return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
00612 }
00613 
00614 void ANIM_OT_copy_driver_button (wmOperatorType *ot)
00615 {
00616     /* identifiers */
00617     ot->name= "Copy Driver";
00618     ot->idname= "ANIM_OT_copy_driver_button";
00619     ot->description= "Copy the driver for the highlighted button";
00620     
00621     /* callbacks */
00622     ot->exec= copy_driver_button_exec; 
00623     //op->poll= ??? // TODO: need to have some driver to be able to do this...
00624     
00625     /* flags */
00626     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00627 }
00628 
00629 /* Paste Driver Button Operator ------------------------ */
00630 
00631 static int paste_driver_button_exec (bContext *C, wmOperator *op)
00632 {
00633     PointerRNA ptr= {{NULL}};
00634     PropertyRNA *prop= NULL;
00635     short success= 0;
00636     int index;
00637     
00638     /* try to create driver using property retrieved from UI */
00639     uiContextActiveProperty(C, &ptr, &prop, &index);
00640     
00641     if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
00642         char *path= get_driver_path_hack(C, &ptr, prop);
00643         
00644         if (path) {
00645             /* only copy the driver for the button that this was involved for */
00646             success= ANIM_paste_driver(op->reports, ptr.id.data, path, index, 0);
00647             
00648             uiContextAnimUpdate(C);
00649             
00650             MEM_freeN(path);
00651         }
00652     }
00653     
00654     /* since we're just copying, we don't really need to do anything else...*/
00655     return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
00656 }
00657 
00658 void ANIM_OT_paste_driver_button (wmOperatorType *ot)
00659 {
00660     /* identifiers */
00661     ot->name= "Paste Driver";
00662     ot->idname= "ANIM_OT_paste_driver_button";
00663     ot->description= "Paste the driver in the copy/paste buffer for the highlighted button";
00664     
00665     /* callbacks */
00666     ot->exec= paste_driver_button_exec; 
00667     //op->poll= ??? // TODO: need to have some driver to be able to do this...
00668     
00669     /* flags */
00670     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00671 }
00672 
00673 /* ************************************************** */