39#include "RNA_prototypes.hh"
56 const char *error_prefix,
58 const char **r_path_full,
60 bool *r_path_no_validate)
68 PyExc_TypeError,
"%.200s this struct has no data, can't be animated", error_prefix);
78 else if (path_index != -1) {
79 PyErr_Format(PyExc_ValueError,
80 "%.200s path includes index, must be a separate argument",
86 PyErr_Format(PyExc_ValueError,
"%.200s path spans ID blocks", error_prefix, path);
95 if (prop ==
nullptr) {
96 if (r_path_no_validate) {
97 *r_path_no_validate =
true;
100 PyErr_Format(PyExc_TypeError,
"%.200s property \"%s\" not found", error_prefix, path);
104 if (r_path_no_validate) {
109 PyErr_Format(PyExc_TypeError,
"%.200s property \"%s\" not animatable", error_prefix, path);
114 if ((*r_index) == -1) {
118 PyErr_Format(PyExc_TypeError,
119 "%.200s index %d was given while property \"%s\" is not an array",
128 if ((*r_index) < -1 || (*r_index) >= array_len) {
129 PyErr_Format(PyExc_TypeError,
130 "%.200s index out of range \"%s\", given %d, array length is %d",
145 *r_path_full = path_full ?
BLI_strdup(path_full->c_str()) :
nullptr;
147 if (*r_path_full ==
nullptr) {
148 PyErr_Format(PyExc_TypeError,
"%.200s could not make path to \"%s\"", error_prefix, path);
157 const char *error_prefix,
159 const char **r_path_full,
169 const char *error_prefix,
171 const char **r_path_full)
181 PyErr_Format(PyExc_TypeError,
182 "%.200s could not make path for type %s",
199 const char *error_prefix,
201 const char **r_path_full,
204 bool path_unresolved =
false;
206 ptr, error_prefix, path, r_path_full, r_index, &path_unresolved) == -1)
208 if (path_unresolved ==
true) {
224 const char *parse_str,
225 const char *error_prefix,
227 const char **r_path_full,
230 const char **r_group_name,
234 static const char *kwlist[] = {
235 "data_path",
"index",
"frame",
"group",
"options",
"keytype",
nullptr};
236 PyObject *pyoptions =
nullptr;
237 char *keytype_name =
nullptr;
241 if (!PyArg_ParseTupleAndKeywords(args,
277 int keytype_as_int = 0;
292 ".. method:: keyframe_insert(data_path, index=-1, 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))) {
391 result = insert_keyframe_direct(&reports,
407 const std::optional<blender::StringRefNull> channel_group = group_name ?
408 std::optional(group_name) :
414 {{path_full, {}, index}},
419 const int success_count = combined_result.
get_count(SingleKeyingResult::SUCCESS);
420 if (success_count == 0) {
430 result = success_count != 0;
447 return PyBool_FromLong(result);
451 ".. method:: keyframe_delete(data_path, index=-1, 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))) {
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,
"bpy_struct.driver_add():", path, &path_full, &index) == -1)
601 PyObject *
ret =
nullptr;
619 ID *
id =
self->ptr.owner_id;
646 PyErr_SetString(PyExc_TypeError,
647 "bpy_struct.driver_add(): failed because of an internal error");
657 ".. method:: driver_remove(path, index=-1)\n"
659 " Remove driver(s) from the given property\n"
661 " :arg path: path to the property to drive, analogous to the fcurve's data path.\n"
663 " :arg index: array index of the property drive. Defaults to -1 for all indices or a single "
664 "channel if the property is not an array.\n"
665 " :type index: int\n"
666 " :return: Success of driver removal.\n"
670 const char *path, *path_full;
675 if (!PyArg_ParseTuple(args,
"s|i:driver_remove", &path, &index)) {
680 &
self->ptr,
"bpy_struct.driver_remove():", path, &path_full, &index) == -1)
692 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(void)
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
const Depsgraph * depsgraph
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.
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(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)