svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r20855:20928
[blender-staging.git] / source / blender / editors / animation / drivers.c
1 /* Testing code for 2.5 animation system 
2  * Copyright 2009, Joshua Leung
3  */
4  
5 #include <stdio.h>
6 #include <stddef.h>
7 #include <string.h>
8 #include <math.h>
9 #include <float.h>
10
11 #include "MEM_guardedalloc.h"
12
13 #include "BLI_blenlib.h"
14 #include "BLI_arithb.h"
15 #include "BLI_dynstr.h"
16
17 #include "DNA_anim_types.h"
18 #include "DNA_action_types.h"
19 #include "DNA_armature_types.h"
20 #include "DNA_constraint_types.h"
21 #include "DNA_key_types.h"
22 #include "DNA_object_types.h"
23 #include "DNA_material_types.h"
24 #include "DNA_scene_types.h"
25 #include "DNA_userdef_types.h"
26 #include "DNA_windowmanager_types.h"
27
28 #include "BKE_animsys.h"
29 #include "BKE_action.h"
30 #include "BKE_constraint.h"
31 #include "BKE_fcurve.h"
32 #include "BKE_utildefines.h"
33 #include "BKE_context.h"
34 #include "BKE_report.h"
35 #include "BKE_key.h"
36 #include "BKE_material.h"
37
38 #include "ED_anim_api.h"
39 #include "ED_keyframing.h"
40 #include "ED_keyframes_edit.h"
41 #include "ED_screen.h"
42 #include "ED_util.h"
43
44 #include "UI_interface.h"
45
46 #include "WM_api.h"
47 #include "WM_types.h"
48
49 #include "RNA_access.h"
50 #include "RNA_define.h"
51 #include "RNA_types.h"
52
53 /* ************************************************** */
54 /* Animation Data Validation */
55
56 /* Get (or add relevant data to be able to do so) F-Curve from the driver stack, 
57  * for the given Animation Data block. This assumes that all the destinations are valid.
58  */
59 FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_index, short add)
60 {
61         AnimData *adt;
62         FCurve *fcu;
63         
64         /* sanity checks */
65         if ELEM(NULL, id, rna_path)
66                 return NULL;
67         
68         /* init animdata if none available yet */
69         adt= BKE_animdata_from_id(id);
70         if ((adt == NULL) && (add))
71                 adt= BKE_id_add_animdata(id);
72         if (adt == NULL) { 
73                 /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
74                 return NULL;
75         }
76                 
77         /* try to find f-curve matching for this setting 
78          *      - add if not found and allowed to add one
79          *              TODO: add auto-grouping support? how this works will need to be resolved
80          */
81         fcu= list_find_fcurve(&adt->drivers, rna_path, array_index);
82         
83         if ((fcu == NULL) && (add)) {
84                 /* use default settings to make a F-Curve */
85                 fcu= MEM_callocN(sizeof(FCurve), "FCurve");
86                 
87                 fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
88                 
89                 /* store path - make copy, and store that */
90                 fcu->rna_path= BLI_strdupn(rna_path, strlen(rna_path));
91                 fcu->array_index= array_index;
92                 
93                 /* add some new driver data */
94                 fcu->driver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
95                 
96                 /* add simple generator modifier for driver so that there is some visible representation */
97                 fcurve_add_modifier(fcu, FMODIFIER_TYPE_GENERATOR);
98                 
99                 /* just add F-Curve to end of driver list */
100                 BLI_addtail(&adt->drivers, fcu);
101         }
102         
103         /* return the F-Curve */
104         return fcu;
105 }
106
107 /* ************************************************** */
108 /* Driver Management API */
109
110 /* Main Driver Management API calls:
111  *      Add a new driver for the specified property on the given ID block
112  */
113 short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short flag)
114 {       
115         PointerRNA id_ptr, ptr;
116         PropertyRNA *prop;
117         FCurve *fcu;
118         
119         /* validate pointer first - exit if failure */
120         RNA_id_pointer_create(id, &id_ptr);
121         if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) {
122                 printf("Insert Key: Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path);
123                 return 0;
124         }
125         
126         /* create F-Curve with Driver */
127         fcu= verify_driver_fcurve(id, rna_path, array_index, 1);
128         
129         /* done */
130         return (fcu != NULL);
131 }
132
133 /* Main Driver Management API calls:
134  *      Remove the driver for the specified property on the given ID block (if available)
135  */
136 short ANIM_remove_driver (struct ID *id, const char rna_path[], int array_index, short flag)
137 {
138         AnimData *adt;
139         FCurve *fcu;
140         
141         /* get F-Curve
142          * Note: here is one of the places where we don't want new F-Curve + Driver added!
143          *              so 'add' var must be 0
144          */
145         /* we don't check the validity of the path here yet, but it should be ok... */
146         fcu= verify_driver_fcurve(id, rna_path, array_index, 0);
147         adt= BKE_animdata_from_id(id);
148         
149         /* only continue if we have an driver to remove */
150         if (adt && fcu) {
151                 /* remove F-Curve from driver stack, then free it */
152                 BLI_remlink(&adt->drivers, fcu);
153                 free_fcurve(fcu);
154                 
155                 /* done successfully */
156                 return 1;
157         }
158         
159         /* failed */
160         return 0;
161 }
162
163
164 /* ************************************************** */
165 /* UI-Button Interface */
166
167 /* Add Driver Button Operator ------------------------ */
168
169 static int add_driver_button_exec (bContext *C, wmOperator *op)
170 {
171         PointerRNA ptr;
172         PropertyRNA *prop= NULL;
173         char *path;
174         short success= 0;
175         int a, index, length, all= RNA_boolean_get(op->ptr, "all");
176         
177         /* try to insert keyframe using property retrieved from UI */
178         memset(&ptr, 0, sizeof(PointerRNA));
179         uiAnimContextProperty(C, &ptr, &prop, &index);
180         
181         if (ptr.data && prop && RNA_property_animateable(ptr.data, prop)) {
182                 path= RNA_path_from_ID_to_property(&ptr, prop);
183                 
184                 if (path) {
185                         if (all) {
186                                 length= RNA_property_array_length(prop);
187                                 
188                                 if (length) index= 0;
189                                 else length= 1;
190                         }
191                         else
192                                 length= 1;
193                         
194                         for (a=0; a<length; a++)
195                                 success+= ANIM_add_driver(ptr.id.data, path, index+a, 0);
196                         
197                         MEM_freeN(path);
198                 }
199         }
200         
201         if (success) {
202                 /* send updates */
203                 ED_anim_dag_flush_update(C);    
204                 
205                 /* for now, only send ND_KEYS for KeyingSets */
206                 WM_event_add_notifier(C, ND_KEYS, NULL); // XXX
207         }
208         
209         return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
210 }
211
212 void ANIM_OT_add_driver_button (wmOperatorType *ot)
213 {
214         /* identifiers */
215         ot->name= "Add Driver";
216         ot->idname= "ANIM_OT_add_driver_button";
217         
218         /* callbacks */
219         ot->exec= add_driver_button_exec; 
220         //op->poll= ???
221         
222         /* flags */
223         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
224
225         /* properties */
226         RNA_def_boolean(ot->srna, "all", 1, "All", "Insert a keyframe for all element of the array.");
227 }
228
229 /* Remove Driver Button Operator ------------------------ */
230
231 static int remove_driver_button_exec (bContext *C, wmOperator *op)
232 {
233         PointerRNA ptr;
234         PropertyRNA *prop= NULL;
235         char *path;
236         short success= 0;
237         int a, index, length, all= RNA_boolean_get(op->ptr, "all");
238         
239         /* try to insert keyframe using property retrieved from UI */
240         memset(&ptr, 0, sizeof(PointerRNA));
241         uiAnimContextProperty(C, &ptr, &prop, &index);
242
243         if (ptr.data && prop) {
244                 path= RNA_path_from_ID_to_property(&ptr, prop);
245                 
246                 if (path) {
247                         if (all) {
248                                 length= RNA_property_array_length(prop);
249                                 
250                                 if(length) index= 0;
251                                 else length= 1;
252                         }
253                         else
254                                 length= 1;
255                         
256                         for (a=0; a<length; a++)
257                                 success+= ANIM_remove_driver(ptr.id.data, path, index+a, 0);
258                         
259                         MEM_freeN(path);
260                 }
261         }
262         
263         
264         if (success) {
265                 /* send updates */
266                 ED_anim_dag_flush_update(C);    
267                 
268                 /* for now, only send ND_KEYS for KeyingSets */
269                 WM_event_add_notifier(C, ND_KEYS, NULL);  // XXX
270         }
271         
272         return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
273 }
274
275 void ANIM_OT_remove_driver_button (wmOperatorType *ot)
276 {
277         /* identifiers */
278         ot->name= "Remove Driver";
279         ot->idname= "ANIM_OT_remove_driver_button";
280         
281         /* callbacks */
282         ot->exec= remove_driver_button_exec; 
283         //op->poll= ???
284         
285         /* flags */
286         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
287
288         /* properties */
289         RNA_def_boolean(ot->srna, "all", 1, "All", "Delete keyfames from all elements of the array.");
290 }
291
292 /* ************************************************** */