Blender V4.3
animrig/intern/fcurve.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 <cfloat>
10#include <cmath>
11#include <cstring>
12
13#include "ANIM_animdata.hh"
14#include "ANIM_fcurve.hh"
15#include "BKE_fcurve.hh"
16#include "BLI_math_base.h"
18#include "BLI_string.h"
19#include "DNA_anim_types.h"
20#include "MEM_guardedalloc.h"
21
22namespace blender::animrig {
23
24KeyframeSettings get_keyframe_settings(const bool from_userprefs)
25{
26 KeyframeSettings settings = {};
28 settings.handle = HD_AUTO_ANIM;
29 settings.interpolation = BEZT_IPO_BEZ;
30
31 if (from_userprefs) {
32 settings.interpolation = eBezTriple_Interpolation(U.ipo_new);
33 settings.handle = eBezTriple_Handle(U.keyhandles_new);
34 }
35 return settings;
36}
37
38const FCurve *fcurve_find(Span<const FCurve *> fcurves, const FCurveDescriptor fcurve_descriptor)
39{
40 for (const FCurve *fcurve : fcurves) {
41 /* Check indices first, much cheaper than a string comparison. */
42 if (fcurve->array_index == fcurve_descriptor.array_index && fcurve->rna_path &&
43 StringRef(fcurve->rna_path) == fcurve_descriptor.rna_path)
44 {
45 return fcurve;
46 }
47 }
48 return nullptr;
49}
50FCurve *fcurve_find(Span<FCurve *> fcurves, const FCurveDescriptor fcurve_descriptor)
51{
52 const FCurve *fcurve = fcurve_find(fcurves.cast<const FCurve *>(), fcurve_descriptor);
53 return const_cast<FCurve *>(fcurve);
54}
55
57{
59 fcu->rna_path = BLI_strdupn(fcurve_descriptor.rna_path.data(),
60 fcurve_descriptor.rna_path.size());
61 fcu->array_index = fcurve_descriptor.array_index;
63 fcu->auto_smoothing = U.auto_smoothing_new;
64
65 /* Set the fcurve's color mode if needed/able. */
66 if ((U.keying_flag & KEYING_FLAG_XYZ2RGB) != 0 && fcurve_descriptor.prop_subtype.has_value()) {
67 switch (*fcurve_descriptor.prop_subtype) {
69 case PROP_XYZ:
70 case PROP_EULER:
71 case PROP_COLOR:
72 case PROP_COORDS:
74 break;
75
76 case PROP_QUATERNION:
78 break;
79
80 default:
81 /* Leave the color mode as default. */
82 break;
83 }
84 }
85
86 return fcu;
87}
88
89bool fcurve_delete_keyframe_at_time(FCurve *fcurve, const float time)
90{
91 if (BKE_fcurve_is_protected(fcurve)) {
92 return false;
93 }
94 bool found;
95
96 const int index = BKE_fcurve_bezt_binarysearch_index(
97 fcurve->bezt, time, fcurve->totvert, &found);
98 if (!found) {
99 return false;
100 }
101
102 BKE_fcurve_delete_key(fcurve, index);
104
105 return true;
106}
107
109{
110 if (!fcurve_delete_keyframe_at_time(fcu, cfra)) {
111 return false;
112 }
113
114 /* Empty curves get automatically deleted. */
115 if (BKE_fcurve_is_empty(fcu)) {
116 animdata_fcurve_delete(nullptr, adt, fcu);
117 }
118
119 return true;
120}
121
122/* ************************************************** */
123/* KEYFRAME INSERTION */
124
125/* -------------- BezTriple Insertion -------------------- */
126
127/* Change the Y position of a keyframe to match the input, adjusting handles. */
128static void replace_bezt_keyframe_ypos(BezTriple *dst, const BezTriple *bezt)
129{
130 /* Just change the values when replacing, so as to not overwrite handles. */
131 float dy = bezt->vec[1][1] - dst->vec[1][1];
132
133 /* Just apply delta value change to the handle values. */
134 dst->vec[0][1] += dy;
135 dst->vec[1][1] += dy;
136 dst->vec[2][1] += dy;
137
138 dst->f1 = bezt->f1;
139 dst->f2 = bezt->f2;
140 dst->f3 = bezt->f3;
141
142 /* TODO: perform some other operations? */
143}
144
146{
147 int i = 0;
148
149 /* Are there already keyframes? */
150 if (fcu->bezt) {
151 bool replace;
152 i = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, bezt->vec[1][0], fcu->totvert, &replace);
153
154 /* Replace an existing keyframe? */
155 if (replace) {
156 /* 'i' may in rare cases exceed arraylen. */
157 if ((i >= 0) && (i < fcu->totvert)) {
159 fcu->bezt[i] = *bezt;
160 }
161 else {
162 replace_bezt_keyframe_ypos(&fcu->bezt[i], bezt);
163 }
164
166 /* If replacing an end point of a cyclic curve without offset,
167 * modify the other end too. */
168 if (ELEM(i, 0, fcu->totvert - 1) && BKE_fcurve_get_cycle_type(fcu) == FCU_CYCLE_PERFECT)
169 {
170 replace_bezt_keyframe_ypos(&fcu->bezt[i == 0 ? fcu->totvert - 1 : 0], bezt);
171 }
172 }
173 }
174 }
175 /* Keyframing modes allow not replacing the keyframe. */
176 else if ((flag & INSERTKEY_REPLACE) == 0) {
177 /* Insert new - if we're not restricted to replacing keyframes only. */
178 BezTriple *newb = static_cast<BezTriple *>(
179 MEM_callocN((fcu->totvert + 1) * sizeof(BezTriple), "beztriple"));
180
181 /* Add the beztriples that should occur before the beztriple to be pasted
182 * (originally in fcu). */
183 if (i > 0) {
184 memcpy(newb, fcu->bezt, i * sizeof(BezTriple));
185 }
186
187 /* Add beztriple to paste at index i. */
188 *(newb + i) = *bezt;
189
190 /* Add the beztriples that occur after the beztriple to be pasted (originally in fcu). */
191 if (i < fcu->totvert) {
192 memcpy(newb + i + 1, fcu->bezt + i, (fcu->totvert - i) * sizeof(BezTriple));
193 }
194
195 /* Replace (+ free) old with new, only if necessary to do so. */
196 MEM_freeN(fcu->bezt);
197 fcu->bezt = newb;
198
199 fcu->totvert++;
200 }
201 else {
202 return -1;
203 }
204 }
205 /* No keyframes yet, but can only add if...
206 * 1) keyframing modes say that keyframes can only be replaced, so adding new ones won't know
207 * 2) there are no samples on the curve
208 * NOTE: maybe we may want to allow this later when doing samples -> bezt conversions,
209 * but for now, having both is asking for trouble
210 */
211 else if ((flag & INSERTKEY_REPLACE) == 0 && (fcu->fpt == nullptr)) {
212 /* Create new keyframes array. */
213 fcu->bezt = static_cast<BezTriple *>(MEM_callocN(sizeof(BezTriple), "beztriple"));
214 *(fcu->bezt) = *bezt;
215 fcu->totvert = 1;
216 }
217 /* Cannot add anything. */
218 else {
219 /* Return error code -1 to prevent any misunderstandings. */
220 return -1;
221 }
222
223 /* We need to return the index, so that some tools which do post-processing can
224 * detect where we added the BezTriple in the array.
225 */
226 return i;
227}
228
239static void subdivide_nonauto_handles(const FCurve *fcu,
240 BezTriple *bezt,
241 BezTriple *prev,
243{
244 if (prev->ipo != BEZT_IPO_BEZ || bezt->ipo != BEZT_IPO_BEZ) {
245 return;
246 }
247
248 /* Don't change Vector handles, or completely auto regions. */
249 const bool bezt_auto = BEZT_IS_AUTOH(bezt) || (bezt->h1 == HD_VECT && bezt->h2 == HD_VECT);
250 const bool prev_auto = BEZT_IS_AUTOH(prev) || (prev->h2 == HD_VECT);
251 const bool next_auto = BEZT_IS_AUTOH(next) || (next->h1 == HD_VECT);
252 if (bezt_auto && prev_auto && next_auto) {
253 return;
254 }
255
256 /* Subdivide the curve. */
257 float delta;
258 if (!BKE_fcurve_bezt_subdivide_handles(bezt, prev, next, &delta)) {
259 return;
260 }
261
262 /* Decide when to force auto to manual. */
263 if (!BEZT_IS_AUTOH(bezt)) {
264 return;
265 }
266 if ((prev_auto || next_auto) && fcu->auto_smoothing == FCURVE_SMOOTH_CONT_ACCEL) {
267 const float hx = bezt->vec[1][0] - bezt->vec[0][0];
268 const float dx = bezt->vec[1][0] - prev->vec[1][0];
269
270 /* This mode always uses 1/3 of key distance for handle x size. */
271 const bool auto_works_well = fabsf(hx - dx / 3.0f) < 0.001f;
272 if (auto_works_well) {
273 return;
274 }
275 }
276
277 /* Turn off auto mode. */
278 bezt->h1 = bezt->h2 = HD_ALIGN;
279}
280
282 const float2 position,
283 const KeyframeSettings &settings,
284 const eFCurve_Flags fcu_flags)
285{
286 /* Set all three points, for nicer start position.
287 * NOTE: +/- 1 on vec.x for left and right handles is so that 'free' handles work ok...
288 */
289 beztr->vec[0][0] = position.x - 1.0f;
290 beztr->vec[0][1] = position.y;
291 beztr->vec[1][0] = position.x;
292 beztr->vec[1][1] = position.y;
293 beztr->vec[2][0] = position.x + 1.0f;
294 beztr->vec[2][1] = position.y;
295 beztr->f1 = beztr->f2 = beztr->f3 = SELECT;
296
297 beztr->h1 = beztr->h2 = settings.handle;
298 beztr->ipo = settings.interpolation;
299
300 /* Interpolation type used is constrained by the type of values the curve can take. */
301 if (fcu_flags & FCURVE_DISCRETE_VALUES) {
302 beztr->ipo = BEZT_IPO_CONST;
303 }
304 else if ((beztr->ipo == BEZT_IPO_BEZ) && (fcu_flags & FCURVE_INT_VALUES)) {
305 beztr->ipo = BEZT_IPO_LIN;
306 }
307
308 /* Set keyframe type value (supplied),
309 * which should come from the scene settings in most cases. */
310 BEZKEYTYPE_LVALUE(beztr) = settings.keyframe_type;
311
312 /* Set default values for "easing" interpolation mode settings.
313 * NOTE: Even if these modes aren't currently used, if users switch
314 * to these later, we want these to work in a sane way out of
315 * the box.
316 */
317
318 /* "back" easing - This value used to be used when overshoot=0, but that
319 * introduced discontinuities in how the param worked. */
320 beztr->back = 1.70158f;
321
322 /* "elastic" easing - Values here were hand-optimized for a default duration of
323 * ~10 frames (typical motion-graph motion length). */
324 beztr->amplitude = 0.8f;
325 beztr->period = 4.1f;
326}
327
343static bool new_key_needed(const FCurve &fcu, const float frame, const float value)
344{
345 if (fcu.totvert == 0) {
346 return true;
347 }
348
349 bool replace;
350 const int bezt_index = BKE_fcurve_bezt_binarysearch_index(
351 fcu.bezt, frame, fcu.totvert, &replace);
352
353 if (replace) {
354 /* If there is already a key, we only need to modify it if the proposed value is different. */
355 return fcu.bezt[bezt_index].vec[1][1] != value;
356 }
357
358 const int diff_ulp = 32;
359 const float fcu_eval = evaluate_fcurve(&fcu, frame);
360 /* No need to insert a key if the same value is already the value of the FCurve at that point. */
361 if (compare_ff_relative(fcu_eval, value, FLT_EPSILON, diff_ulp)) {
362 return false;
363 }
364
365 return true;
366}
367
373 const eFCU_Cycle_Type type,
374 float2 position)
375{
376 if (fcu.totvert < 2 || !fcu.bezt) {
377 return position;
378 }
379
380 if (type == FCU_CYCLE_NONE) {
381 return position;
382 }
383
384 BezTriple *first = &fcu.bezt[0], *last = &fcu.bezt[fcu.totvert - 1];
385 const float start = first->vec[1][0], end = last->vec[1][0];
386
387 if (start >= end) {
388 return position;
389 }
390
391 if (position.x < start || position.x > end) {
392 const float period = end - start;
393 const float step = floorf((position.x - start) / period);
394 position.x -= step * period;
395
396 if (type == FCU_CYCLE_OFFSET) {
397 /* Nasty check to handle the case when the modes are different better. */
398 FMod_Cycles *data = static_cast<FMod_Cycles *>(((FModifier *)fcu.modifiers.first)->data);
399 short mode = (step >= 0) ? data->after_mode : data->before_mode;
400
401 if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
402 position.y -= step * (last->vec[1][1] - first->vec[1][1]);
403 }
404 }
405 }
406
407 return position;
408}
409
411 const float2 position,
412 const KeyframeSettings &settings,
414{
415 BLI_assert(fcu != nullptr);
416
417 float2 remapped_position = position;
418 /* Adjust coordinates for cycle aware insertion. */
421 remapped_position = remap_cyclic_keyframe_location(*fcu, type, position);
422 if (type != FCU_CYCLE_PERFECT) {
423 /* Inhibit action from insert_bezt_fcurve unless it's a perfect cycle. */
424 flag &= ~INSERTKEY_CYCLE_AWARE;
425 }
426 }
427
428 if ((flag & INSERTKEY_NEEDED) && !new_key_needed(*fcu, remapped_position.x, remapped_position.y))
429 {
431 }
432
433 BezTriple beztr = {{{0}}};
434 initialize_bezt(&beztr, remapped_position, settings, eFCurve_Flags(fcu->flag));
435
436 uint oldTot = fcu->totvert;
437 int a;
438
439 /* Add temp beztriple to keyframes. */
440 a = insert_bezt_fcurve(fcu, &beztr, flag);
442
443 /* Key insertion failed. */
444 if (a < 0) {
445 /* TODO: we need more info from `insert_bezt_fcurve()` called above to
446 * return a more specific failure. */
448 }
449
450 /* Set handle-type and interpolation. */
451 if ((fcu->totvert > 2) && (flag & INSERTKEY_REPLACE) == 0) {
452 BezTriple *bezt = (fcu->bezt + a);
453
454 /* Set interpolation from previous (if available),
455 * but only if we didn't just replace some keyframe:
456 * - Replacement is indicated by no-change in number of verts.
457 * - When replacing, the user may have specified some interpolation that should be kept.
458 */
459 if (fcu->totvert > oldTot) {
460 if (a > 0) {
461 bezt->ipo = (bezt - 1)->ipo;
462 }
463 else if (a < fcu->totvert - 1) {
464 bezt->ipo = (bezt + 1)->ipo;
465 }
466
467 if (0 < a && a < (fcu->totvert - 1) && (flag & INSERTKEY_OVERWRITE_FULL) == 0) {
468 subdivide_nonauto_handles(fcu, bezt, bezt - 1, bezt + 1);
469 }
470 }
471 }
472
473 /* Don't recalculate handles if fast is set.
474 * - this is a hack to make importers faster
475 * - we may calculate twice (due to auto-handle needing to be calculated twice)
476 */
477 if ((flag & INSERTKEY_FAST) == 0) {
479 }
480
481 /* Return the index at which the keyframe was added. */
483}
484
486 const float start_frame,
487 const float sample_rate,
488 float *samples,
489 const int sample_count)
490{
491 for (int i = 0; i < sample_count; i++) {
492 const float evaluation_time = start_frame + (float(i) / sample_rate);
493 samples[i] = evaluate_fcurve(fcu, evaluation_time);
494 }
495}
496
498 const int2 range,
499 const BakeCurveRemove removal_mode)
500{
501 switch (removal_mode) {
502
505 break;
506 }
507
509 bool replace;
510
511 int before_index = BKE_fcurve_bezt_binarysearch_index(
512 fcu->bezt, range[0], fcu->totvert, &replace);
513
514 if (before_index > 0) {
515 BKE_fcurve_delete_keys(fcu, {0, uint(before_index)});
516 }
517
518 int after_index = BKE_fcurve_bezt_binarysearch_index(
519 fcu->bezt, range[1], fcu->totvert, &replace);
520 /* #OUT_RANGE is treated as exclusive on both ends. */
521 if (replace) {
522 after_index++;
523 }
524 if (after_index < fcu->totvert) {
525 BKE_fcurve_delete_keys(fcu, {uint(after_index), fcu->totvert});
526 }
527 break;
528 }
529
531 bool replace;
532 const int range_start_index = BKE_fcurve_bezt_binarysearch_index(
533 fcu->bezt, range[0], fcu->totvert, &replace);
534 int range_end_index = BKE_fcurve_bezt_binarysearch_index(
535 fcu->bezt, range[1], fcu->totvert, &replace);
536 if (replace) {
537 range_end_index++;
538 }
539
540 if (range_end_index > range_start_index) {
541 BKE_fcurve_delete_keys(fcu, {uint(range_start_index), uint(range_end_index)});
542 }
543 break;
544 }
545
546 default:
547 break;
548 }
549}
550
552 const int2 range,
553 const float step,
554 const BakeCurveRemove remove_existing)
555{
556 BLI_assert(step > 0);
557 const int sample_count = (range[1] - range[0]) / step + 1;
558 float *samples = static_cast<float *>(
559 MEM_callocN(sample_count * sizeof(float), "Channel Bake Samples"));
560 const float sample_rate = 1.0f / step;
561 sample_fcurve_segment(fcu, range[0], sample_rate, samples, sample_count);
562
563 if (remove_existing != BakeCurveRemove::NONE) {
564 remove_fcurve_key_range(fcu, range, remove_existing);
565 }
566
567 BezTriple *baked_keys = static_cast<BezTriple *>(
568 MEM_callocN(sample_count * sizeof(BezTriple), "beztriple"));
569
570 const KeyframeSettings settings = get_keyframe_settings(true);
571
572 for (int i = 0; i < sample_count; i++) {
573 BezTriple *key = &baked_keys[i];
574 float2 key_position = {range[0] + i * step, samples[i]};
575 initialize_bezt(key, key_position, settings, eFCurve_Flags(fcu->flag));
576 }
577
578 int merged_size;
579 BezTriple *merged_bezt = BKE_bezier_array_merge(
580 baked_keys, sample_count, fcu->bezt, fcu->totvert, &merged_size);
581
582 if (fcu->bezt != nullptr) {
583 /* Can happen if we removed all keys beforehand. */
584 MEM_freeN(fcu->bezt);
585 }
586 MEM_freeN(baked_keys);
587 fcu->bezt = merged_bezt;
588 fcu->totvert = merged_size;
589
590 MEM_freeN(samples);
592}
593
595 float frame, val;
596};
597
599{
600 const BezTriple *bezt, *start = nullptr, *end = nullptr;
601 TempFrameValCache *value_cache, *fp;
602 int sfra, range;
603 int i, n;
604
605 if (fcu->bezt == nullptr) {
606 return;
607 }
608
610 settings.keyframe_type = BEZT_KEYTYPE_BREAKDOWN;
611
612 /* Find selected keyframes... once pair has been found, add keyframes. */
613 for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
614 /* check if selected, and which end this is */
615 if (BEZT_ISSEL_ANY(bezt)) {
616 if (start) {
617 /* If next bezt is also selected, don't start sampling yet,
618 * but instead wait for that one to reconsider, to avoid
619 * changing the curve when sampling consecutive segments
620 * (#53229)
621 */
622 if (i < fcu->totvert - 1) {
623 BezTriple *next = &fcu->bezt[i + 1];
624 if (BEZT_ISSEL_ANY(next)) {
625 continue;
626 }
627 }
628
629 end = bezt;
630
631 /* Cache values then add keyframes using these values, as adding
632 * keyframes while sampling will affect the outcome...
633 * - Only start sampling+adding from index=1, so that we don't overwrite original keyframe.
634 */
635 range = int(ceil(end->vec[1][0] - start->vec[1][0]));
636 sfra = int(floor(start->vec[1][0]));
637
638 if (range) {
639 value_cache = static_cast<TempFrameValCache *>(
640 MEM_callocN(sizeof(TempFrameValCache) * range, "IcuFrameValCache"));
641
642 /* Sample values. */
643 for (n = 1, fp = value_cache; n < range && fp; n++, fp++) {
644 fp->frame = float(sfra + n);
645 fp->val = evaluate_fcurve(fcu, fp->frame);
646 }
647
648 /* Add keyframes with these, tagging as 'breakdowns'. */
649 for (n = 1, fp = value_cache; n < range && fp; n++, fp++) {
651 fcu, {fp->frame, fp->val}, settings, INSERTKEY_NOFLAGS);
652 }
653
654 MEM_freeN(value_cache);
655
656 /* As we added keyframes, we need to compensate so that bezt is at the right place. */
657 bezt = fcu->bezt + i + range - 1;
658 i += (range - 1);
659 }
660
661 /* The current selection island has ended, so start again from scratch. */
662 start = nullptr;
663 end = nullptr;
664 }
665 else {
666 /* Just set start keyframe. */
667 start = bezt;
668 end = nullptr;
669 }
670 }
671 }
672
674}
675
676} // namespace blender::animrig
Functions to work with AnimData.
Functions to modify FCurves.
void BKE_fcurve_delete_keys(FCurve *fcu, blender::uint2 index_range)
int BKE_fcurve_bezt_binarysearch_index(const BezTriple array[], float frame, int arraylen, bool *r_replace)
void BKE_fcurve_handles_recalc(FCurve *fcu)
eFCU_Cycle_Type
@ FCU_CYCLE_OFFSET
@ FCU_CYCLE_NONE
@ FCU_CYCLE_PERFECT
bool BKE_fcurve_is_empty(const FCurve *fcu)
eFCU_Cycle_Type BKE_fcurve_get_cycle_type(const FCurve *fcu)
FCurve * BKE_fcurve_create(void)
void BKE_fcurve_active_keyframe_set(FCurve *fcu, const BezTriple *active_bezt)
bool BKE_fcurve_is_protected(const FCurve *fcu)
bool BKE_fcurve_bezt_subdivide_handles(BezTriple *bezt, BezTriple *prev, BezTriple *next, float *r_pdelta)
float evaluate_fcurve(const FCurve *fcu, float evaltime)
BezTriple * BKE_bezier_array_merge(const BezTriple *a, int size_a, const BezTriple *b, int size_b, int *r_merged_size)
void BKE_fcurve_delete_key(FCurve *fcu, int index)
void BKE_fcurve_delete_keys_all(FCurve *fcu)
#define BLI_assert(a)
Definition BLI_assert.h:50
MINLINE int compare_ff_relative(float a, float b, float max_diff, int max_ulps)
char * BLI_strdupn(const char *str, size_t len) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition string.c:29
unsigned int uint
#define ELEM(...)
@ FCM_EXTRAPOLATE_CYCLIC_OFFSET
@ FCURVE_COLOR_AUTO_RGB
@ FCURVE_COLOR_AUTO_YRGB
eInsertKeyFlags
@ INSERTKEY_FAST
@ INSERTKEY_CYCLE_AWARE
@ INSERTKEY_OVERWRITE_FULL
@ INSERTKEY_REPLACE
@ INSERTKEY_NEEDED
@ INSERTKEY_NOFLAGS
eFCurve_Flags
@ FCURVE_INT_VALUES
@ FCURVE_SELECTED
@ FCURVE_DISCRETE_VALUES
@ FCURVE_VISIBLE
@ FCURVE_SMOOTH_CONT_ACCEL
#define BEZT_IS_AUTOH(bezt)
#define BEZT_ISSEL_ANY(bezt)
eBezTriple_Handle
@ HD_AUTO_ANIM
@ HD_VECT
@ HD_ALIGN
eBezTriple_Interpolation
@ BEZT_IPO_CONST
@ BEZT_IPO_BEZ
@ BEZT_IPO_LIN
#define BEZKEYTYPE_LVALUE(bezt)
@ BEZT_KEYTYPE_BREAKDOWN
@ BEZT_KEYTYPE_KEYFRAME
@ KEYING_FLAG_XYZ2RGB
Read Guarded memory(de)allocation.
@ PROP_XYZ
Definition RNA_types.hh:172
@ PROP_COLOR
Definition RNA_types.hh:163
@ PROP_EULER
Definition RNA_types.hh:169
@ PROP_COORDS
Definition RNA_types.hh:177
@ PROP_TRANSLATION
Definition RNA_types.hh:164
@ PROP_QUATERNION
Definition RNA_types.hh:170
unsigned int U
Definition btGjkEpa3.h:78
Span< NewT > constexpr cast() const
Definition BLI_span.hh:419
constexpr int64_t size() const
constexpr const char * data() const
#define SELECT
#define floorf(x)
#define fabsf(x)
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
IndexRange range
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
ccl_device_inline float2 floor(const float2 a)
ccl_device_inline float3 ceil(const float3 a)
static ulong * next
static float2 remap_cyclic_keyframe_location(const FCurve &fcu, const eFCU_Cycle_Type type, float2 position)
KeyframeSettings get_keyframe_settings(bool from_userprefs)
static bool new_key_needed(const FCurve &fcu, const float frame, const float value)
static void remove_fcurve_key_range(FCurve *fcu, const int2 range, const BakeCurveRemove removal_mode)
void initialize_bezt(BezTriple *beztr, float2 position, const KeyframeSettings &settings, eFCurve_Flags fcu_flags)
void sample_fcurve_segment(const FCurve *fcu, float start_frame, float sample_rate, float *samples, int sample_count)
const FCurve * fcurve_find(Span< const FCurve * > fcurves, FCurveDescriptor fcurve_descriptor)
bool fcurve_delete_keyframe_at_time(FCurve *fcurve, float time)
SingleKeyingResult insert_vert_fcurve(FCurve *fcu, const float2 position, const KeyframeSettings &settings, eInsertKeyFlags flag)
Main Key-framing API call.
void bake_fcurve(FCurve *fcu, blender::int2 range, float step, BakeCurveRemove remove_existing)
static void subdivide_nonauto_handles(const FCurve *fcu, BezTriple *bezt, BezTriple *prev, BezTriple *next)
int insert_bezt_fcurve(FCurve *fcu, const BezTriple *bezt, eInsertKeyFlags flag)
Lesser Key-framing API call.
bool delete_keyframe_fcurve_legacy(AnimData *adt, FCurve *fcu, float cfra)
static void replace_bezt_keyframe_ypos(BezTriple *dst, const BezTriple *bezt)
void bake_fcurve_segments(FCurve *fcu)
void animdata_fcurve_delete(bAnimContext *ac, AnimData *adt, FCurve *fcu)
Definition animdata.cc:253
FCurve * create_fcurve_for_channel(FCurveDescriptor fcurve_descriptor)
float vec[3][3]
char * rna_path
FPoint * fpt
BezTriple * bezt
int array_index
unsigned int totvert
char auto_smoothing
ListBase modifiers
void * first
std::optional< PropertySubType > prop_subtype
eBezTriple_KeyframeType keyframe_type
uint8_t flag
Definition wm_window.cc:138