38#include "RNA_prototypes.hh"
57 const char *error_prefix,
59 const char **r_path_full,
61 bool *r_path_no_validate)
67 if (
ptr->data ==
nullptr) {
69 PyExc_TypeError,
"%.200s this struct has no data, cannot be animated", error_prefix);
79 else if (path_index != -1) {
80 PyErr_Format(PyExc_ValueError,
81 "%.200s path includes index, must be a separate argument",
87 PyErr_Format(PyExc_ValueError,
"%.200s path spans ID blocks", error_prefix, path);
96 if (prop ==
nullptr) {
97 if (r_path_no_validate) {
98 *r_path_no_validate =
true;
101 PyErr_Format(PyExc_TypeError,
"%.200s property \"%s\" not found", error_prefix, path);
105 if (r_path_no_validate) {
110 PyErr_Format(PyExc_TypeError,
"%.200s property \"%s\" not animatable", error_prefix, path);
115 if ((*r_index) == -1) {
119 PyErr_Format(PyExc_TypeError,
120 "%.200s index %d was given while property \"%s\" is not an array",
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",
146 *r_path_full = path_full ?
BLI_strdup(path_full->c_str()) :
nullptr;
148 if (*r_path_full ==
nullptr) {
149 PyErr_Format(PyExc_TypeError,
"%.200s could not make path to \"%s\"", error_prefix, path);
158 const char *error_prefix,
160 const char **r_path_full,
170 const char *error_prefix,
172 const char **r_path_full)
182 PyErr_Format(PyExc_TypeError,
183 "%.200s could not make path for type %s",
200 const char *error_prefix,
202 const char **r_path_full,
205 bool path_unresolved =
false;
207 ptr, error_prefix, path, r_path_full, r_index, &path_unresolved) == -1)
209 if (path_unresolved ==
true) {
225 const char *parse_str,
226 const char *error_prefix,
228 const char **r_path_full,
231 const char **r_group_name,
235 static const char *kwlist[] = {
236 "data_path",
"index",
"frame",
"group",
"options",
"keytype",
nullptr};
237 PyObject *pyoptions =
nullptr;
238 char *keytype_name =
nullptr;
242 if (!PyArg_ParseTupleAndKeywords(args,
270 int keytype_as_int = 0;
293 ".. method:: keyframe_insert(data_path, /, *, index=-1, "
294 "frame=bpy.context.scene.frame_current, "
295 "group=\"\", options=set(), keytype='KEYFRAME')\n"
297 " Insert a keyframe on the property given, adding fcurves and animation data when "
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 "
305 " :type index: int\n"
306 " :arg frame: The frame on which the keyframe is inserted, defaulting to the current "
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 "
311 " :type group: str\n"
312 " :arg options: Optional set of flags:\n"
314 " - ``INSERTKEY_NEEDED`` Only insert keyframes where they're needed in the relevant "
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"
331 const char *path_full =
nullptr;
334 const char *group_name =
nullptr;
343 "s|$ifsO!s:bpy_struct.keyframe_insert()",
344 "bpy_struct.keyframe_insert()",
371 if (
self->ptr->type == &RNA_NlaStrip) {
379 const char *prop_name;
382 prop_name = strrchr(path_full,
'.');
383 if ((prop_name >= path_full) && (prop_name + 1 < path_full + strlen(path_full))) {
406 const std::optional<blender::StringRefNull> channel_group = group_name ?
407 std::optional(group_name) :
413 {{path_full, {}, index}},
419 if (success_count == 0) {
429 result = success_count != 0;
446 return PyBool_FromLong(
result);
450 ".. method:: keyframe_delete(data_path, /, *, index=-1, "
451 "frame=bpy.context.scene.frame_current, "
454 " Remove a keyframe from this properties fcurve.\n"
456 " :arg data_path: path to the property to remove a key, analogous to the fcurve's data "
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 "
466 " :type group: str\n"
467 " :return: Success of keyframe deletion.\n"
472 const char *path_full =
nullptr;
475 const char *group_name =
nullptr;
482 "s|$ifsOs!:bpy_struct.keyframe_delete()",
483 "bpy_struct.keyframe_insert()",
499 if (
self->ptr->type == &RNA_NlaStrip) {
507 const char *prop_name;
510 prop_name = strrchr(path_full,
'.');
511 if ((prop_name >= path_full) && (prop_name + 1 < path_full + strlen(path_full))) {
516 ID *
id =
ptr.owner_id;
527 "Not deleting keyframe for locked F-Curve for NLA Strip influence on %s - %s '%s'",
555 RNAPath rna_path = {path_full, std::nullopt, index};
557 rna_path.
index = std::nullopt;
560 G.main, &reports,
self->ptr->owner_id, rna_path, cfra) != 0);
569 return PyBool_FromLong(
result);
573 ".. method:: driver_add(path, index=-1, /)\n"
575 " Adds driver(s) to the given property\n"
577 " :arg path: path to the property to drive, analogous to the fcurve's data path.\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";
586 const char *path, *path_full;
591 if (!PyArg_ParseTuple(args,
"s|i:driver_add", &path, &index)) {
596 &
self->ptr.value(),
"bpy_struct.driver_add():", path, &path_full, &index) == -1)
601 PyObject *
ret =
nullptr;
614 PyErr_SetString(PyExc_TypeError,
615 "bpy_struct.driver_add(): failed because of an internal error");
618 ID *
id =
self->ptr->owner_id;
650 ".. method:: driver_remove(path, index=-1, /)\n"
652 " Remove driver(s) from the given property\n"
654 " :arg path: path to the property to drive, analogous to the fcurve's data path.\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"
663 const char *path, *path_full;
668 if (!PyArg_ParseTuple(args,
"s|i:driver_remove", &path, &index)) {
673 &
self->ptr.value(),
"bpy_struct.driver_remove():", path, &path_full, &index) == -1)
685 if (path != path_full) {
698 return PyBool_FromLong(
result);
Functions to insert, delete or modify keyframes.
AnimData * BKE_animdata_from_id(const ID *id)
AnimationEvalContext BKE_animsys_eval_context_construct(struct Depsgraph *depsgraph, float eval_time) ATTR_WARN_UNUSED_RESULT
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)
const char * BKE_idtype_idcode_to_name(short idcode)
bool BKE_id_is_in_global_main(ID *id)
@ RPT_PRINT_HANDLED_BY_OWNER
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_reports_free(ReportList *reports)
void BKE_report_print_level_set(ReportList *reports, eReportType level)
void BKE_reports_init(ReportList *reports, int flag)
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
#define BLI_string_joinN(...)
#define BLI_string_join_by_sep_charN(...)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
Read Guarded memory(de)allocation.
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()
BPy_StructRNA * depsgraph
PyObject * pyrna_struct_CreatePyObject(PointerRNA *ptr)
#define PYRNA_STRUCT_CHECK_OBJ(obj)
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.
bool ANIM_remove_driver(ID *id, const char rna_path[], int array_index)
Main Driver Management API calls.
void MEM_freeN(void *vmemh)
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)
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[]
std::optional< std::string > RNA_path_from_ID_to_struct(const PointerRNA *ptr)
std::optional< std::string > RNA_path_from_ID_to_property(const PointerRNA *ptr, PropertyRNA *prop)
bool RNA_path_resolve_property_full(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
std::optional< int > index
void WM_event_add_notifier(const bContext *C, uint type, void *reference)