From c5e5c8a67ab577f4cff5615c073ccc12112d779d Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Tue, 17 Dec 2024 13:36:49 +0100 Subject: [PATCH] Fix #131669: Camera not autokeyed in special case The autokeying code for cameras used the keyingset code to insert keys. In the case of "Only Insert Available" turned on this would use the "Available" keyingset. However, in the case of looking through the camera and moving the viewport when the camera is not active, the poll function of that keyingset would return false. Instead of modifying the poll function, the fix is to use the more direct keying code using `RNAPath`. This can be backported to 4.2 but not 3.6 due to the changes to the keying code done in 4.0 Pull Request: https://projects.blender.org/blender/blender/pulls/131796 --- source/blender/animrig/ANIM_keyframing.hh | 2 +- .../blender/animrig/intern/keyframing_auto.cc | 4 +- .../editors/space_view3d/view3d_utils.cc | 62 ++++++++++++------- 3 files changed, 43 insertions(+), 25 deletions(-) diff --git a/source/blender/animrig/ANIM_keyframing.hh b/source/blender/animrig/ANIM_keyframing.hh index 0e5c8a005d3..e739e28b6e7 100644 --- a/source/blender/animrig/ANIM_keyframing.hh +++ b/source/blender/animrig/ANIM_keyframing.hh @@ -209,7 +209,7 @@ bool autokeyframe_cfra_can_key(const Scene *scene, ID *id); * * \param rna_paths: Only inserts keys on those RNA paths. */ -void autokeyframe_object(bContext *C, Scene *scene, Object *ob, Span rna_paths); +void autokeyframe_object(bContext *C, const Scene *scene, Object *ob, Span rna_paths); /** * Auto-keyframing feature - for objects * diff --git a/source/blender/animrig/intern/keyframing_auto.cc b/source/blender/animrig/intern/keyframing_auto.cc index 348086646df..18a4a6a1ad1 100644 --- a/source/blender/animrig/intern/keyframing_auto.cc +++ b/source/blender/animrig/intern/keyframing_auto.cc @@ -29,7 +29,7 @@ namespace blender::animrig { -static eInsertKeyFlags get_autokey_flags(Scene *scene) +static eInsertKeyFlags get_autokey_flags(const Scene *scene) { eInsertKeyFlags flag = INSERTKEY_NOFLAGS; @@ -103,7 +103,7 @@ bool autokeyframe_cfra_can_key(const Scene *scene, ID *id) return true; } -void autokeyframe_object(bContext *C, Scene *scene, Object *ob, Span rna_paths) +void autokeyframe_object(bContext *C, const Scene *scene, Object *ob, Span rna_paths) { BLI_assert(ob != nullptr); BLI_assert(scene != nullptr); diff --git a/source/blender/editors/space_view3d/view3d_utils.cc b/source/blender/editors/space_view3d/view3d_utils.cc index 60cc8895710..50904282f3a 100644 --- a/source/blender/editors/space_view3d/view3d_utils.cc +++ b/source/blender/editors/space_view3d/view3d_utils.cc @@ -19,6 +19,8 @@ #include "DNA_scene_types.h" #include "DNA_world_types.h" +#include "RNA_path.hh" + #include "MEM_guardedalloc.h" #include "BLI_array_utils.h" @@ -28,6 +30,7 @@ #include "BLI_math_rotation.h" #include "BLI_math_vector.h" #include "BLI_utildefines.h" +#include "BLI_vector.hh" #include "BKE_camera.h" #include "BKE_context.hh" @@ -674,30 +677,45 @@ bool ED_view3d_camera_lock_sync(const Depsgraph *depsgraph, View3D *v3d, RegionV bool ED_view3d_camera_autokey( const Scene *scene, ID *id_key, bContext *C, const bool do_rotate, const bool do_translate) { - using namespace blender::animrig; - if (autokeyframe_cfra_can_key(scene, id_key)) { - const float cfra = float(scene->r.cfra); - blender::Vector sources; - /* add data-source override for the camera object */ - ANIM_relative_keyingset_add_source(sources, id_key); + BLI_assert(GS(id_key->name) == ID_OB); + using namespace blender; - /* insert keyframes - * 1) on the first frame - * 2) on each subsequent frame - * TODO: need to check in future that frame changed before doing this - */ - if (do_rotate) { - KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_ROTATION_ID); - ANIM_apply_keyingset(C, &sources, ks, ModifyKeyMode::INSERT, cfra); - } - if (do_translate) { - KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID); - ANIM_apply_keyingset(C, &sources, ks, ModifyKeyMode::INSERT, cfra); - } - - return true; + /* While `autokeyframe_object` does already call `autokeyframe_cfra_can_key` we need this here + * because at the time of writing this it returns void. Once the keying result is returned, like + * implemented for `blender::animrig::insert_keyframes`, this `if` can be removed. */ + if (!animrig::autokeyframe_cfra_can_key(scene, id_key)) { + return false; } - return false; + + Object *camera_object = reinterpret_cast(id_key); + + Vector rna_paths; + + if (do_rotate) { + switch (camera_object->rotmode) { + case ROT_MODE_QUAT: + rna_paths.append({"rotation_quaternion"}); + break; + + case ROT_MODE_AXISANGLE: + rna_paths.append({"rotation_axis_angle"}); + break; + + case ROT_MODE_EUL: + rna_paths.append({"rotation_euler"}); + break; + + default: + break; + } + } + if (do_translate) { + rna_paths.append({"location"}); + } + + animrig::autokeyframe_object(C, scene, camera_object, rna_paths); + WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_ADDED, nullptr); + return true; } bool ED_view3d_camera_lock_autokey(