57#ifdef WITH_ANIM_BAKLAVA
73 if (typeinfo !=
nullptr) {
114 if (iat->
adt ==
nullptr) {
152 "Could not set action '%s' onto ID '%s', as it does not have suitably rooted paths "
159 if (*act_slot == act) {
170 if (act ==
nullptr) {
185 if (adt ==
nullptr) {
206 if (adt ==
nullptr) {
213 BKE_report(reports,
RPT_ERROR,
"Cannot change action, as it is still being edited in NLA");
217#ifdef WITH_ANIM_BAKLAVA
229 return !is_tweaking_strip;
234 const int idcode =
GS(owner->
name);
236 if (action ==
nullptr) {
241#ifdef WITH_ANIM_BAKLAVA
252 if (action->
idroot == 0) {
258 return (action->
idroot == idcode);
281#ifdef WITH_ANIM_BAKLAVA
284 "Expecting action un-assignment to always work when not in NLA tweak mode");
292#ifdef WITH_ANIM_BAKLAVA
296 BLI_assert_msg(unassign_ok,
"Expecting tmpaction un-assignment to always work");
328 if (adt ==
nullptr) {
365 std::optional<Library *> owner_library,
375 if (adt ==
nullptr) {
400 reinterpret_cast<ID *
>(dadt->
action),
407 reinterpret_cast<ID *
>(dadt->
tmpact),
412 else if (do_id_user) {
456 if ((id_to && id_from) && (
GS(id_to->
name) !=
GS(id_from->
name))) {
473 const bool set_newid,
474 const bool do_linked_id)
488 const bool assign_ok = assign_action(&cloned_action->wrap(), *
id);
489 BLI_assert_msg(assign_ok,
"Expected action assignment to work when copying animdata");
501 const bool assign_ok = assign_tmpaction(&cloned_action->wrap(), {*id, *adt});
502 BLI_assert_msg(assign_ok,
"Expected tmp-action assignment to work when copying animdata");
523 const uint duplicate_flags)
537 if (
ELEM(
nullptr, dst, src)) {
545 "Merging AnimData blocks while editing NLA is dangerous as it may cause data corruption");
570 ListBase tracks = {
nullptr,
nullptr};
578 ListBase drivers = {
nullptr,
nullptr};
590 if (dtar->id == src_id) {
615 return (path && basepath) &&
STRPREFIX(path, basepath);
619 const char *old_basepath,
620 const char *new_basepath)
623 if (
STREQ(old_basepath, new_basepath)) {
642 const char *src_basepath,
643 const char *dst_basepath)
646 if (
ELEM(
nullptr, srcAct, dstAct, src_basepath, dst_basepath)) {
649 "srcAct: %p, dstAct: %p, src_basepath: %p, dst_basepath: %p has insufficient "
653 (
void *)src_basepath,
654 (
void *)dst_basepath);
667 fcurves_to_move.append(&fcurve);
672 for (
FCurve *fcurve_to_move : fcurves_to_move) {
680 const char *src_basepath,
681 const char *dst_basepath)
696 AnimData *srcAdt =
nullptr, *dstAdt =
nullptr;
699 if (
ELEM(
nullptr, srcID, dstID)) {
701 CLOG_ERROR(&
LOG,
"no source or destination ID to separate AnimData with");
710 if (
ELEM(
nullptr, srcAdt, dstAdt)) {
720 if (dstAdt->action == srcAdt->
action) {
722 "Source and Destination share animation! "
723 "('%s' and '%s' both use '%s') Making new empty action",
730 BLI_assert_msg(unassign_ok,
"Expected Action unassignment to work");
736 if (!dstAdt->action) {
755 basepath_change->src_basepath,
756 basepath_change->dst_basepath);
764 srcAdt, dstAdt, basepath_change->src_basepath, basepath_change->dst_basepath);
797 char *prefixPtr = strstr(oldpath, prefix);
798 if (prefixPtr ==
nullptr) {
802 char *oldNamePtr = strstr(oldpath, oldName);
803 if (oldNamePtr ==
nullptr) {
807 int prefixLen = strlen(prefix);
808 int oldNameLen = strlen(oldName);
813 if (prefixPtr + prefixLen == oldNamePtr) {
817 const char *postfixPtr = oldNamePtr + oldNameLen;
818 char *newPath =
nullptr;
821 if (prefixPtr > oldpath) {
865 bool is_changed =
false;
867 for (
FCurve *fcu : curves) {
868 if (fcu->rna_path ==
nullptr) {
871 const char *old_path = fcu->rna_path;
874 owner_id, prefix, oldKey, newKey, fcu->rna_path, verify_paths);
878 if (fcu->rna_path != old_path) {
881 if (oldName !=
nullptr && (agrp !=
nullptr) &&
STREQ(oldName, agrp->
name)) {
900 bool is_changed =
false;
904 if (fcu->rna_path !=
nullptr) {
905 const char *old_rna_path = fcu->rna_path;
907 owner_id, prefix, oldKey, newKey, fcu->rna_path, verify_paths);
908 is_changed |= (fcu->rna_path != old_rna_path);
910 if (fcu->driver ==
nullptr) {
919 if (dtar->rna_path && dtar->id) {
920 const char *old_rna_path = dtar->rna_path;
922 dtar->id, prefix, oldKey, newKey, dtar->rna_path, verify_paths);
923 is_changed |= (dtar->rna_path != old_rna_path);
926 if (strstr(prefix,
"bones")) {
927 if (((dtar->id) && (
GS(dtar->id->name) ==
ID_OB) &&
928 (!ref_id || ((
Object *)(dtar->id))->data == ref_id)) &&
929 (dtar->pchan_name[0]) &&
STREQ(oldName, dtar->pchan_name))
932 STRNCPY(dtar->pchan_name, newName);
952 bool is_changed =
false;
956 if (strip->act !=
nullptr) {
966 if (is_changed_action) {
969 is_changed |= is_changed_action;
974 owner_id, prefix, oldName, newName, oldKey, newKey, &strip->strips, verify_paths);
994 if (
ELEM(
nullptr, owner_id, old_path)) {
1002 if ((oldName !=
nullptr) && (newName !=
nullptr)) {
1004 const size_t name_old_len = strlen(oldName);
1005 const size_t name_new_len = strlen(newName);
1006 char *name_old_esc =
static_cast<char *
>(
1008 char *name_new_esc =
static_cast<char *
>(
1023 printf(
"%s | %s | oldpath = %p ", oldN, newN, old_path);
1027 printf(
"path rename result = %p\n", result);
1041 const char *oldName,
1042 const char *newName,
1050 if (
ELEM(
nullptr, owner_id, act)) {
1055 if ((oldName !=
nullptr) && (newName !=
nullptr)) {
1057 const size_t name_old_len = strlen(oldName);
1058 const size_t name_new_len = strlen(newName);
1059 char *name_old_esc =
static_cast<char *
>(
1061 char *name_new_esc =
static_cast<char *
>(
1093 const char *oldName,
1094 const char *newName,
1101 if (
ELEM(
nullptr, owner_id, adt)) {
1104 bool is_self_changed =
false;
1106 if ((oldName !=
nullptr) && (newName !=
nullptr)) {
1108 const size_t name_old_len = strlen(oldName);
1109 const size_t name_new_len = strlen(newName);
1110 char *name_old_esc =
static_cast<char *
>(
1112 char *name_new_esc =
static_cast<char *
>(
1125 if (adt->
action !=
nullptr) {
1153 owner_id, ref_id, prefix, oldName, newName, oldN, newN, &adt->
drivers, verify_paths);
1157 owner_id, prefix, oldName, newName, oldN, newN, &nlt->strips, verify_paths);
1160 if (is_self_changed) {
1174 bool any_removed =
false;
1180 for (fcu =
static_cast<FCurve *
>(curves->first); fcu; fcu = fcn) {
1197 bool any_removed =
false;
1204 *strip->act, strip->action_slot_handle, prefix);
1221 bool any_removed =
false;
1250 for (
FCurve *fcu : fcurves) {
1305 if (adt !=
nullptr) {
1324#define ANIMDATA_IDS_CB(first) \
1325 for (id = static_cast<ID *>(first); id; id = static_cast<ID *>(id->next)) { \
1326 AnimData *adt = BKE_animdata_from_id(id); \
1334#define ANIMDATA_NODETREE_IDS_CB(first, NtId_Type) \
1335 for (id = static_cast<ID *>(first); id; id = static_cast<ID *>(id->next)) { \
1336 AnimData *adt = BKE_animdata_from_id(id); \
1337 NtId_Type *ntp = (NtId_Type *)id; \
1338 if (ntp->nodetree) { \
1339 AnimData *adt2 = BKE_animdata_from_id((ID *)ntp->nodetree); \
1431 const char *oldName,
1432 const char *newName)
1434 Main *bmain =
G.main;
1441 const char *oldName,
1442 const char *newName,
1443 const int oldSubscript,
1444 const int newSubscript,
1445 const bool verify_paths)
1449 id, adt, ref_id, prefix, oldName, newName, oldSubscript, newSubscript, verify_paths);
1485 if (!iat || !iat->
adt) {
1490 if (adt ==
nullptr) {
Functions and classes to work with Actions.
Functionality to iterate an Action in various ways.
Functions for backward compatibility with the legacy Action API.
Blender kernel action and pose functionality.
eAnimData_MergeCopy_Modes
void BKE_fcurve_foreach_id(FCurve *fcu, LibraryForeachIDData *data)
void BKE_fcurve_blend_write_listbase(BlendWriter *writer, ListBase *fcurves)
void BKE_fcurve_blend_read_data_listbase(BlendDataReader *reader, ListBase *fcurves)
void BKE_fcurves_free(ListBase *list)
void BKE_fcurves_copy(ListBase *dst, ListBase *src)
void BKE_fcurve_free(FCurve *fcu)
#define DRIVER_TARGETS_USED_LOOPER_BEGIN(dvar)
#define DRIVER_TARGETS_LOOPER_END
@ IDTYPE_FLAGS_NO_ANIMDATA
const IDTypeInfo * BKE_idtype_get_info_from_idcode(short id_code)
@ LIB_ID_CREATE_NO_USER_REFCOUNT
struct ID * BKE_id_copy_in_lib(Main *bmain, std::optional< Library * > owner_library, const ID *id, const ID *new_owner_id, ID **new_id_p, int flag)
ID * BKE_id_copy(Main *bmain, const ID *id)
#define BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data_, func_call_)
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(data_, id_super_, cb_flag_)
void BKE_nla_tracks_copy_from_adt(Main *bmain, AnimData *adt_dest, const AnimData *adt_source, int flag)
void BKE_nla_tweakmode_exit(OwnedAnimData owned_adt)
void BKE_nla_tweakmode_exit_nofollowptr(AnimData *adt)
void BKE_nla_tracks_copy(Main *bmain, ListBase *dst, const ListBase *src, int flag)
void BKE_nla_blend_write(BlendWriter *writer, ListBase *tracks)
void BKE_nla_tracks_free(ListBase *tracks, bool do_id_user)
void BKE_nla_liboverride_post_process(ID *id, AnimData *adt)
void BKE_nla_blend_read_data(BlendDataReader *reader, ID *id_owner, ListBase *tracks)
void BKE_nla_strip_foreach_id(NlaStrip *strip, LibraryForeachIDData *data)
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_array_alloca(arr, realsize)
#define BLI_assert_unreachable()
#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()
void BLI_dynstr_nappend(DynStr *__restrict ds, const char *cstr, int len) ATTR_NONNULL()
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr) ATTR_NONNULL()
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void void void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
char * BLI_sprintfN(const char *__restrict format,...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1
#define STRNCPY(dst, src)
size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define UNUSED_VARS_NDEBUG(...)
#define BLO_write_struct(writer, struct_name, data_ptr)
void BLO_write_string(BlendWriter *writer, const char *data_ptr)
#define BLO_read_struct_list(reader, struct_name, list)
#define BLO_read_struct(reader, struct_name, ptr_p)
#define CLOG_ERROR(clg_ref,...)
#define CLOG_WARN(clg_ref,...)
void DEG_id_tag_update(ID *id, unsigned int flags)
ID and Library types, which are fundamental for SDNA.
#define ID_IS_LINKED(_id)
#define ID_IS_OVERRIDE_LIBRARY(_id)
#define ID_NEW_SET(_id, _idn)
#define USER_EXPERIMENTAL_TEST(userdef, member)
Read Guarded memory(de)allocation.
static bool fcurves_path_remove_from_listbase(const char *prefix, ListBase *curves)
void BKE_animdata_main_cb(Main *bmain, const FunctionRef< void(ID *, AnimData *)> func)
bool BKE_animdata_copy_id(Main *bmain, ID *id_to, ID *id_from, const int flag)
bool BKE_animdata_id_is_animated(const ID *id)
static void animdata_copy_id_action(Main *bmain, ID *id, const bool set_newid, const bool do_linked_id)
static void adt_apply_all_fcurves_cb(ID *id, AnimData *adt, const FunctionRef< void(ID *, FCurve *)> func)
bool BKE_animdata_action_ensure_idroot(const ID *owner, bAction *action)
bool BKE_animdata_fix_paths_remove(ID *id, const char *prefix)
static void nlastrips_apply_all_curves_cb(ID *id, ListBase *strips, const FunctionRef< void(ID *, FCurve *)> func)
void BKE_animdata_fix_paths_rename_all_ex(Main *bmain, ID *ref_id, const char *prefix, const char *oldName, const char *newName, const int oldSubscript, const int newSubscript, const bool verify_paths)
void BKE_animdata_merge_copy(Main *bmain, ID *dst_id, ID *src_id, eAnimData_MergeCopy_Modes action_mode, bool fix_drivers)
void BKE_animdata_blend_write(BlendWriter *writer, ID *id)
static bool drivers_path_rename_fix(ID *owner_id, ID *ref_id, const char *prefix, const char *oldName, const char *newName, const char *oldKey, const char *newKey, ListBase *curves, bool verify_paths)
static bool check_rna_path_is_valid(ID *owner_id, const char *path)
AnimData * BKE_animdata_ensure_id(ID *id)
static bool nlastrips_path_rename_fix(ID *owner_id, const char *prefix, const char *oldName, const char *newName, const char *oldKey, const char *newKey, ListBase *strips, bool verify_paths)
bool id_can_have_animdata(const ID *id)
void BKE_action_fix_paths_rename(ID *owner_id, bAction *act, const char *prefix, const char *oldName, const char *newName, int oldSubscript, int newSubscript, bool verify_paths)
void BKE_animdata_foreach_id(AnimData *adt, LibraryForeachIDData *data)
#define ANIMDATA_NODETREE_IDS_CB(first, NtId_Type)
bool id_type_can_have_animdata(const short id_type)
static void fcurves_listbase_apply_cb(ID *id, ListBase *fcurves, const FunctionRef< void(ID *, FCurve *)> func)
void BKE_fcurves_id_cb(ID *id, const FunctionRef< void(ID *, FCurve *)> func)
bool BKE_animdata_action_editable(const AnimData *adt)
bool BKE_animdata_set_action(ReportList *reports, ID *id, bAction *act)
void BKE_animdata_free(ID *id, const bool do_id_user)
static bool animpath_matches_basepath(const char path[], const char basepath[])
AnimData * BKE_animdata_from_id(const ID *id)
void BKE_fcurves_main_cb(Main *bmain, const FunctionRef< void(ID *, FCurve *)> func)
static bool nlastrips_path_remove_fix(const char *prefix, ListBase *strips)
void BKE_animdata_blend_read_data(BlendDataReader *reader, ID *id)
static char * rna_path_rename_fix(ID *owner_id, const char *prefix, const char *oldName, const char *newName, char *oldpath, bool verify_paths)
AnimData * BKE_animdata_copy_in_lib(Main *bmain, std::optional< Library * > owner_library, AnimData *adt, const int flag)
static bool animdata_set_action(ReportList *reports, ID *id, bAction **act_slot, bAction *act)
static void fcurves_apply_cb(ID *id, blender::Span< FCurve * > fcurves, const FunctionRef< void(ID *, FCurve *)> func)
void BKE_animdata_liboverride_post_process(ID *id)
void BKE_animdata_duplicate_id_action(Main *bmain, ID *id, const uint duplicate_flags)
static void animpath_update_basepath(FCurve *fcu, const char *old_basepath, const char *new_basepath)
#define ANIMDATA_IDS_CB(first)
void BKE_animdata_transfer_by_basepath(Main *bmain, ID *srcID, ID *dstID, ListBase *basepaths)
void BKE_animdata_fix_paths_rename_all(ID *ref_id, const char *prefix, const char *oldName, const char *newName)
bool BKE_animdata_set_tmpact(ReportList *reports, ID *id, bAction *act)
void BKE_animdata_copy_id_action(Main *bmain, ID *id)
static void action_move_fcurves_by_basepath(bAction *srcAct, const animrig::slot_handle_t src_slot_handle, bAction *dstAct, const animrig::slot_handle_t dst_slot_handle, const char *src_basepath, const char *dst_basepath)
char * BKE_animsys_fix_rna_path_rename(ID *owner_id, char *old_path, const char *prefix, const char *oldName, const char *newName, int oldSubscript, int newSubscript, bool verify_paths)
AnimData * BKE_animdata_copy(Main *bmain, AnimData *adt, const int flag)
static void animdata_move_drivers_by_basepath(AnimData *srcAdt, AnimData *dstAdt, const char *src_basepath, const char *dst_basepath)
void BKE_animdata_fix_paths_rename(ID *owner_id, AnimData *adt, ID *ref_id, const char *prefix, const char *oldName, const char *newName, int oldSubscript, int newSubscript, bool verify_paths)
static bool fcurves_path_rename_fix(ID *owner_id, const char *prefix, const char *oldName, const char *newName, const char *oldKey, const char *newKey, blender::Span< FCurve * > curves, bool verify_paths)
Slot & slot_add_for_id(const ID &animated_id)
bool is_action_legacy() const
bool is_action_layered() const
bool is_slot_animated(slot_handle_t slot_handle) const
static void users_invalidate(Main &bmain)
static constexpr slot_handle_t unassigned
void MEM_freeN(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
void *(* MEM_dupallocN)(const void *vmemh)
Vector< const FCurve * > fcurves_all(const bAction *action)
bool action_fcurves_remove(bAction &action, slot_handle_t slot_handle, StringRefNull rna_path_prefix)
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)
void action_fcurve_move(Action &action_dst, slot_handle_t action_slot_dst, Action &action_src, FCurve &fcurve)
Action & action_add(Main &bmain, StringRefNull name)
decltype(::ActionSlot::handle) slot_handle_t
bool assign_tmpaction(bAction *action, OwnedAnimData owned_adt)
bool unassign_action(ID &animated_id)
bool assign_action(bAction *action, ID &animated_id)
bNodeTree * node_tree_from_id(ID *id)
PointerRNA RNA_id_pointer_create(ID *id)
bool RNA_path_resolve_property(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)