whitespace edits for bpy api, split some really long lines.
[blender-staging.git] / source / blender / python / intern / bpy_rna_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): Campbell Barton
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 /** \file blender/python/intern/bpy_rna_anim.c
26  *  \ingroup pythonintern
27  */
28
29 #include <Python.h>
30 #include <float.h> /* FLT_MIN/MAX */
31
32 #include "MEM_guardedalloc.h"
33
34 #include "BLI_string.h"
35
36 #include "DNA_scene_types.h"
37 #include "DNA_anim_types.h"
38 #include "ED_keyframing.h"
39
40 #include "BKE_report.h"
41 #include "BKE_context.h"
42 #include "BKE_animsys.h"
43 #include "BKE_fcurve.h"
44
45 #include "RNA_access.h"
46
47 #include "bpy_rna.h"
48 #include "bpy_util.h"
49 #include "bpy_rna_anim.h"
50
51 #define TRUE 1
52 #define FALSE 0
53
54 /* for keyframes and drivers */
55 static int pyrna_struct_anim_args_parse(PointerRNA *ptr, const char *error_prefix, const char *path,
56                                         const char **path_full, int *index)
57 {
58         const int is_idbase= RNA_struct_is_ID(ptr->type);
59         PropertyRNA *prop;
60         PointerRNA r_ptr;
61
62         if (ptr->data==NULL) {
63                 PyErr_Format(PyExc_TypeError,
64                              "%.200s this struct has no data, can't be animated",
65                              error_prefix);
66                 return -1;
67         }
68
69         /* full paths can only be given from ID base */
70         if(is_idbase) {
71                 int r_index= -1;
72                 if(RNA_path_resolve_full(ptr, path, &r_ptr, &prop, &r_index)==0) {
73                         prop= NULL;
74                 }
75                 else if(r_index != -1) {
76                         PyErr_Format(PyExc_ValueError,
77                                      "%.200s path includes index, must be a separate argument",
78                                      error_prefix, path);
79                         return -1;
80                 }
81                 else if(ptr->id.data != r_ptr.id.data) {
82                         PyErr_Format(PyExc_ValueError,
83                                      "%.200s path spans ID blocks",
84                                      error_prefix, path);
85                         return -1;
86                 }
87         }
88         else {
89                 prop= RNA_struct_find_property(ptr, path);
90                 r_ptr= *ptr;
91         }
92
93         if (prop==NULL) {
94                 PyErr_Format(PyExc_TypeError,
95                              "%.200s property \"%s\" not found",
96                              error_prefix, path);
97                 return -1;
98         }
99
100         if (!RNA_property_animateable(&r_ptr, prop)) {
101                 PyErr_Format(PyExc_TypeError,
102                              "%.200s property \"%s\" not animatable",
103                              error_prefix, path);
104                 return -1;
105         }
106
107         if(RNA_property_array_check(&r_ptr, prop) == 0) {
108                 if((*index) == -1) {
109                         *index= 0;
110                 }
111                 else {
112                         PyErr_Format(PyExc_TypeError,
113                                      "%.200s index %d was given while property \"%s\" is not an array",
114                                      error_prefix, *index, path);
115                         return -1;
116                 }
117         }
118         else {
119                 int array_len= RNA_property_array_length(&r_ptr, prop);
120                 if((*index) < -1 || (*index) >= array_len) {
121                         PyErr_Format(PyExc_TypeError,
122                                      "%.200s index out of range \"%s\", given %d, array length is %d",
123                                      error_prefix, path, *index, array_len);
124                         return -1;
125                 }
126         }
127
128         if(is_idbase) {
129                 *path_full= BLI_strdup(path);
130         }
131         else {
132                 *path_full= RNA_path_from_ID_to_property(&r_ptr, prop);
133
134                 if (*path_full==NULL) {
135                         PyErr_Format(PyExc_TypeError,
136                                      "%.200s could not make path to \"%s\"",
137                                      error_prefix, path);
138                         return -1;
139                 }
140         }
141
142         return 0;
143 }
144
145 /* internal use for insert and delete */
146 static int pyrna_struct_keyframe_parse(PointerRNA *ptr, PyObject *args, PyObject *kw, const char *parse_str, const char *error_prefix,
147                                        const char **path_full, int *index, float *cfra, const char **group_name) /* return values */
148 {
149         static const char *kwlist[]= {"data_path", "index", "frame", "group", NULL};
150         const char *path;
151
152         /* note, parse_str MUST start with 's|ifs' */
153         if (!PyArg_ParseTupleAndKeywords(args, kw, parse_str, (char **)kwlist, &path, index, cfra, group_name))
154                 return -1;
155
156         if(pyrna_struct_anim_args_parse(ptr, error_prefix, path, path_full, index) < 0)
157                 return -1;
158
159         if(*cfra==FLT_MAX)
160                 *cfra= CTX_data_scene(BPy_GetContext())->r.cfra;
161
162         return 0; /* success */
163 }
164
165 char pyrna_struct_keyframe_insert_doc[] =
166 ".. method:: keyframe_insert(data_path, index=-1, frame=bpy.context.scene.frame_current, group=\"\")\n"
167 "\n"
168 "   Insert a keyframe on the property given, adding fcurves and animation data when necessary.\n"
169 "\n"
170 "   :arg data_path: path to the property to key, analogous to the fcurve's data path.\n"
171 "   :type data_path: string\n"
172 "   :arg index: array index of the property to key. Defaults to -1 which will key all indices or a single channel if the property is not an array.\n"
173 "   :type index: int\n"
174 "   :arg frame: The frame on which the keyframe is inserted, defaulting to the current frame.\n"
175 "   :type frame: float\n"
176 "   :arg group: The name of the group the F-Curve should be added to if it doesn't exist yet.\n"
177 "   :type group: str\n"
178 "   :return: Success of keyframe insertion.\n"
179 "   :rtype: boolean\n"
180 ;
181 PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyObject *kw)
182 {
183         /* args, pyrna_struct_keyframe_parse handles these */
184         const char *path_full= NULL;
185         int index= -1;
186         float cfra= FLT_MAX;
187         const char *group_name= NULL;
188
189         PYRNA_STRUCT_CHECK_OBJ(self)
190
191         if(pyrna_struct_keyframe_parse(&self->ptr, args, kw,
192                                        "s|ifs:bpy_struct.keyframe_insert()", "bpy_struct.keyframe_insert()",
193                                        &path_full, &index, &cfra, &group_name) == -1)
194         {
195                 return NULL;
196         }
197         else {
198                 short result;
199                 ReportList reports;
200
201                 BKE_reports_init(&reports, RPT_STORE);
202
203                 result= insert_keyframe(&reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0);
204                 MEM_freeN((void *)path_full);
205
206                 if(BPy_reports_to_error(&reports, PyExc_RuntimeError, TRUE) == -1)
207                         return NULL;
208
209                 return PyBool_FromLong(result);
210         }
211 }
212
213 char pyrna_struct_keyframe_delete_doc[] =
214 ".. method:: keyframe_delete(data_path, index=-1, frame=bpy.context.scene.frame_current, group=\"\")\n"
215 "\n"
216 "   Remove a keyframe from this properties fcurve.\n"
217 "\n"
218 "   :arg data_path: path to the property to remove a key, analogous to the fcurve's data path.\n"
219 "   :type data_path: string\n"
220 "   :arg index: array index of the property to remove a key. Defaults to -1 removing all indices or a single channel if the property is not an array.\n"
221 "   :type index: int\n"
222 "   :arg frame: The frame on which the keyframe is deleted, defaulting to the current frame.\n"
223 "   :type frame: float\n"
224 "   :arg group: The name of the group the F-Curve should be added to if it doesn't exist yet.\n"
225 "   :type group: str\n"
226 "   :return: Success of keyframe deleation.\n"
227 "   :rtype: boolean\n"
228 ;
229 PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyObject *kw)
230 {
231         /* args, pyrna_struct_keyframe_parse handles these */
232         const char *path_full= NULL;
233         int index= -1;
234         float cfra= FLT_MAX;
235         const char *group_name= NULL;
236
237         PYRNA_STRUCT_CHECK_OBJ(self)
238
239         if(pyrna_struct_keyframe_parse(&self->ptr, args, kw,
240                                        "s|ifs:bpy_struct.keyframe_delete()",
241                                        "bpy_struct.keyframe_insert()",
242                                        &path_full, &index, &cfra, &group_name) == -1)
243         {
244                 return NULL;
245         }
246         else {
247                 short result;
248                 ReportList reports;
249
250                 BKE_reports_init(&reports, RPT_STORE);
251
252                 result= delete_keyframe(&reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0);
253                 MEM_freeN((void *)path_full);
254
255                 if(BPy_reports_to_error(&reports, PyExc_RuntimeError, TRUE) == -1)
256                         return NULL;
257
258                 return PyBool_FromLong(result);
259         }
260
261 }
262
263 char pyrna_struct_driver_add_doc[] =
264 ".. method:: driver_add(path, index=-1)\n"
265 "\n"
266 "   Adds driver(s) to the given property\n"
267 "\n"
268 "   :arg path: path to the property to drive, analogous to the fcurve's data path.\n"
269 "   :type path: string\n"
270 "   :arg index: array index of the property drive. Defaults to -1 for all indices or a single channel if the property is not an array.\n"
271 "   :type index: int\n"
272 "   :return: The driver(s) added.\n"
273 "   :rtype: :class:`FCurve` or list if index is -1 with an array property.\n"
274 ;
275 PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args)
276 {
277         const char *path, *path_full;
278         int index= -1;
279
280         PYRNA_STRUCT_CHECK_OBJ(self)
281
282         if (!PyArg_ParseTuple(args, "s|i:driver_add", &path, &index))
283                 return NULL;
284
285         if(pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_add():", path, &path_full, &index) < 0) {
286                 return NULL;
287         }
288         else {
289                 PyObject *ret= NULL;
290                 ReportList reports;
291                 int result;
292
293                 BKE_reports_init(&reports, RPT_STORE);
294
295                 result= ANIM_add_driver(&reports, (ID *)self->ptr.id.data, path_full, index, 0, DRIVER_TYPE_PYTHON);
296
297                 if(BPy_reports_to_error(&reports, PyExc_RuntimeError, TRUE) == -1)
298                         return NULL;
299
300                 if(result) {
301                         ID *id= self->ptr.id.data;
302                         AnimData *adt= BKE_animdata_from_id(id);
303                         FCurve *fcu;
304
305                         PointerRNA tptr;
306                         PyObject *item;
307
308                         if(index == -1) { /* all, use a list */
309                                 int i= 0;
310                                 ret= PyList_New(0);
311                                 while((fcu= list_find_fcurve(&adt->drivers, path_full, i++))) {
312                                         RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr);
313                                         item= pyrna_struct_CreatePyObject(&tptr);
314                                         PyList_Append(ret, item);
315                                         Py_DECREF(item);
316                                 }
317                         }
318                         else {
319                                 fcu= list_find_fcurve(&adt->drivers, path_full, index);
320                                 RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr);
321                                 ret= pyrna_struct_CreatePyObject(&tptr);
322                         }
323                 }
324                 else {
325                         /* XXX, should be handled by reports, */
326                         PyErr_SetString(PyExc_TypeError, "bpy_struct.driver_add(): failed because of an internal error");
327                         return NULL;
328                 }
329
330                 MEM_freeN((void *)path_full);
331
332                 return ret;
333         }
334 }
335
336
337 char pyrna_struct_driver_remove_doc[] =
338 ".. method:: driver_remove(path, index=-1)\n"
339 "\n"
340 "   Remove driver(s) from the given property\n"
341 "\n"
342 "   :arg path: path to the property to drive, analogous to the fcurve's data path.\n"
343 "   :type path: string\n"
344 "   :arg index: array index of the property drive. Defaults to -1 for all indices or a single channel if the property is not an array.\n"
345 "   :type index: int\n"
346 "   :return: Success of driver removal.\n"
347 "   :rtype: boolean\n"
348 ;
349 PyObject *pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args)
350 {
351         const char *path, *path_full;
352         int index= -1;
353
354         PYRNA_STRUCT_CHECK_OBJ(self)
355
356         if (!PyArg_ParseTuple(args, "s|i:driver_remove", &path, &index))
357                 return NULL;
358
359         if(pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_remove():", path, &path_full, &index) < 0) {
360                 return NULL;
361         }
362         else {
363                 short result;
364                 ReportList reports;
365
366                 BKE_reports_init(&reports, RPT_STORE);
367
368                 result= ANIM_remove_driver(&reports, (ID *)self->ptr.id.data, path_full, index, 0);
369
370                 MEM_freeN((void *)path_full);
371
372                 if(BPy_reports_to_error(&reports, PyExc_RuntimeError, TRUE) == -1)
373                         return NULL;
374
375                 return PyBool_FromLong(result);
376         }
377 }