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