38#include "RNA_prototypes.hh"
55 const char *error_prefix,
57 const char **r_path_full,
59 bool *r_path_no_validate)
65 if (
ptr->data ==
nullptr) {
67 PyExc_TypeError,
"%.200s this struct has no data, can't be animated", error_prefix);
77 else if (path_index != -1) {
78 PyErr_Format(PyExc_ValueError,
79 "%.200s path includes index, must be a separate argument",
85 PyErr_Format(PyExc_ValueError,
"%.200s path spans ID blocks", error_prefix, path);
94 if (prop ==
nullptr) {
95 if (r_path_no_validate) {
96 *r_path_no_validate =
true;
99 PyErr_Format(PyExc_TypeError,
"%.200s property \"%s\" not found", error_prefix, path);
103 if (r_path_no_validate) {
108 PyErr_Format(PyExc_TypeError,
"%.200s property \"%s\" not animatable", error_prefix, path);
113 if ((*r_index) == -1) {
117 PyErr_Format(PyExc_TypeError,
118 "%.200s index %d was given while property \"%s\" is not an array",
127 if ((*r_index) < -1 || (*r_index) >= array_len) {
128 PyErr_Format(PyExc_TypeError,
129 "%.200s index out of range \"%s\", given %d, array length is %d",
144 *r_path_full = path_full ?
BLI_strdup(path_full->c_str()) :
nullptr;
146 if (*r_path_full ==
nullptr) {
147 PyErr_Format(PyExc_TypeError,
"%.200s could not make path to \"%s\"", error_prefix, path);
156 const char *error_prefix,
158 const char **r_path_full,
168 const char *error_prefix,
170 const char **r_path_full)
180 PyErr_Format(PyExc_TypeError,
181 "%.200s could not make path for type %s",
198 const char *error_prefix,
200 const char **r_path_full,
203 bool path_unresolved =
false;
205 ptr, error_prefix, path, r_path_full, r_index, &path_unresolved) == -1)
207 if (path_unresolved ==
true) {
223 const char *parse_str,
224 const char *error_prefix,
226 const char **r_path_full,
229 const char **r_group_name,
233 static const char *kwlist[] = {
234 "data_path",
"index",
"frame",
"group",
"options",
"keytype",
nullptr};
235 PyObject *pyoptions =
nullptr;
236 char *keytype_name =
nullptr;
240 if (!PyArg_ParseTupleAndKeywords(args,
268 int keytype_as_int = 0;
291 ".. method:: keyframe_insert(data_path, /, *, index=-1, "
292 "frame=bpy.context.scene.frame_current, "
293 "group=\"\", options=set(), keytype='KEYFRAME')\n"
295 " Insert a keyframe on the property given, adding fcurves and animation data when "
298 " :arg data_path: path to the property to key, analogous to the fcurve's data path.\n"
299 " :type data_path: str\n"
300 " :arg index: array index of the property to key.\n"
301 " Defaults to -1 which will key all indices or a single channel if the property is not "
303 " :type index: int\n"
304 " :arg frame: The frame on which the keyframe is inserted, defaulting to the current "
306 " :type frame: float\n"
307 " :arg group: The name of the group the F-Curve should be added to if it doesn't exist "
309 " :type group: str\n"
310 " :arg options: Optional set of flags:\n"
312 " - ``INSERTKEY_NEEDED`` Only insert keyframes where they're needed in the relevant "
314 " - ``INSERTKEY_VISUAL`` Insert keyframes based on 'visual transforms'.\n"
315 " - ``INSERTKEY_XYZ_TO_RGB`` This flag is no longer in use, and is here so that code "
316 "that uses it doesn't break. The XYZ=RGB coloring is determined by the animation "
318 " - ``INSERTKEY_REPLACE`` Only replace already existing keyframes.\n"
319 " - ``INSERTKEY_AVAILABLE`` Only insert into already existing F-Curves.\n"
320 " - ``INSERTKEY_CYCLE_AWARE`` Take cyclic extrapolation into account "
321 "(Cycle-Aware Keying option).\n"
322 " :type options: set[str]\n"
323 " :arg keytype: Type of the key: 'KEYFRAME', 'BREAKDOWN', 'MOVING_HOLD', 'EXTREME', "
324 "'JITTER', or 'GENERATED'\n"
325 " :type keytype: str\n"
326 " :return: Success of keyframe insertion.\n"
332 const char *path_full =
nullptr;
335 const char *group_name =
nullptr;
344 "s|$ifsO!s:bpy_struct.keyframe_insert()",
345 "bpy_struct.keyframe_insert()",
372 if (
self->ptr->type == &RNA_NlaStrip) {
380 const char *prop_name;
383 prop_name = strrchr(path_full,
'.');
384 if ((prop_name >= path_full) && (prop_name + 1 < path_full + strlen(path_full))) {
407 const std::optional<blender::StringRefNull> channel_group = group_name ?
408 std::optional(group_name) :
414 {{path_full, {}, index}},
420 if (success_count == 0) {
430 result = success_count != 0;
447 return PyBool_FromLong(
result);
451 ".. method:: keyframe_delete(data_path, /, *, index=-1, "
452 "frame=bpy.context.scene.frame_current, "
455 " Remove a keyframe from this properties fcurve.\n"
457 " :arg data_path: path to the property to remove a key, analogous to the fcurve's data "
459 " :type data_path: str\n"
460 " :arg index: array index of the property to remove a key. Defaults to -1 removing all "
461 "indices or a single channel if the property is not an array.\n"
462 " :type index: int\n"
463 " :arg frame: The frame on which the keyframe is deleted, defaulting to the current frame.\n"
464 " :type frame: float\n"
465 " :arg group: The name of the group the F-Curve should be added to if it doesn't exist "
467 " :type group: str\n"
468 " :return: Success of keyframe deletion.\n"
473 const char *path_full =
nullptr;
476 const char *group_name =
nullptr;
483 "s|$ifsOs!:bpy_struct.keyframe_delete()",
484 "bpy_struct.keyframe_insert()",
500 if (
self->ptr->type == &RNA_NlaStrip) {
508 const char *prop_name;
511 prop_name = strrchr(path_full,
'.');
512 if ((prop_name >= path_full) && (prop_name + 1 < path_full + strlen(path_full))) {
517 ID *
id =
ptr.owner_id;
528 "Not deleting keyframe for locked F-Curve for NLA Strip influence on %s - %s '%s'",
556 RNAPath rna_path = {path_full, std::nullopt, index};
558 rna_path.
index = std::nullopt;
561 G.main, &
reports,
self->ptr->owner_id, rna_path, cfra) != 0);
570 return PyBool_FromLong(
result);
574 ".. method:: driver_add(path, index=-1, /)\n"
576 " Adds driver(s) to the given property\n"
578 " :arg path: path to the property to drive, analogous to the fcurve's data path.\n"
580 " :arg index: array index of the property drive. Defaults to -1 for all indices or a single "
581 "channel if the property is not an array.\n"
582 " :type index: int\n"
583 " :return: The driver added or a list of drivers when index is -1.\n"
584 " :rtype: :class:`bpy.types.FCurve` | list[:class:`bpy.types.FCurve`]\n";
587 const char *path, *path_full;
592 if (!PyArg_ParseTuple(args,
"s|i:driver_add", &path, &index)) {
597 &
self->ptr.value(),
"bpy_struct.driver_add():", path, &path_full, &index) == -1)
602 PyObject *
ret =
nullptr;
620 PyErr_SetString(PyExc_TypeError,
621 "bpy_struct.driver_add(): failed because of an internal error");
624 ID *
id =
self->ptr->owner_id;
656 ".. method:: driver_remove(path, index=-1, /)\n"
658 " Remove driver(s) from the given property\n"
660 " :arg path: path to the property to drive, analogous to the fcurve's data path.\n"
662 " :arg index: array index of the property drive. Defaults to -1 for all indices or a single "
663 "channel if the property is not an array.\n"
664 " :type index: int\n"
665 " :return: Success of driver removal.\n"
669 const char *path, *path_full;
674 if (!PyArg_ParseTuple(args,
"s|i:driver_remove", &path, &index)) {
679 &
self->ptr.value(),
"bpy_struct.driver_remove():", path, &path_full, &index) == -1)
691 if (path != path_full) {
704 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)
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)
@ CREATEDRIVER_WITH_FMODIFIER
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)