Dopesheet: Keyframe size can be adjusted as part of theme settings
[blender.git] / source / blender / editors / animation / drivers.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Joshua Leung (full recode)
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/animation/drivers.c
29  *  \ingroup edanimation
30  */
31
32  
33 #include <stdio.h>
34 #include <string.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "BLI_blenlib.h"
39 #include "BLI_utildefines.h"
40 #include "BLI_string.h"
41
42 #include "DNA_anim_types.h"
43 #include "DNA_texture_types.h"
44
45 #include "BKE_animsys.h"
46 #include "BKE_depsgraph.h"
47 #include "BKE_fcurve.h"
48 #include "BKE_context.h"
49 #include "BKE_report.h"
50
51 #include "ED_keyframing.h"
52
53 #include "UI_interface.h"
54 #include "UI_resources.h"
55
56 #include "WM_api.h"
57 #include "WM_types.h"
58
59 #include "RNA_access.h"
60 #include "RNA_define.h"
61
62 #include "anim_intern.h"
63
64 /* ************************************************** */
65 /* Animation Data Validation */
66
67 /* Get (or add relevant data to be able to do so) F-Curve from the driver stack, 
68  * for the given Animation Data block. This assumes that all the destinations are valid.
69  *      
70  *      - add:  0 - don't add anything if not found, 
71  *                      1 - add new Driver FCurve (with keyframes for visual tweaking),
72  *                      2 - add new Driver FCurve (with generator, for script backwards compatibility)
73  *                      -1 - add new Driver FCurve without driver stuff (for pasting)
74  */
75 FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_index, short add)
76 {
77         AnimData *adt;
78         FCurve *fcu;
79         
80         /* sanity checks */
81         if (ELEM(NULL, id, rna_path))
82                 return NULL;
83         
84         /* init animdata if none available yet */
85         adt = BKE_animdata_from_id(id);
86         if ((adt == NULL) && (add))
87                 adt = BKE_animdata_add_id(id);
88         if (adt == NULL) {
89                 /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
90                 return NULL;
91         }
92                 
93         /* try to find f-curve matching for this setting 
94          *      - add if not found and allowed to add one
95          *              TODO: add auto-grouping support? how this works will need to be resolved
96          */
97         fcu = list_find_fcurve(&adt->drivers, rna_path, array_index);
98         
99         if ((fcu == NULL) && (add)) {
100                 /* use default settings to make a F-Curve */
101                 fcu = MEM_callocN(sizeof(FCurve), "FCurve");
102                 
103                 fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
104                 
105                 /* store path - make copy, and store that */
106                 fcu->rna_path = BLI_strdup(rna_path);
107                 fcu->array_index = array_index;
108                 
109                 /* if add is negative, don't init this data yet, since it will be filled in by the pasted driver */
110                 if (add > 0) {
111                         BezTriple *bezt;
112                         size_t i;
113                         
114                         /* add some new driver data */
115                         fcu->driver = MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
116                         fcu->driver->flag |= DRIVER_FLAG_SHOWDEBUG;
117                         
118                         /* F-Modifier or Keyframes? */
119                         // FIXME: replace these magic numbers with defines
120                         if (add == 2) {
121                                 /* Python API Backwards compatibility hack:
122                                  * Create FModifier so that old scripts won't break
123                                  * for now before 2.7 series -- (September 4, 2013)
124                                  */
125                                 add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR);
126                         }
127                         else {
128                                 /* add 2 keyframes so that user has something to work with 
129                                  * - These are configured to 0,0 and 1,1 to give a 1-1 mapping
130                                  *   which can be easily tweaked from there.
131                                  */
132                                 insert_vert_fcurve(fcu, 0.0f, 0.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
133                                 insert_vert_fcurve(fcu, 1.0f, 1.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
134                                 
135                                 /* configure this curve to extrapolate */
136                                 for (i = 0, bezt = fcu->bezt;  (i < fcu->totvert) && bezt;  i++, bezt++) {
137                                         bezt->h1 = bezt->h2 = HD_VECT;
138                                 }
139                                 
140                                 fcu->extend = FCURVE_EXTRAPOLATE_LINEAR;
141                                 calchandles_fcurve(fcu);
142                         }
143                 }
144                 
145                 /* just add F-Curve to end of driver list */
146                 BLI_addtail(&adt->drivers, fcu);
147         }
148         
149         /* return the F-Curve */
150         return fcu;
151 }
152
153 /* ************************************************** */
154 /* Driver Management API */
155
156 /* Helper for ANIM_add_driver_with_target - Adds the actual driver */
157 static int add_driver_with_target(
158         ReportList *UNUSED(reports),
159         ID *dst_id, const char dst_path[], int dst_index,
160         ID *src_id, const char src_path[], int src_index,
161         PointerRNA *dst_ptr, PropertyRNA *dst_prop,
162         PointerRNA *src_ptr, PropertyRNA *src_prop,
163         short flag, int driver_type)
164 {
165         FCurve *fcu;
166         short add_mode = (flag & CREATEDRIVER_WITH_FMODIFIER) ? 2 : 1;
167         const char *prop_name = RNA_property_identifier(src_prop);
168         
169         /* Create F-Curve with Driver */
170         fcu = verify_driver_fcurve(dst_id, dst_path, dst_index, add_mode);
171         
172         if (fcu && fcu->driver) {
173                 ChannelDriver *driver = fcu->driver;
174                 DriverVar *dvar;
175                 
176                 /* Set the type of the driver */
177                 driver->type = driver_type;
178                 
179                 /* Set driver expression, so that the driver works out of the box
180                  *
181                  * The following checks define a bit of "autodetection magic" we use
182                  * to ensure that the drivers will behave as expected out of the box
183                  * when faced with properties with different units.
184                  */
185                 /* XXX: if we have N-1 mapping, should we include all those in the expression? */
186                 if ((RNA_property_unit(dst_prop) == PROP_UNIT_ROTATION) && 
187                     (RNA_property_unit(src_prop) != PROP_UNIT_ROTATION))
188                 {
189                         /* Rotation Destination:  normal -> radians,  so convert src to radians
190                          * (However, if both input and output is a rotation, don't apply such corrections)
191                          */
192                         BLI_strncpy(driver->expression, "radians(var)", sizeof(driver->expression));
193                 }
194                 else if ((RNA_property_unit(src_prop) == PROP_UNIT_ROTATION) &&
195                          (RNA_property_unit(dst_prop) != PROP_UNIT_ROTATION))
196                 {
197                         /* Rotation Source:  radians -> normal,  so convert src to degrees
198                          * (However, if both input and output is a rotation, don't apply such corrections)
199                          */
200                         BLI_strncpy(driver->expression, "degrees(var)", sizeof(driver->expression));
201                 }
202                 else {
203                         /* Just a normal property without any unit problems */
204                         BLI_strncpy(driver->expression, "var", sizeof(driver->expression));
205                 }
206                 
207                 /* Create a driver variable for the target
208                  *   - For transform properties, we want to automatically use "transform channel" instead
209                  *     (The only issue is with quat rotations vs euler channels...)
210                  *   - To avoid problems with transform properties depending on the final transform that they
211                  *     control (thus creating pseudo-cycles - see T48734), we don't use transform channels
212                  *     when both the source and destinations are in same places.
213                  */
214                 dvar = driver_add_new_variable(driver);
215                 
216                 if (ELEM(src_ptr->type, &RNA_Object, &RNA_PoseBone) &&  
217                     (STREQ(prop_name, "location") || STREQ(prop_name, "scale") || STRPREFIX(prop_name, "rotation_")) &&
218                     (src_ptr->data != dst_ptr->data))
219                 {
220                         /* Transform Channel */
221                         DriverTarget *dtar;
222                         
223                         driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN);
224                         dtar = &dvar->targets[0];
225                         
226                         /* Bone or Object target? */
227                         dtar->id = src_id;
228                         dtar->idtype = GS(src_id->name);
229                         
230                         if (src_ptr->type == &RNA_PoseBone) {
231                                 RNA_string_get(src_ptr, "name", dtar->pchan_name);
232                         }
233                         
234                         /* Transform channel depends on type */
235                         if (STREQ(prop_name, "location")) {
236                                 if (src_index == 2)
237                                         dtar->transChan = DTAR_TRANSCHAN_LOCZ;
238                                 else if (src_index == 1)
239                                         dtar->transChan = DTAR_TRANSCHAN_LOCY;
240                                 else
241                                         dtar->transChan = DTAR_TRANSCHAN_LOCX;
242                         }
243                         else if (STREQ(prop_name, "scale")) {
244                                 if (src_index == 2)
245                                         dtar->transChan = DTAR_TRANSCHAN_SCALEZ;
246                                 else if (src_index == 1)
247                                         dtar->transChan = DTAR_TRANSCHAN_SCALEY;
248                                 else
249                                         dtar->transChan = DTAR_TRANSCHAN_SCALEX;
250                         }
251                         else {
252                                 /* XXX: With quaternions and axis-angle, this mapping might not be correct...
253                                  *      But since those have 4 elements instead, there's not much we can do
254                                  */
255                                 if (src_index == 2)
256                                         dtar->transChan = DTAR_TRANSCHAN_ROTZ;
257                                 else if (src_index == 1)
258                                         dtar->transChan = DTAR_TRANSCHAN_ROTY;
259                                 else
260                                         dtar->transChan = DTAR_TRANSCHAN_ROTX;
261                         }
262                 }
263                 else {
264                         /* Single RNA Property */
265                         DriverTarget *dtar = &dvar->targets[0];
266                         
267                         /* ID is as-is */
268                         dtar->id = src_id;
269                         dtar->idtype = GS(src_id->name);
270                         
271                         /* Need to make a copy of the path (or build one with array index built in) */
272                         if (RNA_property_array_check(src_prop)) {
273                                 dtar->rna_path = BLI_sprintfN("%s[%d]", src_path, src_index);
274                         }
275                         else {
276                                 dtar->rna_path = BLI_strdup(src_path);
277                         }
278                 }
279         }
280         
281         /* set the done status */
282         return (fcu != NULL);
283 }
284
285 /* Main Driver Management API calls:
286  *  Add a new driver for the specified property on the given ID block,
287  *  and make it be driven by the specified target.
288  *
289  * This is intended to be used in conjunction with a modal "eyedropper"
290  * for picking the variable that is going to be used to drive this one.
291  *
292  * - flag: eCreateDriverFlags
293  * - driver_type: eDriver_Types
294  * - mapping_type: eCreateDriver_MappingTypes
295  */
296 int ANIM_add_driver_with_target(
297         ReportList *reports, 
298         ID *dst_id, const char dst_path[], int dst_index,
299         ID *src_id, const char src_path[], int src_index,
300         short flag, int driver_type, short mapping_type)
301 {
302         PointerRNA id_ptr, ptr;
303         PropertyRNA *prop;
304         
305         PointerRNA id_ptr2, ptr2;
306         PropertyRNA *prop2;
307         int done_tot = 0;
308         
309         /* validate pointers first - exit if failure */
310         RNA_id_pointer_create(dst_id, &id_ptr);
311         if (RNA_path_resolve_property(&id_ptr, dst_path, &ptr, &prop) == false) {
312                 BKE_reportf(reports, RPT_ERROR, 
313                             "Could not add driver, as RNA path is invalid for the given ID (ID = %s, path = %s)",
314                             dst_id->name, dst_path);
315                 return 0;
316         }
317         
318         RNA_id_pointer_create(src_id, &id_ptr2);
319         if ((RNA_path_resolve_property(&id_ptr2, src_path, &ptr2, &prop2) == false) || 
320             (mapping_type == CREATEDRIVER_MAPPING_NONE))
321         {
322                 /* No target - So, fall back to default method for adding a "simple" driver normally */
323                 return ANIM_add_driver(reports, dst_id, dst_path, dst_index, flag | CREATEDRIVER_WITH_DEFAULT_DVAR, driver_type);
324         }
325         
326         /* handle curve-property mappings based on mapping_type */
327         switch (mapping_type) {
328                 case CREATEDRIVER_MAPPING_N_N: /* N-N - Try to match as much as possible, then use the first one */
329                 {
330                         /* Use the shorter of the two (to avoid out of bounds access) */
331                         int dst_len = (RNA_property_array_check(prop)) ? RNA_property_array_length(&ptr, prop) : 1;
332                         int src_len = (RNA_property_array_check(prop)) ? RNA_property_array_length(&ptr2, prop2) : 1;
333                         
334                         int len = MIN2(dst_len, src_len);
335                         int i;
336                         
337                         for (i = 0; i < len; i++) {
338                                 done_tot += add_driver_with_target(reports, dst_id, dst_path, i, src_id, src_path, i, &ptr, prop, &ptr2, prop2, flag, driver_type);
339                         }
340                         break;
341                 }
342                 
343                 case CREATEDRIVER_MAPPING_1_N: /* 1-N - Specified target index for all */
344                 default:
345                 {
346                         int len = (RNA_property_array_check(prop)) ? RNA_property_array_length(&ptr, prop) : 1;
347                         int i;
348                         
349                         for (i = 0; i < len; i++) {
350                                 done_tot += add_driver_with_target(reports, dst_id, dst_path, i, src_id, src_path, src_index, &ptr, prop, &ptr2, prop2, flag, driver_type);
351                         }
352                         break;
353                 }
354                 
355                 case CREATEDRIVER_MAPPING_1_1: /* 1-1 - Use the specified index (unless -1) */
356                 {
357                         done_tot = add_driver_with_target(reports, dst_id, dst_path, dst_index, src_id, src_path, src_index, &ptr, prop, &ptr2, prop2, flag, driver_type);
358                         break;
359                 }
360         }
361         
362         /* done */
363         return done_tot;
364 }
365
366 /* --------------------------------- */
367
368 /* Main Driver Management API calls:
369  *  Add a new driver for the specified property on the given ID block
370  */
371 int ANIM_add_driver(ReportList *reports, ID *id, const char rna_path[], int array_index, short flag, int type)
372 {       
373         PointerRNA id_ptr, ptr;
374         PropertyRNA *prop;
375         FCurve *fcu;
376         int array_index_max;
377         int done_tot = 0;
378         
379         /* validate pointer first - exit if failure */
380         RNA_id_pointer_create(id, &id_ptr);
381         if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
382                 BKE_reportf(reports, RPT_ERROR, 
383                             "Could not add driver, as RNA path is invalid for the given ID (ID = %s, path = %s)",
384                             id->name, rna_path);
385                 return 0;
386         }
387         
388         /* key entire array convenience method */
389         if (array_index == -1) {
390                 array_index_max = RNA_property_array_length(&ptr, prop);
391                 array_index = 0;
392         }
393         else
394                 array_index_max = array_index;
395         
396         /* maximum index should be greater than the start index */
397         if (array_index == array_index_max)
398                 array_index_max += 1;
399         
400         /* will only loop once unless the array index was -1 */
401         for (; array_index < array_index_max; array_index++) {
402                 short add_mode = (flag & CREATEDRIVER_WITH_FMODIFIER) ? 2 : 1;
403                 
404                 /* create F-Curve with Driver */
405                 fcu = verify_driver_fcurve(id, rna_path, array_index, add_mode);
406                 
407                 if (fcu && fcu->driver) {
408                         ChannelDriver *driver = fcu->driver;
409                         
410                         /* set the type of the driver */
411                         driver->type = type;
412                         
413                         /* creating drivers for buttons will create the driver(s) with type 
414                          * "scripted expression" so that their values won't be lost immediately,
415                          * so here we copy those values over to the driver's expression
416                          */
417                         if (type == DRIVER_TYPE_PYTHON) {
418                                 PropertyType proptype = RNA_property_type(prop);
419                                 int array = RNA_property_array_length(&ptr, prop);
420                                 char *expression = driver->expression;
421                                 int val, maxlen = sizeof(driver->expression);
422                                 float fval;
423                                 
424                                 if (proptype == PROP_BOOLEAN) {
425                                         if (!array) val = RNA_property_boolean_get(&ptr, prop);
426                                         else val = RNA_property_boolean_get_index(&ptr, prop, array_index);
427                                         
428                                         BLI_strncpy(expression, (val) ? "True" : "False", maxlen);
429                                 }
430                                 else if (proptype == PROP_INT) {
431                                         if (!array) val = RNA_property_int_get(&ptr, prop);
432                                         else val = RNA_property_int_get_index(&ptr, prop, array_index);
433                                         
434                                         BLI_snprintf(expression, maxlen, "%d", val);
435                                 }
436                                 else if (proptype == PROP_FLOAT) {
437                                         if (!array) fval = RNA_property_float_get(&ptr, prop);
438                                         else fval = RNA_property_float_get_index(&ptr, prop, array_index);
439                                         
440                                         BLI_snprintf(expression, maxlen, "%.3f", fval);
441                                 }
442                         }
443                         
444                         /* for easier setup of drivers from UI, a driver variable should be 
445                          * added if flag is set (UI calls only)
446                          */
447                         if (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) {
448                                 /* assume that users will mostly want this to be of type "Transform Channel" too,
449                                  * since this allows the easiest setting up of common rig components
450                                  */
451                                 DriverVar *dvar = driver_add_new_variable(driver);
452                                 driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN);
453                         }
454                 }
455                 
456                 /* set the done status */
457                 done_tot += (fcu != NULL);
458         }
459         
460         /* done */
461         return done_tot;
462 }
463
464 /* Main Driver Management API calls:
465  *  Remove the driver for the specified property on the given ID block (if available)
466  */
467 bool ANIM_remove_driver(ReportList *UNUSED(reports), ID *id, const char rna_path[], int array_index, short UNUSED(flag))
468 {
469         AnimData *adt;
470         FCurve *fcu;
471         bool success = false;
472         
473         /* we don't check the validity of the path here yet, but it should be ok... */
474         adt = BKE_animdata_from_id(id);
475         
476         if (adt) {
477                 if (array_index == -1) {
478                         /* step through all drivers, removing all of those with the same base path */
479                         FCurve *fcu_iter = adt->drivers.first;
480                         
481                         while ((fcu = iter_step_fcurve(fcu_iter, rna_path)) != NULL) {
482                                 /* store the next fcurve for looping  */
483                                 fcu_iter = fcu->next;
484                                 
485                                 /* remove F-Curve from driver stack, then free it */
486                                 BLI_remlink(&adt->drivers, fcu);
487                                 free_fcurve(fcu);
488                                 
489                                 /* done successfully */
490                                 success = true;
491                         }
492                 }
493                 else {
494                         /* find the matching driver and remove it only 
495                          * Note: here is one of the places where we don't want new F-Curve + Driver added!
496                          *      so 'add' var must be 0
497                          */
498                         fcu = verify_driver_fcurve(id, rna_path, array_index, 0);
499                         if (fcu) {
500                                 BLI_remlink(&adt->drivers, fcu);
501                                 free_fcurve(fcu);
502                                 
503                                 success = true;
504                         }
505                 }
506         }
507
508         return success;
509 }
510
511 /* ************************************************** */
512 /* Driver Management API - Copy/Paste Drivers */
513
514 /* Copy/Paste Buffer for Driver Data... */
515 static FCurve *channeldriver_copypaste_buf = NULL;
516
517 /* This function frees any MEM_calloc'ed copy/paste buffer data */
518 void ANIM_drivers_copybuf_free(void)
519 {
520         /* free the buffer F-Curve if it exists, as if it were just another F-Curve */
521         if (channeldriver_copypaste_buf)
522                 free_fcurve(channeldriver_copypaste_buf);
523         channeldriver_copypaste_buf = NULL;
524 }
525
526 /* Checks if there is a driver in the copy/paste buffer */
527 bool ANIM_driver_can_paste(void)
528 {
529         return (channeldriver_copypaste_buf != NULL);
530 }
531
532 /* ------------------- */
533
534 /* Main Driver Management API calls:
535  *  Make a copy of the driver for the specified property on the given ID block
536  */
537 bool ANIM_copy_driver(ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag))
538 {
539         PointerRNA id_ptr, ptr;
540         PropertyRNA *prop;
541         FCurve *fcu;
542         
543         /* validate pointer first - exit if failure */
544         RNA_id_pointer_create(id, &id_ptr);
545         if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
546                 BKE_reportf(reports, RPT_ERROR,
547                             "Could not find driver to copy, as RNA path is invalid for the given ID (ID = %s, path = %s)",
548                             id->name, rna_path);
549                 return 0;
550         }
551         
552         /* try to get F-Curve with Driver */
553         fcu = verify_driver_fcurve(id, rna_path, array_index, 0);
554         
555         /* clear copy/paste buffer first (for consistency with other copy/paste buffers) */
556         ANIM_drivers_copybuf_free();
557         
558         /* copy this to the copy/paste buf if it exists */
559         if (fcu && fcu->driver) {
560                 /* make copies of some info such as the rna_path, then clear this info from the F-Curve temporarily
561                  * so that we don't end up wasting memory storing the path which won't get used ever...
562                  */
563                 char *tmp_path = fcu->rna_path;
564                 fcu->rna_path = NULL;
565                 
566                 /* make a copy of the F-Curve with */
567                 channeldriver_copypaste_buf = copy_fcurve(fcu);
568                 
569                 /* restore the path */
570                 fcu->rna_path = tmp_path;
571                 
572                 /* copied... */
573                 return 1;
574         }
575         
576         /* done */
577         return 0;
578 }
579
580 /* Main Driver Management API calls:
581  *  Add a new driver for the specified property on the given ID block or replace an existing one
582  *      with the driver + driver-curve data from the buffer 
583  */
584 bool ANIM_paste_driver(ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag))
585 {       
586         PointerRNA id_ptr, ptr;
587         PropertyRNA *prop;
588         FCurve *fcu;
589         
590         /* validate pointer first - exit if failure */
591         RNA_id_pointer_create(id, &id_ptr);
592         if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
593                 BKE_reportf(reports, RPT_ERROR,
594                             "Could not paste driver, as RNA path is invalid for the given ID (ID = %s, path = %s)",
595                             id->name, rna_path);
596                 return 0;
597         }
598         
599         /* if the buffer is empty, cannot paste... */
600         if (channeldriver_copypaste_buf == NULL) {
601                 BKE_report(reports, RPT_ERROR, "Paste driver: no driver to paste");
602                 return 0;
603         }
604         
605         /* create Driver F-Curve, but without data which will be copied across... */
606         fcu = verify_driver_fcurve(id, rna_path, array_index, -1);
607         
608         if (fcu) {
609                 /* copy across the curve data from the buffer curve 
610                  * NOTE: this step needs care to not miss new settings
611                  */
612                 /* keyframes/samples */
613                 fcu->bezt = MEM_dupallocN(channeldriver_copypaste_buf->bezt);
614                 fcu->fpt = MEM_dupallocN(channeldriver_copypaste_buf->fpt);
615                 fcu->totvert = channeldriver_copypaste_buf->totvert;
616                 
617                 /* modifiers */
618                 copy_fmodifiers(&fcu->modifiers, &channeldriver_copypaste_buf->modifiers);
619                 
620                 /* extrapolation mode */
621                 fcu->extend = channeldriver_copypaste_buf->extend;
622                         
623                 /* the 'juicy' stuff - the driver */
624                 fcu->driver = fcurve_copy_driver(channeldriver_copypaste_buf->driver);
625         }
626         
627         /* done */
628         return (fcu != NULL);
629 }
630
631 /* ************************************************** */
632 /* Driver Management API - Copy/Paste Driver Variables */
633
634 /* Copy/Paste Buffer for Driver Variables... */
635 static ListBase driver_vars_copybuf = {NULL, NULL};
636
637 /* This function frees any MEM_calloc'ed copy/paste buffer data */
638 void ANIM_driver_vars_copybuf_free(void)
639 {
640         /* Free the driver variables kept in the buffer */
641         if (driver_vars_copybuf.first) {
642                 DriverVar *dvar, *dvarn;
643                 
644                 /* Free variables (and any data they use) */
645                 for (dvar = driver_vars_copybuf.first; dvar; dvar = dvarn) {
646                         dvarn = dvar->next;
647                         driver_free_variable(&driver_vars_copybuf, dvar);
648                 }
649         }
650         
651         BLI_listbase_clear(&driver_vars_copybuf);
652 }
653
654 /* Checks if there are driver variables in the copy/paste buffer */
655 bool ANIM_driver_vars_can_paste(void)
656 {
657         return (BLI_listbase_is_empty(&driver_vars_copybuf) == false);
658 }
659
660 /* -------------------------------------------------- */
661
662 /* Copy the given driver's variables to the buffer */
663 bool ANIM_driver_vars_copy(ReportList *reports, FCurve *fcu)
664 {
665         /* sanity checks */
666         if (ELEM(NULL, fcu, fcu->driver)) {
667                 BKE_report(reports, RPT_ERROR, "No driver to copy variables from");
668                 return false;
669         }
670         
671         if (BLI_listbase_is_empty(&fcu->driver->variables)) {
672                 BKE_report(reports, RPT_ERROR, "Driver has no variables to copy");
673                 return false;
674         }
675         
676         /* clear buffer */
677         ANIM_driver_vars_copybuf_free();
678         
679         /* copy over the variables */
680         driver_variables_copy(&driver_vars_copybuf, &fcu->driver->variables);
681         
682         return (BLI_listbase_is_empty(&driver_vars_copybuf) == false);
683 }
684
685 /* Paste the variables in the buffer to the given FCurve */
686 bool ANIM_driver_vars_paste(ReportList *reports, FCurve *fcu, bool replace)
687 {
688         ChannelDriver *driver = (fcu) ? fcu->driver : NULL;
689         ListBase tmp_list = {NULL, NULL};
690         
691         /* sanity checks */
692         if (BLI_listbase_is_empty(&driver_vars_copybuf)) {
693                 BKE_report(reports, RPT_ERROR, "No driver variables in clipboard to paste");
694                 return false;
695         }
696         
697         if (ELEM(NULL, fcu, fcu->driver)) {
698                 BKE_report(reports, RPT_ERROR, "Cannot paste driver variables without a driver");
699                 return false;
700         }
701         
702         /* 1) Make a new copy of the variables in the buffer - these will get pasted later... */
703         driver_variables_copy(&tmp_list, &driver_vars_copybuf);
704         
705         /* 2) Prepare destination array */
706         if (replace) {
707                 DriverVar *dvar, *dvarn;
708                 
709                 /* Free all existing vars first - We aren't retaining anything */
710                 for (dvar = driver->variables.first; dvar; dvar = dvarn) {
711                         dvarn = dvar->next;
712                         driver_free_variable_ex(driver, dvar);
713                 }
714                 
715                 BLI_listbase_clear(&driver->variables);
716         }
717         
718         /* 3) Add new vars */
719         if (driver->variables.last) {
720                 DriverVar *last = driver->variables.last;
721                 DriverVar *first = tmp_list.first;
722                 
723                 last->next = first;
724                 first->prev = last;
725                 
726                 driver->variables.last = tmp_list.last;
727         }
728         else {
729                 driver->variables.first = tmp_list.first;
730                 driver->variables.last = tmp_list.last;
731         }
732         
733 #ifdef WITH_PYTHON
734         /* since driver variables are cached, the expression needs re-compiling too */
735         if (driver->type == DRIVER_TYPE_PYTHON)
736                 driver->flag |= DRIVER_FLAG_RENAMEVAR;
737 #endif
738         
739         return true;
740 }
741
742 /* ************************************************** */
743 /* UI-Button Interface */
744
745 /* Add Driver - Enum Defines ------------------------- */
746
747 /* Mapping Types enum for operators */
748 /* NOTE: Used by ANIM_OT_driver_button_add and UI_OT_eyedropper_driver */
749 // XXX: These names need reviewing
750 EnumPropertyItem prop_driver_create_mapping_types[] = {
751         {CREATEDRIVER_MAPPING_1_N, "SINGLE_MANY", ICON_UI, "All from Target",
752          "Drive all components of this property using the target picked"},
753         {CREATEDRIVER_MAPPING_1_1, "DIRECT", 0, "Single from Target",
754          "Drive this component of this property using the target picked"},
755          
756         {CREATEDRIVER_MAPPING_N_N, "MATCH", ICON_COLOR, "Match Indices",
757          "Create drivers for each pair of corresponding elements"},
758          
759         {CREATEDRIVER_MAPPING_NONE_ALL, "NONE_ALL", ICON_HAND, "Manually Create Later",
760          "Create drivers for all properties without assigning any targets yet"},
761         {CREATEDRIVER_MAPPING_NONE,     "NONE_SINGLE", 0, "Manually Create Later (Single)",
762          "Create driver for this property only and without assigning any targets yet"},
763         {0, NULL, 0, NULL, NULL}
764 };
765
766 /* Filtering callback for driver mapping types enum */
767 static EnumPropertyItem *driver_mapping_type_itemsf(bContext *C, PointerRNA *UNUSED(owner_ptr), PropertyRNA *UNUSED(owner_prop), bool *r_free)
768 {
769         EnumPropertyItem *input = prop_driver_create_mapping_types;
770         EnumPropertyItem *item = NULL;
771         
772         PointerRNA ptr = {{NULL}};
773         PropertyRNA *prop = NULL;
774         int index;
775         
776         int totitem = 0;
777         
778         if (!C) /* needed for docs */
779                 return prop_driver_create_mapping_types;
780         
781         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
782         
783         if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
784                 const bool is_array = RNA_property_array_check(prop);
785                 
786                 while (input->identifier) {
787                         if (ELEM(input->value, CREATEDRIVER_MAPPING_1_1, CREATEDRIVER_MAPPING_NONE) || (is_array)) {
788                                 RNA_enum_item_add(&item, &totitem, input);
789                         }
790                         input++;
791                 }
792         }
793         else {
794                 /* We need at least this one! */
795                 RNA_enum_items_add_value(&item, &totitem, input, CREATEDRIVER_MAPPING_NONE);
796         }
797         
798         RNA_enum_item_end(&item, &totitem);
799         
800         *r_free = true;
801         return item;
802 }
803
804
805 /* Add Driver Button Operator ------------------------ */
806
807 static int add_driver_button_poll(bContext *C)
808 {
809         PointerRNA ptr = {{NULL}};
810         PropertyRNA *prop = NULL;
811         int index;
812         
813         /* this operator can only run if there's a property button active, and it can be animated */
814         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
815         return (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop));
816 }
817
818 /* Wrapper for creating a driver without knowing what the targets will be yet (i.e. "manual/add later") */
819 static int add_driver_button_none(bContext *C, wmOperator *op, short mapping_type)
820 {
821         PointerRNA ptr = {{NULL}};
822         PropertyRNA *prop = NULL;
823         int index;
824         int success = 0;
825         
826         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
827         
828         if (mapping_type == CREATEDRIVER_MAPPING_NONE_ALL)
829                 index = -1;
830         
831         if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
832                 char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
833                 short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
834                 
835                 if (path) {
836                         success += ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON);
837                         MEM_freeN(path);
838                 }
839         }
840         
841         if (success) {
842                 /* send updates */
843                 UI_context_update_anim_flag(C);
844                 DAG_relations_tag_update(CTX_data_main(C));
845                 WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL);  // XXX
846                 
847                 return OPERATOR_FINISHED;
848         }
849         else {
850                 return OPERATOR_CANCELLED;
851         }
852 }
853
854 static int add_driver_button_exec(bContext *C, wmOperator *op)
855 {
856         short mapping_type = RNA_enum_get(op->ptr, "mapping_type");
857         if (ELEM(mapping_type, CREATEDRIVER_MAPPING_NONE, CREATEDRIVER_MAPPING_NONE_ALL)) {
858                 /* Just create driver with no targets */
859                 return add_driver_button_none(C, op, mapping_type);
860         }
861         else {
862                 /* Create Driver using Eyedropper */
863                 wmOperatorType *ot = WM_operatortype_find("UI_OT_eyedropper_driver", true);
864                 
865                 /* XXX: We assume that it's fine to use the same set of properties, since they're actually the same... */
866                 WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, op->ptr);
867                 
868                 return OPERATOR_FINISHED;
869         }
870 }
871
872 /* Show menu or create drivers */
873 static int add_driver_button_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
874 {
875         PropertyRNA *prop;
876         
877         if ((prop = RNA_struct_find_property(op->ptr, "mapping_type")) && RNA_property_is_set(op->ptr, prop)) {
878                 /* Mapping Type is Set - Directly go into creating drivers */
879                 return add_driver_button_exec(C, op);
880         }
881         else {
882                 /* Show menu */
883                 // TODO: This should get filtered by the enum filter
884                 /* important to execute in the region we're currently in */
885                 return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_DEFAULT);
886         }
887 }
888
889 void ANIM_OT_driver_button_add(wmOperatorType *ot)
890 {
891         /* identifiers */
892         ot->name = "Add Driver";
893         ot->idname = "ANIM_OT_driver_button_add";
894         ot->description = "Add driver(s) for the property(s) represented by the highlighted button";
895         
896         /* callbacks */
897         /* NOTE: No exec, as we need all these to use the current context info
898          * (especially the eyedropper, which is interactive)
899          */
900         ot->invoke = add_driver_button_invoke;
901         ot->exec = add_driver_button_exec; 
902         ot->poll = add_driver_button_poll;
903         
904         /* flags */
905         ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
906         
907         /* properties */
908         ot->prop = RNA_def_enum(ot->srna, "mapping_type", prop_driver_create_mapping_types, 0,
909                                 "Mapping Type", "Method used to match target and driven properties");
910         RNA_def_enum_funcs(ot->prop, driver_mapping_type_itemsf);
911 }
912
913 /* Remove Driver Button Operator ------------------------ */
914
915 static int remove_driver_button_exec(bContext *C, wmOperator *op)
916 {
917         PointerRNA ptr = {{NULL}};
918         PropertyRNA *prop = NULL;
919         short success = 0;
920         int index;
921         const bool all = RNA_boolean_get(op->ptr, "all");
922         
923         /* try to find driver using property retrieved from UI */
924         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
925         
926         if (all)
927                 index = -1;
928         
929         if (ptr.id.data && ptr.data && prop) {
930                 char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
931                 
932                 if (path) {
933                         success = ANIM_remove_driver(op->reports, ptr.id.data, path, index, 0);
934
935                         MEM_freeN(path);
936                 }
937         }
938         
939         if (success) {
940                 /* send updates */
941                 UI_context_update_anim_flag(C);
942                 DAG_relations_tag_update(CTX_data_main(C));
943                 WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL);  // XXX
944         }
945         
946         return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
947 }
948
949 void ANIM_OT_driver_button_remove(wmOperatorType *ot)
950 {
951         /* identifiers */
952         ot->name = "Remove Driver";
953         ot->idname = "ANIM_OT_driver_button_remove";
954         ot->description = "Remove the driver(s) for the property(s) connected represented by the highlighted button";
955         
956         /* callbacks */
957         ot->exec = remove_driver_button_exec; 
958         //op->poll = ??? // TODO: need to have some driver to be able to do this...
959         
960         /* flags */
961         ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
962
963         /* properties */
964         RNA_def_boolean(ot->srna, "all", 1, "All", "Delete drivers for all elements of the array");
965 }
966
967 /* Copy Driver Button Operator ------------------------ */
968
969 static int copy_driver_button_exec(bContext *C, wmOperator *op)
970 {
971         PointerRNA ptr = {{NULL}};
972         PropertyRNA *prop = NULL;
973         short success = 0;
974         int index;
975         
976         /* try to create driver using property retrieved from UI */
977         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
978         
979         if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
980                 char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
981                 
982                 if (path) {
983                         /* only copy the driver for the button that this was involved for */
984                         success = ANIM_copy_driver(op->reports, ptr.id.data, path, index, 0);
985                         
986                         UI_context_update_anim_flag(C);
987                         
988                         MEM_freeN(path);
989                 }
990         }
991         
992         /* since we're just copying, we don't really need to do anything else...*/
993         return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
994 }
995
996 void ANIM_OT_copy_driver_button(wmOperatorType *ot)
997 {
998         /* identifiers */
999         ot->name = "Copy Driver";
1000         ot->idname = "ANIM_OT_copy_driver_button";
1001         ot->description = "Copy the driver for the highlighted button";
1002         
1003         /* callbacks */
1004         ot->exec = copy_driver_button_exec; 
1005         //op->poll = ??? // TODO: need to have some driver to be able to do this...
1006         
1007         /* flags */
1008         ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
1009 }
1010
1011 /* Paste Driver Button Operator ------------------------ */
1012
1013 static int paste_driver_button_exec(bContext *C, wmOperator *op)
1014 {
1015         PointerRNA ptr = {{NULL}};
1016         PropertyRNA *prop = NULL;
1017         short success = 0;
1018         int index;
1019         
1020         /* try to create driver using property retrieved from UI */
1021         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
1022         
1023         if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
1024                 char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
1025                 
1026                 if (path) {
1027                         /* only copy the driver for the button that this was involved for */
1028                         success = ANIM_paste_driver(op->reports, ptr.id.data, path, index, 0);
1029                         
1030                         UI_context_update_anim_flag(C);
1031                         
1032                         MEM_freeN(path);
1033                 }
1034         }
1035         
1036         /* since we're just copying, we don't really need to do anything else...*/
1037         return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
1038 }
1039
1040 void ANIM_OT_paste_driver_button(wmOperatorType *ot)
1041 {
1042         /* identifiers */
1043         ot->name = "Paste Driver";
1044         ot->idname = "ANIM_OT_paste_driver_button";
1045         ot->description = "Paste the driver in the copy/paste buffer for the highlighted button";
1046         
1047         /* callbacks */
1048         ot->exec = paste_driver_button_exec; 
1049         //op->poll = ??? // TODO: need to have some driver to be able to do this...
1050         
1051         /* flags */
1052         ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
1053 }
1054
1055 /* ************************************************** */