Blender V5.0
bpy_rna_anim.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include <Python.h>
12#include <cfloat> /* FLT_MAX */
13
14#include "MEM_guardedalloc.h"
15
16#include "BLI_string.h"
17#include "BLI_string_utils.hh"
18
19#include "DNA_anim_types.h"
20#include "DNA_scene_types.h"
21
22#include "ED_keyframing.hh"
23
24#include "ANIM_keyframing.hh"
25
26#include "BKE_anim_data.hh"
27#include "BKE_animsys.h"
28#include "BKE_context.hh"
29#include "BKE_fcurve.hh"
30#include "BKE_global.hh"
31#include "BKE_idtype.hh"
32#include "BKE_lib_id.hh"
33#include "BKE_report.hh"
34
35#include "RNA_access.hh"
36#include "RNA_enum_types.hh"
37#include "RNA_path.hh"
38#include "RNA_prototypes.hh"
39
40#include "WM_api.hh"
41#include "WM_types.hh"
42
43#include "bpy_capi_utils.hh"
44#include "bpy_rna.hh"
45#include "bpy_rna_anim.hh"
46
49
50#include "DEG_depsgraph.hh"
52
53#include "CLG_log.h"
54
55/* for keyframes and drivers */
57 const char *error_prefix,
58 const char *path,
59 const char **r_path_full,
60 int *r_index,
61 bool *r_path_no_validate)
62{
63 const bool is_idbase = RNA_struct_is_ID(ptr->type);
64 PropertyRNA *prop;
65 PointerRNA r_ptr;
66
67 if (ptr->data == nullptr) {
68 PyErr_Format(
69 PyExc_TypeError, "%.200s this struct has no data, cannot be animated", error_prefix);
70 return -1;
71 }
72
73 /* full paths can only be given from ID base */
74 if (is_idbase) {
75 int path_index = -1;
76 if (RNA_path_resolve_property_full(ptr, path, &r_ptr, &prop, &path_index) == false) {
77 prop = nullptr;
78 }
79 else if (path_index != -1) {
80 PyErr_Format(PyExc_ValueError,
81 "%.200s path includes index, must be a separate argument",
82 error_prefix,
83 path);
84 return -1;
85 }
86 else if (ptr->owner_id != r_ptr.owner_id) {
87 PyErr_Format(PyExc_ValueError, "%.200s path spans ID blocks", error_prefix, path);
88 return -1;
89 }
90 }
91 else {
92 prop = RNA_struct_find_property(ptr, path);
93 r_ptr = *ptr;
94 }
95
96 if (prop == nullptr) {
97 if (r_path_no_validate) {
98 *r_path_no_validate = true;
99 return -1;
100 }
101 PyErr_Format(PyExc_TypeError, "%.200s property \"%s\" not found", error_prefix, path);
102 return -1;
103 }
104
105 if (r_path_no_validate) {
106 /* Don't touch the index. */
107 }
108 else {
109 if (!RNA_property_animateable(&r_ptr, prop)) {
110 PyErr_Format(PyExc_TypeError, "%.200s property \"%s\" not animatable", error_prefix, path);
111 return -1;
112 }
113
114 if (RNA_property_array_check(prop) == 0) {
115 if ((*r_index) == -1) {
116 *r_index = 0;
117 }
118 else {
119 PyErr_Format(PyExc_TypeError,
120 "%.200s index %d was given while property \"%s\" is not an array",
121 error_prefix,
122 *r_index,
123 path);
124 return -1;
125 }
126 }
127 else {
128 const int array_len = RNA_property_array_length(&r_ptr, prop);
129 if ((*r_index) < -1 || (*r_index) >= array_len) {
130 PyErr_Format(PyExc_TypeError,
131 "%.200s index out of range \"%s\", given %d, array length is %d",
132 error_prefix,
133 path,
134 *r_index,
135 array_len);
136 return -1;
137 }
138 }
139 }
140
141 if (is_idbase) {
142 *r_path_full = BLI_strdup(path);
143 }
144 else {
145 const std::optional<std::string> path_full = RNA_path_from_ID_to_property(&r_ptr, prop);
146 *r_path_full = path_full ? BLI_strdup(path_full->c_str()) : nullptr;
147
148 if (*r_path_full == nullptr) {
149 PyErr_Format(PyExc_TypeError, "%.200s could not make path to \"%s\"", error_prefix, path);
150 return -1;
151 }
152 }
153
154 return 0;
155}
156
158 const char *error_prefix,
159 const char *path,
160 const char **r_path_full,
161 int *r_index)
162{
163 return pyrna_struct_anim_args_parse_ex(ptr, error_prefix, path, r_path_full, r_index, nullptr);
164}
165
170 const char *error_prefix,
171 const char *path,
172 const char **r_path_full)
173{
174 const bool is_idbase = RNA_struct_is_ID(ptr->type);
175 if (is_idbase) {
176 *r_path_full = path;
177 return 0;
178 }
179
180 const std::optional<std::string> path_prefix = RNA_path_from_ID_to_struct(ptr);
181 if (!path_prefix) {
182 PyErr_Format(PyExc_TypeError,
183 "%.200s could not make path for type %s",
184 error_prefix,
186 return -1;
187 }
188
189 if (*path == '[') {
190 *r_path_full = BLI_string_joinN(path_prefix->c_str(), path);
191 }
192 else {
193 *r_path_full = BLI_string_join_by_sep_charN('.', path_prefix->c_str(), path);
194 }
195
196 return 0;
197}
198
200 const char *error_prefix,
201 const char *path,
202 const char **r_path_full,
203 int *r_index)
204{
205 bool path_unresolved = false;
207 ptr, error_prefix, path, r_path_full, r_index, &path_unresolved) == -1)
208 {
209 if (path_unresolved == true) {
210 if (pyrna_struct_anim_args_parse_no_resolve(ptr, error_prefix, path, r_path_full) == -1) {
211 return -1;
212 }
213 }
214 else {
215 return -1;
216 }
217 }
218 return 0;
219}
220
221/* internal use for insert and delete */
223 PyObject *args,
224 PyObject *kw,
225 const char *parse_str,
226 const char *error_prefix,
227 /* return values */
228 const char **r_path_full,
229 int *r_index,
230 float *r_cfra,
231 const char **r_group_name,
232 int *r_options,
233 eBezTriple_KeyframeType *r_keytype)
234{
235 static const char *kwlist[] = {
236 "data_path", "index", "frame", "group", "options", "keytype", nullptr};
237 PyObject *pyoptions = nullptr;
238 char *keytype_name = nullptr;
239 const char *path;
240
241 /* NOTE: `parse_str` MUST start with `s|ifsO!`. */
242 if (!PyArg_ParseTupleAndKeywords(args,
243 kw,
244 parse_str,
245 (char **)kwlist,
246 &path,
247 r_index,
248 r_cfra,
249 r_group_name,
250 &PySet_Type,
251 &pyoptions,
252 &keytype_name))
253 {
254 return -1;
255 }
256
257 /* flag may be null (no option currently for remove keyframes e.g.). */
258 if (r_options) {
259 if (pyoptions &&
261 rna_enum_keying_flag_api_items, pyoptions, r_options, error_prefix) == -1))
262 {
263 return -1;
264 }
265
266 *r_options |= INSERTKEY_NO_USERPREF;
267 }
268
269 if (r_keytype) {
270 int keytype_as_int = 0;
272 keytype_name,
273 &keytype_as_int,
274 error_prefix) == -1)
275 {
276 return -1;
277 }
278 *r_keytype = eBezTriple_KeyframeType(keytype_as_int);
279 }
280
281 if (pyrna_struct_anim_args_parse(ptr, error_prefix, path, r_path_full, r_index) == -1) {
282 return -1;
283 }
284
285 if (*r_cfra == FLT_MAX) {
286 *r_cfra = CTX_data_scene(BPY_context_get())->r.cfra;
287 }
288
289 return 0; /* success */
290}
291
293 ".. method:: keyframe_insert(data_path, /, *, index=-1, "
294 "frame=bpy.context.scene.frame_current, "
295 "group=\"\", options=set(), keytype='KEYFRAME')\n"
296 "\n"
297 " Insert a keyframe on the property given, adding fcurves and animation data when "
298 "necessary.\n"
299 "\n"
300 " :arg data_path: path to the property to key, analogous to the fcurve's data path.\n"
301 " :type data_path: str\n"
302 " :arg index: array index of the property to key.\n"
303 " Defaults to -1 which will key all indices or a single channel if the property is not "
304 "an array.\n"
305 " :type index: int\n"
306 " :arg frame: The frame on which the keyframe is inserted, defaulting to the current "
307 "frame.\n"
308 " :type frame: float\n"
309 " :arg group: The name of the group the F-Curve should be added to if it doesn't exist "
310 "yet.\n"
311 " :type group: str\n"
312 " :arg options: Optional set of flags:\n"
313 "\n"
314 " - ``INSERTKEY_NEEDED`` Only insert keyframes where they're needed in the relevant "
315 "F-Curves.\n"
316 " - ``INSERTKEY_VISUAL`` Insert keyframes based on 'visual transforms'.\n"
317 " - ``INSERTKEY_REPLACE`` Only replace already existing keyframes.\n"
318 " - ``INSERTKEY_AVAILABLE`` Only insert into already existing F-Curves.\n"
319 " - ``INSERTKEY_CYCLE_AWARE`` Take cyclic extrapolation into account "
320 "(Cycle-Aware Keying option).\n"
321 " :type options: set[str]\n"
322 " :arg keytype: Type of the key: 'KEYFRAME', 'BREAKDOWN', 'MOVING_HOLD', 'EXTREME', "
323 "'JITTER', or 'GENERATED'\n"
324 " :type keytype: str\n"
325 " :return: Success of keyframe insertion.\n"
326 " :rtype: bool\n";
327PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyObject *kw)
328{
329 using namespace blender::animrig;
330 /* args, pyrna_struct_keyframe_parse handles these */
331 const char *path_full = nullptr;
332 int index = -1;
333 float cfra = FLT_MAX;
334 const char *group_name = nullptr;
336 int options = 0;
337
339
340 if (pyrna_struct_keyframe_parse(&self->ptr.value(),
341 args,
342 kw,
343 "s|$ifsO!s:bpy_struct.keyframe_insert()",
344 "bpy_struct.keyframe_insert()",
345 &path_full,
346 &index,
347 &cfra,
348 &group_name,
349 &options,
350 &keytype) == -1)
351 {
352 return nullptr;
353 }
354
355 ReportList reports;
356 bool result = false;
357
359
360 /* This assumes that keyframes are only added on original data & using the active depsgraph. If
361 * it turns out to be necessary for some reason to insert keyframes on evaluated objects, we can
362 * revisit this and add an explicit `depsgraph` keyword argument to the function call.
363 *
364 * The depsgraph is only used for evaluating the NLA so this might not be needed in the future.
365 */
369 cfra);
370
371 if (self->ptr->type == &RNA_NlaStrip) {
372 /* Handle special properties for NLA Strips, whose F-Curves are stored on the
373 * strips themselves. These are stored separately or else the properties will
374 * not have any effect.
375 */
376
377 PointerRNA &ptr = *self->ptr;
378 PropertyRNA *prop = nullptr;
379 const char *prop_name;
380
381 /* Retrieve the property identifier from the full path, since we can't get it any other way */
382 prop_name = strrchr(path_full, '.');
383 if ((prop_name >= path_full) && (prop_name + 1 < path_full + strlen(path_full))) {
384 prop = RNA_struct_find_property(&ptr, prop_name + 1);
385 }
386
387 if (prop) {
388 NlaStrip *strip = static_cast<NlaStrip *>(ptr.data);
389 FCurve *fcu = BKE_fcurve_find(&strip->fcurves, RNA_property_identifier(prop), index);
391 ptr,
392 prop,
393 fcu,
394 &anim_eval_context,
396 nullptr,
398 }
399 else {
400 BKE_reportf(&reports, RPT_ERROR, "Could not resolve path (%s)", path_full);
401 }
402 }
403 else {
405
406 const std::optional<blender::StringRefNull> channel_group = group_name ?
407 std::optional(group_name) :
408 std::nullopt;
409 PointerRNA id_pointer = RNA_id_pointer_create(self->ptr->owner_id);
411 &id_pointer,
412 channel_group,
413 {{path_full, {}, index}},
414 std::nullopt,
415 anim_eval_context,
418 const int success_count = combined_result.get_count(SingleKeyingResult::SUCCESS);
419 if (success_count == 0) {
420 /* Ideally this would use the GUI presentation of RPT_ERROR, as the resulting pop-up has more
421 * vertical space than the single-line warning in the status bar. However, semantically these
422 * may not be errors at all, as skipping the keying of certain properties due to the 'only
423 * insert available' flag is not an error.
424 *
425 * Furthermore, using RPT_ERROR here would cause this function to raise a Python exception,
426 * rather than returning a boolean. */
427 combined_result.generate_reports(&reports, RPT_WARNING);
428 }
429 result = success_count != 0;
430 }
431
432 MEM_freeN(path_full);
433
434 if (BPy_reports_to_error(&reports, PyExc_RuntimeError, false) == -1) {
435 BKE_reports_free(&reports);
436 return nullptr;
437 }
439 BPy_reports_write_stdout(&reports, nullptr);
440 BKE_reports_free(&reports);
441
442 if (result) {
444 }
445
446 return PyBool_FromLong(result);
447}
448
450 ".. method:: keyframe_delete(data_path, /, *, index=-1, "
451 "frame=bpy.context.scene.frame_current, "
452 "group=\"\")\n"
453 "\n"
454 " Remove a keyframe from this properties fcurve.\n"
455 "\n"
456 " :arg data_path: path to the property to remove a key, analogous to the fcurve's data "
457 "path.\n"
458 " :type data_path: str\n"
459 " :arg index: array index of the property to remove a key. Defaults to -1 removing all "
460 "indices or a single channel if the property is not an array.\n"
461 " :type index: int\n"
462 " :arg frame: The frame on which the keyframe is deleted, defaulting to the current frame.\n"
463 " :type frame: float\n"
464 " :arg group: The name of the group the F-Curve should be added to if it doesn't exist "
465 "yet.\n"
466 " :type group: str\n"
467 " :return: Success of keyframe deletion.\n"
468 " :rtype: bool\n";
469PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyObject *kw)
470{
471 /* args, pyrna_struct_keyframe_parse handles these */
472 const char *path_full = nullptr;
473 int index = -1;
474 float cfra = FLT_MAX;
475 const char *group_name = nullptr;
476
478
479 if (pyrna_struct_keyframe_parse(&self->ptr.value(),
480 args,
481 kw,
482 "s|$ifsOs!:bpy_struct.keyframe_delete()",
483 "bpy_struct.keyframe_insert()",
484 &path_full,
485 &index,
486 &cfra,
487 &group_name,
488 nullptr,
489 nullptr) == -1)
490 {
491 return nullptr;
492 }
493
494 ReportList reports;
495 bool result = false;
496
498
499 if (self->ptr->type == &RNA_NlaStrip) {
500 /* Handle special properties for NLA Strips, whose F-Curves are stored on the
501 * strips themselves. These are stored separately or else the properties will
502 * not have any effect.
503 */
504
505 PointerRNA ptr = *self->ptr;
506 PropertyRNA *prop = nullptr;
507 const char *prop_name;
508
509 /* Retrieve the property identifier from the full path, since we can't get it any other way */
510 prop_name = strrchr(path_full, '.');
511 if ((prop_name >= path_full) && (prop_name + 1 < path_full + strlen(path_full))) {
512 prop = RNA_struct_find_property(&ptr, prop_name + 1);
513 }
514
515 if (prop) {
516 ID *id = ptr.owner_id;
517 NlaStrip *strip = static_cast<NlaStrip *>(ptr.data);
518 FCurve *fcu = BKE_fcurve_find(&strip->fcurves, RNA_property_identifier(prop), index);
519
520 /* NOTE: This should be true, or else we wouldn't be able to get here. */
521 BLI_assert(fcu != nullptr);
522
523 if (BKE_fcurve_is_protected(fcu)) {
525 &reports,
527 "Not deleting keyframe for locked F-Curve for NLA Strip influence on %s - %s '%s'",
528 strip->name,
530 id->name + 2);
531 }
532 else {
533 /* remove the keyframe directly
534 * NOTE: cannot use delete_keyframe_fcurve(), as that will free the curve,
535 * and delete_keyframe() expects the FCurve to be part of an action
536 */
537 bool found = false;
538 int i;
539
540 /* try to find index of beztriple to get rid of */
541 i = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, cfra, fcu->totvert, &found);
542 if (found) {
543 /* delete the key at the index (will sanity check + do recalc afterwards) */
546 result = true;
547 }
548 }
549 }
550 else {
551 BKE_reportf(&reports, RPT_ERROR, "Could not resolve path (%s)", path_full);
552 }
553 }
554 else {
555 RNAPath rna_path = {path_full, std::nullopt, index};
556 if (index < 0) {
557 rna_path.index = std::nullopt;
558 }
560 G.main, &reports, self->ptr->owner_id, rna_path, cfra) != 0);
561 }
562
563 MEM_freeN(path_full);
564
565 if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) {
566 return nullptr;
567 }
568
569 return PyBool_FromLong(result);
570}
571
573 ".. method:: driver_add(path, index=-1, /)\n"
574 "\n"
575 " Adds driver(s) to the given property\n"
576 "\n"
577 " :arg path: path to the property to drive, analogous to the fcurve's data path.\n"
578 " :type path: str\n"
579 " :arg index: array index of the property drive. Defaults to -1 for all indices or a single "
580 "channel if the property is not an array.\n"
581 " :type index: int\n"
582 " :return: The driver added or a list of drivers when index is -1.\n"
583 " :rtype: :class:`bpy.types.FCurve` | list[:class:`bpy.types.FCurve`]\n";
584PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args)
585{
586 const char *path, *path_full;
587 int index = -1;
588
590
591 if (!PyArg_ParseTuple(args, "s|i:driver_add", &path, &index)) {
592 return nullptr;
593 }
594
596 &self->ptr.value(), "bpy_struct.driver_add():", path, &path_full, &index) == -1)
597 {
598 return nullptr;
599 }
600
601 PyObject *ret = nullptr;
602 ReportList reports;
603 int result;
604
606
607 result = ANIM_add_driver(&reports, self->ptr->owner_id, path_full, index, 0, DRIVER_TYPE_PYTHON);
608
609 if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) {
610 /* Pass. */
611 }
612 else if (result == 0) {
613 /* XXX: should be handled by reports. */
614 PyErr_SetString(PyExc_TypeError,
615 "bpy_struct.driver_add(): failed because of an internal error");
616 }
617 else {
618 ID *id = self->ptr->owner_id;
620 FCurve *fcu;
621
622 PointerRNA tptr;
623
624 if (index == -1) { /* all, use a list */
625 int i = 0;
626 ret = PyList_New(0);
627 while ((fcu = BKE_fcurve_find(&adt->drivers, path_full, i++))) {
628 tptr = RNA_pointer_create_discrete(id, &RNA_FCurve, fcu);
629 PyList_APPEND(ret, pyrna_struct_CreatePyObject(&tptr));
630 }
631 }
632 else {
633 fcu = BKE_fcurve_find(&adt->drivers, path_full, index);
634 tptr = RNA_pointer_create_discrete(id, &RNA_FCurve, fcu);
636 }
637
638 bContext *context = BPY_context_get();
642 }
643
644 MEM_freeN(path_full);
645
646 return ret;
647}
648
650 ".. method:: driver_remove(path, index=-1, /)\n"
651 "\n"
652 " Remove driver(s) from the given property\n"
653 "\n"
654 " :arg path: path to the property to drive, analogous to the fcurve's data path.\n"
655 " :type path: str\n"
656 " :arg index: array index of the property drive. Defaults to -1 for all indices or a single "
657 "channel if the property is not an array.\n"
658 " :type index: int\n"
659 " :return: Success of driver removal.\n"
660 " :rtype: bool\n";
662{
663 const char *path, *path_full;
664 int index = -1;
665
667
668 if (!PyArg_ParseTuple(args, "s|i:driver_remove", &path, &index)) {
669 return nullptr;
670 }
671
673 &self->ptr.value(), "bpy_struct.driver_remove():", path, &path_full, &index) == -1)
674 {
675 return nullptr;
676 }
677
678 short result;
679 ReportList reports;
680
682
683 result = ANIM_remove_driver(self->ptr->owner_id, path_full, index);
684
685 if (path != path_full) {
686 MEM_freeN(path_full);
687 }
688
689 if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) {
690 return nullptr;
691 }
692
693 bContext *context = BPY_context_get();
697
698 return PyBool_FromLong(result);
699}
Functions to insert, delete or modify keyframes.
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:83
AnimationEvalContext BKE_animsys_eval_context_construct(struct Depsgraph *depsgraph, float eval_time) ATTR_WARN_UNUSED_RESULT
Definition anim_sys.cc:738
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
int BKE_fcurve_bezt_binarysearch_index(const BezTriple array[], float frame, int arraylen, bool *r_replace)
void BKE_fcurve_handles_recalc(FCurve *fcu)
FCurve * BKE_fcurve_find(ListBase *list, const char rna_path[], int array_index)
bool BKE_fcurve_is_protected(const FCurve *fcu)
void BKE_fcurve_delete_key(FCurve *fcu, int index)
#define G_MAIN
const char * BKE_idtype_idcode_to_name(short idcode)
Definition idtype.cc:164
bool BKE_id_is_in_global_main(ID *id)
Definition lib_id.cc:2500
@ RPT_PRINT_HANDLED_BY_OWNER
Definition BKE_report.hh:60
@ RPT_STORE
Definition BKE_report.hh:56
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
@ RPT_DEBUG
Definition BKE_report.hh:34
@ RPT_ERROR
Definition BKE_report.hh:39
@ RPT_WARNING
Definition BKE_report.hh:38
void BKE_reports_free(ReportList *reports)
Definition report.cc:97
void BKE_report_print_level_set(ReportList *reports, eReportType level)
Definition report.cc:265
void BKE_reports_init(ReportList *reports, int flag)
Definition report.cc:82
#define BLI_assert(a)
Definition BLI_assert.h:46
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.cc:41
#define BLI_string_joinN(...)
#define BLI_string_join_by_sep_charN(...)
bool CLG_quiet_get()
Definition clog.cc:945
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1118
@ ID_RECALC_ANIMATION
Definition DNA_ID.h:1077
@ DRIVER_TYPE_PYTHON
eInsertKeyFlags
@ INSERTKEY_NO_USERPREF
eBezTriple_KeyframeType
@ BEZT_KEYTYPE_KEYFRAME
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
#define NC_ANIMATION
Definition WM_types.hh:388
#define NA_EDITED
Definition WM_types.hh:584
#define ND_FCURVES_ORDER
Definition WM_types.hh:499
#define ND_ANIMCHAN
Definition WM_types.hh:496
void BPy_reports_write_stdout(const ReportList *reports, const char *header)
short BPy_reports_to_error(ReportList *reports, PyObject *exception, const bool clear)
struct bContext * BPY_context_get()
PyObject * self
BPy_StructRNA * depsgraph
PyObject * pyrna_struct_CreatePyObject(PointerRNA *ptr)
Definition bpy_rna.cc:8496
#define PYRNA_STRUCT_CHECK_OBJ(obj)
Definition bpy_rna.hh:78
char pyrna_struct_driver_add_doc[]
char pyrna_struct_keyframe_insert_doc[]
PyObject * pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyObject *kw)
PyObject * pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args)
PyObject * pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args)
static int pyrna_struct_anim_args_parse_no_resolve(PointerRNA *ptr, const char *error_prefix, const char *path, const char **r_path_full)
static int pyrna_struct_anim_args_parse_ex(PointerRNA *ptr, const char *error_prefix, const char *path, const char **r_path_full, int *r_index, bool *r_path_no_validate)
static int pyrna_struct_keyframe_parse(PointerRNA *ptr, PyObject *args, PyObject *kw, const char *parse_str, const char *error_prefix, const char **r_path_full, int *r_index, float *r_cfra, const char **r_group_name, int *r_options, eBezTriple_KeyframeType *r_keytype)
char pyrna_struct_driver_remove_doc[]
static int pyrna_struct_anim_args_parse_no_resolve_fallback(PointerRNA *ptr, const char *error_prefix, const char *path, const char **r_path_full, int *r_index)
char pyrna_struct_keyframe_delete_doc[]
PyObject * pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyObject *kw)
static int pyrna_struct_anim_args_parse(PointerRNA *ptr, const char *error_prefix, const char *path, const char **r_path_full, int *r_index)
int get_count(const SingleKeyingResult result) const
void generate_reports(ReportList *reports, eReportType report_level=RPT_ERROR)
CCL_NAMESPACE_BEGIN struct Options options
int ANIM_add_driver(ReportList *reports, ID *id, const char rna_path[], int array_index, short flag, int type)
Main Driver Management API calls.
Definition drivers.cc:383
bool ANIM_remove_driver(ID *id, const char rna_path[], int array_index)
Main Driver Management API calls.
Definition drivers.cc:505
#define GS(x)
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
int delete_keyframe(Main *bmain, ReportList *reports, ID *id, const RNAPath &rna_path, float cfra)
Main Delete Key-Framing API call.
CombinedKeyingResult insert_keyframes(Main *bmain, PointerRNA *struct_pointer, std::optional< StringRefNull > channel_group, const blender::Span< RNAPath > rna_paths, std::optional< float > scene_frame, const AnimationEvalContext &anim_eval_context, eBezTriple_KeyframeType key_type, eInsertKeyFlags insert_key_flags)
Main key-frame insertion API.
bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, const AnimationEvalContext *anim_eval_context, eBezTriple_KeyframeType keytype, NlaKeyframingContext *nla_context, eInsertKeyFlags flag)
Secondary Insert Key-framing API call.
int pyrna_enum_value_from_id(const EnumPropertyItem *item, const char *identifier, int *r_value, const char *error_prefix)
int pyrna_enum_bitfield_from_set(const EnumPropertyItem *items, PyObject *value, int *r_value, const char *error_prefix)
header-only utilities
return ret
bool RNA_property_array_check(PropertyRNA *prop)
bool RNA_struct_is_ID(const StructRNA *type)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_property_animateable(const PointerRNA *ptr, PropertyRNA *prop_orig)
const char * RNA_struct_identifier(const StructRNA *type)
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
const char * RNA_property_identifier(const PropertyRNA *prop)
PointerRNA RNA_id_pointer_create(ID *id)
const EnumPropertyItem rna_enum_keying_flag_api_items[]
const EnumPropertyItem rna_enum_beztriple_keyframe_type_items[]
Definition rna_fcurve.cc:77
std::optional< std::string > RNA_path_from_ID_to_struct(const PointerRNA *ptr)
Definition rna_path.cc:1014
std::optional< std::string > RNA_path_from_ID_to_property(const PointerRNA *ptr, PropertyRNA *prop)
Definition rna_path.cc:1173
bool RNA_path_resolve_property_full(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
Definition rna_path.cc:572
#define FLT_MAX
Definition stdcycles.h:14
ListBase drivers
BezTriple * bezt
unsigned int totvert
Definition DNA_ID.h:414
char name[258]
Definition DNA_ID.h:432
ListBase fcurves
char name[64]
ID * owner_id
Definition RNA_types.hh:51
std::optional< int > index
Definition RNA_path.hh:66
struct RenderData r
i
Definition text_draw.cc:230
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4238