diff options
Diffstat (limited to 'source/blender/blenkernel/intern/action.c')
-rw-r--r-- | source/blender/blenkernel/intern/action.c | 207 |
1 files changed, 188 insertions, 19 deletions
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 64a8ae15fd3..126063288d8 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -47,6 +47,7 @@ #include "BLT_translation.h" #include "BKE_action.h" +#include "BKE_anim_data.h" #include "BKE_anim_visualization.h" #include "BKE_animsys.h" #include "BKE_armature.h" @@ -60,6 +61,7 @@ #include "BKE_main.h" #include "BKE_object.h" +#include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" #include "BIK_api.h" @@ -198,17 +200,17 @@ static void action_blend_read_data(BlendDataReader *reader, ID *id) bAction *act = (bAction *)id; BLO_read_list(reader, &act->curves); - BLO_read_list(reader, &act->chanbase); // XXX deprecated - old animation system + BLO_read_list(reader, &act->chanbase); /* XXX deprecated - old animation system */ BLO_read_list(reader, &act->groups); BLO_read_list(reader, &act->markers); - // XXX deprecated - old animation system <<< + /* XXX deprecated - old animation system <<< */ LISTBASE_FOREACH (bActionChannel *, achan, &act->chanbase) { BLO_read_data_address(reader, &achan->grp); BLO_read_list(reader, &achan->constraintChannels); } - // >>> XXX deprecated - old animation system + /* >>> XXX deprecated - old animation system */ BKE_fcurve_blend_read_data(reader, &act->curves); @@ -229,12 +231,12 @@ static void action_blend_read_lib(BlendLibReader *reader, ID *id) { bAction *act = (bAction *)id; - // XXX deprecated - old animation system <<< + /* XXX deprecated - old animation system <<< */ LISTBASE_FOREACH (bActionChannel *, chan, &act->chanbase) { BLO_read_id_address(reader, act->id.lib, &chan->ipo); blend_read_lib_constraint_channels(reader, &act->id, &chan->constraintChannels); } - // >>> XXX deprecated - old animation system + /* >>> XXX deprecated - old animation system */ BKE_fcurve_blend_read_lib(reader, &act->id, &act->curves); @@ -256,12 +258,12 @@ static void action_blend_read_expand(BlendExpander *expander, ID *id) { bAction *act = (bAction *)id; - // XXX deprecated - old animation system -------------- + /* XXX deprecated - old animation system -------------- */ LISTBASE_FOREACH (bActionChannel *, chan, &act->chanbase) { BLO_expand(expander, chan->ipo); blend_read_expand_constraint_channels(expander, &chan->constraintChannels); } - // --------------------------------------------------- + /* --------------------------------------------------- */ /* F-Curves in Action */ BKE_fcurve_blend_read_expand(expander, &act->curves); @@ -281,7 +283,7 @@ IDTypeInfo IDType_ID_AC = { .name = "Action", .name_plural = "actions", .translation_context = BLT_I18NCONTEXT_ID_ACTION, - .flags = 0, + .flags = IDTYPE_FLAGS_NO_ANIMDATA, .init_data = NULL, .copy_data = action_copy_data, @@ -294,6 +296,8 @@ IDTypeInfo IDType_ID_AC = { .blend_read_data = action_blend_read_data, .blend_read_lib = action_blend_read_lib, .blend_read_expand = action_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; /* ***************** Library data level operations on action ************** */ @@ -302,20 +306,13 @@ bAction *BKE_action_add(Main *bmain, const char name[]) { bAction *act; - act = BKE_libblock_alloc(bmain, ID_AC, name, 0); + act = BKE_id_new(bmain, ID_AC, name); return act; } /* .................................. */ -bAction *BKE_action_copy(Main *bmain, const bAction *act_src) -{ - bAction *act_copy; - BKE_id_copy(bmain, &act_src->id, (ID **)&act_copy); - return act_copy; -} - /* *************** Action Groups *************** */ /* Get the active action-group for an Action */ @@ -774,7 +771,7 @@ const char *BKE_pose_ikparam_get_name(bPose *pose) } /** - * Allocate a new pose on the heap, and copy the src pose and it's channels + * Allocate a new pose on the heap, and copy the src pose and its channels * into the new pose. *dst is set to the newly allocated structure, and assumed to be NULL. * * \param dst: Should be freed already, makes entire duplicate. @@ -833,7 +830,7 @@ void BKE_pose_copy_data_ex(bPose **dst, if (copy_constraints) { BKE_constraints_copy_ex( - &listb, &pchan->constraints, flag, true); // BKE_constraints_copy NULLs listb + &listb, &pchan->constraints, flag, true); /* BKE_constraints_copy NULLs listb */ pchan->constraints = listb; /* XXX: This is needed for motionpath drawing to work. @@ -1817,8 +1814,9 @@ void what_does_obaction(Object *ob, workob->adt = &adt; adt.action = act; + BKE_animdata_action_ensure_idroot(&workob->id, act); - /* execute effects of Action on to workob (or it's PoseChannels) */ + /* execute effects of Action on to workob (or its PoseChannels) */ BKE_animsys_evaluate_animdata(&workob->id, &adt, anim_eval_context, ADT_RECALC_ANIM, false); } } @@ -1849,3 +1847,174 @@ void BKE_pose_check_uuids_unique_and_report(const bPose *pose) BLI_gset_free(used_uuids, NULL); } + +void BKE_pose_blend_write(BlendWriter *writer, bPose *pose, bArmature *arm) +{ + /* Write each channel */ + if (pose == NULL) { + return; + } + + BLI_assert(arm != NULL); + + /* Write channels */ + LISTBASE_FOREACH (bPoseChannel *, chan, &pose->chanbase) { + /* Write ID Properties -- and copy this comment EXACTLY for easy finding + * of library blocks that implement this.*/ + if (chan->prop) { + IDP_BlendWrite(writer, chan->prop); + } + + BKE_constraint_blend_write(writer, &chan->constraints); + + animviz_motionpath_blend_write(writer, chan->mpath); + + /* Prevent crashes with autosave, + * when a bone duplicated in edit-mode has not yet been assigned to its pose-channel. + * Also needed with memundo, in some cases we can store a step before pose has been + * properly rebuilt from previous undo step. */ + Bone *bone = (pose->flag & POSE_RECALC) ? BKE_armature_find_bone_name(arm, chan->name) : + chan->bone; + if (bone != NULL) { + /* gets restored on read, for library armatures */ + chan->selectflag = bone->flag & BONE_SELECTED; + } + + BLO_write_struct(writer, bPoseChannel, chan); + } + + /* Write groups */ + LISTBASE_FOREACH (bActionGroup *, grp, &pose->agroups) { + BLO_write_struct(writer, bActionGroup, grp); + } + + /* write IK param */ + if (pose->ikparam) { + const char *structname = BKE_pose_ikparam_get_name(pose); + if (structname) { + BLO_write_struct_by_name(writer, structname, pose->ikparam); + } + } + + /* Write this pose */ + BLO_write_struct(writer, bPose, pose); +} + +void BKE_pose_blend_read_data(BlendDataReader *reader, bPose *pose) +{ + if (!pose) { + return; + } + + BLO_read_list(reader, &pose->chanbase); + BLO_read_list(reader, &pose->agroups); + + pose->chanhash = NULL; + pose->chan_array = NULL; + + LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) { + BKE_pose_channel_runtime_reset(&pchan->runtime); + BKE_pose_channel_session_uuid_generate(pchan); + + pchan->bone = NULL; + BLO_read_data_address(reader, &pchan->parent); + BLO_read_data_address(reader, &pchan->child); + BLO_read_data_address(reader, &pchan->custom_tx); + + BLO_read_data_address(reader, &pchan->bbone_prev); + BLO_read_data_address(reader, &pchan->bbone_next); + + BKE_constraint_blend_read_data(reader, &pchan->constraints); + + BLO_read_data_address(reader, &pchan->prop); + IDP_BlendDataRead(reader, &pchan->prop); + + BLO_read_data_address(reader, &pchan->mpath); + if (pchan->mpath) { + animviz_motionpath_blend_read_data(reader, pchan->mpath); + } + + BLI_listbase_clear(&pchan->iktree); + BLI_listbase_clear(&pchan->siktree); + + /* in case this value changes in future, clamp else we get undefined behavior */ + CLAMP(pchan->rotmode, ROT_MODE_MIN, ROT_MODE_MAX); + + pchan->draw_data = NULL; + } + pose->ikdata = NULL; + if (pose->ikparam != NULL) { + BLO_read_data_address(reader, &pose->ikparam); + } +} + +void BKE_pose_blend_read_lib(BlendLibReader *reader, Object *ob, bPose *pose) +{ + bArmature *arm = ob->data; + + if (!pose || !arm) { + return; + } + + /* always rebuild to match proxy or lib changes, but on Undo */ + bool rebuild = false; + + if (!BLO_read_lib_is_undo(reader)) { + if (ob->proxy || ob->id.lib != arm->id.lib) { + rebuild = true; + } + } + + if (ob->proxy) { + /* sync proxy layer */ + if (pose->proxy_layer) { + arm->layer = pose->proxy_layer; + } + + /* sync proxy active bone */ + if (pose->proxy_act_bone[0]) { + Bone *bone = BKE_armature_find_bone_name(arm, pose->proxy_act_bone); + if (bone) { + arm->act_bone = bone; + } + } + } + + LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) { + BKE_constraint_blend_read_lib(reader, (ID *)ob, &pchan->constraints); + + pchan->bone = BKE_armature_find_bone_name(arm, pchan->name); + + IDP_BlendReadLib(reader, pchan->prop); + + BLO_read_id_address(reader, arm->id.lib, &pchan->custom); + if (UNLIKELY(pchan->bone == NULL)) { + rebuild = true; + } + else if ((ob->id.lib == NULL) && arm->id.lib) { + /* local pose selection copied to armature, bit hackish */ + pchan->bone->flag &= ~BONE_SELECTED; + pchan->bone->flag |= pchan->selectflag; + } + } + + if (rebuild) { + Main *bmain = BLO_read_lib_get_main(reader); + DEG_id_tag_update_ex( + bmain, &ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); + BKE_pose_tag_recalc(bmain, pose); + } +} + +void BKE_pose_blend_read_expand(BlendExpander *expander, bPose *pose) +{ + if (!pose) { + return; + } + + LISTBASE_FOREACH (bPoseChannel *, chan, &pose->chanbase) { + BKE_constraint_blend_read_expand(expander, &chan->constraints); + IDP_BlendReadExpand(expander, chan->prop); + BLO_expand(expander, chan->custom); + } +} |