Merging with trunk up to r38631.
[blender.git] / source / blender / editors / interface / interface_anim.c
1 /** \file blender/editors/interface/interface_anim.c
2  *  \ingroup edinterface
3  */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8
9 #include "MEM_guardedalloc.h"
10
11 #include "DNA_anim_types.h"
12 #include "DNA_scene_types.h"
13 #include "DNA_screen_types.h"
14
15 #include "BLI_listbase.h"
16 #include "BLI_string.h"
17 #include "BLI_utildefines.h"
18
19 #include "BKE_context.h"
20 #include "BKE_animsys.h"
21 #include "BKE_fcurve.h"
22 #include "BKE_global.h"
23
24 #include "ED_keyframing.h"
25
26 #include "UI_interface.h"
27
28 #include "RNA_access.h"
29
30 #include "WM_api.h"
31 #include "WM_types.h"
32
33 #include "interface_intern.h"
34
35 static FCurve *ui_but_get_fcurve(uiBut *but, bAction **action, int *driven)
36 {
37         return rna_get_fcurve(&but->rnapoin, but->rnaprop, but->rnaindex, action, driven);
38 }
39
40 void ui_but_anim_flag(uiBut *but, float cfra)
41 {
42         FCurve *fcu;
43         int driven;
44
45         but->flag &= ~(UI_BUT_ANIMATED|UI_BUT_ANIMATED_KEY|UI_BUT_DRIVEN);
46
47         fcu= ui_but_get_fcurve(but, NULL, &driven);
48
49         if(fcu) {
50                 if(!driven) {
51                         but->flag |= UI_BUT_ANIMATED;
52                         
53                         if(fcurve_frame_has_keyframe(fcu, cfra, 0))
54                                 but->flag |= UI_BUT_ANIMATED_KEY;
55                 }
56                 else {
57                         but->flag |= UI_BUT_DRIVEN;
58                 }
59         }
60 }
61
62 int ui_but_anim_expression_get(uiBut *but, char *str, int maxlen)
63 {
64         FCurve *fcu;
65         ChannelDriver *driver;
66         int driven;
67
68         fcu= ui_but_get_fcurve(but, NULL, &driven);
69
70         if(fcu && driven) {
71                 driver= fcu->driver;
72
73                 if(driver && driver->type == DRIVER_TYPE_PYTHON) {
74                         BLI_strncpy(str, driver->expression, maxlen);
75                         return 1;
76                 }
77         }
78
79         return 0;
80 }
81
82 int ui_but_anim_expression_set(uiBut *but, const char *str)
83 {
84         FCurve *fcu;
85         ChannelDriver *driver;
86         int driven;
87
88         fcu= ui_but_get_fcurve(but, NULL, &driven);
89
90         if(fcu && driven) {
91                 driver= fcu->driver;
92                 
93                 if(driver && driver->type == DRIVER_TYPE_PYTHON) {
94                         BLI_strncpy(driver->expression, str, sizeof(driver->expression));
95                         driver->flag |= DRIVER_FLAG_RECOMPILE;
96                         WM_event_add_notifier(but->block->evil_C, NC_ANIMATION|ND_KEYFRAME, NULL);
97                         return 1;
98                 }
99         }
100
101         return 0;
102 }
103
104 /* create new expression for button (i.e. a "scripted driver"), if it can be created... */
105 int ui_but_anim_expression_create(uiBut *but, const char *str)
106 {
107         bContext *C = but->block->evil_C;
108         ID *id;
109         FCurve *fcu;
110         char *path;
111         short ok=0;
112         
113         /* button must have RNA-pointer to a numeric-capable property */
114         if (ELEM(NULL, but->rnapoin.data, but->rnaprop)) {
115                 if (G.f & G_DEBUG) 
116                         printf("ERROR: create expression failed - button has no RNA info attached\n");
117                 return 0;
118         }
119         
120         /* make sure we have animdata for this */
121         // FIXME: until materials can be handled by depsgraph, don't allow drivers to be created for them
122         id = (ID *)but->rnapoin.id.data;
123         if ((id == NULL) || (GS(id->name)==ID_MA) || (GS(id->name)==ID_TE)) {
124                 if (G.f & G_DEBUG)
125                         printf("ERROR: create expression failed - invalid id-datablock for adding drivers (%p)\n", id);
126                 return 0;
127         }
128         
129         /* get path */
130         path = RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop);
131         
132         /* create driver */
133         fcu = verify_driver_fcurve(id, path, but->rnaindex, 1);
134         if (fcu) {
135                 ChannelDriver *driver= fcu->driver;
136                 
137                 if (driver) {
138                         /* set type of driver */
139                         driver->type = DRIVER_TYPE_PYTHON;
140                         
141                         /* set the expression */
142                         // TODO: need some way of identifying variables used
143                         BLI_strncpy(driver->expression, str, sizeof(driver->expression));
144                         
145                         /* FIXME: for now, assume that 
146                          *      - for expressions, users are likely to be using "frame" -> current frame" as a variable
147                          *      - driver_add_new_variable() adds a single-prop variable by default
148                          */
149                         {
150                                 DriverVar *dvar;
151                                 DriverTarget *dtar;
152                                 
153                                 dvar = driver_add_new_variable(driver);
154                                 BLI_strncpy(dvar->name, "frame", sizeof(dvar->name));
155                                 
156                                 dtar = &dvar->targets[0];
157                                 dtar->id = (ID *)CTX_data_scene(C); // XXX: should we check that C is valid first?
158                                 dtar->rna_path = BLI_sprintfN("frame_current");
159                         }
160                         
161                         /* updates */
162                         driver->flag |= DRIVER_FLAG_RECOMPILE;
163                         WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME, NULL);
164                 }
165         }
166         
167         MEM_freeN(path);
168         
169         return ok;
170 }
171
172 void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
173 {
174         ID *id;
175         bAction *action;
176         FCurve *fcu;
177         int driven;
178
179         fcu= ui_but_get_fcurve(but, &action, &driven);
180
181         if(fcu && !driven) {
182                 id= but->rnapoin.id.data;
183                 
184                 // TODO: this should probably respect the keyingset only option for anim
185                 if(autokeyframe_cfra_can_key(scene, id)) {
186                         ReportList *reports = CTX_wm_reports(C);
187                         short flag = ANIM_get_keyframing_flags(scene, 1);
188                         
189                         fcu->flag &= ~FCURVE_SELECTED;
190                         insert_keyframe(reports, id, action, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
191                         WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL);
192                 }
193         }
194 }
195
196 void ui_but_anim_insert_keyframe(bContext *C)
197 {
198         /* this operator calls uiContextActiveProperty */
199         WM_operator_name_call(C, "ANIM_OT_keyframe_insert_button", WM_OP_INVOKE_DEFAULT, NULL);
200 }
201
202 void ui_but_anim_delete_keyframe(bContext *C)
203 {
204         /* this operator calls uiContextActiveProperty */
205         WM_operator_name_call(C, "ANIM_OT_keyframe_delete_button", WM_OP_INVOKE_DEFAULT, NULL);
206 }
207
208 void ui_but_anim_add_driver(bContext *C)
209 {
210         /* this operator calls uiContextActiveProperty */
211         WM_operator_name_call(C, "ANIM_OT_driver_button_add", WM_OP_INVOKE_DEFAULT, NULL);
212 }
213
214 void ui_but_anim_remove_driver(bContext *C)
215 {
216         /* this operator calls uiContextActiveProperty */
217         WM_operator_name_call(C, "ANIM_OT_driver_button_remove", WM_OP_INVOKE_DEFAULT, NULL);
218 }
219
220 void ui_but_anim_copy_driver(bContext *C)
221 {
222         /* this operator calls uiContextActiveProperty */
223         WM_operator_name_call(C, "ANIM_OT_copy_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
224 }
225
226 void ui_but_anim_paste_driver(bContext *C)
227 {
228         /* this operator calls uiContextActiveProperty */
229         WM_operator_name_call(C, "ANIM_OT_paste_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
230 }
231
232 void ui_but_anim_add_keyingset(bContext *C)
233 {
234         /* this operator calls uiContextActiveProperty */
235         WM_operator_name_call(C, "ANIM_OT_keyingset_button_add", WM_OP_INVOKE_DEFAULT, NULL);
236 }
237
238 void ui_but_anim_remove_keyingset(bContext *C)
239 {
240         /* this operator calls uiContextActiveProperty */
241         WM_operator_name_call(C, "ANIM_OT_keyingset_button_remove", WM_OP_INVOKE_DEFAULT, NULL);
242 }