12#include <fmt/format.h>
46#include "RNA_prototypes.hh"
54 result_counter.fill(0);
59 result_counter[
int(result)] +=
count;
64 for (
int i = 0; i < result_counter.size(); i++) {
65 result_counter[i] += other.result_counter[i];
71 return result_counter[
int(result)];
79 for (
int i = 1; i < result_counter.size(); i++) {
80 if (result_counter[i] > 0) {
91 reports,
RPT_WARNING,
"No keys have been inserted and no errors have been reported.");
99 fmt::format(
RPT_(
"There were {:d} keying failures for unknown reasons."), error_count));
104 errors.
append(fmt::format(
RPT_(
"Could not create {:d} F-Curve(s). This can happen when only "
105 "inserting to available F-Curves."),
112 fmt::format(
RPT_(
"{:d} F-Curve(s) are not keyframeable. They might be locked or sampled."),
118 errors.
append(fmt::format(
119 RPT_(
"Due to the setting 'Only Insert Needed', {:d} keyframe(s) have not been inserted."),
126 fmt::format(
RPT_(
"Due to the NLA stack setup, {:d} keyframe(s) have not been inserted."),
132 errors.
append(fmt::format(
RPT_(
"Inserting keys on {:d} data-block(s) has been skipped because "
133 "they are not editable."),
139 errors.
append(fmt::format(
RPT_(
"Inserting keys on {:d} data-block(s) has been skipped because "
140 "they cannot be animated."),
146 errors.
append(fmt::format(
RPT_(
"Inserting keys on {:d} data-block(s) has been skipped because "
147 "the RNA path wasn't valid for them."),
153 errors.
append(fmt::format(
RPT_(
"Inserting keys on {:d} data-block(s) has been skipped because "
154 "there were no layers that could accept the keys."),
160 errors.
append(fmt::format(
RPT_(
"Inserting keys on {:d} data-block(s) has been skipped because "
161 "there were no strips that could accept the keys."),
167 errors.
append(fmt::format(
RPT_(
"Inserting keys on {:d} data-block(s) has been skipped because "
168 "of missing action slots."),
177 if (errors.
size() == 1) {
178 BKE_report(reports, report_level, errors[0].c_str());
182 std::string error_message =
RPT_(
"Inserting keyframes failed:");
183 for (
const std::string &
error : errors) {
184 error_message.append(fmt::format(
"\n- {}",
error));
186 BKE_report(reports, report_level, error_message.c_str());
192 if (animated_struct->
type == &RNA_PoseBone) {
195 return pose_channel->
name;
198 if (animated_struct->
type == &RNA_Object) {
206 return "Object Transforms";
238 return (scene->toolsettings->keying_flag &
flag) || (
U.keying_flag &
flag);
240 return U.keying_flag &
flag;
277 const float period = action_range[1] - action_range[0];
284 const float frame_offset = fcu->
bezt[0].
vec[1][0] - action_range[0];
285 const float fix =
floorf(frame_offset / period) * period;
296 fcu->
bezt[1].
vec[0][0] += period;
297 fcu->
bezt[1].
vec[1][0] += period;
298 fcu->
bezt[1].
vec[2][0] += period;
311 const bool force_all,
312 const BitSpan successful_remaps)
317 int total_failed = 0;
318 for (
int i = 0; i <
count; i++) {
319 const bool cur_index_evaluated =
ELEM(index, i, -1) || force_all;
320 if (!cur_index_evaluated) {
325 if (successful_remaps[i]) {
335 if (total_failed == 0) {
345 "Could not insert %i keyframe(s) due to zero NLA influence, base value, or value "
346 "remapping failed: %s.%s for indices [%s]",
382 BitVector<> successful_remaps(values.size(),
false);
384 nla_context, &
ptr, &prop, values, index, anim_eval_context, force_all, successful_remaps);
386 reports,
ptr, &prop, index, values.size(),
false, successful_remaps);
387 return successful_remaps;
398 if (adt && adt->
action == act) {
400 nla_cache, id_ptr, adt, anim_eval_context);
403 return remapped_frame;
406 *r_nla_context =
nullptr;
419 settings.keyframe_type = keytype;
434 if (fcu ==
nullptr) {
441 reports,
RPT_ERROR,
"No RNA pointer available to retrieve values for keyframing from");
445 if (prop ==
nullptr) {
453 "Could not insert keyframe, as RNA path is invalid for the given ID (ID = %s, "
472 values.as_mutable_span(),
481 float current_value = 0.0f;
482 if (index >= 0 && index < values.size()) {
483 current_value = values[index];
487 if (!successful_remaps[index]) {
491 const float cfra = anim_eval_context->
eval_time;
497 "Failed to insert keys on F-Curve with path '%s[%d]', ensure that it is not "
498 "locked or sampled, and try removing F-Modifiers",
511 const char rna_path[],
513 const float fcurve_frame,
534 const bool is_new_curve = (fcu->
totvert == 0);
539 if (is_cyclic_action && fcu->
totvert == 1) {
547 fcu, fcurve_frame, curval, keytype,
flag);
550 if (is_cyclic_action && is_new_curve) {
570 if (adt->
action ==
nullptr) {
586 if (
ELEM(
nullptr,
id, adt)) {
598 "Could not delete keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
600 rna_path.
path.c_str());
610 int array_index = rna_path.
index.value_or(0);
611 int array_index_max = array_index + 1;
613 if (!rna_path.
index.has_value()) {
619 if (array_index_max == array_index) {
624 Action &action = act->wrap();
636 for (; array_index < array_index_max; array_index++) {
638 if (fcurve ==
nullptr) {
642 modified_fcurves.
append(fcurve);
648 for (; array_index < array_index_max; array_index++) {
651 if (fcu ==
nullptr) {
658 "Not deleting keyframe for locked F-Curve '%s' for %s '%s'",
666 modified_fcurves.
append(fcu);
672 for (
FCurve *fcurve : modified_fcurves) {
680 return modified_fcurves.
size();
690 if (
ELEM(
nullptr,
id, adt)) {
702 "Could not clear keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
704 rna_path.
path.c_str());
714 Action &action = act->wrap();
721 if (rna_path.index.has_value() && rna_path.index.value() != fcurve.array_index) {
730 for (
FCurve *fcu : fcurves) {
738 int array_index = rna_path.index.value_or(0);
739 int array_index_max = array_index + 1;
740 if (!rna_path.index.has_value()) {
747 if (array_index_max == array_index) {
752 for (; array_index < array_index_max; array_index++) {
755 if (fcu ==
nullptr) {
762 "Not clearing all keyframes from locked F-Curve '%s' for %s '%s'",
787 const std::optional<StringRefNull> channel_group,
788 const std::string &rna_path,
797 BLI_assert(action->wrap().is_action_legacy());
800 if (channel_group.has_value()) {
801 group = channel_group->c_str();
806 group = default_group.has_value() ? default_group->c_str() :
nullptr;
809 int property_array_index = 0;
811 for (
float value : values) {
812 if (!keying_mask[property_array_index]) {
813 combined_result.
add(SingleKeyingResult::UNABLE_TO_INSERT_TO_NLA_STACK);
814 property_array_index++;
823 property_array_index,
828 combined_result.
add(keying_result);
829 property_array_index++;
831 return combined_result;
844 const std::string &rna_path,
845 const std::optional<PropertySubType> prop_subtype,
846 const std::optional<blender::StringRefNull> channel_group,
854 Strip *strip = layer.strip(0);
858 {rna_path, key_data.
array_index, prop_subtype, channel_group},
868 const std::optional<StringRefNull> channel_group,
870 const float scene_frame,
878 "The animated ID should not be using another Action than the one passed to this function");
883 "The conditions that would cause this Slot assigment to fail (such as the ID not being "
884 "animatible) should have been caught and handled by higher-level functions.");
899 for (
const RNAPath &rna_path : rna_paths) {
903 rna_pointer, rna_path.path.c_str(), &
ptr, &prop);
904 if (!path_resolved) {
906 "Failed to insert key on slot %s due to unresolved RNA path: %s\n",
908 rna_path.path.c_str());
909 combined_result.
add(SingleKeyingResult::CANNOT_RESOLVE_PATH);
916 const std::optional<blender::StringRefNull> this_rna_path_channel_group =
917 channel_group.has_value() ? *channel_group :
923 for (
const int property_index : rna_values.
index_range()) {
927 if (rna_path.index.has_value() && *rna_path.index != -1 && *rna_path.index != property_index)
932 const KeyInsertData key_data = {{scene_frame, rna_values[property_index]}, property_index};
937 *rna_path_id_to_prop,
939 this_rna_path_channel_group,
943 combined_result.
add(result);
949 return combined_result;
954 const std::optional<StringRefNull> channel_group,
956 const std::optional<float> scene_frame,
968 if (adt ==
nullptr) {
969 combined_result.
add(SingleKeyingResult::ID_NOT_ANIMATABLE);
970 return combined_result;
974 combined_result.
add(SingleKeyingResult::CANNOT_CREATE_FCURVE, rna_paths.
size());
975 return combined_result;
982 Action &action = dna_action->wrap();
991 scene_frame.value_or(anim_eval_context.
eval_time),
997 ListBase nla_cache = {
nullptr,
nullptr};
1008 for (
const RNAPath &rna_path : rna_paths) {
1012 struct_pointer, rna_path.path.c_str(), &
ptr, &prop);
1013 if (!path_resolved) {
1014 combined_result.
add(SingleKeyingResult::CANNOT_RESOLVE_PATH);
1028 rna_path.index.value_or(-1),
1035 if (!rna_path_id_to_prop.has_value()) {
1052 bool at_least_one_would_succeed =
false;
1053 for (
int i = 0; i < rna_values.
size(); i++) {
1062 at_least_one_would_succeed =
true;
1071 at_least_one_would_succeed =
true;
1078 if (at_least_one_would_succeed) {
1088 rna_path_id_to_prop->c_str(),
1091 insert_key_flags_adjusted,
1094 combined_result.
merge(result);
1099 if (combined_result.
get_count(SingleKeyingResult::SUCCESS) > 0) {
1107 if (!
ELEM(adt->
action,
nullptr, dna_action)) {
1112 return combined_result;
Functions and classes to work with Actions.
Functionality to iterate an Action in various ways.
Functions for backward compatibility with the legacy Action API.
Functions to work with AnimData.
Functions to modify FCurves.
Functions to insert, delete or modify keyframes.
Helper functions for animation to interact with the RNA system.
Functions to work with the visual keying system.
Blender kernel action and pose functionality.
AnimData * BKE_animdata_ensure_id(ID *id)
AnimData * BKE_animdata_from_id(const ID *id)
void BKE_animsys_free_nla_keyframing_context_cache(struct ListBase *cache)
void BKE_animsys_nla_remap_keyframe_values(struct NlaKeyframingContext *context, struct PointerRNA *prop_ptr, struct PropertyRNA *prop, const blender::MutableSpan< float > values, int index, const struct AnimationEvalContext *anim_eval_context, bool *r_force_all, blender::BitVector<> &r_values_mask)
struct NlaKeyframingContext * BKE_animsys_get_nla_keyframing_context(struct ListBase *cache, struct PointerRNA *ptr, struct AnimData *adt, const struct AnimationEvalContext *anim_eval_context)
bool BKE_fcurve_is_keyframable(const FCurve *fcu)
int BKE_fcurve_bezt_binarysearch_index(const BezTriple array[], float frame, int arraylen, bool *r_replace)
FModifier * add_fmodifier(ListBase *modifiers, int type, FCurve *owner_fcu)
bool BKE_fcurve_is_empty(const FCurve *fcu)
bool BKE_fcurve_is_protected(const FCurve *fcu)
const char * BKE_idtype_idcode_to_name(short idcode)
float BKE_nla_tweakedit_remap(AnimData *adt, float cframe, short mode)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
#define BLI_assert_msg(a, msg)
A dynamically sized string ADT.
char * BLI_dynstr_get_cstring(const DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_id_tag_update_ex(Main *bmain, ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
@ ID_RECALC_ANIMATION_NO_FLUSH
@ MANUALKEY_FLAG_INSERTNEEDED
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
constexpr int64_t size() const
static constexpr int64_t not_found
constexpr int64_t find(char c, int64_t pos=0) const
void append(const T &value)
IndexRange index_range() const
MutableSpan< T > as_mutable_span()
Span< T > as_span() const
void layer_keystrip_ensure()
Layer * get_layer_for_keyframing()
bool is_action_layered() const
Slot * slot_for_handle(slot_handle_t handle)
void merge(const CombinedKeyingResult &other)
int get_count(const SingleKeyingResult result) const
void generate_reports(ReportList *reports, eReportType report_level=RPT_ERROR)
void add(SingleKeyingResult result, int count=1)
const T & data(const Action &owning_action) const
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void MEM_freeN(void *vmemh)
static void error(const char *str)
bool action_treat_as_legacy(const bAction &action)
void foreach_fcurve_in_action_slot(Action &action, slot_handle_t handle, FunctionRef< void(FCurve &fcurve)> callback)
bool action_fcurve_remove(Action &action, FCurve &fcu)
void assert_baklava_phase_1_invariants(const Action &action)
static SingleKeyingResult insert_key_layer(Main *bmain, Action &action, Layer &layer, const Slot &slot, const std::string &rna_path, const std::optional< PropertySubType > prop_subtype, const std::optional< blender::StringRefNull > channel_group, const KeyInsertData &key_data, const KeyframeSettings &key_settings, const eInsertKeyFlags insert_key_flags)
static Vector< float > get_keyframe_values(PointerRNA *ptr, PropertyRNA *prop, const bool visual_key)
KeyframeSettings get_keyframe_settings(bool from_userprefs)
Slot * assign_action_ensure_slot_for_keying(Action &action, ID &animated_id)
bAction * id_action_ensure(Main *bmain, ID *id)
FCurve * action_fcurve_ensure(Main *bmain, bAction *act, const char group[], PointerRNA *ptr, FCurveDescriptor fcurve_descriptor)
void update_autoflags_fcurve_direct(FCurve *fcu, PropertyRNA *prop)
Vector< float > visualkey_get_values(PointerRNA *ptr, PropertyRNA *prop)
bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
static SingleKeyingResult insert_keyframe_value(FCurve *fcu, float cfra, float curval, eBezTriple_KeyframeType keytype, eInsertKeyFlags flag)
static CombinedKeyingResult insert_key_legacy_action(Main *bmain, bAction *action, PointerRNA *ptr, PropertyRNA *prop, const std::optional< StringRefNull > channel_group, const std::string &rna_path, const float frame, const Span< float > values, eInsertKeyFlags insert_key_flag, eBezTriple_KeyframeType key_type, const BitSpan keying_mask)
Vector< float > get_rna_values(PointerRNA *ptr, PropertyRNA *prop)
static CombinedKeyingResult insert_key_layered_action(Main *bmain, Action &action, PointerRNA *rna_pointer, const std::optional< StringRefNull > channel_group, const blender::Span< RNAPath > rna_paths, const float scene_frame, const KeyframeSettings &key_settings, const eInsertKeyFlags insert_key_flags)
static void get_keyframe_values_create_reports(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, const int index, const int count, const bool force_all, const BitSpan successful_remaps)
int clear_keyframe(Main *bmain, ReportList *reports, ID *id, const RNAPath &rna_path)
const FCurve * fcurve_find(Span< const FCurve * > fcurves, FCurveDescriptor fcurve_descriptor)
int delete_keyframe(Main *bmain, ReportList *reports, ID *id, const RNAPath &rna_path, float cfra)
Main Delete Key-Framing API call.
bool fcurve_delete_keyframe_at_time(FCurve *fcurve, float time)
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.
SingleKeyingResult insert_vert_fcurve(FCurve *fcu, const float2 position, const KeyframeSettings &settings, eInsertKeyFlags flag)
Main Key-framing API call.
Span< FCurve * > fcurves_for_action_slot(Action &action, slot_handle_t slot_handle)
static void make_new_fcurve_cyclic(FCurve *fcu, const blender::float2 &action_range)
Action * get_action(ID &animated_id)
static BitVector nla_map_keyframe_values_and_generate_reports(const MutableSpan< float > values, const int index, PointerRNA &ptr, PropertyRNA &prop, NlaKeyframingContext *nla_context, const AnimationEvalContext *anim_eval_context, ReportList *reports, bool *force_all)
const std::optional< StringRefNull > default_channel_group_for_path(const PointerRNA *animated_struct, const StringRef prop_rna_path)
FCurve * fcurve_find_in_action(bAction *act, FCurveDescriptor fcurve_descriptor)
static float nla_time_remap(float time, const AnimationEvalContext *anim_eval_context, PointerRNA *id_ptr, AnimData *adt, bAction *act, ListBase *nla_cache, NlaKeyframingContext **r_nla_context)
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.
bool is_keying_flag(const Scene *scene, eKeying_Flag flag)
bool key_insertion_may_create_fcurve(eInsertKeyFlags insert_key_flags)
static SingleKeyingResult insert_keyframe_fcurve_value(Main *bmain, PointerRNA *ptr, PropertyRNA *prop, bAction *act, const char group[], const char rna_path[], int array_index, const float fcurve_frame, float curval, eBezTriple_KeyframeType keytype, eInsertKeyFlags flag)
static void deg_tag_after_keyframe_delete(Main *bmain, ID *id, AnimData *adt)
void animdata_fcurve_delete(bAnimContext *ac, AnimData *adt, FCurve *fcu)
eInsertKeyFlags get_keyframing_flags(Scene *scene)
@ UNABLE_TO_INSERT_TO_NLA_STACK
@ FCURVE_NOT_KEYFRAMEABLE
PropertyType RNA_property_type(PropertyRNA *prop)
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
const char * RNA_property_ui_name(const PropertyRNA *prop)
PropertySubType RNA_property_subtype(PropertyRNA *prop)
PointerRNA RNA_id_pointer_create(ID *id)
std::optional< std::string > RNA_path_from_ID_to_property(const PointerRNA *ptr, PropertyRNA *prop)
bool RNA_path_resolve_property(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
std::optional< int > index
eBezTriple_KeyframeType keyframe_type