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