Anim: Don't use keying sets when inserting keyframes during autokeying #115522
|
@ -139,13 +139,10 @@ bool is_autokey_flag(const Scene *scene, eKeyInsert_Flag flag);
|
|||
*/
|
||||
bool autokeyframe_cfra_can_key(const Scene *scene, ID *id);
|
||||
|
||||
void autokeyframe_object(
|
||||
bContext *C, Scene *scene, ViewLayer *view_layer, Object *ob, eTfmMode tmode);
|
||||
void autokeyframe_object(bContext *C, Scene *scene, Object *ob);
|
||||
nathanvegdahl marked this conversation as resolved
|
||||
/**
|
||||
* Auto-keyframing feature - for objects
|
||||
nathanvegdahl marked this conversation as resolved
Nathan Vegdahl
commented
"for objects" -> "for poses" (presumably). "for objects" -> "for poses" (presumably).
This comment was moved as is when I moved the code. My best guess is that it was originally copy pasted from the This comment was moved as is when I moved the code. My best guess is that it was originally copy pasted from the `autokeyframe_object` function
Edit: I'll make a separate PR for this. No point in diluting the intent of this one
Nathan Vegdahl
commented
Oh, interesting. Yeah, I think making a separate PR for the documentation changes/additions after more refactoring is fine. Maybe just add a TODO to update/add the docs, then? Oh, interesting. Yeah, I think making a separate PR for the documentation changes/additions after more refactoring is fine. Maybe just add a TODO to update/add the docs, then?
actually I think the diff had us fooled here. actually I think the diff had us fooled here.
The docstring for `autokeyframe_pose` mentions `for poses/pose-channels` but the code was folded in a confusing way
Anyway I noticed the docstring still mentioned the `tmode` param. I removed that now
|
||||
*
|
||||
* \param tmode: A transform mode.
|
||||
*
|
||||
* \note Context may not always be available,
|
||||
* so must check before using it as it's a luxury for a few cases.
|
||||
*/
|
||||
|
@ -154,14 +151,12 @@ bool autokeyframe_pchan(bContext *C, Scene *scene, Object *ob, bPoseChannel *pch
|
|||
/**
|
||||
* Auto-keyframing feature - for poses/pose-channels
|
||||
*
|
||||
* \param tmode: A transform mode.
|
||||
*
|
||||
* targetless_ik: has targetless ik been done on any channels?
|
||||
*
|
||||
* \note Context may not always be available,
|
||||
* so must check before using it as it's a luxury for a few cases.
|
||||
*/
|
||||
void autokeyframe_pose(bContext *C, Scene *scene, Object *ob, int tmode, short targetless_ik);
|
||||
void autokeyframe_pose(bContext *C, Scene *scene, Object *ob, short targetless_ik);
|
||||
/**
|
||||
* Use for auto-key-framing.
|
||||
* \param only_if_property_keyed: if true, auto-key-framing only creates keyframes on already keyed
|
||||
|
|
|
@ -82,10 +82,20 @@ bool autokeyframe_cfra_can_key(const Scene *scene, ID *id)
|
|||
return true;
|
||||
}
|
||||
|
||||
void autokeyframe_object(
|
||||
bContext *C, Scene *scene, ViewLayer *view_layer, Object *ob, const eTfmMode tmode)
|
||||
static std::string get_rotation_mode_path(const eRotationModes rotmode)
|
||||
{
|
||||
switch (rotmode) {
|
||||
case ROT_MODE_QUAT:
|
||||
return "rotation_quaternion";
|
||||
case ROT_MODE_AXISANGLE:
|
||||
return "rotation_axis_angle";
|
||||
default:
|
||||
return "rotation_euler";
|
||||
}
|
||||
}
|
||||
|
||||
void autokeyframe_object(bContext *C, Scene *scene, Object *ob)
|
||||
{
|
||||
/* TODO: this should probably be done per channel instead. */
|
||||
ID *id = &ob->id;
|
||||
if (!autokeyframe_cfra_can_key(scene, id)) {
|
||||
return;
|
||||
|
@ -96,10 +106,9 @@ void autokeyframe_object(
|
|||
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
|
||||
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(
|
||||
depsgraph, BKE_scene_frame_get(scene));
|
||||
eInsertKeyFlags flag = eInsertKeyFlags(0);
|
||||
|
||||
/* Get flags used for inserting keyframes. */
|
||||
flag = ANIM_get_keyframing_flags(scene, true);
|
||||
const eInsertKeyFlags flag = ANIM_get_keyframing_flags(scene, true);
|
||||
nathanvegdahl marked this conversation as resolved
Outdated
Nathan Vegdahl
commented
I think this can be const. I think this can be const.
|
||||
|
||||
/* Add data-source override for the object. */
|
||||
blender::Vector<PointerRNA> sources;
|
||||
|
@ -112,9 +121,10 @@ void autokeyframe_object(
|
|||
*/
|
||||
ANIM_apply_keyingset(
|
||||
C, &sources, active_ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
|
||||
return;
|
||||
}
|
||||
|
||||
else if (is_autokey_flag(scene, AUTOKEY_FLAG_INSERTAVAILABLE)) {
|
||||
if (is_autokey_flag(scene, AUTOKEY_FLAG_INSERTAVAILABLE)) {
|
||||
/* Only key on available channels. */
|
||||
AnimData *adt = ob->adt;
|
||||
ToolSettings *ts = scene->toolsettings;
|
||||
|
@ -134,64 +144,22 @@ void autokeyframe_object(
|
|||
flag);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
else if (is_autokey_flag(scene, AUTOKEY_FLAG_INSERTNEEDED)) {
|
||||
bool do_loc = false, do_rot = false, do_scale = false;
|
||||
const float scene_frame = BKE_scene_frame_get(scene);
|
||||
std::string rotation_rna_path = get_rotation_mode_path(eRotationModes(ob->rotmode));
|
||||
Vector<std::string> rna_paths = {"location", rotation_rna_path, "scale"};
|
||||
nathanvegdahl marked this conversation as resolved
Nathan Vegdahl
commented
Should this respect the "Default Key Channels", like manual keying does? Not saying it should, just double-checking. Should this respect the "Default Key Channels", like manual keying does? Not saying it should, just double-checking.
I'd argue no. Auto-keying and manual-keying are two very different concepts and having the Default channels influence auto-keying would be quite annoying I think I'd argue no. Auto-keying and manual-keying are two very different concepts and having the Default channels influence auto-keying would be quite annoying I think
Nathan Vegdahl
commented
Makes sense! Thanks for the explanation. :-) Makes sense! Thanks for the explanation. :-)
|
||||
Main *bmain = CTX_data_main(C);
|
||||
|
||||
/* Filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D). */
|
||||
if (tmode == TFM_TRANSLATION) {
|
||||
do_loc = true;
|
||||
}
|
||||
else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) {
|
||||
if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) {
|
||||
BKE_view_layer_synced_ensure(scene, view_layer);
|
||||
if (ob != BKE_view_layer_active_object_get(view_layer)) {
|
||||
do_loc = true;
|
||||
}
|
||||
}
|
||||
else if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CURSOR) {
|
||||
do_loc = true;
|
||||
}
|
||||
|
||||
if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
|
||||
do_rot = true;
|
||||
}
|
||||
}
|
||||
else if (tmode == TFM_RESIZE) {
|
||||
if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) {
|
||||
BKE_view_layer_synced_ensure(scene, view_layer);
|
||||
if (ob != BKE_view_layer_active_object_get(view_layer)) {
|
||||
do_loc = true;
|
||||
}
|
||||
}
|
||||
else if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CURSOR) {
|
||||
do_loc = true;
|
||||
}
|
||||
|
||||
if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
|
||||
do_scale = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_loc) {
|
||||
KeyingSet *ks = ANIM_builtin_keyingset_get_named(ANIM_KS_LOCATION_ID);
|
||||
ANIM_apply_keyingset(C, &sources, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
|
||||
}
|
||||
if (do_rot) {
|
||||
KeyingSet *ks = ANIM_builtin_keyingset_get_named(ANIM_KS_ROTATION_ID);
|
||||
ANIM_apply_keyingset(C, &sources, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
|
||||
}
|
||||
if (do_scale) {
|
||||
KeyingSet *ks = ANIM_builtin_keyingset_get_named(ANIM_KS_SCALING_ID);
|
||||
ANIM_apply_keyingset(C, &sources, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
|
||||
}
|
||||
}
|
||||
|
||||
/* Insert keyframe in all (transform) channels. */
|
||||
else {
|
||||
KeyingSet *ks = ANIM_builtin_keyingset_get_named(ANIM_KS_LOC_ROT_SCALE_ID);
|
||||
ANIM_apply_keyingset(C, &sources, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
|
||||
for (PointerRNA ptr : sources) {
|
||||
insert_key_rna(&ptr,
|
||||
rna_paths.as_span(),
|
||||
scene_frame,
|
||||
flag,
|
||||
eBezTriple_KeyframeType(scene->toolsettings->keyframe_type),
|
||||
bmain,
|
||||
reports);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,7 +199,7 @@ bool autokeyframe_pchan(bContext *C, Scene *scene, Object *ob, bPoseChannel *pch
|
|||
return true;
|
||||
}
|
||||
|
||||
void autokeyframe_pose(bContext *C, Scene *scene, Object *ob, int tmode, short targetless_ik)
|
||||
void autokeyframe_pose(bContext *C, Scene *scene, Object *ob, short targetless_ik)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
ID *id = &ob->id;
|
||||
|
@ -247,16 +215,16 @@ void autokeyframe_pose(bContext *C, Scene *scene, Object *ob, int tmode, short t
|
|||
ToolSettings *ts = scene->toolsettings;
|
||||
KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene);
|
||||
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
|
||||
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(
|
||||
depsgraph, BKE_scene_frame_get(scene));
|
||||
eInsertKeyFlags flag = eInsertKeyFlags(0);
|
||||
const float scene_frame = BKE_scene_frame_get(scene);
|
||||
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
|
||||
scene_frame);
|
||||
|
||||
/* flag is initialized from UserPref keyframing settings
|
||||
* - special exception for targetless IK - INSERTKEY_MATRIX keyframes should get
|
||||
* visual keyframes even if flag not set, as it's not that useful otherwise
|
||||
* (for quick animation recording)
|
||||
*/
|
||||
flag = ANIM_get_keyframing_flags(scene, true);
|
||||
eInsertKeyFlags flag = ANIM_get_keyframing_flags(scene, true);
|
||||
|
||||
if (targetless_ik) {
|
||||
flag |= INSERTKEY_MATRIX;
|
||||
|
@ -278,87 +246,51 @@ void autokeyframe_pose(bContext *C, Scene *scene, Object *ob, int tmode, short t
|
|||
/* Run the active Keying Set on the current data-source. */
|
||||
ANIM_apply_keyingset(
|
||||
C, &sources, active_ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* only insert into available channels? */
|
||||
else if (blender::animrig::is_autokey_flag(scene, AUTOKEY_FLAG_INSERTAVAILABLE)) {
|
||||
if (act) {
|
||||
LISTBASE_FOREACH (FCurve *, fcu, &act->curves) {
|
||||
/* only insert keyframes for this F-Curve if it affects the current bone */
|
||||
char pchan_name[sizeof(pchan->name)];
|
||||
if (!BLI_str_quoted_substr(fcu->rna_path, "bones[", pchan_name, sizeof(pchan_name))) {
|
||||
continue;
|
||||
}
|
||||
if (blender::animrig::is_autokey_flag(scene, AUTOKEY_FLAG_INSERTAVAILABLE)) {
|
||||
if (!act) {
|
||||
continue;
|
||||
}
|
||||
LISTBASE_FOREACH (FCurve *, fcu, &act->curves) {
|
||||
/* only insert keyframes for this F-Curve if it affects the current bone */
|
||||
char pchan_name[sizeof(pchan->name)];
|
||||
if (!BLI_str_quoted_substr(fcu->rna_path, "bones[", pchan_name, sizeof(pchan_name))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* only if bone name matches too...
|
||||
* NOTE: this will do constraints too, but those are ok to do here too?
|
||||
*/
|
||||
if (STREQ(pchan_name, pchan->name)) {
|
||||
blender::animrig::insert_keyframe(bmain,
|
||||
reports,
|
||||
id,
|
||||
act,
|
||||
((fcu->grp) ? (fcu->grp->name) : (nullptr)),
|
||||
fcu->rna_path,
|
||||
fcu->array_index,
|
||||
&anim_eval_context,
|
||||
eBezTriple_KeyframeType(ts->keyframe_type),
|
||||
flag);
|
||||
}
|
||||
/* only if bone name matches too...
|
||||
* NOTE: this will do constraints too, but those are ok to do here too?
|
||||
*/
|
||||
if (STREQ(pchan_name, pchan->name)) {
|
||||
blender::animrig::insert_keyframe(bmain,
|
||||
reports,
|
||||
id,
|
||||
act,
|
||||
((fcu->grp) ? (fcu->grp->name) : (nullptr)),
|
||||
fcu->rna_path,
|
||||
fcu->array_index,
|
||||
&anim_eval_context,
|
||||
eBezTriple_KeyframeType(ts->keyframe_type),
|
||||
flag);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* only insert keyframe if needed? */
|
||||
else if (blender::animrig::is_autokey_flag(scene, AUTOKEY_FLAG_INSERTNEEDED)) {
|
||||
bool do_loc = false, do_rot = false, do_scale = false;
|
||||
|
||||
/* Filter the conditions when this happens
|
||||
* (assume that 'curarea->spacetype == SPACE_VIEW3D'). */
|
||||
if (tmode == TFM_TRANSLATION) {
|
||||
if (targetless_ik) {
|
||||
do_rot = true;
|
||||
}
|
||||
else {
|
||||
do_loc = true;
|
||||
}
|
||||
}
|
||||
else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) {
|
||||
if (ELEM(scene->toolsettings->transform_pivot_point, V3D_AROUND_CURSOR, V3D_AROUND_ACTIVE))
|
||||
{
|
||||
do_loc = true;
|
||||
}
|
||||
|
||||
if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
|
||||
do_rot = true;
|
||||
}
|
||||
}
|
||||
else if (tmode == TFM_RESIZE) {
|
||||
if (ELEM(scene->toolsettings->transform_pivot_point, V3D_AROUND_CURSOR, V3D_AROUND_ACTIVE))
|
||||
{
|
||||
do_loc = true;
|
||||
}
|
||||
|
||||
if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
|
||||
do_scale = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_loc) {
|
||||
KeyingSet *ks = ANIM_builtin_keyingset_get_named(ANIM_KS_LOCATION_ID);
|
||||
ANIM_apply_keyingset(C, &sources, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
|
||||
}
|
||||
if (do_rot) {
|
||||
KeyingSet *ks = ANIM_builtin_keyingset_get_named(ANIM_KS_ROTATION_ID);
|
||||
ANIM_apply_keyingset(C, &sources, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
|
||||
}
|
||||
if (do_scale) {
|
||||
KeyingSet *ks = ANIM_builtin_keyingset_get_named(ANIM_KS_SCALING_ID);
|
||||
ANIM_apply_keyingset(C, &sources, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
|
||||
}
|
||||
}
|
||||
/* insert keyframe in all (transform) channels */
|
||||
else {
|
||||
KeyingSet *ks = ANIM_builtin_keyingset_get_named(ANIM_KS_LOC_ROT_SCALE_ID);
|
||||
ANIM_apply_keyingset(C, &sources, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
|
||||
Main *bmain = CTX_data_main(C);
|
||||
std::string rotation_rna_path = get_rotation_mode_path(eRotationModes(pchan->rotmode));
|
||||
Vector<std::string> rna_paths = {"location", rotation_rna_path, "scale"};
|
||||
for (PointerRNA &ptr : sources) {
|
||||
insert_key_rna(&ptr,
|
||||
rna_paths,
|
||||
scene_frame,
|
||||
flag,
|
||||
eBezTriple_KeyframeType(scene->toolsettings->keyframe_type),
|
||||
bmain,
|
||||
reports);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1326,7 +1326,7 @@ static void recalcData_pose(TransInfo *t)
|
|||
int targetless_ik = (t->flag & T_AUTOIK);
|
||||
|
||||
animrecord_check_state(t, &ob->id);
|
||||
blender::animrig::autokeyframe_pose(t->context, t->scene, ob, t->mode, targetless_ik);
|
||||
blender::animrig::autokeyframe_pose(t->context, t->scene, ob, targetless_ik);
|
||||
}
|
||||
|
||||
if (motionpath_need_update_pose(t->scene, ob)) {
|
||||
|
@ -1589,7 +1589,7 @@ static void special_aftertrans_update__pose(bContext *C, TransInfo *t)
|
|||
/* automatic inserting of keys and unkeyed tagging -
|
||||
* only if transform wasn't canceled (or TFM_DUMMY) */
|
||||
if (!canceled && (t->mode != TFM_DUMMY)) {
|
||||
blender::animrig::autokeyframe_pose(C, t->scene, ob, t->mode, targetless_ik);
|
||||
blender::animrig::autokeyframe_pose(C, t->scene, ob, targetless_ik);
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -780,7 +780,7 @@ static void recalcData_objects(TransInfo *t)
|
|||
* (FPoints) instead of keyframes? */
|
||||
if ((t->animtimer) && blender::animrig::is_autokey_on(t->scene)) {
|
||||
animrecord_check_state(t, &ob->id);
|
||||
blender::animrig::autokeyframe_object(t->context, t->scene, t->view_layer, ob, t->mode);
|
||||
blender::animrig::autokeyframe_object(t->context, t->scene, ob);
|
||||
}
|
||||
|
||||
motionpath_update |= motionpath_need_update_object(t->scene, ob);
|
||||
|
@ -855,7 +855,7 @@ static void special_aftertrans_update__object(bContext *C, TransInfo *t)
|
|||
|
||||
/* Set auto-key if necessary. */
|
||||
if (!canceled) {
|
||||
blender::animrig::autokeyframe_object(C, t->scene, t->view_layer, ob, t->mode);
|
||||
blender::animrig::autokeyframe_object(C, t->scene, ob);
|
||||
}
|
||||
|
||||
motionpath_update |= motionpath_need_update_object(t->scene, ob);
|
||||
|
|
Add documentation for this. I think it would be especially useful for the doc comments of this and
autokeyframe_pose()
to make it clear what the difference between them is, and what their respective responsibilities are.well honestly I am not quite sure what the differences are yet. I realized there was this duplication when I moved all the functions into the same file. Once the refactoring is complete, it may be we can merge the functions