|
Blender
V2.59
|
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 /* ************************************************** */