Blender V4.3
keyframing_auto.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "BKE_animsys.h"
10#include "BKE_context.hh"
11#include "BKE_fcurve.hh"
12#include "BKE_scene.hh"
13
14#include "BLI_listbase.h"
15#include "BLI_string.h"
16
17#include "DNA_scene_types.h"
18
19#include "RNA_access.hh"
20#include "RNA_path.hh"
21#include "RNA_prototypes.hh"
22
23#include "ED_keyframing.hh"
24
25#include "ANIM_keyframing.hh"
26#include "ANIM_keyingsets.hh"
27
28#include "WM_api.hh"
29#include "WM_types.hh"
30
31namespace blender::animrig {
32
34{
36
37 /* Visual keying. */
40 }
41
42 /* Only needed. */
45 }
46
47 /* Only insert available. */
50 }
51
52 /* Keyframing mode - only replace existing keyframes. */
55 }
56
57 /* Cycle-aware keyframe insertion - preserve cycle period and flow. */
60 }
61
62 return flag;
63}
64
65bool is_autokey_on(const Scene *scene)
66{
67 if (scene) {
68 return scene->toolsettings->autokey_mode & AUTOKEY_ON;
69 }
70 return U.autokey_mode & AUTOKEY_ON;
71}
72
73bool is_autokey_mode(const Scene *scene, const eAutokey_Mode mode)
74{
75 if (scene) {
76 return scene->toolsettings->autokey_mode == mode;
77 }
78 return U.autokey_mode == mode;
79}
80
81bool autokeyframe_cfra_can_key(const Scene *scene, ID *id)
82{
83 /* Only filter if auto-key mode requires this. */
84 if (!is_autokey_on(scene)) {
85 return false;
86 }
87
89 /* Replace Mode:
90 * For whole block, only key if there's a keyframe on that frame already
91 * This is a valid assumption when we're blocking + tweaking
92 */
93 const float cfra = BKE_scene_frame_get(scene);
94 return id_frame_has_keyframe(id, cfra);
95 }
96
97 /* Normal Mode (or treat as being normal mode):
98 *
99 * Just in case the flags aren't set properly (i.e. only on/off is set, without a mode)
100 * let's set the "normal" flag too, so that it will all be sane everywhere...
101 */
102 scene->toolsettings->autokey_mode = AUTOKEY_MODE_NORMAL;
103
104 return true;
105}
106
107void autokeyframe_object(bContext *C, Scene *scene, Object *ob, Span<RNAPath> rna_paths)
108{
109 BLI_assert(ob != nullptr);
110 BLI_assert(scene != nullptr);
111 BLI_assert(C != nullptr);
112
113 ID *id = &ob->id;
114 if (!autokeyframe_cfra_can_key(scene, id)) {
115 return;
116 }
117
118 ReportList *reports = CTX_wm_reports(C);
119 KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene);
123
124 /* Get flags used for inserting keyframes. */
126
127 /* Add data-source override for the object. */
130
131 if (is_keying_flag(scene, AUTOKEY_FLAG_ONLYKEYINGSET) && (active_ks)) {
132 /* Only insert into active keyingset
133 * NOTE: we assume here that the active Keying Set
134 * does not need to have its iterator overridden.
135 */
137 C, &sources, active_ks, ModifyKeyMode::INSERT, anim_eval_context.eval_time);
138 return;
139 }
140
141 const float scene_frame = BKE_scene_frame_get(scene);
142 Main *bmain = CTX_data_main(C);
143
144 CombinedKeyingResult combined_result;
145 for (PointerRNA ptr : sources) {
147 bmain,
148 &ptr,
149 std::nullopt,
150 rna_paths,
151 scene_frame,
152 anim_eval_context,
153 eBezTriple_KeyframeType(scene->toolsettings->keyframe_type),
154 flag);
155 combined_result.merge(result);
156 }
157
158 if (combined_result.get_count(SingleKeyingResult::SUCCESS) == 0) {
159 combined_result.generate_reports(reports);
160 }
161}
162
164{
165 if (!autokeyframe_cfra_can_key(scene, &ob->id)) {
166 return false;
167 }
168
169 /* Now insert the key-frame(s) using the Keying Set:
170 * 1) Add data-source override for the Object.
171 * 2) Insert key-frames.
172 * 3) Free the extra info.
173 */
177
178 return true;
179}
180
182{
183 if (!autokeyframe_cfra_can_key(scene, &ob->id)) {
184 return false;
185 }
186
187 /* Now insert the keyframe(s) using the Keying Set:
188 * 1) Add data-source override for the pose-channel.
189 * 2) Insert key-frames.
190 * 3) Free the extra info.
191 */
193 ANIM_relative_keyingset_add_source(sources, &ob->id, &RNA_PoseBone, pchan);
195
196 return true;
197}
198
200 Scene *scene,
201 Object *ob,
202 bPoseChannel *pose_channel,
203 Span<RNAPath> rna_paths,
204 short targetless_ik)
205{
206 BLI_assert(C != nullptr);
207 BLI_assert(scene != nullptr);
208 BLI_assert(ob != nullptr);
209 BLI_assert(pose_channel != nullptr);
210
211 Main *bmain = CTX_data_main(C);
212 ID *id = &ob->id;
213
215 return;
216 }
217
218 ReportList *reports = CTX_wm_reports(C);
219 KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene);
221 const float scene_frame = BKE_scene_frame_get(scene);
223 scene_frame);
224
225 /* flag is initialized from UserPref keyframing settings
226 * - special exception for targetless IK - INSERTKEY_MATRIX keyframes should get
227 * visual keyframes even if flag not set, as it's not that useful otherwise
228 * (for quick animation recording)
229 */
231
232 if (targetless_ik) {
234 }
235
236 Vector<PointerRNA> sources;
237 /* Add data-source override for the camera object. */
238 ANIM_relative_keyingset_add_source(sources, id, &RNA_PoseBone, pose_channel);
239
240 /* only insert into active keyingset? */
241 if (is_keying_flag(scene, AUTOKEY_FLAG_ONLYKEYINGSET) && (active_ks)) {
242 /* Run the active Keying Set on the current data-source. */
244 C, &sources, active_ks, ModifyKeyMode::INSERT, anim_eval_context.eval_time);
245 return;
246 }
247
248 CombinedKeyingResult combined_result;
249 for (PointerRNA &ptr : sources) {
251 bmain,
252 &ptr,
253 std::nullopt,
254 rna_paths,
255 scene_frame,
256 anim_eval_context,
257 eBezTriple_KeyframeType(scene->toolsettings->keyframe_type),
258 flag);
259 combined_result.merge(result);
260 }
261
262 if (combined_result.get_count(SingleKeyingResult::SUCCESS) == 0) {
263 combined_result.generate_reports(reports);
264 }
265}
266
268 Scene *scene,
270 PropertyRNA *prop,
271 const int rnaindex,
272 const float cfra,
273 const bool only_if_property_keyed)
274{
275
278 cfra);
279 bAction *action;
280 bool driven;
281 bool special;
282
283 /* For entire array buttons we check the first component, it's not perfect
284 * but works well enough in typical cases. */
285 const int rnaindex_check = (rnaindex == -1) ? 0 : rnaindex;
287 C, ptr, prop, rnaindex_check, nullptr, &action, &driven, &special);
288
289 /* Only early out when we actually want an existing F-curve already
290 * (e.g. auto-keyframing from buttons). */
291 if (fcu == nullptr && (driven || special || only_if_property_keyed)) {
292 return false;
293 }
294
295 if (driven) {
296 return false;
297 }
298
299 bool changed = false;
300 if (special) {
301 /* NLA Strip property. */
302 if (is_autokey_on(scene)) {
303 ReportList *reports = CTX_wm_reports(C);
304 ToolSettings *ts = scene->toolsettings;
305
306 changed = insert_keyframe_direct(reports,
307 *ptr,
308 prop,
309 fcu,
310 &anim_eval_context,
312 nullptr,
313 eInsertKeyFlags(0));
315 }
316 }
317 else {
318 ID *id = ptr->owner_id;
319 Main *bmain = CTX_data_main(C);
320
321 /* TODO: this should probably respect the keyingset only option for anim */
322 if (autokeyframe_cfra_can_key(scene, id)) {
323 ToolSettings *ts = scene->toolsettings;
325
326 if (only_if_property_keyed) {
327 /* NOTE: We use rnaindex instead of fcu->array_index,
328 * because a button may control all items of an array at once.
329 * E.g., color wheels (see #42567). */
330 BLI_assert((fcu->array_index == rnaindex) || (rnaindex == -1));
331 }
332
333 const std::optional<std::string> group = (fcu && fcu->grp) ? std::optional(fcu->grp->name) :
334 std::nullopt;
335 const std::string path = fcu ? fcu->rna_path :
336 RNA_path_from_ID_to_property(ptr, prop).value_or("");
337 /* NOTE: `rnaindex == -1` is a magic number, meaning either "operate on
338 * all elements" or "not an array property". */
339 const std::optional<int> array_index = rnaindex < 0 ? std::nullopt : std::optional(rnaindex);
340
343 &id_pointer,
344 group,
345 {{path, {}, array_index}},
346 std::nullopt,
347 anim_eval_context,
349 flag);
350 changed = result.get_count(SingleKeyingResult::SUCCESS) != 0;
352 }
353 }
354 return changed;
355}
356
357} // namespace blender::animrig
Functions to insert, delete or modify keyframes.
Functionality to interact with keying sets.
AnimationEvalContext BKE_animsys_eval_context_construct(struct Depsgraph *depsgraph, float eval_time) ATTR_WARN_UNUSED_RESULT
Definition anim_sys.cc:734
ReportList * CTX_wm_reports(const bContext *C)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Main * CTX_data_main(const bContext *C)
FCurve * BKE_fcurve_find_by_rna_context_ui(bContext *C, const PointerRNA *ptr, PropertyRNA *prop, int rnaindex, AnimData **r_animdata, bAction **r_action, bool *r_driven, bool *r_special)
float BKE_scene_frame_get(const Scene *scene)
Definition scene.cc:2331
#define BLI_assert(a)
Definition BLI_assert.h:50
eInsertKeyFlags
@ INSERTKEY_CYCLE_AWARE
@ INSERTKEY_REPLACE
@ INSERTKEY_MATRIX
@ INSERTKEY_NEEDED
@ INSERTKEY_AVAILABLE
@ INSERTKEY_NOFLAGS
eBezTriple_KeyframeType
@ AUTOKEY_FLAG_INSERTNEEDED
@ KEYING_FLAG_VISUALKEY
@ KEYING_FLAG_CYCLEAWARE
@ AUTOKEY_FLAG_ONLYKEYINGSET
@ AUTOKEY_FLAG_INSERTAVAILABLE
@ AUTOKEY_MODE_NORMAL
@ AUTOKEY_MODE_EDITKEYS
@ AUTOKEY_ON
#define NC_ANIMATION
Definition WM_types.hh:355
#define NA_EDITED
Definition WM_types.hh:550
#define ND_KEYFRAME
Definition WM_types.hh:461
unsigned int U
Definition btGjkEpa3.h:78
void merge(const CombinedKeyingResult &other)
int get_count(const SingleKeyingResult result) const
void generate_reports(ReportList *reports, eReportType report_level=RPT_ERROR)
const Depsgraph * depsgraph
bool id_frame_has_keyframe(ID *id, float frame)
Main Keyframe Checking API call.
void ANIM_relative_keyingset_add_source(blender::Vector< PointerRNA > &sources, ID *id, StructRNA *srna, void *data)
KeyingSet * ANIM_scene_get_active_keyingset(const Scene *scene)
int ANIM_apply_keyingset(bContext *C, blender::Vector< PointerRNA > *sources, KeyingSet *keyingset, const blender::animrig::ModifyKeyMode mode, const float cfra)
void autokeyframe_object(bContext *C, Scene *scene, Object *ob, Span< RNAPath > rna_paths)
bool is_autokey_on(const Scene *scene)
bool autokeyframe_cfra_can_key(const Scene *scene, ID *id)
bool is_autokey_mode(const Scene *scene, eAutokey_Mode mode)
static eInsertKeyFlags get_autokey_flags(Scene *scene)
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.
bool autokeyframe_pchan(bContext *C, Scene *scene, Object *ob, bPoseChannel *pchan, KeyingSet *ks)
bool autokeyframe_property(bContext *C, Scene *scene, PointerRNA *ptr, PropertyRNA *prop, int rnaindex, float cfra, bool only_if_property_keyed)
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)
void autokeyframe_pose_channel(bContext *C, Scene *scene, Object *ob, bPoseChannel *pose_channel, Span< RNAPath > rna_paths, short targetless_ik)
PointerRNA RNA_id_pointer_create(ID *id)
std::optional< std::string > RNA_path_from_ID_to_property(const PointerRNA *ptr, PropertyRNA *prop)
Definition rna_path.cc:1166
bActionGroup * grp
char * rna_path
int array_index
Definition DNA_ID.h:413
ID * owner_id
Definition RNA_types.hh:40
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4126
uint8_t flag
Definition wm_window.cc:138