Cleanup: get rid of last G.main's in bpy area.
[blender.git] / source / blender / python / intern / bpy_rna_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): Campbell Barton
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/python/intern/bpy_rna_anim.c
24  *  \ingroup pythonintern
25  *
26  * This file defines the animation related methods used in bpy_rna.c
27  */
28
29 #include <Python.h>
30 #include <float.h> /* FLT_MAX */
31
32 #include "MEM_guardedalloc.h"
33
34 #include "BLI_utildefines.h"
35 #include "BLI_string.h"
36
37 #include "DNA_scene_types.h"
38 #include "DNA_anim_types.h"
39
40 #include "ED_keyframing.h"
41 #include "ED_keyframes_edit.h"
42
43 #include "BKE_animsys.h"
44 #include "BKE_context.h"
45 #include "BKE_fcurve.h"
46 #include "BKE_global.h"
47 #include "BKE_idcode.h"
48 #include "BKE_library.h"
49 #include "BKE_report.h"
50
51 #include "RNA_access.h"
52 #include "RNA_enum_types.h"
53
54 #include "WM_api.h"
55 #include "WM_types.h"
56
57 #include "bpy_rna.h"
58 #include "bpy_capi_utils.h"
59 #include "bpy_rna_anim.h"
60
61 #include "../generic/python_utildefines.h"
62
63 /* for keyframes and drivers */
64 static int pyrna_struct_anim_args_parse(
65         PointerRNA *ptr, const char *error_prefix, const char *path,
66         const char **path_full, int *index)
67 {
68         const bool is_idbase = RNA_struct_is_ID(ptr->type);
69         PropertyRNA *prop;
70         PointerRNA r_ptr;
71
72         if (ptr->data == NULL) {
73                 PyErr_Format(PyExc_TypeError,
74                              "%.200s this struct has no data, can't be animated",
75                              error_prefix);
76                 return -1;
77         }
78
79         /* full paths can only be given from ID base */
80         if (is_idbase) {
81                 int r_index = -1;
82                 if (RNA_path_resolve_property_full(ptr, path, &r_ptr, &prop, &r_index) == false) {
83                         prop = NULL;
84                 }
85                 else if (r_index != -1) {
86                         PyErr_Format(PyExc_ValueError,
87                                      "%.200s path includes index, must be a separate argument",
88                                      error_prefix, path);
89                         return -1;
90                 }
91                 else if (ptr->id.data != r_ptr.id.data) {
92                         PyErr_Format(PyExc_ValueError,
93                                      "%.200s path spans ID blocks",
94                                      error_prefix, path);
95                         return -1;
96                 }
97         }
98         else {
99                 prop = RNA_struct_find_property(ptr, path);
100                 r_ptr = *ptr;
101         }
102
103         if (prop == NULL) {
104                 PyErr_Format(PyExc_TypeError,
105                              "%.200s property \"%s\" not found",
106                              error_prefix, path);
107                 return -1;
108         }
109
110         if (!RNA_property_animateable(&r_ptr, prop)) {
111                 PyErr_Format(PyExc_TypeError,
112                              "%.200s property \"%s\" not animatable",
113                              error_prefix, path);
114                 return -1;
115         }
116
117         if (RNA_property_array_check(prop) == 0) {
118                 if ((*index) == -1) {
119                         *index = 0;
120                 }
121                 else {
122                         PyErr_Format(PyExc_TypeError,
123                                      "%.200s index %d was given while property \"%s\" is not an array",
124                                      error_prefix, *index, path);
125                         return -1;
126                 }
127         }
128         else {
129                 int array_len = RNA_property_array_length(&r_ptr, prop);
130                 if ((*index) < -1 || (*index) >= array_len) {
131                         PyErr_Format(PyExc_TypeError,
132                                      "%.200s index out of range \"%s\", given %d, array length is %d",
133                                      error_prefix, path, *index, array_len);
134                         return -1;
135                 }
136         }
137
138         if (is_idbase) {
139                 *path_full = BLI_strdup(path);
140         }
141         else {
142                 *path_full = RNA_path_from_ID_to_property(&r_ptr, prop);
143
144                 if (*path_full == NULL) {
145                         PyErr_Format(PyExc_TypeError,
146                                      "%.200s could not make path to \"%s\"",
147                                      error_prefix, path);
148                         return -1;
149                 }
150         }
151
152         return 0;
153 }
154
155 /* internal use for insert and delete */
156 static int pyrna_struct_keyframe_parse(
157         PointerRNA *ptr, PyObject *args, PyObject *kw, const char *parse_str, const char *error_prefix,
158         const char **path_full, int *index, float *cfra, const char **group_name, int *options)     /* return values */
159 {
160         static const char *kwlist[] = {"data_path", "index", "frame", "group", "options", NULL};
161         PyObject *pyoptions = NULL;
162         const char *path;
163
164         /* note, parse_str MUST start with 's|ifsO!' */
165         if (!PyArg_ParseTupleAndKeywords(args, kw, parse_str, (char **)kwlist, &path, index, cfra, group_name,
166                                          &PySet_Type, &pyoptions))
167         {
168                 return -1;
169         }
170
171         if (pyrna_struct_anim_args_parse(ptr, error_prefix, path, path_full, index) == -1)
172                 return -1;
173
174         if (*cfra == FLT_MAX)
175                 *cfra = CTX_data_scene(BPy_GetContext())->r.cfra;
176
177         /* flag may be null (no option currently for remove keyframes e.g.). */
178         if (options) {
179                 if (pyoptions && (pyrna_set_to_enum_bitfield(rna_enum_keying_flag_items, pyoptions, options, error_prefix) == -1)) {
180                         return -1;
181                 }
182
183                 *options |= INSERTKEY_NO_USERPREF;
184         }
185
186         return 0; /* success */
187 }
188
189 char pyrna_struct_keyframe_insert_doc[] =
190 ".. method:: keyframe_insert(data_path, index=-1, frame=bpy.context.scene.frame_current, group=\"\")\n"
191 "\n"
192 "   Insert a keyframe on the property given, adding fcurves and animation data when necessary.\n"
193 "\n"
194 "   :arg data_path: path to the property to key, analogous to the fcurve's data path.\n"
195 "   :type data_path: string\n"
196 "   :arg index: array index of the property to key.\n"
197 "      Defaults to -1 which will key all indices or a single channel if the property is not an array.\n"
198 "   :type index: int\n"
199 "   :arg frame: The frame on which the keyframe is inserted, defaulting to the current frame.\n"
200 "   :type frame: float\n"
201 "   :arg group: The name of the group the F-Curve should be added to if it doesn't exist yet.\n"
202 "   :type group: str\n"
203 "   :arg options: Optional flags:\n"
204 "\n"
205 "      - ``INSERTKEY_NEEDED`` Only insert keyframes where they're needed in the relevant F-Curves.\n"
206 "      - ``INSERTKEY_VISUAL`` Insert keyframes based on 'visual transforms'.\n"
207 "      - ``INSERTKEY_XYZ_TO_RGB`` Color for newly added transformation F-Curves (Location, Rotation, Scale)\n"
208 "         and also Color is based on the transform axis.\n"
209 "   :type flag: set\n"
210 "   :return: Success of keyframe insertion.\n"
211 "   :rtype: boolean\n"
212 ;
213 PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyObject *kw)
214 {
215         /* args, pyrna_struct_keyframe_parse handles these */
216         const char *path_full = NULL;
217         int index = -1;
218         float cfra = FLT_MAX;
219         const char *group_name = NULL;
220         char keytype = BEZT_KEYTYPE_KEYFRAME; /* XXX: Expose this as a one-off option... */
221         int options = 0;
222
223         PYRNA_STRUCT_CHECK_OBJ(self);
224
225         if (pyrna_struct_keyframe_parse(&self->ptr, args, kw,
226                                         "s|ifsO!:bpy_struct.keyframe_insert()", "bpy_struct.keyframe_insert()",
227                                         &path_full, &index, &cfra, &group_name, &options) == -1)
228         {
229                 return NULL;
230         }
231         else if (self->ptr.type == &RNA_NlaStrip) {
232                 /* Handle special properties for NLA Strips, whose F-Curves are stored on the
233                  * strips themselves. These are stored separately or else the properties will
234                  * not have any effect.
235                  */
236                 ReportList reports;
237                 short result = 0;
238
239                 PointerRNA ptr = self->ptr;
240                 PropertyRNA *prop = NULL;
241                 const char *prop_name;
242
243                 BKE_reports_init(&reports, RPT_STORE);
244
245                 /* Retrieve the property identifier from the full path, since we can't get it any other way */
246                 prop_name = strrchr(path_full, '.');
247                 if ((prop_name >= path_full) &&
248                     (prop_name + 1 < path_full + strlen(path_full)))
249                 {
250                         prop = RNA_struct_find_property(&ptr, prop_name + 1);
251                 }
252
253                 if (prop) {
254                         NlaStrip *strip = (NlaStrip *)ptr.data;
255                         FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index);
256
257                         result = insert_keyframe_direct(&reports, ptr, prop, fcu, cfra, keytype, options);
258                 }
259                 else {
260                         BKE_reportf(&reports, RPT_ERROR, "Could not resolve path (%s)", path_full);
261                 }
262                 MEM_freeN((void *)path_full);
263
264                 if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1)
265                         return NULL;
266
267                 return PyBool_FromLong(result);
268         }
269         else {
270                 ID *id = self->ptr.id.data;
271                 ReportList reports;
272                 short result;
273
274                 BKE_reports_init(&reports, RPT_STORE);
275
276                 BLI_assert(BKE_id_is_in_gobal_main(id));
277                 result = insert_keyframe(G_MAIN, &reports, id, NULL, group_name, path_full, index, cfra, keytype, options);
278                 MEM_freeN((void *)path_full);
279
280                 if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1)
281                         return NULL;
282
283                 return PyBool_FromLong(result);
284         }
285 }
286
287 char pyrna_struct_keyframe_delete_doc[] =
288 ".. method:: keyframe_delete(data_path, index=-1, frame=bpy.context.scene.frame_current, group=\"\")\n"
289 "\n"
290 "   Remove a keyframe from this properties fcurve.\n"
291 "\n"
292 "   :arg data_path: path to the property to remove a key, analogous to the fcurve's data path.\n"
293 "   :type data_path: string\n"
294 "   :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"
295 "   :type index: int\n"
296 "   :arg frame: The frame on which the keyframe is deleted, defaulting to the current frame.\n"
297 "   :type frame: float\n"
298 "   :arg group: The name of the group the F-Curve should be added to if it doesn't exist yet.\n"
299 "   :type group: str\n"
300 "   :return: Success of keyframe deleation.\n"
301 "   :rtype: boolean\n"
302 ;
303 PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyObject *kw)
304 {
305         /* args, pyrna_struct_keyframe_parse handles these */
306         const char *path_full = NULL;
307         int index = -1;
308         float cfra = FLT_MAX;
309         const char *group_name = NULL;
310
311         PYRNA_STRUCT_CHECK_OBJ(self);
312
313         if (pyrna_struct_keyframe_parse(&self->ptr, args, kw,
314                                         "s|ifsO!:bpy_struct.keyframe_delete()",
315                                         "bpy_struct.keyframe_insert()",
316                                         &path_full, &index, &cfra, &group_name, NULL) == -1)
317         {
318                 return NULL;
319         }
320         else if (self->ptr.type == &RNA_NlaStrip) {
321                 /* Handle special properties for NLA Strips, whose F-Curves are stored on the
322                  * strips themselves. These are stored separately or else the properties will
323                  * not have any effect.
324                  */
325                 ReportList reports;
326                 short result = 0;
327
328                 PointerRNA ptr = self->ptr;
329                 PropertyRNA *prop = NULL;
330                 const char *prop_name;
331
332                 BKE_reports_init(&reports, RPT_STORE);
333
334                 /* Retrieve the property identifier from the full path, since we can't get it any other way */
335                 prop_name = strrchr(path_full, '.');
336                 if ((prop_name >= path_full) &&
337                     (prop_name + 1 < path_full + strlen(path_full)))
338                 {
339                         prop = RNA_struct_find_property(&ptr, prop_name + 1);
340                 }
341
342                 if (prop) {
343                         ID *id = ptr.id.data;
344                         NlaStrip *strip = (NlaStrip *)ptr.data;
345                         FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index);
346
347                         BLI_assert(fcu != NULL); /* NOTE: This should be true, or else we wouldn't be able to get here */
348
349                         if (BKE_fcurve_is_protected(fcu)) {
350                                 BKE_reportf(&reports, RPT_WARNING,
351                                             "Not deleting keyframe for locked F-Curve for NLA Strip influence on %s - %s '%s'",
352                                             strip->name, BKE_idcode_to_name(GS(id->name)), id->name + 2);
353                         }
354                         else {
355                                 /* remove the keyframe directly
356                                  * NOTE: cannot use delete_keyframe_fcurve(), as that will free the curve,
357                                  *       and delete_keyframe() expects the FCurve to be part of an action
358                                  */
359                                 bool found = false;
360                                 int i;
361
362                                 /* try to find index of beztriple to get rid of */
363                                 i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
364                                 if (found) {
365                                         /* delete the key at the index (will sanity check + do recalc afterwards) */
366                                         delete_fcurve_key(fcu, i, 1);
367                                         result = true;
368                                 }
369                         }
370                 }
371                 else {
372                         BKE_reportf(&reports, RPT_ERROR, "Could not resolve path (%s)", path_full);
373                 }
374                 MEM_freeN((void *)path_full);
375
376                 if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1)
377                         return NULL;
378
379                 return PyBool_FromLong(result);
380         }
381         else {
382                 short result;
383                 ReportList reports;
384
385                 BKE_reports_init(&reports, RPT_STORE);
386
387                 result = delete_keyframe(&reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0);
388                 MEM_freeN((void *)path_full);
389
390                 if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1)
391                         return NULL;
392
393                 return PyBool_FromLong(result);
394         }
395
396 }
397
398 char pyrna_struct_driver_add_doc[] =
399 ".. method:: driver_add(path, index=-1)\n"
400 "\n"
401 "   Adds driver(s) to the given property\n"
402 "\n"
403 "   :arg path: path to the property to drive, analogous to the fcurve's data path.\n"
404 "   :type path: string\n"
405 "   :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"
406 "   :type index: int\n"
407 "   :return: The driver(s) added.\n"
408 "   :rtype: :class:`bpy.types.FCurve` or list if index is -1 with an array property.\n"
409 ;
410 PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args)
411 {
412         const char *path, *path_full;
413         int index = -1;
414
415         PYRNA_STRUCT_CHECK_OBJ(self);
416
417         if (!PyArg_ParseTuple(args, "s|i:driver_add", &path, &index))
418                 return NULL;
419
420         if (pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_add():", path, &path_full, &index) == -1) {
421                 return NULL;
422         }
423         else {
424                 PyObject *ret = NULL;
425                 ReportList reports;
426                 int result;
427
428                 BKE_reports_init(&reports, RPT_STORE);
429
430                 result = ANIM_add_driver(&reports, (ID *)self->ptr.id.data, path_full, index,
431                                          CREATEDRIVER_WITH_FMODIFIER, DRIVER_TYPE_PYTHON);
432
433                 if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1)
434                         return NULL;
435
436                 if (result) {
437                         ID *id = self->ptr.id.data;
438                         AnimData *adt = BKE_animdata_from_id(id);
439                         FCurve *fcu;
440
441                         PointerRNA tptr;
442
443                         if (index == -1) { /* all, use a list */
444                                 int i = 0;
445                                 ret = PyList_New(0);
446                                 while ((fcu = list_find_fcurve(&adt->drivers, path_full, i++))) {
447                                         RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr);
448                                         PyList_APPEND(ret, pyrna_struct_CreatePyObject(&tptr));
449                                 }
450                         }
451                         else {
452                                 fcu = list_find_fcurve(&adt->drivers, path_full, index);
453                                 RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr);
454                                 ret = pyrna_struct_CreatePyObject(&tptr);
455                         }
456
457                         WM_event_add_notifier(BPy_GetContext(), NC_ANIMATION | ND_FCURVES_ORDER, NULL);
458                 }
459                 else {
460                         /* XXX, should be handled by reports, */
461                         PyErr_SetString(PyExc_TypeError, "bpy_struct.driver_add(): failed because of an internal error");
462                         return NULL;
463                 }
464
465                 MEM_freeN((void *)path_full);
466
467                 return ret;
468         }
469 }
470
471
472 char pyrna_struct_driver_remove_doc[] =
473 ".. method:: driver_remove(path, index=-1)\n"
474 "\n"
475 "   Remove driver(s) from the given property\n"
476 "\n"
477 "   :arg path: path to the property to drive, analogous to the fcurve's data path.\n"
478 "   :type path: string\n"
479 "   :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"
480 "   :type index: int\n"
481 "   :return: Success of driver removal.\n"
482 "   :rtype: boolean\n"
483 ;
484 PyObject *pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args)
485 {
486         const char *path, *path_full;
487         int index = -1;
488
489         PYRNA_STRUCT_CHECK_OBJ(self);
490
491         if (!PyArg_ParseTuple(args, "s|i:driver_remove", &path, &index))
492                 return NULL;
493
494         if (pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_remove():", path, &path_full, &index) == -1) {
495                 return NULL;
496         }
497         else {
498                 short result;
499                 ReportList reports;
500
501                 BKE_reports_init(&reports, RPT_STORE);
502
503                 result = ANIM_remove_driver(&reports, (ID *)self->ptr.id.data, path_full, index, 0);
504
505                 MEM_freeN((void *)path_full);
506
507                 if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1)
508                         return NULL;
509
510                 WM_event_add_notifier(BPy_GetContext(), NC_ANIMATION | ND_FCURVES_ORDER, NULL);
511
512                 return PyBool_FromLong(result);
513         }
514 }