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