1edd43d4e01eed6af7dc992906c12314ae04613d
[blender.git] / source / blender / editors / interface / interface_anim.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  * Contributor(s):
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/editors/interface/interface_anim.c
24  *  \ingroup edinterface
25  */
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "MEM_guardedalloc.h"
32
33 #include "DNA_anim_types.h"
34 #include "DNA_scene_types.h"
35 #include "DNA_screen_types.h"
36
37 #include "BLI_listbase.h"
38 #include "BLI_string.h"
39 #include "BLI_string_utf8.h"
40 #include "BLI_utildefines.h"
41
42 #include "BKE_context.h"
43 #include "BKE_animsys.h"
44 #include "BKE_fcurve.h"
45 #include "BKE_global.h"
46
47 #include "ED_keyframing.h"
48
49 #include "UI_interface.h"
50
51 #include "RNA_access.h"
52
53 #include "WM_api.h"
54 #include "WM_types.h"
55
56 #include "interface_intern.h"
57
58 static FCurve *ui_but_get_fcurve(uiBut *but, bAction **action, int *driven)
59 {
60         return rna_get_fcurve(&but->rnapoin, but->rnaprop, but->rnaindex, action, driven);
61 }
62
63 void ui_but_anim_flag(uiBut *but, float cfra)
64 {
65         FCurve *fcu;
66         int driven;
67
68         but->flag &= ~(UI_BUT_ANIMATED|UI_BUT_ANIMATED_KEY|UI_BUT_DRIVEN);
69
70         fcu= ui_but_get_fcurve(but, NULL, &driven);
71
72         if(fcu) {
73                 if(!driven) {
74                         but->flag |= UI_BUT_ANIMATED;
75                         
76                         if(fcurve_frame_has_keyframe(fcu, cfra, 0))
77                                 but->flag |= UI_BUT_ANIMATED_KEY;
78                 }
79                 else {
80                         but->flag |= UI_BUT_DRIVEN;
81                 }
82         }
83 }
84
85 int ui_but_anim_expression_get(uiBut *but, char *str, size_t maxlen)
86 {
87         FCurve *fcu;
88         ChannelDriver *driver;
89         int driven;
90
91         fcu= ui_but_get_fcurve(but, NULL, &driven);
92
93         if(fcu && driven) {
94                 driver= fcu->driver;
95
96                 if(driver && driver->type == DRIVER_TYPE_PYTHON) {
97                         BLI_strncpy(str, driver->expression, maxlen);
98                         return 1;
99                 }
100         }
101
102         return 0;
103 }
104
105 int ui_but_anim_expression_set(uiBut *but, const char *str)
106 {
107         FCurve *fcu;
108         ChannelDriver *driver;
109         int driven;
110
111         fcu= ui_but_get_fcurve(but, NULL, &driven);
112
113         if(fcu && driven) {
114                 driver= fcu->driver;
115                 
116                 if(driver && driver->type == DRIVER_TYPE_PYTHON) {
117                         BLI_strncpy_utf8(driver->expression, str, sizeof(driver->expression));
118                         driver->flag |= DRIVER_FLAG_RECOMPILE;
119                         WM_event_add_notifier(but->block->evil_C, NC_ANIMATION|ND_KEYFRAME, NULL);
120                         return 1;
121                 }
122         }
123
124         return 0;
125 }
126
127 /* create new expression for button (i.e. a "scripted driver"), if it can be created... */
128 int ui_but_anim_expression_create(uiBut *but, const char *str)
129 {
130         bContext *C = but->block->evil_C;
131         ID *id;
132         FCurve *fcu;
133         char *path;
134         short ok=0;
135         
136         /* button must have RNA-pointer to a numeric-capable property */
137         if (ELEM(NULL, but->rnapoin.data, but->rnaprop)) {
138                 if (G.f & G_DEBUG) 
139                         printf("ERROR: create expression failed - button has no RNA info attached\n");
140                 return 0;
141         }
142         
143         /* make sure we have animdata for this */
144         // FIXME: until materials can be handled by depsgraph, don't allow drivers to be created for them
145         id = (ID *)but->rnapoin.id.data;
146         if ((id == NULL) || (GS(id->name)==ID_MA) || (GS(id->name)==ID_TE)) {
147                 if (G.f & G_DEBUG)
148                         printf("ERROR: create expression failed - invalid id-datablock for adding drivers (%p)\n", id);
149                 return 0;
150         }
151         
152         /* get path */
153         path = RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop);
154         
155         /* create driver */
156         fcu = verify_driver_fcurve(id, path, but->rnaindex, 1);
157         if (fcu) {
158                 ChannelDriver *driver= fcu->driver;
159                 
160                 if (driver) {
161                         /* set type of driver */
162                         driver->type = DRIVER_TYPE_PYTHON;
163                         
164                         /* set the expression */
165                         // TODO: need some way of identifying variables used
166                         BLI_strncpy_utf8(driver->expression, str, sizeof(driver->expression));
167                         
168                         /* FIXME: for now, assume that 
169                          *      - for expressions, users are likely to be using "frame" -> current frame" as a variable
170                          *      - driver_add_new_variable() adds a single-prop variable by default
171                          */
172                         {
173                                 DriverVar *dvar;
174                                 DriverTarget *dtar;
175                                 
176                                 dvar = driver_add_new_variable(driver);
177                                 BLI_strncpy(dvar->name, "frame", sizeof(dvar->name));
178                                 
179                                 dtar = &dvar->targets[0];
180                                 dtar->id = (ID *)CTX_data_scene(C); // XXX: should we check that C is valid first?
181                                 dtar->idtype= ID_SCE;
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 }