holding shift with cont. grab now works on the hsv cube and the value slider.
[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.debug & 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.debug & 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                         /* updates */
169                         driver->flag |= DRIVER_FLAG_RECOMPILE;
170                         WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME, NULL);
171                 }
172         }
173         
174         MEM_freeN(path);
175         
176         return ok;
177 }
178
179 void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
180 {
181         ID *id;
182         bAction *action;
183         FCurve *fcu;
184         int driven;
185
186         fcu = ui_but_get_fcurve(but, &action, &driven);
187
188         if (fcu && !driven) {
189                 id = but->rnapoin.id.data;
190
191                 /* TODO: this should probably respect the keyingset only option for anim */
192                 if (autokeyframe_cfra_can_key(scene, id)) {
193                         ReportList *reports = CTX_wm_reports(C);
194                         short flag = ANIM_get_keyframing_flags(scene, 1);
195
196                         fcu->flag &= ~FCURVE_SELECTED;
197                         insert_keyframe(reports, id, action, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
198                         WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
199                 }
200         }
201 }
202
203 void ui_but_anim_insert_keyframe(bContext *C)
204 {
205         /* this operator calls uiContextActiveProperty */
206         WM_operator_name_call(C, "ANIM_OT_keyframe_insert_button", WM_OP_INVOKE_DEFAULT, NULL);
207 }
208
209 void ui_but_anim_delete_keyframe(bContext *C)
210 {
211         /* this operator calls uiContextActiveProperty */
212         WM_operator_name_call(C, "ANIM_OT_keyframe_delete_button", WM_OP_INVOKE_DEFAULT, NULL);
213 }
214
215 void ui_but_anim_clear_keyframe(bContext *C)
216 {
217         /* this operator calls uiContextActiveProperty */
218         WM_operator_name_call(C, "ANIM_OT_keyframe_clear_button", WM_OP_INVOKE_DEFAULT, NULL);
219 }
220  void ui_but_anim_add_driver(bContext *C)
221 {
222         /* this operator calls uiContextActiveProperty */
223         WM_operator_name_call(C, "ANIM_OT_driver_button_add", WM_OP_INVOKE_DEFAULT, NULL);
224 }
225
226 void ui_but_anim_remove_driver(bContext *C)
227 {
228         /* this operator calls uiContextActiveProperty */
229         WM_operator_name_call(C, "ANIM_OT_driver_button_remove", WM_OP_INVOKE_DEFAULT, NULL);
230 }
231
232 void ui_but_anim_copy_driver(bContext *C)
233 {
234         /* this operator calls uiContextActiveProperty */
235         WM_operator_name_call(C, "ANIM_OT_copy_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
236 }
237
238 void ui_but_anim_paste_driver(bContext *C)
239 {
240         /* this operator calls uiContextActiveProperty */
241         WM_operator_name_call(C, "ANIM_OT_paste_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
242 }
243
244 void ui_but_anim_add_keyingset(bContext *C)
245 {
246         /* this operator calls uiContextActiveProperty */
247         WM_operator_name_call(C, "ANIM_OT_keyingset_button_add", WM_OP_INVOKE_DEFAULT, NULL);
248 }
249
250 void ui_but_anim_remove_keyingset(bContext *C)
251 {
252         /* this operator calls uiContextActiveProperty */
253         WM_operator_name_call(C, "ANIM_OT_keyingset_button_remove", WM_OP_INVOKE_DEFAULT, NULL);
254 }