Blender V4.3
anim_sys.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009 Blender Authors, Joshua Leung. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cfloat>
10#include <cmath>
11#include <cstddef>
12#include <cstdio>
13#include <cstring>
14
15#include "MEM_guardedalloc.h"
16
17#include "BLI_alloca.h"
18#include "BLI_bit_vector.hh"
19#include "BLI_blenlib.h"
20#include "BLI_dynstr.h"
21#include "BLI_listbase.h"
23#include "BLI_math_rotation.h"
24#include "BLI_math_vector.h"
26#include "BLI_string_utils.hh"
27#include "BLI_utildefines.h"
28
29#include "BLT_translation.hh"
30
31#include "DNA_anim_types.h"
32#include "DNA_light_types.h"
33#include "DNA_material_types.h"
34#include "DNA_object_types.h"
35#include "DNA_scene_types.h"
36#include "DNA_screen_types.h"
37#include "DNA_space_types.h"
38#include "DNA_texture_types.h"
39#include "DNA_world_types.h"
40
41#include "BKE_action.hh"
42#include "BKE_anim_data.hh"
43#include "BKE_animsys.h"
44#include "BKE_context.hh"
45#include "BKE_fcurve.hh"
46#include "BKE_global.hh"
47#include "BKE_lib_id.hh"
48#include "BKE_lib_query.hh"
49#include "BKE_main.hh"
50#include "BKE_material.h"
51#include "BKE_nla.hh"
52#include "BKE_node.hh"
53#include "BKE_report.hh"
54#include "BKE_texture.h"
55
56#include "ANIM_action.hh"
57#include "ANIM_action_legacy.hh"
58#include "ANIM_evaluation.hh"
59
60#include "DEG_depsgraph.hh"
62
63#include "RNA_access.hh"
64#include "RNA_path.hh"
65#include "RNA_prototypes.hh"
66
67#include "BLO_read_write.hh"
68
69#include "nla_private.h"
70
71#include "atomic_ops.h"
72
73#include "CLG_log.h"
74
75static CLG_LogRef LOG = {"bke.anim_sys"};
76
77using namespace blender;
78
79/* *********************************** */
80/* KeyingSet API */
81
82/* Finding Tools --------------------------- */
83
85 ID *id,
86 const char group_name[],
87 const char rna_path[],
88 int array_index,
89 int /*group_mode*/)
90{
91 /* sanity checks */
92 if (ELEM(nullptr, ks, rna_path, id)) {
93 return nullptr;
94 }
95
96 /* loop over paths in the current KeyingSet, finding the first one where all settings match
97 * (i.e. the first one where none of the checks fail and equal 0)
98 */
99 LISTBASE_FOREACH (KS_Path *, ksp, &ks->paths) {
100 short eq_id = 1, eq_path = 1, eq_index = 1, eq_group = 1;
101
102 /* id */
103 if (id != ksp->id) {
104 eq_id = 0;
105 }
106
107 /* path */
108 if ((ksp->rna_path == nullptr) || !STREQ(rna_path, ksp->rna_path)) {
109 eq_path = 0;
110 }
111
112 /* index - need to compare whole-array setting too... */
113 if (ksp->array_index != array_index) {
114 eq_index = 0;
115 }
116
117 /* group */
118 if (group_name) {
119 /* FIXME: these checks need to be coded... for now, it's not too important though */
120 }
121
122 /* if all aspects are ok, return */
123 if (eq_id && eq_path && eq_index && eq_group) {
124 return ksp;
125 }
126 }
127
128 /* none found */
129 return nullptr;
130}
131
132/* Defining Tools --------------------------- */
133
135 ListBase *list, const char idname[], const char name[], short flag, short keyingflag)
136{
137 KeyingSet *ks;
138
139 /* allocate new KeyingSet */
140 ks = static_cast<KeyingSet *>(MEM_callocN(sizeof(KeyingSet), "KeyingSet"));
141
142 STRNCPY_UTF8(ks->idname, (idname) ? idname : (name) ? name : DATA_("KeyingSet"));
143 STRNCPY_UTF8(ks->name, (name) ? name : (idname) ? idname : DATA_("Keying Set"));
144
145 ks->flag = flag;
146 ks->keyingflag = keyingflag;
147 /* NOTE: assume that if one is set one way, the other should be too, so that it'll work */
148 ks->keyingoverride = keyingflag;
149
150 /* add KeyingSet to list */
151 BLI_addtail(list, ks);
152
153 /* Make sure KeyingSet has a unique idname */
155 list, ks, DATA_("KeyingSet"), '.', offsetof(KeyingSet, idname), sizeof(ks->idname));
156
157 /* Make sure KeyingSet has a unique label (this helps with identification) */
158 BLI_uniquename(list, ks, DATA_("Keying Set"), '.', offsetof(KeyingSet, name), sizeof(ks->name));
159
160 /* return new KeyingSet for further editing */
161 return ks;
162}
163
165 ID *id,
166 const char group_name[],
167 const char rna_path[],
168 int array_index,
169 short flag,
170 short groupmode)
171{
172 KS_Path *ksp;
173
174 /* sanity checks */
175 if (ELEM(nullptr, ks, rna_path)) {
176 CLOG_ERROR(&LOG, "no Keying Set and/or RNA Path to add path with");
177 return nullptr;
178 }
179
180 /* ID is required for all types of KeyingSets */
181 if (id == nullptr) {
182 CLOG_ERROR(&LOG, "No ID provided for Keying Set Path");
183 return nullptr;
184 }
185
186 /* don't add if there is already a matching KS_Path in the KeyingSet */
187 if (BKE_keyingset_find_path(ks, id, group_name, rna_path, array_index, groupmode)) {
188 if (G.debug & G_DEBUG) {
189 CLOG_ERROR(&LOG, "destination already exists in Keying Set");
190 }
191 return nullptr;
192 }
193
194 /* allocate a new KeyingSet Path */
195 ksp = static_cast<KS_Path *>(MEM_callocN(sizeof(KS_Path), "KeyingSet Path"));
196
197 /* just store absolute info */
198 ksp->id = id;
199 if (group_name) {
200 STRNCPY(ksp->group, group_name);
201 }
202 else {
203 ksp->group[0] = '\0';
204 }
205
206 /* store additional info for relative paths (just in case user makes the set relative) */
207 if (id) {
208 ksp->idtype = GS(id->name);
209 }
210
211 /* just copy path info */
212 /* TODO: should array index be checked too? */
213 ksp->rna_path = BLI_strdup(rna_path);
214 ksp->array_index = array_index;
215
216 /* store flags */
217 ksp->flag = flag;
218 ksp->groupmode = groupmode;
219
220 /* add KeyingSet path to KeyingSet */
221 BLI_addtail(&ks->paths, ksp);
222
223 /* return this path */
224 return ksp;
225}
226
228{
229 /* sanity check */
230 if (ELEM(nullptr, ks, ksp)) {
231 return;
232 }
233
234 /* free RNA-path info */
235 if (ksp->rna_path) {
236 MEM_freeN(ksp->rna_path);
237 }
238
239 /* free path itself */
240 BLI_freelinkN(&ks->paths, ksp);
241}
242
243void BKE_keyingsets_copy(ListBase *newlist, const ListBase *list)
244{
245 BLI_duplicatelist(newlist, list);
246
247 LISTBASE_FOREACH (KeyingSet *, ksn, newlist) {
248 BLI_duplicatelist(&ksn->paths, &ksn->paths);
249
250 LISTBASE_FOREACH (KS_Path *, kspn, &ksn->paths) {
251 kspn->rna_path = static_cast<char *>(MEM_dupallocN(kspn->rna_path));
252 }
253 }
254}
255
257{
258 LISTBASE_FOREACH (KeyingSet *, ksn, keyingsets) {
259 LISTBASE_FOREACH (KS_Path *, kspn, &ksn->paths) {
261 }
262 }
263}
264
265/* Freeing Tools --------------------------- */
266
268{
269 KS_Path *ksp, *kspn;
270
271 /* sanity check */
272 if (ks == nullptr) {
273 return;
274 }
275
276 /* free each path as we go to avoid looping twice */
277 for (ksp = static_cast<KS_Path *>(ks->paths.first); ksp; ksp = kspn) {
278 kspn = ksp->next;
280 }
281}
282
284{
285 KeyingSet *ks, *ksn;
286
287 /* sanity check */
288 if (list == nullptr) {
289 return;
290 }
291
292 /* loop over KeyingSets freeing them
293 * - BKE_keyingset_free_paths() doesn't free the set itself, but it frees its sub-data
294 */
295 for (ks = static_cast<KeyingSet *>(list->first); ks; ks = ksn) {
296 ksn = ks->next;
298 BLI_freelinkN(list, ks);
299 }
300}
301
303{
304 LISTBASE_FOREACH (KeyingSet *, ks, list) {
305 /* KeyingSet */
306 BLO_write_struct(writer, KeyingSet, ks);
307
308 /* Paths */
309 LISTBASE_FOREACH (KS_Path *, ksp, &ks->paths) {
310 /* Path */
311 BLO_write_struct(writer, KS_Path, ksp);
312
313 if (ksp->rna_path) {
314 BLO_write_string(writer, ksp->rna_path);
315 }
316 }
317 }
318}
319
321{
322 LISTBASE_FOREACH (KeyingSet *, ks, list) {
323 /* paths */
324 BLO_read_struct_list(reader, KS_Path, &ks->paths);
325
326 LISTBASE_FOREACH (KS_Path *, ksp, &ks->paths) {
327 /* rna path */
328 BLO_read_string(reader, &ksp->rna_path);
329 }
330 }
331}
332
333/* ***************************************** */
334/* Evaluation Data-Setting Backend */
335
336static bool is_fcurve_evaluatable(const FCurve *fcu)
337{
338 if (fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) {
339 return false;
340 }
341 if (fcu->grp != nullptr && (fcu->grp->flag & AGRP_MUTED)) {
342 return false;
343 }
344 if (BKE_fcurve_is_empty(fcu)) {
345 return false;
346 }
347 return true;
348}
349
351 PointerRNA *ptr, /* typically 'fcu->rna_path', 'fcu->array_index' */
352 const char *rna_path,
353 const int array_index,
354 PathResolvedRNA *r_result)
355{
356 if (rna_path == nullptr) {
357 return false;
358 }
359
360 const char *path = rna_path;
361 if (!RNA_path_resolve_property(ptr, path, &r_result->ptr, &r_result->prop)) {
362 /* failed to get path */
363 /* XXX don't tag as failed yet though, as there are some legit situations (Action Constraint)
364 * where some channels will not exist, but shouldn't lock up Action */
365 if (G.debug & G_DEBUG) {
366 CLOG_WARN(&LOG,
367 "Animato: Invalid path. ID = '%s', '%s[%d]'",
368 (ptr->owner_id) ? (ptr->owner_id->name + 2) : "<No ID>",
369 path,
370 array_index);
371 }
372 return false;
373 }
374
375 if (ptr->owner_id != nullptr && !RNA_property_animateable(&r_result->ptr, r_result->prop)) {
376 return false;
377 }
378
379 int array_len = RNA_property_array_length(&r_result->ptr, r_result->prop);
380 if (array_len && array_index >= array_len) {
381 if (G.debug & G_DEBUG) {
382 CLOG_WARN(&LOG,
383 "Animato: Invalid array index. ID = '%s', '%s[%d]', array length is %d",
384 (ptr->owner_id) ? (ptr->owner_id->name + 2) : "<No ID>",
385 path,
386 array_index,
387 array_len - 1);
388 }
389 return false;
390 }
391
392 r_result->prop_index = array_len ? array_index : -1;
393 return true;
394}
395
396/* less than 1.0 evaluates to false, use epsilon to avoid float error */
397#define ANIMSYS_FLOAT_AS_BOOL(value) ((value) > (1.0f - FLT_EPSILON))
398
399bool BKE_animsys_read_from_rna_path(PathResolvedRNA *anim_rna, float *r_value)
400{
401 PropertyRNA *prop = anim_rna->prop;
402 PointerRNA *ptr = &anim_rna->ptr;
403 int array_index = anim_rna->prop_index;
404 float orig_value;
405
406 /* caller must ensure this is animatable */
407 BLI_assert(RNA_property_animateable(ptr, prop) || ptr->owner_id == nullptr);
408
409 switch (RNA_property_type(prop)) {
410 case PROP_BOOLEAN: {
411 if (array_index != -1) {
412 const int orig_value_coerce = RNA_property_boolean_get_index(ptr, prop, array_index);
413 orig_value = float(orig_value_coerce);
414 }
415 else {
416 const int orig_value_coerce = RNA_property_boolean_get(ptr, prop);
417 orig_value = float(orig_value_coerce);
418 }
419 break;
420 }
421 case PROP_INT: {
422 if (array_index != -1) {
423 const int orig_value_coerce = RNA_property_int_get_index(ptr, prop, array_index);
424 orig_value = float(orig_value_coerce);
425 }
426 else {
427 const int orig_value_coerce = RNA_property_int_get(ptr, prop);
428 orig_value = float(orig_value_coerce);
429 }
430 break;
431 }
432 case PROP_FLOAT: {
433 if (array_index != -1) {
434 const float orig_value_coerce = RNA_property_float_get_index(ptr, prop, array_index);
435 orig_value = float(orig_value_coerce);
436 }
437 else {
438 const float orig_value_coerce = RNA_property_float_get(ptr, prop);
439 orig_value = float(orig_value_coerce);
440 }
441 break;
442 }
443 case PROP_ENUM: {
444 const int orig_value_coerce = RNA_property_enum_get(ptr, prop);
445 orig_value = float(orig_value_coerce);
446 break;
447 }
448 default: /* nothing can be done here... so it is unsuccessful? */
449 return false;
450 }
451
452 if (r_value != nullptr) {
453 *r_value = orig_value;
454 }
455
456 /* successful */
457 return true;
458}
459
460bool BKE_animsys_write_to_rna_path(PathResolvedRNA *anim_rna, const float value)
461{
462 PropertyRNA *prop = anim_rna->prop;
463 PointerRNA *ptr = &anim_rna->ptr;
464 int array_index = anim_rna->prop_index;
465
466 /* caller must ensure this is animatable */
467 BLI_assert(RNA_property_animateable(ptr, prop) || ptr->owner_id == nullptr);
468
469 /* Check whether value is new. Otherwise we skip all the updates. */
470 float old_value;
471 if (!BKE_animsys_read_from_rna_path(anim_rna, &old_value)) {
472 return false;
473 }
474 if (old_value == value) {
475 return true;
476 }
477
478 switch (RNA_property_type(prop)) {
479 case PROP_BOOLEAN: {
480 const int value_coerce = ANIMSYS_FLOAT_AS_BOOL(value);
481 if (array_index != -1) {
482 RNA_property_boolean_set_index(ptr, prop, array_index, value_coerce);
483 }
484 else {
485 RNA_property_boolean_set(ptr, prop, value_coerce);
486 }
487 break;
488 }
489 case PROP_INT: {
490 int value_coerce = int(value);
491 RNA_property_int_clamp(ptr, prop, &value_coerce);
492 if (array_index != -1) {
493 RNA_property_int_set_index(ptr, prop, array_index, value_coerce);
494 }
495 else {
496 RNA_property_int_set(ptr, prop, value_coerce);
497 }
498 break;
499 }
500 case PROP_FLOAT: {
501 float value_coerce = value;
502 RNA_property_float_clamp(ptr, prop, &value_coerce);
503 if (array_index != -1) {
504 RNA_property_float_set_index(ptr, prop, array_index, value_coerce);
505 }
506 else {
507 RNA_property_float_set(ptr, prop, value_coerce);
508 }
509 break;
510 }
511 case PROP_ENUM: {
512 const int value_coerce = int(value);
513 RNA_property_enum_set(ptr, prop, value_coerce);
514 break;
515 }
516 default: /* nothing can be done here... so it is unsuccessful? */
517 return false;
518 }
519
520 /* successful */
521 return true;
522}
523
525{
526 *ptr_orig = *ptr;
527 /* NOTE: nlastrip_evaluate_controls() creates PointerRNA with ID of nullptr. Technically, this is
528 * not a valid pointer, but there are exceptions in various places of this file which handles
529 * such pointers.
530 * We do special trickery here as well, to quickly go from evaluated to original NlaStrip. */
531 if (ptr->owner_id == nullptr) {
532 if (ptr->type != &RNA_NlaStrip) {
533 return false;
534 }
535 NlaStrip *strip = ((NlaStrip *)ptr_orig->data);
536 if (strip->orig_strip == nullptr) {
537 return false;
538 }
539 ptr_orig->data = strip->orig_strip;
540 }
541 else {
542 ptr_orig->owner_id = ptr_orig->owner_id->orig_id;
543 ptr_orig->data = ptr_orig->owner_id;
544 }
545 return true;
546}
547
549 const char *rna_path,
550 int array_index,
551 float value)
552{
553 PointerRNA ptr_orig;
554 if (!animsys_construct_orig_pointer_rna(ptr, &ptr_orig)) {
555 return;
556 }
557 PathResolvedRNA orig_anim_rna;
558 /* TODO(sergey): Should be possible to cache resolved path in dependency graph somehow. */
559 if (BKE_animsys_rna_path_resolve(&ptr_orig, rna_path, array_index, &orig_anim_rna)) {
560 BKE_animsys_write_to_rna_path(&orig_anim_rna, value);
561 }
562}
563
570 Span<FCurve *> fcurves,
571 const AnimationEvalContext *anim_eval_context,
572 bool flush_to_original)
573{
574 /* Calculate then execute each curve. */
575 for (FCurve *fcu : fcurves) {
576
577 if (!is_fcurve_evaluatable(fcu)) {
578 continue;
579 }
580
581 PathResolvedRNA anim_rna;
582 if (BKE_animsys_rna_path_resolve(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
583 const float curval = calculate_fcurve(&anim_rna, fcu, anim_eval_context);
584 BKE_animsys_write_to_rna_path(&anim_rna, curval);
585 if (flush_to_original) {
586 animsys_write_orig_anim_rna(ptr, fcu->rna_path, fcu->array_index, curval);
587 }
588 }
589 }
590}
591
598 Span<FCurve *> quat_fcurves,
599 const AnimationEvalContext *anim_eval_context,
600 float r_quaternion[4])
601{
602 BLI_assert(quat_fcurves.size() <= 4);
603
604 /* Initialize r_quaternion to the unit quaternion so that half-keyed quaternions at least have
605 * *some* value in there. */
606 r_quaternion[0] = 1.0f;
607 r_quaternion[1] = 0.0f;
608 r_quaternion[2] = 0.0f;
609 r_quaternion[3] = 0.0f;
610
611 for (FCurve *quat_curve_fcu : quat_fcurves) {
612 const int array_index = quat_curve_fcu->array_index;
613 quat_rna.prop_index = array_index;
614 r_quaternion[array_index] = calculate_fcurve(&quat_rna, quat_curve_fcu, anim_eval_context);
615 }
616
617 if (quat_fcurves.size() < 4) {
618 /* This quaternion was incompletely keyed, so the result is a mixture of the unit quaternion
619 * and values from FCurves. This means that it's almost certainly no longer of unit length. */
620 normalize_qt(r_quaternion);
621 }
622}
623
629 Span<FCurve *> quaternion_fcurves,
630 const AnimationEvalContext *anim_eval_context,
631 const float blend_factor)
632{
633 BLI_assert(quaternion_fcurves.size() <= 4);
634
635 float current_quat[4];
636 RNA_property_float_get_array(&anim_rna->ptr, anim_rna->prop, current_quat);
637
638 float target_quat[4];
640 *anim_rna, quaternion_fcurves, anim_eval_context, target_quat);
641
642 float blended_quat[4];
643 interp_qt_qtqt(blended_quat, current_quat, target_quat, blend_factor);
644
645 RNA_property_float_set_array(&anim_rna->ptr, anim_rna->prop, blended_quat);
646}
647
648/* LERP between current value (blend_factor=0.0) and the value from the FCurve (blend_factor=1.0)
649 */
651 Span<FCurve *> fcurves,
652 const AnimationEvalContext *anim_eval_context,
653 const float blend_factor)
654{
655 char *channel_to_skip = nullptr;
656 int num_channels_to_skip = 0;
657 for (int fcurve_index : fcurves.index_range()) {
658 FCurve *fcu = fcurves[fcurve_index];
659
660 if (num_channels_to_skip) {
661 /* For skipping already-handled rotation channels. Rotation channels are handled per group,
662 * and not per individual channel. */
663 BLI_assert(channel_to_skip != nullptr);
664 if (STREQ(channel_to_skip, fcu->rna_path)) {
665 /* This is indeed the channel we want to skip. */
666 num_channels_to_skip--;
667 continue;
668 }
669 }
670
671 if (!is_fcurve_evaluatable(fcu)) {
672 continue;
673 }
674
675 PathResolvedRNA anim_rna;
676 if (!BKE_animsys_rna_path_resolve(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
677 continue;
678 }
679
680 if (STREQ(RNA_property_identifier(anim_rna.prop), "rotation_quaternion")) {
681 /* Construct a list of quaternion F-Curves so they can be treated as one unit. */
682 Vector<FCurve *> quat_fcurves = {fcu};
683 for (FCurve *quat_fcurve : fcurves.slice_safe(fcurve_index + 1, 3)) {
684 if (STREQ(quat_fcurve->rna_path, fcu->rna_path)) {
685 quat_fcurves.append(quat_fcurve);
686 }
687 }
688 animsys_blend_fcurves_quaternion(&anim_rna, quat_fcurves, anim_eval_context, blend_factor);
689
690 /* Skip the next up-to-three channels, because those have already been handled here. */
691 MEM_SAFE_FREE(channel_to_skip);
692 channel_to_skip = BLI_strdup(fcu->rna_path);
693 num_channels_to_skip = quat_fcurves.size() - 1;
694 continue;
695 }
696 /* TODO(Sybren): do something similar as above for Euler and Axis/Angle representations. */
697
698 const float fcurve_value = calculate_fcurve(&anim_rna, fcu, anim_eval_context);
699
700 float current_value;
701 float value_to_write;
702 if (BKE_animsys_read_from_rna_path(&anim_rna, &current_value)) {
703 value_to_write = (1 - blend_factor) * current_value + blend_factor * fcurve_value;
704
705 switch (RNA_property_type(anim_rna.prop)) {
706 case PROP_BOOLEAN: /* Without this, anything less than 1.0 is converted to 'False' by
707 * ANIMSYS_FLOAT_AS_BOOL(). This is probably not desirable for blends,
708 * where anything
709 * above a 50% blend should act more like the FCurve than like the
710 * current value. */
711 case PROP_INT:
712 case PROP_ENUM:
713 value_to_write = roundf(value_to_write);
714 break;
715 /* All other types are just handled as float, and value_to_write is already correct. */
716 default:
717 break;
718 }
719 }
720 else {
721 /* Unable to read the current value for blending, so just apply the FCurve value instead. */
722 value_to_write = fcurve_value;
723 }
724
725 BKE_animsys_write_to_rna_path(&anim_rna, value_to_write);
726 }
727
728 MEM_SAFE_FREE(channel_to_skip);
729}
730
731/* ***************************************** */
732/* Driver Evaluation */
733
735{
737 ctx.depsgraph = depsgraph;
738 ctx.eval_time = eval_time;
739 return ctx;
740}
741
743 const AnimationEvalContext *anim_eval_context, float eval_time)
744{
745 return BKE_animsys_eval_context_construct(anim_eval_context->depsgraph, eval_time);
746}
747
748/* Evaluate Drivers */
750 AnimData *adt,
751 const AnimationEvalContext *anim_eval_context)
752{
753 /* drivers are stored as F-Curves, but we cannot use the standard code, as we need to check if
754 * the depsgraph requested that this driver be evaluated...
755 */
756 LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
757 ChannelDriver *driver = fcu->driver;
758 bool ok = false;
759
760 /* check if this driver's curve should be skipped */
761 if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) {
762 /* check if driver itself is tagged for recalculation */
763 /* XXX driver recalc flag is not set yet by depsgraph! */
764 if ((driver) && !(driver->flag & DRIVER_FLAG_INVALID)) {
765 /* evaluate this using values set already in other places
766 * NOTE: for 'layering' option later on, we should check if we should remove old value
767 * before adding new to only be done when drivers only changed. */
768 PathResolvedRNA anim_rna;
769 if (BKE_animsys_rna_path_resolve(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
770 const float curval = calculate_fcurve(&anim_rna, fcu, anim_eval_context);
771 ok = BKE_animsys_write_to_rna_path(&anim_rna, curval);
772 }
773
774 /* set error-flag if evaluation failed */
775 if (ok == 0) {
776 driver->flag |= DRIVER_FLAG_INVALID;
777 }
778 }
779 }
780 }
781}
782
783/* ***************************************** */
784/* Actions Evaluation */
785
786/* strictly not necessary for actual "evaluation", but it is a useful safety check
787 * to reduce the amount of times that users end up having to "revive" wrongly-assigned
788 * actions
789 */
791{
792 int idcode = 0;
793
794 /* just in case */
795 if (ELEM(nullptr, id, act)) {
796 return;
797 }
798
799#ifdef WITH_ANIM_BAKLAVA
801 /* Layered Actions can always be assigned to any ID. It's actually the Slot that is limited
802 * to an ID type (similar to legacy Actions). Layered Actions are evaluated differently,
803 * though, and their evaluation shouldn't end up here. At the moment of writing it can still
804 * happen through NLA evaluation, though, so there's no assert here to prevent this. */
805 /* TODO: when possible, add a BLI_assert_unreachable() here. */
806 return;
807 }
808#endif
809
810 idcode = GS(id->name);
811
812 /* the actual checks... hopefully not too much of a performance hit in the long run... */
813 if (act->idroot == 0) {
814 /* use the current root if not set already
815 * (i.e. newly created actions and actions from 2.50-2.57 builds).
816 * - this has problems if there are 2 users, and the first one encountered is the invalid one
817 * in which case, the user will need to manually fix this (?)
818 */
819 act->idroot = idcode;
820 }
821 else if (act->idroot != idcode) {
822 /* only report this error if debug mode is enabled (to save performance everywhere else) */
823 if (G.debug & G_DEBUG) {
824 printf(
825 "AnimSys Safety Check Failed: Action '%s' is not meant to be used from ID-Blocks of "
826 "type %d such as '%s'\n",
827 act->id.name + 2,
828 idcode,
829 id->name);
830 }
831 }
832}
833
834/* ----------------------------------------- */
835
837 bAction *act,
838 bActionGroup *agrp,
839 const AnimationEvalContext *anim_eval_context)
840{
841 FCurve *fcu;
842
843 /* check if mapper is appropriate for use here (we set to nullptr if it's inappropriate) */
844 if (ELEM(nullptr, act, agrp)) {
845 return;
846 }
847
849
850 /* if group is muted, don't evaluated any of the F-Curve */
851 if (agrp->flag & AGRP_MUTED) {
852 return;
853 }
854
855 const auto visit_fcurve = [&](FCurve *fcu) {
856 /* check if this curve should be skipped */
857 if ((fcu->flag & FCURVE_MUTED) == 0 && !BKE_fcurve_is_empty(fcu)) {
858 PathResolvedRNA anim_rna;
859 if (BKE_animsys_rna_path_resolve(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
860 const float curval = calculate_fcurve(&anim_rna, fcu, anim_eval_context);
861 BKE_animsys_write_to_rna_path(&anim_rna, curval);
862 }
863 }
864 };
865
866#ifdef WITH_ANIM_BAKLAVA
867 blender::animrig::ChannelGroup channel_group = agrp->wrap();
868 if (channel_group.is_legacy()) {
869#endif
870 /* calculate then execute each curve */
871 for (fcu = static_cast<FCurve *>(agrp->channels.first); (fcu) && (fcu->grp == agrp);
872 fcu = fcu->next)
873 {
874 visit_fcurve(fcu);
875 }
876#ifdef WITH_ANIM_BAKLAVA
877 return;
878 }
879
880 for (FCurve *fcurve : channel_group.fcurves()) {
881 visit_fcurve(fcurve);
882 }
883#endif
884}
885
887 bAction *act,
888 const int32_t action_slot_handle,
889 const AnimationEvalContext *anim_eval_context,
890 const bool flush_to_original)
891{
892 /* check if mapper is appropriate for use here (we set to nullptr if it's inappropriate) */
893 if (act == nullptr) {
894 return;
895 }
896
897 animrig::Action &action = act->wrap();
898
899 if (action.is_action_legacy()) {
901
903 animsys_evaluate_fcurves(ptr, fcurves, anim_eval_context, flush_to_original);
904 return;
905 }
906
907 /* TODO: check the slot to see if its IDtype is suitable for the animated ID. */
908
909 /* Note that this is _only_ for evaluation of actions linked by NLA strips. As in, legacy code
910 * paths that I (Sybren) tried to keep as much intact as possible when adding support for slotted
911 * Actions. This code will go away when we implement layered Actions. */
912 Span<FCurve *> fcurves = animrig::fcurves_for_action_slot(action, action_slot_handle);
913 animsys_evaluate_fcurves(ptr, fcurves, anim_eval_context, flush_to_original);
914}
915
917 bAction *act,
918 const int32_t action_slot_handle,
919 const AnimationEvalContext *anim_eval_context,
920 const float blend_factor)
921{
922 animrig::Action &action = act->wrap();
923
924 if (action.is_action_legacy()) {
926 }
927
928 Vector<FCurve *> fcurves = animrig::legacy::fcurves_for_action_slot(act, action_slot_handle);
929 animsys_blend_in_fcurves(ptr, fcurves, anim_eval_context, blend_factor);
930}
931
932/* ***************************************** */
933/* NLA System - Evaluation */
934
935/* calculate influence of strip based for given frame based on blendin/out values */
936static float nlastrip_get_influence(NlaStrip *strip, float cframe)
937{
938 /* sanity checks - normalize the blendin/out values? */
939 strip->blendin = fabsf(strip->blendin);
940 strip->blendout = fabsf(strip->blendout);
941
942 /* result depends on where frame is in respect to blendin/out values */
943 if (IS_EQF(strip->blendin, 0.0f) == false && (cframe <= (strip->start + strip->blendin))) {
944 /* there is some blend-in */
945 return fabsf(cframe - strip->start) / (strip->blendin);
946 }
947 if (IS_EQF(strip->blendout, 0.0f) == false && (cframe >= (strip->end - strip->blendout))) {
948 /* there is some blend-out */
949 return fabsf(strip->end - cframe) / (strip->blendout);
950 }
951
952 /* in the middle of the strip, we should be full strength */
953 return 1.0f;
954}
955
956/* evaluate the evaluation time and influence for the strip, storing the results in the strip */
958 const AnimationEvalContext *anim_eval_context,
959 const bool flush_to_original)
960{
961 /* now strip's evaluate F-Curves for these settings (if applicable) */
962 if (strip->fcurves.first) {
963
964 /* create RNA-pointer needed to set values */
965 PointerRNA strip_ptr = RNA_pointer_create(nullptr, &RNA_NlaStrip, strip);
966
967 /* execute these settings as per normal */
969 animsys_evaluate_fcurves(&strip_ptr, strip_fcurves, anim_eval_context, flush_to_original);
970 }
971
972 /* analytically generate values for influence and time (if applicable)
973 * - we do this after the F-Curves have been evaluated to override the effects of those
974 * in case the override has been turned off.
975 */
976 if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0) {
977 strip->influence = nlastrip_get_influence(strip, anim_eval_context->eval_time);
978 }
979
980 /* Bypass evaluation time computation if time mapping is disabled. */
981 if ((strip->flag & NLASTRIP_FLAG_NO_TIME_MAP) != 0) {
982 strip->strip_time = anim_eval_context->eval_time;
983 return;
984 }
985
986 if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0) {
988 strip, anim_eval_context->eval_time, NLATIME_CONVERT_EVAL);
989 }
990
991 /* if user can control the evaluation time (using F-Curves), consider the option which allows
992 * this time to be clamped to lie within extents of the action-clip, so that a steady changing
993 * rate of progress through several cycles of the clip can be achieved easily.
994 */
995 /* NOTE: if we add any more of these special cases, we better group them up nicely... */
996 if ((strip->flag & NLASTRIP_FLAG_USR_TIME) && (strip->flag & NLASTRIP_FLAG_USR_TIME_CYCLIC)) {
997 strip->strip_time = fmod(strip->strip_time - strip->actstart, strip->actend - strip->actstart);
998 }
999}
1000
1002 ListBase *strips,
1003 short index,
1004 const AnimationEvalContext *anim_eval_context,
1005 const bool flush_to_original)
1006{
1007 NlaStrip *estrip = nullptr;
1008 NlaEvalStrip *nes;
1009 short side = 0;
1010 float ctime = anim_eval_context->eval_time;
1011
1012 /* loop over strips, checking if they fall within the range */
1013 LISTBASE_FOREACH (NlaStrip *, strip, strips) {
1014 /* Check if current time occurs within this strip. */
1015
1016 /* This block leads to the Action Track and non-time-remapped tweak strip evaluation to respect
1017 * the extrapolation modes. If in_range, these two tracks will always output NES_TIME_WITHIN so
1018 * fcurve extrapolation isn't clamped to the keyframe bounds. */
1019 bool in_range = IN_RANGE_INCL(ctime, strip->start, strip->end);
1020 if (strip->flag & NLASTRIP_FLAG_NO_TIME_MAP) {
1021 switch (strip->extendmode) {
1023 in_range = true;
1024 break;
1026 in_range = ctime >= strip->start;
1027 break;
1028 }
1029 }
1030
1031 if (in_range) {
1032 /* this strip is active, so try to use it */
1033 estrip = strip;
1034 side = NES_TIME_WITHIN;
1035 break;
1036 }
1037
1038 /* if time occurred before current strip... */
1039 if (ctime < strip->start) {
1040 if (strip == strips->first) {
1041 /* before first strip - only try to use it if it extends backwards in time too */
1042 if (strip->extendmode == NLASTRIP_EXTEND_HOLD) {
1043 estrip = strip;
1044 }
1045
1046 /* side is 'before' regardless of whether there's a useful strip */
1047 side = NES_TIME_BEFORE;
1048 }
1049 else {
1050 /* before next strip - previous strip has ended, but next hasn't begun,
1051 * so blending mode depends on whether strip is being held or not...
1052 * - only occurs when no transition strip added, otherwise the transition would have
1053 * been picked up above...
1054 */
1055 strip = strip->prev;
1056
1057 if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) {
1058 estrip = strip;
1059 }
1060 side = NES_TIME_AFTER;
1061 }
1062 break;
1063 }
1064
1065 /* if time occurred after current strip... */
1066 if (ctime > strip->end) {
1067 /* only if this is the last strip should we do anything, and only if that is being held */
1068 if (strip == strips->last) {
1069 if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) {
1070 estrip = strip;
1071 }
1072
1073 side = NES_TIME_AFTER;
1074 break;
1075 }
1076
1077 /* otherwise, skip... as the 'before' case will catch it more elegantly! */
1078 }
1079 }
1080
1081 /* check if a valid strip was found
1082 * - must not be muted (i.e. will have contribution
1083 */
1084 if ((estrip == nullptr) || (estrip->flag & NLASTRIP_FLAG_MUTED)) {
1085 return nullptr;
1086 }
1087
1088 /* if ctime was not within the boundaries of the strip, clamp! */
1089 switch (side) {
1090 case NES_TIME_BEFORE: /* extend first frame only */
1091 ctime = estrip->start;
1092 break;
1093 case NES_TIME_AFTER: /* extend last frame only */
1094 ctime = estrip->end;
1095 break;
1096 }
1097
1098 /* evaluate strip's evaluation controls
1099 * - skip if no influence (i.e. same effect as muting the strip)
1100 * - negative influence is not supported yet... how would that be defined?
1101 */
1102 /* TODO: this sounds a bit hacky having a few isolated F-Curves
1103 * stuck on some data it operates on... */
1105 anim_eval_context, ctime);
1106 nlastrip_evaluate_controls(estrip, &clamped_eval_context, flush_to_original);
1107 if (estrip->influence <= 0.0f) {
1108 return nullptr;
1109 }
1110
1111 /* check if strip has valid data to evaluate,
1112 * and/or perform any additional type-specific actions
1113 */
1114 switch (estrip->type) {
1115 case NLASTRIP_TYPE_CLIP: /* clip must have some action to evaluate */
1116 if (estrip->act == nullptr) {
1117 return nullptr;
1118 }
1119 break;
1120 /* There must be strips to transition from and to (i.e. `prev` and `next` required). */
1122 if (ELEM(nullptr, estrip->prev, estrip->next)) {
1123 return nullptr;
1124 }
1125
1126 /* evaluate controls for the relevant extents of the bordering strips... */
1128 anim_eval_context, estrip->start);
1130 anim_eval_context, estrip->end);
1131 nlastrip_evaluate_controls(estrip->prev, &start_eval_context, flush_to_original);
1132 nlastrip_evaluate_controls(estrip->next, &end_eval_context, flush_to_original);
1133 break;
1134 }
1135
1136 /* add to list of strips we need to evaluate */
1137 nes = static_cast<NlaEvalStrip *>(MEM_callocN(sizeof(NlaEvalStrip), "NlaEvalStrip"));
1138
1139 nes->strip = estrip;
1140 nes->strip_mode = side;
1141 nes->track_index = index;
1142 nes->strip_time = estrip->strip_time;
1143
1144 if (list) {
1145 BLI_addtail(list, nes);
1146 }
1147
1148 return nes;
1149}
1150
1152 ListBase *dst_list,
1153 NlaStrip *single_strip,
1154 const AnimationEvalContext *anim_eval_context,
1155 const bool flush_to_original)
1156{
1157 ListBase single_tracks_list;
1158 single_tracks_list.first = single_tracks_list.last = single_strip;
1159
1161 dst_list, &single_tracks_list, -1, anim_eval_context, flush_to_original);
1162}
1163
1164/* ---------------------- */
1165
1166/* Initialize a valid mask, allocating memory if necessary. */
1167static void nlavalidmask_init(NlaValidMask *mask, int bits)
1168{
1169 if (BLI_BITMAP_SIZE(bits) > sizeof(mask->buffer)) {
1170 mask->ptr = BLI_BITMAP_NEW(bits, "NlaValidMask");
1171 }
1172 else {
1173 mask->ptr = mask->buffer;
1174 }
1175}
1176
1177/* Free allocated memory for the mask. */
1179{
1180 if (mask->ptr != mask->buffer) {
1181 MEM_freeN(mask->ptr);
1182 }
1183}
1184
1185/* ---------------------- */
1186
1187/* Hashing functions for NlaEvalChannelKey. */
1188static uint nlaevalchan_keyhash(const void *ptr)
1189{
1190 const NlaEvalChannelKey *key = static_cast<const NlaEvalChannelKey *>(ptr);
1192 return hash ^ BLI_ghashutil_ptrhash(key->prop);
1193}
1194
1195static bool nlaevalchan_keycmp(const void *a, const void *b)
1196{
1197 const NlaEvalChannelKey *A = static_cast<const NlaEvalChannelKey *>(a);
1198 const NlaEvalChannelKey *B = static_cast<const NlaEvalChannelKey *>(b);
1199
1200 return ((A->ptr.data != B->ptr.data) || (A->prop != B->prop));
1201}
1202
1203/* ---------------------- */
1204
1205/* Allocate a new blending value snapshot for the channel. */
1207{
1208 int length = nec->base_snapshot.length;
1209
1210 size_t byte_size = sizeof(NlaEvalChannelSnapshot) + sizeof(float) * length;
1211 NlaEvalChannelSnapshot *nec_snapshot = static_cast<NlaEvalChannelSnapshot *>(
1212 MEM_callocN(byte_size, "NlaEvalChannelSnapshot"));
1213
1214 nec_snapshot->channel = nec;
1215 nec_snapshot->length = length;
1216 nlavalidmask_init(&nec_snapshot->blend_domain, length);
1217 nlavalidmask_init(&nec_snapshot->remap_domain, length);
1218
1219 return nec_snapshot;
1220}
1221
1222/* Free a channel's blending value snapshot. */
1224{
1225 BLI_assert(!nec_snapshot->is_base);
1226
1227 nlavalidmask_free(&nec_snapshot->blend_domain);
1228 nlavalidmask_free(&nec_snapshot->remap_domain);
1229 MEM_freeN(nec_snapshot);
1230}
1231
1232/* Copy all data in the snapshot. */
1234 const NlaEvalChannelSnapshot *src)
1235{
1236 BLI_assert(dst->channel == src->channel);
1237
1238 memcpy(dst->values, src->values, sizeof(float) * dst->length);
1239}
1240
1241/* ---------------------- */
1242
1243/* Initialize a blending state snapshot structure. */
1245 NlaEvalData *nlaeval,
1246 NlaEvalSnapshot *base)
1247{
1248 snapshot->base = base;
1249 snapshot->size = std::max(16, nlaeval->num_channels);
1250 snapshot->channels = static_cast<NlaEvalChannelSnapshot **>(
1251 MEM_callocN(sizeof(*snapshot->channels) * snapshot->size, "NlaEvalSnapshot::channels"));
1252}
1253
1254/* Retrieve the individual channel snapshot. */
1256{
1257 return (index < snapshot->size) ? snapshot->channels[index] : nullptr;
1258}
1259
1260/* Ensure at least this number of slots exists. */
1261static void nlaeval_snapshot_ensure_size(NlaEvalSnapshot *snapshot, int size)
1262{
1263 if (size > snapshot->size) {
1264 snapshot->size *= 2;
1265 CLAMP_MIN(snapshot->size, size);
1266 CLAMP_MIN(snapshot->size, 16);
1267
1268 size_t byte_size = sizeof(*snapshot->channels) * snapshot->size;
1269 snapshot->channels = static_cast<NlaEvalChannelSnapshot **>(
1270 MEM_recallocN_id(snapshot->channels, byte_size, "NlaEvalSnapshot::channels"));
1271 }
1272}
1273
1274/* Retrieve the address of a slot in the blending state snapshot for this channel (may realloc). */
1276 NlaEvalChannel *nec)
1277{
1279 return &snapshot->channels[nec->index];
1280}
1281
1282/* Retrieve the blending snapshot for the specified channel, with fallback to base. */
1284 NlaEvalChannel *nec)
1285{
1286 while (snapshot != nullptr) {
1287 NlaEvalChannelSnapshot *nec_snapshot = nlaeval_snapshot_get(snapshot, nec->index);
1288 if (nec_snapshot != nullptr) {
1289 return nec_snapshot;
1290 }
1291 snapshot = snapshot->base;
1292 }
1293
1294 return &nec->base_snapshot;
1295}
1296
1297/* Retrieve or create the channel value snapshot, copying from the other snapshot
1298 * (or default values) */
1300 NlaEvalChannel *nec)
1301{
1303
1304 if (*slot == nullptr) {
1305 NlaEvalChannelSnapshot *base_snapshot, *nec_snapshot;
1306
1307 nec_snapshot = nlaevalchan_snapshot_new(nec);
1308 base_snapshot = nlaeval_snapshot_find_channel(snapshot->base, nec);
1309
1310 nlaevalchan_snapshot_copy(nec_snapshot, base_snapshot);
1311
1312 *slot = nec_snapshot;
1313 }
1314
1315 return *slot;
1316}
1317
1318/* Free all memory owned by this blending snapshot structure. */
1320{
1321 if (snapshot->channels != nullptr) {
1322 for (int i = 0; i < snapshot->size; i++) {
1323 NlaEvalChannelSnapshot *nec_snapshot = snapshot->channels[i];
1324 if (nec_snapshot != nullptr) {
1325 nlaevalchan_snapshot_free(nec_snapshot);
1326 }
1327 }
1328
1329 MEM_freeN(snapshot->channels);
1330 }
1331
1332 snapshot->base = nullptr;
1333 snapshot->size = 0;
1334 snapshot->channels = nullptr;
1335}
1336
1337/* ---------------------- */
1338
1339/* Free memory owned by this evaluation channel. */
1341{
1343 nec->key.~NlaEvalChannelKey();
1344}
1345
1346/* Initialize a full NLA evaluation state structure. */
1347static void nlaeval_init(NlaEvalData *nlaeval)
1348{
1349 memset(nlaeval, 0, sizeof(*nlaeval));
1350
1351 nlaeval->path_hash = BLI_ghash_str_new("NlaEvalData::path_hash");
1352 nlaeval->key_hash = BLI_ghash_new(
1353 nlaevalchan_keyhash, nlaevalchan_keycmp, "NlaEvalData::key_hash");
1354}
1355
1356static void nlaeval_free(NlaEvalData *nlaeval)
1357{
1358 /* Delete base snapshot - its channels are part of NlaEvalChannel and shouldn't be freed. */
1360
1361 /* Delete result snapshot. */
1363
1364 /* Delete channels. */
1365 LISTBASE_FOREACH (NlaEvalChannel *, nec, &nlaeval->channels) {
1367 }
1368
1369 BLI_freelistN(&nlaeval->channels);
1370 BLI_ghash_free(nlaeval->path_hash, nullptr, nullptr);
1371 BLI_ghash_free(nlaeval->key_hash, nullptr, nullptr);
1372}
1373
1374/* ---------------------- */
1375
1376static int nlaevalchan_validate_index(const NlaEvalChannel *nec, int index)
1377{
1378 if (nec->is_array) {
1379 if (index >= 0 && index < nec->base_snapshot.length) {
1380 return index;
1381 }
1382
1383 return -1;
1384 }
1385 return 0;
1386}
1387
1388static bool nlaevalchan_validate_index_ex(const NlaEvalChannel *nec, const int array_index)
1389{
1392 const int index = nlaevalchan_validate_index(nec, array_index);
1393
1394 if (index < 0) {
1395 if (G.debug & G_DEBUG) {
1396 ID *id = nec->key.ptr.owner_id;
1397 CLOG_WARN(&LOG,
1398 "Animation: Invalid array index. ID = '%s', '%s[%d]', array length is %d",
1399 id ? (id->name + 2) : "<No ID>",
1400 nec->rna_path,
1401 array_index,
1402 nec->base_snapshot.length);
1403 }
1404
1405 return false;
1406 }
1407 return true;
1408}
1409
1410/* Initialize default values for NlaEvalChannel from the property data. */
1411static void nlaevalchan_get_default_values(NlaEvalChannel *nec, float *r_values)
1412{
1413 PointerRNA *ptr = &nec->key.ptr;
1414 PropertyRNA *prop = nec->key.prop;
1415 int length = nec->base_snapshot.length;
1416
1417 /* Use unit quaternion for quaternion properties. */
1418 if (nec->mix_mode == NEC_MIX_QUATERNION) {
1419 unit_qt(r_values);
1420 return;
1421 }
1422 /* Use all zero for Axis-Angle properties. */
1423 if (nec->mix_mode == NEC_MIX_AXIS_ANGLE) {
1424 zero_v4(r_values);
1425 return;
1426 }
1427
1428 /* NOTE: while this doesn't work for all RNA properties as default values aren't in fact
1429 * set properly for most of them, at least the common ones (which also happen to get used
1430 * in NLA strips a lot, e.g. scale) are set correctly.
1431 */
1432 if (RNA_property_array_check(prop)) {
1433 BLI_assert(length == RNA_property_array_length(ptr, prop));
1434 bool *tmp_bool;
1435 int *tmp_int;
1436
1437 switch (RNA_property_type(prop)) {
1438 case PROP_BOOLEAN:
1439 tmp_bool = static_cast<bool *>(MEM_malloc_arrayN(length, sizeof(*tmp_bool), __func__));
1441 for (int i = 0; i < length; i++) {
1442 r_values[i] = float(tmp_bool[i]);
1443 }
1444 MEM_freeN(tmp_bool);
1445 break;
1446 case PROP_INT:
1447 tmp_int = static_cast<int *>(MEM_malloc_arrayN(length, sizeof(*tmp_int), __func__));
1449 for (int i = 0; i < length; i++) {
1450 r_values[i] = float(tmp_int[i]);
1451 }
1452 MEM_freeN(tmp_int);
1453 break;
1454 case PROP_FLOAT:
1456 break;
1457 default:
1458 memset(r_values, 0, sizeof(float) * length);
1459 }
1460 }
1461 else {
1462 BLI_assert(length == 1);
1463
1464 switch (RNA_property_type(prop)) {
1465 case PROP_BOOLEAN:
1466 *r_values = float(RNA_property_boolean_get_default(ptr, prop));
1467 break;
1468 case PROP_INT:
1469 *r_values = float(RNA_property_int_get_default(ptr, prop));
1470 break;
1471 case PROP_FLOAT:
1472 *r_values = RNA_property_float_get_default(ptr, prop);
1473 break;
1474 case PROP_ENUM:
1475 *r_values = float(RNA_property_enum_get_default(ptr, prop));
1476 break;
1477 default:
1478 *r_values = 0.0f;
1479 }
1480 }
1481
1482 /* Ensure multiplicative properties aren't reset to 0. */
1483 if (nec->mix_mode == NEC_MIX_MULTIPLY) {
1484 for (int i = 0; i < length; i++) {
1485 if (r_values[i] == 0.0f) {
1486 r_values[i] = 1.0f;
1487 }
1488 }
1489 }
1490}
1491
1493{
1495
1496 if (subtype == PROP_QUATERNION && length == 4) {
1497 return NEC_MIX_QUATERNION;
1498 }
1499 if (subtype == PROP_AXISANGLE && length == 4) {
1500 return NEC_MIX_AXIS_ANGLE;
1501 }
1503 return NEC_MIX_MULTIPLY;
1504 }
1505 return NEC_MIX_ADD;
1506}
1507
1508/* Verify that an appropriate NlaEvalChannel for this property exists. */
1510 const char *path,
1511 NlaEvalChannelKey *key)
1512{
1513 /* Look it up in the key hash. */
1514 NlaEvalChannel **p_key_nec;
1515 NlaEvalChannelKey **p_key;
1516 bool found_key = BLI_ghash_ensure_p_ex(
1517 nlaeval->key_hash, key, (void ***)&p_key, (void ***)&p_key_nec);
1518
1519 if (found_key) {
1520 return *p_key_nec;
1521 }
1522
1523 /* Create the channel. */
1524 bool is_array = RNA_property_array_check(key->prop);
1525 int length = is_array ? RNA_property_array_length(&key->ptr, key->prop) : 1;
1526
1527 NlaEvalChannel *nec = static_cast<NlaEvalChannel *>(
1528 MEM_callocN(sizeof(NlaEvalChannel) + sizeof(float) * length, "NlaEvalChannel"));
1529
1530 /* Initialize the channel. */
1531 nec->rna_path = path;
1532 new (&nec->key) NlaEvalChannelKey(*key);
1533
1534 nec->owner = nlaeval;
1535 nec->index = nlaeval->num_channels++;
1536 nec->is_array = is_array;
1537
1538 nec->mix_mode = nlaevalchan_detect_mix_mode(key, length);
1539
1540 nlavalidmask_init(&nec->domain, length);
1541
1542 nec->base_snapshot.channel = nec;
1544 nec->base_snapshot.is_base = true;
1545
1547
1548 /* Store channel in data structures. */
1549 BLI_addtail(&nlaeval->channels, nec);
1550
1552
1553 *p_key_nec = nec;
1554 *p_key = &nec->key;
1555
1556 return nec;
1557}
1558
1559/* Verify that an appropriate NlaEvalChannel for this path exists. */
1560static NlaEvalChannel *nlaevalchan_verify(PointerRNA *ptr, NlaEvalData *nlaeval, const char *path)
1561{
1562 if (path == nullptr) {
1563 return nullptr;
1564 }
1565
1566 /* Lookup the path in the path based hash. */
1567 NlaEvalChannel **p_path_nec;
1568 bool found_path = BLI_ghash_ensure_p(nlaeval->path_hash, (void *)path, (void ***)&p_path_nec);
1569
1570 if (found_path) {
1571 return *p_path_nec;
1572 }
1573
1574 /* Cache nullptr result for now. */
1575 *p_path_nec = nullptr;
1576
1577 /* Resolve the property and look it up in the key hash. */
1578 NlaEvalChannelKey key{};
1579
1580 if (!RNA_path_resolve_property(ptr, path, &key.ptr, &key.prop)) {
1581 /* Report failure to resolve the path. */
1582 if (G.debug & G_DEBUG) {
1583 CLOG_WARN(&LOG,
1584 "Animato: Invalid path. ID = '%s', '%s'",
1585 (ptr->owner_id) ? (ptr->owner_id->name + 2) : "<No ID>",
1586 path);
1587 }
1588
1589 return nullptr;
1590 }
1591
1592 /* Check that the property can be animated. */
1593 if (ptr->owner_id != nullptr && !RNA_property_animateable(&key.ptr, key.prop)) {
1594 return nullptr;
1595 }
1596
1597 NlaEvalChannel *nec = nlaevalchan_verify_key(nlaeval, path, &key);
1598
1599 if (nec->rna_path == nullptr) {
1600 nec->rna_path = path;
1601 }
1602
1603 return *p_path_nec = nec;
1604}
1605
1606/* ---------------------- */
1607
1609static bool nla_blend_get_inverted_lower_value(const int blendmode,
1610 const float strip_value,
1611 const float blended_value,
1612 const float influence,
1613 float *r_lower_value)
1614{
1615 if (IS_EQF(influence, 0.0f)) {
1616 *r_lower_value = blended_value;
1617 return true;
1618 }
1619
1620 switch (blendmode) {
1621 case NLASTRIP_MODE_ADD: /* Simply subtract the scaled value on to the stack. */
1622 *r_lower_value = blended_value - (strip_value * influence);
1623 return true;
1624
1625 case NLASTRIP_MODE_SUBTRACT: /* Simply add the scaled value from the stack. */
1626 *r_lower_value = blended_value + (strip_value * influence);
1627 return true;
1628
1630 /* Check for division by zero. */
1631 const float denominator = (influence * strip_value + (1.0f - influence));
1632 if (IS_EQF(denominator, 0.0f)) {
1633 /* For 0/0, any r_lower_value is a solution. We'll just choose 1.
1634 *
1635 * Any r_lower_value is a solution. In this case, ideally we would insert redundant
1636 * keyframes, those that don't change the fcurve's shape. Otherwise, we're likely messing
1637 * up interpolation for the animator, requiring further cleanup on their part.
1638 */
1639 if (IS_EQF(blended_value, 0.0f)) {
1640 /* When denominator==0:
1641 *
1642 * denominator = (inf * strip_value + (1.0f - inf))
1643 * 0 = inf * strip_value + (1-inf)
1644 * -inf * strip_value = 1 - inf
1645 * -strip_value = (1 - inf) / inf
1646 * strip_value = (inf - 1) / inf
1647 * strip_value = 1 - (1/inf)
1648 *
1649 * For blending, nla_blend_value(), this results in:
1650 *
1651 * blended_value = inf * (lower_value * strip_value) + (1 - inf) * lower_value;
1652 * = inf * (lower_value * (1 - (1/inf))) + ...
1653 * = inf * (1 - (1/inf)) * lower_value + ...
1654 * = (inf - (inf/inf)) * lower_value + ...
1655 * = -(inf - 1) * lower_value + (1 - inf) * lower_value;
1656 * blended_value = 0
1657 *
1658 * Effectively, blended_value will equal 0 no matter what lower_value is. Put another
1659 * way, when (blended_value==0 and denominator==0), then lower_value can be any value and
1660 * blending will give us back blended_value=0. We have infinite solutions for this case.
1661 */
1662 *r_lower_value = 1;
1663 return true;
1664 }
1665 /* No solution for division by zero. */
1666 return false;
1667 }
1668 /* Math:
1669 * blended_value = inf * (lower_value * strip_value) + (1 - inf) * lower_value
1670 * = lower_value * (inf * strip_value + (1-inf))
1671 * lower_value = blended_value / (inf * strip_value + (1-inf))
1672 * lower_value = blended_value / denominator
1673 */
1674 *r_lower_value = blended_value / denominator;
1675 return true;
1676 }
1678 BLI_assert_msg(0, "Use nla_combine_get_inverted_lower_value()");
1679 return false;
1680
1682
1683 /* No solution if lower strip has 0 influence. */
1684 if (IS_EQF(influence, 1.0f)) {
1685 return false;
1686 }
1687
1688 /* Math:
1689 *
1690 * blended_value = lower_value * (1.0f - inf) + (strip_value * inf)
1691 * blended_value - (strip_value * inf) = lower_value * (1.0f - inf)
1692 * blended_value - (strip_value * inf) / (1.0f - inf) = lower_value
1693 *
1694 * lower_value = blended_value - (strip_value * inf) / (1.0f - inf)
1695 */
1696 *r_lower_value = (blended_value - (strip_value * influence)) / (1.0f - influence);
1697 return true;
1698 }
1699
1700 BLI_assert_msg(0, "invalid blend mode");
1701 return false;
1702}
1703
1705static bool nla_combine_get_inverted_lower_value(const int mix_mode,
1706 float base_value,
1707 const float strip_value,
1708 const float blended_value,
1709 const float influence,
1710 float *r_lower_value)
1711{
1712 if (IS_EQF(influence, 0.0f)) {
1713 *r_lower_value = blended_value;
1714 return true;
1715 }
1716
1717 /* Perform blending. */
1718 switch (mix_mode) {
1719 case NEC_MIX_ADD:
1720 case NEC_MIX_AXIS_ANGLE:
1721 *r_lower_value = blended_value - (strip_value - base_value) * influence;
1722 return true;
1723 case NEC_MIX_MULTIPLY: /* Division by zero. */
1724 if (IS_EQF(strip_value, 0.0f)) {
1725 /* Resolve 0/0 to 1.
1726 *
1727 * Any r_lower_value is a solution. In this case, ideally we would insert redundant
1728 * keyframes, those that don't change the fcurve's shape. Otherwise, we're likely messing
1729 * up interpolation for the animator, requiring further cleanup on their part.
1730 */
1731 if (IS_EQF(blended_value, 0.0f)) {
1732 /* For blending, nla_combine_value(), when `strip_value == 0`:
1733 * \code{.cc}
1734 * blended_value = lower_value * powf(strip_value / base_value, infl);
1735 * blended_value = lower_value * powf(0, infl);
1736 * blended_value = lower_value * 0;
1737 * blended_value = 0;
1738 * \endcode
1739 *
1740 * Effectively, blended_value will equal 0 no matter what lower_value is. Put another
1741 * way, when (blended_value==0 and strip_value==0), then lower_value can be any value and
1742 * blending will give us back blended_value=0. We have infinite solutions for this case.
1743 */
1744 *r_lower_value = 1.0f;
1745 return true;
1746 }
1747 /* No solution. */
1748 return false;
1749 }
1750
1751 if (IS_EQF(base_value, 0.0f)) {
1752 base_value = 1.0f;
1753 }
1754
1755 *r_lower_value = blended_value / powf(strip_value / base_value, influence);
1756 return true;
1757
1758 case NEC_MIX_QUATERNION:
1759 BLI_assert_msg(0, "Use nla_combine_quaternion_get_inverted_lower_values()");
1760 return false;
1761 }
1762
1763 BLI_assert_msg(0, "Mixmode not implemented");
1764 return false;
1765}
1766
1767static void nla_combine_quaternion_get_inverted_lower_values(const float strip_values[4],
1768 const float blended_values[4],
1769 const float influence,
1770 float r_lower_value[4])
1771{
1772 if (IS_EQF(influence, 0.0f)) {
1773 normalize_qt_qt(r_lower_value, blended_values);
1774 return;
1775 }
1776
1777 /* blended_value = lower_values @ strip_values^infl
1778 * blended_value @ inv(strip_values^inf) = lower_values
1779 *
1780 * Returns: lower_values = blended_value @ inv(strip_values^inf) */
1781 float tmp_strip_values[4], tmp_blended[4];
1782
1783 normalize_qt_qt(tmp_strip_values, strip_values);
1784 normalize_qt_qt(tmp_blended, blended_values);
1785
1786 pow_qt_fl_normalized(tmp_strip_values, influence);
1787 invert_qt_normalized(tmp_strip_values);
1788
1789 mul_qt_qtqt(r_lower_value, tmp_blended, tmp_strip_values);
1790}
1791
1792/* Blend the lower nla stack value and upper strip value of a channel according to mode and
1793 * influence. */
1794static float nla_blend_value(const int blendmode,
1795 const float lower_value,
1796 const float strip_value,
1797 const float influence)
1798{
1799 /* Optimization: no need to try applying if there is no influence. */
1800 if (IS_EQF(influence, 0.0f)) {
1801 return lower_value;
1802 }
1803
1804 /* Perform blending. */
1805 switch (blendmode) {
1806 case NLASTRIP_MODE_ADD: /* Simply add the scaled value on to the stack. */
1807 return lower_value + (strip_value * influence);
1808
1809 case NLASTRIP_MODE_SUBTRACT: /* Simply subtract the scaled value from the stack. */
1810 return lower_value - (strip_value * influence);
1811
1812 case NLASTRIP_MODE_MULTIPLY: /* Multiply the scaled value with the stack. */
1813 return influence * (lower_value * strip_value) + (1 - influence) * lower_value;
1814
1816 BLI_assert_msg(0, "combine mode");
1818
1819 default: /* TODO: Do we really want to blend by default? it seems more uses might prefer add...
1820 */
1821 /* Do linear interpolation. The influence of the accumulated data
1822 * (elsewhere, that is called `dstwegiht`) is 1 - influence,
1823 * since the strip's influence is `srcweight`. */
1824 return lower_value * (1.0f - influence) + (strip_value * influence);
1825 }
1826}
1827
1828/* Blend the lower nla stack value and upper strip value of a channel according to mode and
1829 * influence. */
1830static float nla_combine_value(const int mix_mode,
1831 float base_value,
1832 const float lower_value,
1833 const float strip_value,
1834 const float influence)
1835{
1836 /* Optimization: No need to try applying if there is no influence. */
1837 if (IS_EQF(influence, 0.0f)) {
1838 return lower_value;
1839 }
1840
1841 /* Perform blending */
1842 switch (mix_mode) {
1843 case NEC_MIX_ADD:
1844 case NEC_MIX_AXIS_ANGLE:
1845 return lower_value + (strip_value - base_value) * influence;
1846
1847 case NEC_MIX_MULTIPLY:
1848 if (IS_EQF(base_value, 0.0f)) {
1849 base_value = 1.0f;
1850 }
1851 return lower_value * powf(strip_value / base_value, influence);
1852
1853 default:
1854 BLI_assert_msg(0, "invalid mix mode");
1855 return lower_value;
1856 }
1857}
1858
1860static bool nla_blend_get_inverted_strip_value(const int blendmode,
1861 const float lower_value,
1862 const float blended_value,
1863 const float influence,
1864 float *r_strip_value)
1865{
1867 if (IS_EQF(influence, 0.0f)) {
1868 return false;
1869 }
1870
1871 switch (blendmode) {
1872 case NLASTRIP_MODE_ADD:
1873 *r_strip_value = (blended_value - lower_value) / influence;
1874 return true;
1875
1877 *r_strip_value = (lower_value - blended_value) / influence;
1878 return true;
1879
1881 if (IS_EQF(lower_value, 0.0f)) {
1882 /* Resolve 0/0 to 1. */
1883 if (IS_EQF(blended_value, 0.0f)) {
1884 *r_strip_value = 1.0f;
1885 return true;
1886 }
1887 /* Division by zero. */
1888 return false;
1889 }
1890
1901 *r_strip_value = ((blended_value - lower_value) / (influence * lower_value)) + 1.0f;
1902 return true;
1903
1905 BLI_assert_msg(0, "combine mode");
1907
1908 default:
1909
1918 *r_strip_value = (blended_value - lower_value * (1.0f - influence)) / influence;
1919 return true;
1920 }
1921}
1922
1924static bool nla_combine_get_inverted_strip_value(const int mix_mode,
1925 float base_value,
1926 const float lower_value,
1927 const float blended_value,
1928 const float influence,
1929 float *r_strip_value)
1930{
1931 /* No solution if strip had no influence. */
1932 if (IS_EQF(influence, 0.0f)) {
1933 return false;
1934 }
1935
1936 switch (mix_mode) {
1937 case NEC_MIX_ADD:
1938 case NEC_MIX_AXIS_ANGLE:
1939 *r_strip_value = base_value + (blended_value - lower_value) / influence;
1940 return true;
1941
1942 case NEC_MIX_MULTIPLY:
1943 if (IS_EQF(base_value, 0.0f)) {
1944 base_value = 1.0f;
1945 }
1946 /* Division by zero. */
1947 if (IS_EQF(lower_value, 0.0f)) {
1948 /* Resolve 0/0 to 1. */
1949 if (IS_EQF(blended_value, 0.0f)) {
1950 *r_strip_value = base_value;
1951 return true;
1952 }
1953 /* Division by zero. */
1954 return false;
1955 }
1956
1957 *r_strip_value = base_value * powf(blended_value / lower_value, 1.0f / influence);
1958 return true;
1959
1960 default:
1961 BLI_assert_msg(0, "invalid mix mode");
1962 return false;
1963 }
1964}
1965
1970static void nla_combine_quaternion(const float lower_values[4],
1971 const float strip_values[4],
1972 const float influence,
1973 float r_blended_value[4])
1974{
1975 float tmp_lower[4], tmp_strip_values[4];
1976
1977 normalize_qt_qt(tmp_lower, lower_values);
1978 normalize_qt_qt(tmp_strip_values, strip_values);
1979
1980 pow_qt_fl_normalized(tmp_strip_values, influence);
1981 mul_qt_qtqt(r_blended_value, tmp_lower, tmp_strip_values);
1982}
1983
1985static bool nla_combine_quaternion_get_inverted_strip_values(const float lower_values[4],
1986 const float blended_values[4],
1987 const float influence,
1988 float r_strip_values[4])
1989{
1990 /* blended_value = lower_values @ r_strip_values^infl
1991 * inv(lower_values) @ blended_value = r_strip_values^infl
1992 * (inv(lower_values) @ blended_value) ^ (1/inf) = r_strip_values
1993 *
1994 * Returns: r_strip_values = (inv(lower_values) @ blended_value) ^ (1/inf) */
1995 if (IS_EQF(influence, 0.0f)) {
1996 return false;
1997 }
1998 float tmp_lower[4], tmp_blended[4];
1999
2000 normalize_qt_qt(tmp_lower, lower_values);
2001 normalize_qt_qt(tmp_blended, blended_values);
2002 invert_qt_normalized(tmp_lower);
2003
2004 mul_qt_qtqt(r_strip_values, tmp_lower, tmp_blended);
2005 pow_qt_fl_normalized(r_strip_values, 1.0f / influence);
2006
2007 return true;
2008}
2009
2010/* ---------------------- */
2011
2012/* Assert necs and necs->channel is nonNull. */
2014{
2015 UNUSED_VARS_NDEBUG(necs);
2016 BLI_assert(necs != nullptr && necs->channel != nullptr);
2017}
2018
2019/* Assert that the channels given can be blended or combined together. */
2021 const NlaEvalChannelSnapshot *lower_necs,
2022 const NlaEvalChannelSnapshot *upper_necs,
2023 const NlaEvalChannelSnapshot *blended_necs)
2024{
2025 UNUSED_VARS_NDEBUG(lower_necs, upper_necs, blended_necs);
2026 BLI_assert(!ELEM(nullptr, lower_necs, blended_necs));
2027 BLI_assert(upper_necs == nullptr || lower_necs->length == upper_necs->length);
2028 BLI_assert(lower_necs->length == blended_necs->length);
2029}
2030
2039 NlaEvalChannelSnapshot *blended_necs, NlaEvalChannelSnapshot *upper_or_lower_necs)
2040{
2041 for (int j = 0; j < 4; j++) {
2042 if (!BLI_BITMAP_TEST_BOOL(blended_necs->remap_domain.ptr, j)) {
2043 BLI_bitmap_set_all(upper_or_lower_necs->remap_domain.ptr, false, 4);
2044 return true;
2045 }
2046 }
2047
2048 return false;
2049}
2050
2051/* Assert that the channels given can be blended or combined together as a quaternion. */
2053 NlaEvalChannelSnapshot *lower_necs,
2054 NlaEvalChannelSnapshot *upper_necs,
2055 NlaEvalChannelSnapshot *blended_necs)
2056{
2057 nlaevalchan_assert_blendOrcombine_compatible(lower_necs, upper_necs, blended_necs);
2058 BLI_assert(lower_necs->length == 4);
2059}
2060
2062{
2063 memcpy(dst->values, src->values, src->length * sizeof(float));
2064}
2065
2071 const NlaEvalChannelSnapshot *lower_necs,
2072 const NlaEvalChannelSnapshot *upper_necs,
2073 const float upper_influence,
2074 NlaEvalChannelSnapshot *r_blended_necs)
2075{
2076 const bool has_influence = !IS_EQF(upper_influence, 0.0f);
2077 if (upper_necs != nullptr && has_influence) {
2078 return false;
2079 }
2080
2081 nlaevalchan_copy_values(r_blended_necs, lower_necs);
2082 return true;
2083}
2084
2094 NlaEvalChannelSnapshot *upper_necs,
2095 const float upper_influence,
2096 NlaEvalChannelSnapshot *r_lower_necs)
2097{
2098 const bool has_influence = !IS_EQF(upper_influence, 0.0f);
2099 if (upper_necs != nullptr && has_influence) {
2100 return false;
2101 }
2102
2103 nlaevalchan_copy_values(r_lower_necs, blended_necs);
2104
2105 /* Must copy remap domain to handle case where some blended values are out of domain. */
2107 r_lower_necs->remap_domain.ptr, blended_necs->remap_domain.ptr, r_lower_necs->length);
2108
2109 return true;
2110}
2111
2119 NlaEvalChannelSnapshot *upper_necs,
2120 const int upper_blendmode,
2121 const float upper_influence,
2122 NlaEvalChannelSnapshot *r_blended_necs)
2123{
2124 nlaevalchan_assert_blendOrcombine_compatible(lower_necs, upper_necs, r_blended_necs);
2126 lower_necs, upper_necs, upper_influence, r_blended_necs))
2127 {
2128 return;
2129 }
2130
2131 const int length = lower_necs->length;
2132 for (int j = 0; j < length; j++) {
2133 if (!BLI_BITMAP_TEST_BOOL(upper_necs->blend_domain.ptr, j)) {
2134 r_blended_necs->values[j] = lower_necs->values[j];
2135 continue;
2136 }
2137
2138 r_blended_necs->values[j] = nla_blend_value(
2139 upper_blendmode, lower_necs->values[j], upper_necs->values[j], upper_influence);
2140 }
2141}
2142
2150 NlaEvalChannelSnapshot *upper_necs,
2151 const float upper_influence,
2152 NlaEvalChannelSnapshot *r_blended_necs)
2153{
2154 nlaevalchan_assert_blendOrcombine_compatible(lower_necs, upper_necs, r_blended_necs);
2156 lower_necs, upper_necs, upper_influence, r_blended_necs))
2157 {
2158 return;
2159 }
2160
2161 /* Assumes every base is the same. */
2162 float *base_values = lower_necs->channel->base_snapshot.values;
2163 const int length = lower_necs->length;
2164 const char mix_mode = lower_necs->channel->mix_mode;
2165
2166 for (int j = 0; j < length; j++) {
2167 if (!BLI_BITMAP_TEST_BOOL(upper_necs->blend_domain.ptr, j)) {
2168 r_blended_necs->values[j] = lower_necs->values[j];
2169 continue;
2170 }
2171
2172 r_blended_necs->values[j] = nla_combine_value(
2173 mix_mode, base_values[j], lower_necs->values[j], upper_necs->values[j], upper_influence);
2174 }
2175}
2176
2184 NlaEvalChannelSnapshot *upper_necs,
2185 const float upper_influence,
2186 NlaEvalChannelSnapshot *r_blended_necs)
2187{
2188 nlaevalchan_assert_blendOrcombine_compatible_quaternion(lower_necs, upper_necs, r_blended_necs);
2190 lower_necs, upper_necs, upper_influence, r_blended_necs))
2191 {
2192 return;
2193 }
2194
2196 if (!BLI_BITMAP_TEST_BOOL(upper_necs->blend_domain.ptr, 0)) {
2197 nlaevalchan_copy_values(r_blended_necs, lower_necs);
2198 return;
2199 }
2200
2202 lower_necs->values, upper_necs->values, upper_influence, r_blended_necs->values);
2203}
2204
2218 NlaEvalChannelSnapshot *upper_necs,
2219 const int upper_blendmode,
2220 const float upper_influence,
2221 NlaEvalChannelSnapshot *r_blended_necs)
2222{
2223 nlaevalchan_assert_nonNull(r_blended_necs);
2224
2225 switch (upper_blendmode) {
2226 case NLASTRIP_MODE_COMBINE: {
2227 switch (r_blended_necs->channel->mix_mode) {
2228 case NEC_MIX_QUATERNION: {
2229 nlaevalchan_combine_quaternion(lower_necs, upper_necs, upper_influence, r_blended_necs);
2230 return;
2231 }
2232 case NEC_MIX_ADD:
2233 case NEC_MIX_AXIS_ANGLE:
2234 case NEC_MIX_MULTIPLY: {
2235 nlaevalchan_combine_value(lower_necs, upper_necs, upper_influence, r_blended_necs);
2236 return;
2237 }
2238 default:
2239 BLI_assert_msg(0, "Mix mode should've been handled");
2240 }
2241 return;
2242 }
2243 case NLASTRIP_MODE_ADD:
2246 case NLASTRIP_MODE_REPLACE: {
2248 lower_necs, upper_necs, upper_blendmode, upper_influence, r_blended_necs);
2249 return;
2250 }
2251 default:
2252 BLI_assert_msg(0, "Blend mode should've been handled");
2253 }
2254}
2255
2264 NlaEvalChannelSnapshot *lower_necs,
2265 NlaEvalChannelSnapshot *blended_necs,
2266 const int upper_blendmode,
2267 const float upper_influence,
2268 NlaEvalChannelSnapshot *r_upper_necs)
2269{
2270 nlaevalchan_assert_nonNull(r_upper_necs);
2271 nlaevalchan_assert_blendOrcombine_compatible(lower_necs, r_upper_necs, blended_necs);
2272
2273 const int length = lower_necs->length;
2274 for (int j = 0; j < length; j++) {
2275 if (!BLI_BITMAP_TEST_BOOL(blended_necs->remap_domain.ptr, j)) {
2276 BLI_BITMAP_DISABLE(r_upper_necs->remap_domain.ptr, j);
2277 continue;
2278 }
2279
2280 const bool success = nla_blend_get_inverted_strip_value(upper_blendmode,
2281 lower_necs->values[j],
2282 blended_necs->values[j],
2283 upper_influence,
2284 &r_upper_necs->values[j]);
2285 BLI_BITMAP_SET(r_upper_necs->remap_domain.ptr, j, success);
2286 }
2287}
2288
2297 NlaEvalChannelSnapshot *lower_necs,
2298 NlaEvalChannelSnapshot *blended_necs,
2299 const float upper_influence,
2300 NlaEvalChannelSnapshot *r_upper_necs)
2301{
2302 nlaevalchan_assert_nonNull(r_upper_necs);
2303 nlaevalchan_assert_blendOrcombine_compatible(lower_necs, r_upper_necs, blended_necs);
2304
2305 /* Assumes every channel's base is the same. */
2306 float *base_values = lower_necs->channel->base_snapshot.values;
2307 const int length = lower_necs->length;
2308 const char mix_mode = lower_necs->channel->mix_mode;
2309
2310 for (int j = 0; j < length; j++) {
2311 if (!BLI_BITMAP_TEST_BOOL(blended_necs->remap_domain.ptr, j)) {
2312 BLI_BITMAP_DISABLE(r_upper_necs->remap_domain.ptr, j);
2313 continue;
2314 }
2315
2316 const bool success = nla_combine_get_inverted_strip_value(mix_mode,
2317 base_values[j],
2318 lower_necs->values[j],
2319 blended_necs->values[j],
2320 upper_influence,
2321 &r_upper_necs->values[j]);
2322
2323 BLI_BITMAP_SET(r_upper_necs->remap_domain.ptr, j, success);
2324 }
2325}
2326
2335 NlaEvalChannelSnapshot *lower_necs,
2336 NlaEvalChannelSnapshot *blended_necs,
2337 const float upper_influence,
2338 NlaEvalChannelSnapshot *r_upper_necs)
2339{
2340 nlaevalchan_assert_nonNull(r_upper_necs);
2341 nlaevalchan_assert_blendOrcombine_compatible_quaternion(lower_necs, r_upper_necs, blended_necs);
2342
2343 if (nlaevalchan_combine_quaternion_handle_undefined_blend_values(blended_necs, r_upper_necs)) {
2344 return;
2345 }
2346
2348 lower_necs->values, blended_necs->values, upper_influence, r_upper_necs->values);
2349
2350 BLI_bitmap_set_all(r_upper_necs->remap_domain.ptr, success, 4);
2351}
2352
2367 NlaEvalChannelSnapshot *lower_necs,
2368 NlaEvalChannelSnapshot *blended_necs,
2369 const int upper_blendmode,
2370 const float upper_influence,
2371 NlaEvalChannelSnapshot *r_upper_necs)
2372{
2373 nlaevalchan_assert_nonNull(r_upper_necs);
2374
2375 if (IS_EQF(upper_influence, 0.0f)) {
2376 BLI_bitmap_set_all(r_upper_necs->remap_domain.ptr, false, r_upper_necs->length);
2377 return;
2378 }
2379
2380 switch (upper_blendmode) {
2381 case NLASTRIP_MODE_COMBINE: {
2382 switch (r_upper_necs->channel->mix_mode) {
2383 case NEC_MIX_QUATERNION: {
2385 lower_necs, blended_necs, upper_influence, r_upper_necs);
2386 return;
2387 }
2388 case NEC_MIX_ADD:
2389 case NEC_MIX_AXIS_ANGLE:
2390 case NEC_MIX_MULTIPLY: {
2392 lower_necs, blended_necs, upper_influence, r_upper_necs);
2393 return;
2394 }
2395 default:
2396 BLI_assert_msg(0, "Mix mode should've been handled");
2397 }
2398 return;
2399 }
2400 case NLASTRIP_MODE_ADD:
2403 case NLASTRIP_MODE_REPLACE: {
2405 lower_necs, blended_necs, upper_blendmode, upper_influence, r_upper_necs);
2406 return;
2407 }
2408 default:
2409 BLI_assert_msg(0, "Blend mode should've been handled");
2410 }
2411}
2412
2414 NlaEvalChannelSnapshot *blended_necs,
2415 NlaEvalChannelSnapshot *upper_necs,
2416 const int upper_blendmode,
2417 const float upper_influence,
2418 NlaEvalChannelSnapshot *r_lower_necs)
2419{
2420 nlaevalchan_assert_blendOrcombine_compatible(r_lower_necs, upper_necs, blended_necs);
2421
2423 blended_necs, upper_necs, upper_influence, r_lower_necs))
2424 {
2425 return;
2426 }
2427
2428 const int length = r_lower_necs->length;
2429
2430 for (int j = 0; j < length; j++) {
2431 if (!BLI_BITMAP_TEST_BOOL(blended_necs->remap_domain.ptr, j)) {
2432 BLI_BITMAP_DISABLE(r_lower_necs->remap_domain.ptr, j);
2433 continue;
2434 }
2435
2436 /* If upper value was not blended, then the blended value was directly copied from the lower
2437 * value. */
2438 if (!BLI_BITMAP_TEST_BOOL(upper_necs->blend_domain.ptr, j)) {
2439 r_lower_necs->values[j] = blended_necs->values[j];
2440 BLI_BITMAP_ENABLE(r_lower_necs->remap_domain.ptr, j);
2441 continue;
2442 }
2443
2444 const bool success = nla_blend_get_inverted_lower_value(upper_blendmode,
2445 upper_necs->values[j],
2446 blended_necs->values[j],
2447 upper_influence,
2448 &r_lower_necs->values[j]);
2449
2450 BLI_BITMAP_SET(r_lower_necs->remap_domain.ptr, j, success);
2451 }
2452}
2453
2455 NlaEvalChannelSnapshot *blended_necs,
2456 NlaEvalChannelSnapshot *upper_necs,
2457 const float upper_influence,
2458 NlaEvalChannelSnapshot *r_lower_necs)
2459{
2460 nlaevalchan_assert_blendOrcombine_compatible(r_lower_necs, upper_necs, blended_necs);
2461
2463 blended_necs, upper_necs, upper_influence, r_lower_necs))
2464 {
2465 return;
2466 }
2467
2468 float *base_values = r_lower_necs->channel->base_snapshot.values;
2469 const int mix_mode = r_lower_necs->channel->mix_mode;
2470 const int length = r_lower_necs->length;
2471
2472 for (int j = 0; j < length; j++) {
2473 if (!BLI_BITMAP_TEST_BOOL(blended_necs->remap_domain.ptr, j)) {
2474 BLI_BITMAP_DISABLE(r_lower_necs->remap_domain.ptr, j);
2475 continue;
2476 }
2477
2478 /* If upper value was not blended, then the blended value was directly copied from the lower
2479 * value. */
2480 if (!BLI_BITMAP_TEST_BOOL(upper_necs->blend_domain.ptr, j)) {
2481 r_lower_necs->values[j] = blended_necs->values[j];
2482 BLI_BITMAP_ENABLE(r_lower_necs->remap_domain.ptr, j);
2483 continue;
2484 }
2485
2486 const bool success = nla_combine_get_inverted_lower_value(mix_mode,
2487 base_values[j],
2488 upper_necs->values[j],
2489 blended_necs->values[j],
2490 upper_influence,
2491 &r_lower_necs->values[j]);
2492
2493 BLI_BITMAP_SET(r_lower_necs->remap_domain.ptr, j, success);
2494 }
2495}
2496
2498 NlaEvalChannelSnapshot *blended_necs,
2499 NlaEvalChannelSnapshot *upper_necs,
2500 const float upper_influence,
2501 NlaEvalChannelSnapshot *r_lower_necs)
2502{
2503 nlaevalchan_assert_blendOrcombine_compatible_quaternion(r_lower_necs, upper_necs, blended_necs);
2504
2505 if (nlaevalchan_combine_quaternion_handle_undefined_blend_values(blended_necs, r_lower_necs)) {
2506 return;
2507 }
2508
2510 blended_necs, upper_necs, upper_influence, r_lower_necs))
2511 {
2512 return;
2513 }
2514
2515 /* If upper value was not blended, then the blended value was directly copied from the lower
2516 * value. */
2517 if (!BLI_BITMAP_TEST_BOOL(upper_necs->blend_domain.ptr, 0)) {
2518 memcpy(r_lower_necs->values, blended_necs->values, 4 * sizeof(float));
2519 BLI_bitmap_set_all(r_lower_necs->remap_domain.ptr, true, 4);
2520 return;
2521 }
2522
2524 upper_necs->values, blended_necs->values, upper_influence, r_lower_necs->values);
2525
2526 BLI_bitmap_set_all(r_lower_necs->remap_domain.ptr, true, 4);
2527}
2528
2543 NlaEvalChannelSnapshot *blended_necs,
2544 NlaEvalChannelSnapshot *upper_necs,
2545 const int upper_blendmode,
2546 const float upper_influence,
2547 NlaEvalChannelSnapshot *r_lower_necs)
2548
2549{
2550 nlaevalchan_assert_nonNull(r_lower_necs);
2551
2552 switch (upper_blendmode) {
2553 case NLASTRIP_MODE_COMBINE: {
2554 switch (r_lower_necs->channel->mix_mode) {
2555 case NEC_MIX_QUATERNION: {
2557 blended_necs, upper_necs, upper_influence, r_lower_necs);
2558 return;
2559 }
2560 case NEC_MIX_ADD:
2561 case NEC_MIX_AXIS_ANGLE:
2562 case NEC_MIX_MULTIPLY: {
2564 blended_necs, upper_necs, upper_influence, r_lower_necs);
2565 return;
2566 }
2567 }
2568 BLI_assert_msg(0, "Mix mode should've been handled");
2569 return;
2570 }
2571 case NLASTRIP_MODE_ADD:
2574 case NLASTRIP_MODE_REPLACE: {
2576 blended_necs, upper_necs, upper_blendmode, upper_influence, r_lower_necs);
2577 return;
2578 }
2579 }
2580
2581 BLI_assert_msg(0, "Blend mode should've been handled");
2582}
2583
2584/* ---------------------- */
2585/* F-Modifier stack joining/separation utilities -
2586 * should we generalize these for BLI_listbase.h interface? */
2587
2588/* Temporarily join two lists of modifiers together, storing the result in a third list */
2589static void nlaeval_fmodifiers_join_stacks(ListBase *result, ListBase *list1, ListBase *list2)
2590{
2591 FModifier *fcm1, *fcm2;
2592
2593 /* if list1 is invalid... */
2594 if (ELEM(nullptr, list1, list1->first)) {
2595 if (list2 && list2->first) {
2596 result->first = list2->first;
2597 result->last = list2->last;
2598 }
2599 }
2600 /* if list 2 is invalid... */
2601 else if (ELEM(nullptr, list2, list2->first)) {
2602 result->first = list1->first;
2603 result->last = list1->last;
2604 }
2605 else {
2606 /* list1 should be added first, and list2 second,
2607 * with the endpoints of these being the endpoints for result
2608 * - the original lists must be left unchanged though, as we need that fact for restoring.
2609 */
2610 result->first = list1->first;
2611 result->last = list2->last;
2612
2613 fcm1 = static_cast<FModifier *>(list1->last);
2614 fcm2 = static_cast<FModifier *>(list2->first);
2615
2616 fcm1->next = fcm2;
2617 fcm2->prev = fcm1;
2618 }
2619}
2620
2621/* Split two temporary lists of modifiers */
2623{
2624 FModifier *fcm1, *fcm2;
2625
2626 /* if list1/2 is invalid... just skip */
2627 if (ELEM(nullptr, list1, list2)) {
2628 return;
2629 }
2630 if (ELEM(nullptr, list1->first, list2->first)) {
2631 return;
2632 }
2633
2634 /* get endpoints */
2635 fcm1 = static_cast<FModifier *>(list1->last);
2636 fcm2 = static_cast<FModifier *>(list2->first);
2637
2638 /* clear their links */
2639 fcm1->next = nullptr;
2640 fcm2->prev = nullptr;
2641}
2642
2643/* ---------------------- */
2644
2647 NlaEvalData *channels,
2648 ListBase *modifiers,
2649 bAction *action,
2650 const animrig::slot_handle_t slot_handle,
2651 const float evaltime,
2652 NlaEvalSnapshot *r_snapshot)
2653{
2655
2656 /* Evaluate modifiers which modify time to evaluate the base curves at. */
2657 FModifiersStackStorage storage;
2658 storage.modifier_count = BLI_listbase_count(modifiers);
2660 storage.buffer = alloca(storage.modifier_count * storage.size_per_modifier);
2661
2662 const float modified_evaltime = evaluate_time_fmodifiers(
2663 &storage, modifiers, nullptr, 0.0f, evaltime);
2664
2665 for (const FCurve *fcu : animrig::legacy::fcurves_for_action_slot(action, slot_handle)) {
2666 if (!is_fcurve_evaluatable(fcu)) {
2667 continue;
2668 }
2669
2670 NlaEvalChannel *nec = nlaevalchan_verify(ptr, channels, fcu->rna_path);
2671
2672 /* Invalid path or property cannot be animated. */
2673 if (nec == nullptr) {
2674 continue;
2675 }
2676
2677 if (!nlaevalchan_validate_index_ex(nec, fcu->array_index)) {
2678 continue;
2679 }
2680
2682
2683 float value = evaluate_fcurve(fcu, modified_evaltime);
2684 evaluate_value_fmodifiers(&storage, modifiers, fcu, &value, evaltime);
2685 necs->values[fcu->array_index] = value;
2686
2687 if (nec->mix_mode == NEC_MIX_QUATERNION) {
2688 BLI_bitmap_set_all(necs->blend_domain.ptr, true, 4);
2689 }
2690 else {
2691 BLI_BITMAP_ENABLE(necs->blend_domain.ptr, fcu->array_index);
2692 }
2693 }
2694}
2695
2696/* evaluate action-clip strip */
2697static void nlastrip_evaluate_actionclip(const int evaluation_mode,
2698 PointerRNA *ptr,
2699 NlaEvalData *channels,
2700 ListBase *modifiers,
2701 NlaEvalStrip *nes,
2702 NlaEvalSnapshot *snapshot)
2703{
2704
2705 NlaStrip *strip = nes->strip;
2706
2707 /* sanity checks for action */
2708 if (strip == nullptr) {
2709 return;
2710 }
2711
2712 if (strip->act == nullptr) {
2713 CLOG_ERROR(&LOG, "NLA-Strip Eval Error: Strip '%s' has no Action", strip->name);
2714 return;
2715 }
2716
2717 ListBase tmp_modifiers = {nullptr, nullptr};
2718
2719 /* join this strip's modifiers to the parent's modifiers (own modifiers first) */
2720 nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &strip->modifiers, modifiers);
2721
2722 switch (evaluation_mode) {
2723 case STRIP_EVAL_BLEND: {
2724
2725 NlaEvalSnapshot strip_snapshot;
2726 nlaeval_snapshot_init(&strip_snapshot, channels, nullptr);
2727
2729 channels,
2730 &tmp_modifiers,
2731 strip->act,
2732 strip->action_slot_handle,
2733 strip->strip_time,
2734 &strip_snapshot);
2736 channels, snapshot, &strip_snapshot, strip->blendmode, strip->influence, snapshot);
2737
2738 nlaeval_snapshot_free_data(&strip_snapshot);
2739
2740 break;
2741 }
2743
2744 NlaEvalSnapshot strip_snapshot;
2745 nlaeval_snapshot_init(&strip_snapshot, channels, nullptr);
2746
2748 channels,
2749 &tmp_modifiers,
2750 strip->act,
2751 strip->action_slot_handle,
2752 strip->strip_time,
2753 &strip_snapshot);
2755 channels, snapshot, &strip_snapshot, strip->blendmode, strip->influence, snapshot);
2756
2757 nlaeval_snapshot_free_data(&strip_snapshot);
2758
2759 break;
2760 }
2761 case STRIP_EVAL_NOBLEND: {
2763 channels,
2764 &tmp_modifiers,
2765 strip->act,
2766 strip->action_slot_handle,
2767 strip->strip_time,
2768 snapshot);
2769 break;
2770 }
2771 }
2772
2773 /* unlink this strip's modifiers from the parent's modifiers again */
2774 nlaeval_fmodifiers_split_stacks(&strip->modifiers, modifiers);
2775}
2776
2777/* evaluate transition strip */
2778static void nlastrip_evaluate_transition(const int evaluation_mode,
2779 PointerRNA *ptr,
2780 NlaEvalData *channels,
2781 ListBase *modifiers,
2782 NlaEvalStrip *nes,
2783 NlaEvalSnapshot *snapshot,
2784 const AnimationEvalContext *anim_eval_context,
2785 const bool flush_to_original)
2786{
2787 ListBase tmp_modifiers = {nullptr, nullptr};
2788 NlaEvalSnapshot snapshot1, snapshot2;
2789 NlaEvalStrip tmp_nes;
2790 NlaStrip *s1, *s2;
2791
2792 /* join this strip's modifiers to the parent's modifiers (own modifiers first) */
2793 nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &nes->strip->modifiers, modifiers);
2794
2795 /* get the two strips to operate on
2796 * - we use the endpoints of the strips directly flanking our strip
2797 * using these as the endpoints of the transition (destination and source)
2798 * - these should have already been determined to be valid...
2799 * - if this strip is being played in reverse, we need to swap these endpoints
2800 * otherwise they will be interpolated wrong
2801 */
2802 if (nes->strip->flag & NLASTRIP_FLAG_REVERSE) {
2803 s1 = nes->strip->next;
2804 s2 = nes->strip->prev;
2805 }
2806 else {
2807 s1 = nes->strip->prev;
2808 s2 = nes->strip->next;
2809 }
2810
2811 switch (evaluation_mode) {
2812 case STRIP_EVAL_BLEND: {
2813
2814 /* prepare template for 'evaluation strip'
2815 * - based on the transition strip's evaluation strip data
2816 * - strip_mode is NES_TIME_TRANSITION_* based on which endpoint
2817 * - strip_time is the 'normalized' (i.e. in-strip) time for evaluation,
2818 * which doubles up as an additional weighting factor for the strip influences
2819 * which allows us to appear to be 'interpolating' between the two extremes
2820 */
2821 tmp_nes = *nes;
2822
2823 /* evaluate these strips into a temp-buffer (tmp_channels) */
2824 /* FIXME: modifier evaluation here needs some work... */
2825 /* first strip */
2827 tmp_nes.strip = s1;
2828 tmp_nes.strip_time = s1->strip_time;
2829 nlaeval_snapshot_init(&snapshot1, channels, snapshot);
2831 channels,
2832 &tmp_modifiers,
2833 &tmp_nes,
2834 &snapshot1,
2835 anim_eval_context,
2836 flush_to_original);
2837
2838 /* second strip */
2840 tmp_nes.strip = s2;
2841 tmp_nes.strip_time = s2->strip_time;
2842 nlaeval_snapshot_init(&snapshot2, channels, snapshot);
2844 channels,
2845 &tmp_modifiers,
2846 &tmp_nes,
2847 &snapshot2,
2848 anim_eval_context,
2849 flush_to_original);
2850
2854 nlasnapshot_ensure_channels(channels, &snapshot2);
2858 channels, &snapshot1, &snapshot2, NLASTRIP_MODE_REPLACE, nes->strip_time, snapshot);
2859
2860 nlaeval_snapshot_free_data(&snapshot1);
2861 nlaeval_snapshot_free_data(&snapshot2);
2862
2863 break;
2864 }
2866 /* No support for remapping values through a transition. Mark all channel values affected by
2867 * transition as non-remappable. */
2868 tmp_nes = *nes;
2869
2870 /* Process first strip. */
2871 tmp_nes.strip = s1;
2872 tmp_nes.strip_time = s1->strip_time;
2873 nlaeval_snapshot_init(&snapshot1, channels, snapshot);
2875 ptr, channels, &tmp_modifiers, &tmp_nes, &snapshot1, anim_eval_context);
2876
2877 /* Remove channel values affected by transition from the remap domain. */
2878 LISTBASE_FOREACH (NlaEvalChannel *, nec, &channels->channels) {
2879 NlaEvalChannelSnapshot *necs = nlaeval_snapshot_get(&snapshot1, nec->index);
2880 if (necs == nullptr) {
2881 continue;
2882 }
2883 NlaEvalChannelSnapshot *output_necs = nlaeval_snapshot_ensure_channel(snapshot, nec);
2884 for (int i = 0; i < necs->length; i++) {
2885 if (BLI_BITMAP_TEST_BOOL(necs->blend_domain.ptr, i)) {
2886 BLI_BITMAP_DISABLE(output_necs->remap_domain.ptr, i);
2887 }
2888 }
2889 }
2890
2891 nlaeval_snapshot_free_data(&snapshot1);
2892
2893 /* Process second strip. */
2894 tmp_nes.strip = s2;
2895 tmp_nes.strip_time = s2->strip_time;
2896 nlaeval_snapshot_init(&snapshot2, channels, snapshot);
2898 ptr, channels, &tmp_modifiers, &tmp_nes, &snapshot2, anim_eval_context);
2899
2900 /* Remove channel values affected by transition from the remap domain. */
2901 LISTBASE_FOREACH (NlaEvalChannel *, nec, &channels->channels) {
2902 NlaEvalChannelSnapshot *necs = nlaeval_snapshot_get(&snapshot2, nec->index);
2903 if (necs == nullptr) {
2904 continue;
2905 }
2906 NlaEvalChannelSnapshot *output_necs = nlaeval_snapshot_ensure_channel(snapshot, nec);
2907 for (int i = 0; i < necs->length; i++) {
2908 if (BLI_BITMAP_TEST_BOOL(necs->blend_domain.ptr, i)) {
2909 BLI_BITMAP_DISABLE(output_necs->remap_domain.ptr, i);
2910 }
2911 }
2912 }
2913
2914 nlaeval_snapshot_free_data(&snapshot2);
2915
2916 break;
2917 }
2918 case STRIP_EVAL_NOBLEND: {
2919 BLI_assert_msg(false,
2920 "This case shouldn't occur. "
2921 "Transitions assumed to not reference other transitions.");
2922 break;
2923 }
2924 }
2925
2926 /* unlink this strip's modifiers from the parent's modifiers again */
2928}
2929
2930/* evaluate meta-strip */
2931static void nlastrip_evaluate_meta(const int evaluation_mode,
2932 PointerRNA *ptr,
2933 NlaEvalData *channels,
2934 ListBase *modifiers,
2935 NlaEvalStrip *nes,
2936 NlaEvalSnapshot *snapshot,
2937 const AnimationEvalContext *anim_eval_context,
2938 const bool flush_to_original)
2939{
2940 ListBase tmp_modifiers = {nullptr, nullptr};
2941 NlaStrip *strip = nes->strip;
2942 NlaEvalStrip *tmp_nes;
2943 float evaltime;
2944
2945 /* meta-strip was calculated normally to have some time to be evaluated at
2946 * and here we 'look inside' the meta strip, treating it as a decorated window to
2947 * its child strips, which get evaluated as if they were some tracks on a strip
2948 * (but with some extra modifiers to apply).
2949 *
2950 * NOTE: keep this in sync with animsys_evaluate_nla()
2951 */
2952
2953 /* join this strip's modifiers to the parent's modifiers (own modifiers first) */
2954 nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &strip->modifiers, modifiers);
2955
2956 /* find the child-strip to evaluate */
2957 evaltime = (nes->strip_time * (strip->end - strip->start)) + strip->start;
2958 AnimationEvalContext child_context = BKE_animsys_eval_context_construct_at(anim_eval_context,
2959 evaltime);
2960 tmp_nes = nlastrips_ctime_get_strip(
2961 nullptr, &strip->strips, -1, &child_context, flush_to_original);
2962
2963 /* Assert currently supported modes. If new mode added, then assertion marks potentially missed
2964 * area.
2965 *
2966 * NOTE: In the future if support is ever added to meta-strips to support nested tracks, then
2967 * STRIP_EVAL_BLEND and STRIP_EVAL_BLEND_GET_INVERTED_LOWER_SNAPSHOT cases are no longer
2968 * equivalent. The output of nlastrips_ctime_get_strip() may return a list of strips. The only
2969 * case difference should be the evaluation order.
2970 */
2971 BLI_assert(ELEM(evaluation_mode,
2975
2976 /* directly evaluate child strip into accumulation buffer...
2977 * - there's no need to use a temporary buffer (as it causes issues [#40082])
2978 */
2979 if (tmp_nes) {
2980 nlastrip_evaluate(evaluation_mode,
2981 ptr,
2982 channels,
2983 &tmp_modifiers,
2984 tmp_nes,
2985 snapshot,
2986 &child_context,
2987 flush_to_original);
2988
2989 /* free temp eval-strip */
2990 MEM_freeN(tmp_nes);
2991 }
2992
2993 /* unlink this strip's modifiers from the parent's modifiers again */
2994 nlaeval_fmodifiers_split_stacks(&strip->modifiers, modifiers);
2995}
2996
2997void nlastrip_evaluate(const int evaluation_mode,
2998 PointerRNA *ptr,
2999 NlaEvalData *channels,
3000 ListBase *modifiers,
3001 NlaEvalStrip *nes,
3002 NlaEvalSnapshot *snapshot,
3003 const AnimationEvalContext *anim_eval_context,
3004 const bool flush_to_original)
3005{
3006 NlaStrip *strip = nes->strip;
3007
3008 /* To prevent potential infinite recursion problems
3009 * (i.e. transition strip, beside meta strip containing a transition
3010 * several levels deep inside it),
3011 * we tag the current strip as being evaluated, and clear this when we leave.
3012 */
3013 /* TODO: be careful with this flag, since some edit tools may be running and have
3014 * set this while animation playback was running. */
3015 if (strip->flag & NLASTRIP_FLAG_EDIT_TOUCHED) {
3016 return;
3017 }
3019
3020 /* actions to take depend on the type of strip */
3021 switch (strip->type) {
3022 case NLASTRIP_TYPE_CLIP: /* action-clip */
3023 nlastrip_evaluate_actionclip(evaluation_mode, ptr, channels, modifiers, nes, snapshot);
3024 break;
3025 case NLASTRIP_TYPE_TRANSITION: /* transition */
3026 nlastrip_evaluate_transition(evaluation_mode,
3027 ptr,
3028 channels,
3029 modifiers,
3030 nes,
3031 snapshot,
3032 anim_eval_context,
3033 flush_to_original);
3034 break;
3035 case NLASTRIP_TYPE_META: /* meta */
3036 nlastrip_evaluate_meta(evaluation_mode,
3037 ptr,
3038 channels,
3039 modifiers,
3040 nes,
3041 snapshot,
3042 anim_eval_context,
3043 flush_to_original);
3044 break;
3045
3046 default: /* do nothing */
3047 break;
3048 }
3049
3050 /* clear temp recursion safe-check */
3051 strip->flag &= ~NLASTRIP_FLAG_EDIT_TOUCHED;
3052}
3053
3055 NlaEvalData *channels,
3056 ListBase *modifiers,
3057 NlaEvalStrip *nes,
3058 NlaEvalSnapshot *snapshot,
3059 const AnimationEvalContext *anim_eval_context,
3060 const bool flush_to_original)
3061{
3063 ptr,
3064 channels,
3065 modifiers,
3066 nes,
3067 snapshot,
3068 anim_eval_context,
3069 flush_to_original);
3070}
3071
3073 PointerRNA *ptr,
3074 NlaEvalData *channels,
3075 ListBase *modifiers,
3076 NlaEvalStrip *nes,
3077 NlaEvalSnapshot *snapshot,
3078 const AnimationEvalContext *anim_eval_context)
3079{
3081 ptr,
3082 channels,
3083 modifiers,
3084 nes,
3085 snapshot,
3086 anim_eval_context,
3087 false);
3088}
3089
3091 NlaEvalData *channels,
3092 ListBase *modifiers,
3093 NlaEvalStrip *nes,
3094 NlaEvalSnapshot *snapshot,
3095 const AnimationEvalContext *anim_eval_context)
3096{
3098 STRIP_EVAL_NOBLEND, ptr, channels, modifiers, nes, snapshot, anim_eval_context, false);
3099}
3100
3102 NlaEvalData *channels,
3103 NlaEvalSnapshot *snapshot,
3104 const bool flush_to_original)
3105{
3106 /* sanity checks */
3107 if (channels == nullptr) {
3108 return;
3109 }
3110
3111 /* for each channel with accumulated values, write its value on the property it affects */
3112 LISTBASE_FOREACH (NlaEvalChannel *, nec, &channels->channels) {
3122 NlaEvalChannelSnapshot *nec_snapshot = nlaeval_snapshot_find_channel(snapshot, nec);
3123
3124 PathResolvedRNA rna = {nec->key.ptr, nec->key.prop, -1};
3125
3126 for (int i = 0; i < nec_snapshot->length; i++) {
3127 if (BLI_BITMAP_TEST(nec->domain.ptr, i)) {
3128 float value = nec_snapshot->values[i];
3129 if (nec->is_array) {
3130 rna.prop_index = i;
3131 }
3132 BKE_animsys_write_to_rna_path(&rna, value);
3133 if (flush_to_original) {
3134 animsys_write_orig_anim_rna(ptr, nec->rna_path, rna.prop_index, value);
3135 }
3136 }
3137 }
3138 }
3139}
3140
3141/* ---------------------- */
3142
3144 NlaEvalData *channels,
3145 bAction *act,
3146 const animrig::slot_handle_t slot_handle,
3147 GSet *touched_actions)
3148{
3149 if (!BLI_gset_add(touched_actions, act)) {
3150 return;
3151 }
3152
3153 for (const FCurve *fcu : animrig::legacy::fcurves_for_action_slot(act, slot_handle)) {
3154 /* check if this curve should be skipped */
3155 if (!is_fcurve_evaluatable(fcu)) {
3156 continue;
3157 }
3158
3159 NlaEvalChannel *nec = nlaevalchan_verify(ptr, channels, fcu->rna_path);
3160
3161 if (nec != nullptr) {
3162 /* For quaternion properties, enable all sub-channels. */
3163 if (nec->mix_mode == NEC_MIX_QUATERNION) {
3164 BLI_bitmap_set_all(nec->domain.ptr, true, 4);
3165 continue;
3166 }
3167
3168 int idx = nlaevalchan_validate_index(nec, fcu->array_index);
3169
3170 if (idx >= 0) {
3171 BLI_BITMAP_ENABLE(nec->domain.ptr, idx);
3172 }
3173 }
3174 }
3175}
3176
3178 NlaEvalData *channels,
3179 ListBase *strips,
3180 GSet *touched_actions)
3181{
3182 LISTBASE_FOREACH (NlaStrip *, strip, strips) {
3183 /* Check strip's action. */
3184 if (strip->act) {
3186 ptr, channels, strip->act, strip->action_slot_handle, touched_actions);
3187 }
3188
3189 /* Check sub-strips (if meta-strips). */
3190 nla_eval_domain_strips(ptr, channels, &strip->strips, touched_actions);
3191 }
3192}
3193
3199{
3200 GSet *touched_actions = BLI_gset_ptr_new(__func__);
3201
3202 /* Include domain of Action Track. */
3203 if ((adt->flag & ADT_NLA_EDIT_ON) == 0) {
3204 if (adt->action) {
3205 nla_eval_domain_action(ptr, channels, adt->action, adt->slot_handle, touched_actions);
3206 }
3207 }
3208 else if (adt->tmpact && (adt->flag & ADT_NLA_EVAL_UPPER_TRACKS)) {
3209 nla_eval_domain_action(ptr, channels, adt->tmpact, adt->tmp_slot_handle, touched_actions);
3210 }
3211
3212 /* NLA Data - Animation Data for Strips */
3213 LISTBASE_FOREACH (NlaTrack *, nlt, &adt->nla_tracks) {
3214 /* solo and muting are mutually exclusive... */
3215 if (adt->flag & ADT_NLA_SOLO_TRACK) {
3216 /* skip if there is a solo track, but this isn't it */
3217 if ((nlt->flag & NLATRACK_SOLO) == 0) {
3218 continue;
3219 }
3220 /* else - mute doesn't matter */
3221 }
3222 else {
3223 /* no solo tracks - skip track if muted */
3224 if (nlt->flag & NLATRACK_MUTED) {
3225 continue;
3226 }
3227 }
3228
3229 nla_eval_domain_strips(ptr, channels, &nlt->strips, touched_actions);
3230 }
3231
3232 BLI_gset_free(touched_actions, nullptr);
3233}
3234
3235/* ---------------------- */
3236
3242 const bool keyframing_to_strip,
3243 NlaStrip *r_tweak_strip)
3244
3245{
3246 /* Copy active strip so we can modify how it evaluates without affecting user data. */
3247 memcpy(r_tweak_strip, adt->actstrip, sizeof(NlaStrip));
3248 r_tweak_strip->next = r_tweak_strip->prev = nullptr;
3249
3250 /* If tweaked strip is syncing action length, then evaluate using action length. */
3251 if (r_tweak_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH) {
3253 }
3254
3255 /* Strips with a user-defined time curve don't get properly remapped for editing
3256 * at the moment, so mapping them just for display may be confusing. */
3257 const bool is_inplace_tweak = !(adt->flag & ADT_NLA_EDIT_NOMAP) &&
3259
3260 if (!is_inplace_tweak) {
3261 /* Use Hold due to no proper remapping yet (the note above). */
3262 r_tweak_strip->extendmode = NLASTRIP_EXTEND_HOLD;
3263
3264 /* Disable range. */
3265 r_tweak_strip->flag |= NLASTRIP_FLAG_NO_TIME_MAP;
3266 }
3267
3268 if (keyframing_to_strip) {
3269 /* Since keying cannot happen when there is no NLA influence, this is a workaround to get keys
3270 * onto the strip in tweak mode while keyframing. */
3271 r_tweak_strip->extendmode = NLASTRIP_EXTEND_HOLD;
3272 }
3273}
3274
3277 const bool keyframing_to_strip,
3278 NlaStrip *r_action_strip)
3279{
3280 using namespace blender::animrig;
3281
3282 memset(r_action_strip, 0, sizeof(NlaStrip));
3283
3284 /* Set settings of dummy NLA strip from AnimData settings. */
3285 bAction *action = adt->action;
3286 slot_handle_t slot_handle = adt->slot_handle;
3287
3288 if (adt->flag & ADT_NLA_EDIT_ON) {
3289 action = adt->tmpact;
3290 slot_handle = adt->tmp_slot_handle;
3291 }
3292
3293 r_action_strip->act = action;
3294 r_action_strip->action_slot_handle = slot_handle;
3295
3296 /* Action range is calculated taking F-Modifiers into account
3297 * (which making new strips doesn't do due to the troublesome nature of that). */
3298 const float2 frame_range = action ? action->wrap().get_frame_range_of_keys(true) :
3299 float2{0.0f, 0.0f};
3300 r_action_strip->actstart = frame_range[0];
3301 r_action_strip->actend = frame_range[1];
3302
3303 BKE_nla_clip_length_ensure_nonzero(&r_action_strip->actstart, &r_action_strip->actend);
3304 r_action_strip->start = r_action_strip->actstart;
3305 r_action_strip->end = r_action_strip->actend;
3306
3307 r_action_strip->blendmode = adt->act_blendmode;
3308 r_action_strip->extendmode = adt->act_extendmode;
3309 r_action_strip->influence = adt->act_influence;
3310
3311 /* Must set NLASTRIP_FLAG_USR_INFLUENCE, or else the default setting overrides, and influence
3312 * doesn't work.
3313 */
3315
3316 const bool tweaking = (adt->flag & ADT_NLA_EDIT_ON) != 0;
3317 const bool soloing = (adt->flag & ADT_NLA_SOLO_TRACK) != 0;
3318 const bool eval_upper = !tweaking || (adt->flag & ADT_NLA_EVAL_UPPER_TRACKS) != 0;
3319 const bool actionstrip_evaluated = r_action_strip->act && !soloing && eval_upper;
3320 if (!actionstrip_evaluated) {
3321 r_action_strip->flag |= NLASTRIP_FLAG_MUTED;
3322 }
3323
3325 if (keyframing_to_strip) {
3326 r_action_strip->extendmode = NLASTRIP_EXTEND_HOLD;
3327 }
3328}
3329
3330static bool is_nlatrack_evaluatable(const AnimData *adt, const NlaTrack *nlt)
3331{
3332 /* Skip disabled tracks unless it contains the tweaked strip. */
3333 const bool contains_tweak_strip = (adt->flag & ADT_NLA_EDIT_ON) && adt->act_track &&
3334 (nlt->index == adt->act_track->index);
3335 if ((nlt->flag & NLATRACK_DISABLED) && !contains_tweak_strip) {
3336 return false;
3337 }
3338
3339 /* Solo and muting are mutually exclusive. */
3340 if (adt->flag & ADT_NLA_SOLO_TRACK) {
3341 /* Skip if there is a solo track, but this isn't it. */
3342 if ((nlt->flag & NLATRACK_SOLO) == 0) {
3343 return false;
3344 }
3345 }
3346 else {
3347 /* Skip track if muted. */
3348 if (nlt->flag & NLATRACK_MUTED) {
3349 return false;
3350 }
3351 }
3352
3353 return true;
3354}
3355
3361 const bool any_strip_evaluated)
3362{
3363 if (adt->action == nullptr) {
3364 return false;
3365 }
3366
3367 if (any_strip_evaluated) {
3368 return false;
3369 }
3370
3372 if ((adt->flag & (ADT_NLA_SOLO_TRACK | ADT_NLA_EDIT_ON)) != 0) {
3373 return false;
3374 }
3375
3377 return true;
3378}
3379
3389{
3390 if (adt == nullptr) {
3391 return nullptr;
3392 }
3393
3394 /* Since the track itself gets disabled, we want the first disabled. */
3395 LISTBASE_FOREACH (NlaTrack *, nlt, &adt->nla_tracks) {
3396 if (nlt->flag & NLATRACK_DISABLED) {
3397 return nlt;
3398 }
3399 }
3400
3401 return nullptr;
3402}
3403
3409 PointerRNA *ptr,
3410 const AnimData *adt,
3411 const AnimationEvalContext *anim_eval_context,
3412 const bool flush_to_original)
3413{
3414 NlaTrack *nlt;
3415 short track_index = 0;
3416 bool has_strips = false;
3417 ListBase estrips = {nullptr, nullptr};
3418 NlaEvalStrip *nes;
3419
3420 NlaStrip tweak_strip;
3421
3422 NlaTrack *tweaked_track = nlatrack_find_tweaked(adt);
3423
3424 /* Get the stack of strips to evaluate at current time (influence calculated here). */
3425 for (nlt = static_cast<NlaTrack *>(adt->nla_tracks.first); nlt; nlt = nlt->next, track_index++) {
3426
3427 if (!is_nlatrack_evaluatable(adt, nlt)) {
3428 continue;
3429 }
3430
3431 if (nlt->strips.first) {
3432 has_strips = true;
3433 }
3434
3436 if (nlt == tweaked_track) {
3438 animsys_create_tweak_strip(adt, false, &tweak_strip);
3440 &estrips, &tweak_strip, anim_eval_context, flush_to_original);
3441 }
3442 else {
3444 &estrips, &nlt->strips, track_index, anim_eval_context, flush_to_original);
3445 }
3446 if (nes) {
3447 nes->track = nlt;
3448 }
3449 }
3450
3451 if (is_action_track_evaluated_without_nla(adt, has_strips)) {
3452 BLI_freelistN(&estrips);
3453 return false;
3454 }
3455
3456 NlaStrip action_strip = {nullptr};
3457 animsys_create_action_track_strip(adt, false, &action_strip);
3458 nlastrips_ctime_get_strip_single(&estrips, &action_strip, anim_eval_context, flush_to_original);
3459
3460 /* Per strip, evaluate and accumulate on top of existing channels. */
3461 LISTBASE_FOREACH (NlaEvalStrip *, nes, &estrips) {
3463 echannels,
3464 nullptr,
3465 nes,
3466 &echannels->eval_snapshot,
3467 anim_eval_context,
3468 flush_to_original);
3469 }
3470
3471 /* Free temporary evaluation data that's not used elsewhere. */
3472 BLI_freelistN(&estrips);
3473 return true;
3474}
3475
3478 const AnimData *adt,
3479 const AnimationEvalContext *anim_eval_context,
3480 NlaKeyframingContext *r_context)
3481{
3482 if (!r_context) {
3483 return;
3484 }
3485
3486 /* Early out. If NLA track is soloing and tweaked action isn't it, then don't allow keyframe
3487 * insertion. */
3488 if (adt->flag & ADT_NLA_SOLO_TRACK) {
3489 if (!(adt->act_track && (adt->act_track->flag & NLATRACK_SOLO))) {
3490 r_context->eval_strip = nullptr;
3491 return;
3492 }
3493 }
3494
3495 NlaTrack *nlt;
3496 short track_index = 0;
3497 bool has_strips = false;
3498
3499 ListBase *upper_estrips = &r_context->upper_estrips;
3500 ListBase lower_estrips = {nullptr, nullptr};
3501 NlaEvalStrip *nes;
3502
3503 NlaTrack *tweaked_track = nlatrack_find_tweaked(adt);
3504
3505 /* Get the lower stack of strips to evaluate at current time (influence calculated here). */
3506 for (nlt = static_cast<NlaTrack *>(adt->nla_tracks.first); nlt; nlt = nlt->next, track_index++) {
3507
3508 if (!is_nlatrack_evaluatable(adt, nlt)) {
3509 continue;
3510 }
3511
3512 /* Tweaked strip effect should not be stored in any snapshot. */
3513 if (nlt == tweaked_track) {
3514 break;
3515 }
3516
3517 if (nlt->strips.first) {
3518 has_strips = true;
3519 }
3520
3521 /* Get strip to evaluate for this channel. */
3523 &lower_estrips, &nlt->strips, track_index, anim_eval_context, false);
3524 if (nes) {
3525 nes->track = nlt;
3526 }
3527 }
3528
3529 /* Get the upper stack of strips to evaluate at current time (influence calculated here).
3530 * Var nlt exists only if tweak strip exists. */
3531 if (nlt) {
3532
3533 /* Skip tweaked strip. */
3534 nlt = nlt->next;
3535 track_index++;
3536
3537 for (; nlt; nlt = nlt->next, track_index++) {
3538
3539 if (!is_nlatrack_evaluatable(adt, nlt)) {
3540 continue;
3541 }
3542
3543 if (nlt->strips.first) {
3544 has_strips = true;
3545 }
3546
3547 /* Get strip to evaluate for this channel. */
3549 upper_estrips, &nlt->strips, track_index, anim_eval_context, false);
3550 }
3551 }
3552
3553 /* NOTE: Although we early out, we can still keyframe to the non-pushed action since the
3554 * keyframe remap function detects (r_context->strip.act == nullptr) and will keyframe without
3555 * remapping. */
3556 if (is_action_track_evaluated_without_nla(adt, has_strips)) {
3557 BLI_freelistN(&lower_estrips);
3558 return;
3559 }
3560
3561 /* Write r_context->eval_strip. */
3562 if (adt->flag & ADT_NLA_EDIT_ON) {
3563 /* Append action_track_strip to upper estrips. */
3564 NlaStrip *action_strip = &r_context->action_track_strip;
3565 animsys_create_action_track_strip(adt, false, action_strip);
3566 nlastrips_ctime_get_strip_single(upper_estrips, action_strip, anim_eval_context, false);
3567
3568 NlaStrip *tweak_strip = &r_context->strip;
3569 animsys_create_tweak_strip(adt, true, tweak_strip);
3571 nullptr, tweak_strip, anim_eval_context, false);
3572 }
3573 else {
3574
3575 NlaStrip *action_strip = &r_context->strip;
3576 animsys_create_action_track_strip(adt, true, action_strip);
3578 nullptr, action_strip, anim_eval_context, false);
3579 }
3580
3581 /* If nullptr, then keyframing will fail. No need to do any more processing. */
3582 if (!r_context->eval_strip) {
3583 BLI_freelistN(&lower_estrips);
3584 return;
3585 }
3586
3587 /* If tweak strip is full REPLACE, then lower strips not needed. */
3588 if (r_context->strip.blendmode == NLASTRIP_MODE_REPLACE &&
3589 IS_EQF(r_context->strip.influence, 1.0f))
3590 {
3591 BLI_freelistN(&lower_estrips);
3592 return;
3593 }
3594
3595 /* For each strip, evaluate then accumulate on top of existing channels. */
3596 LISTBASE_FOREACH (NlaEvalStrip *, nes, &lower_estrips) {
3598 &r_context->lower_eval_data,
3599 nullptr,
3600 nes,
3601 &r_context->lower_eval_data.eval_snapshot,
3602 anim_eval_context,
3603 false);
3604 }
3605
3606 /* Free temporary evaluation data that's not used elsewhere. */
3607 BLI_freelistN(&lower_estrips);
3608}
3609
3618 AnimData *adt,
3619 const AnimationEvalContext *anim_eval_context,
3620 const bool flush_to_original)
3621{
3622 NlaEvalData echannels;
3623
3624 nlaeval_init(&echannels);
3625
3626 /* evaluate the NLA stack, obtaining a set of values to flush */
3627 const bool did_evaluate_something = animsys_evaluate_nla_for_flush(
3628 &echannels, ptr, adt, anim_eval_context, flush_to_original);
3629 if (did_evaluate_something) {
3630 /* reset any channels touched by currently inactive actions to default value */
3631 animsys_evaluate_nla_domain(ptr, &echannels, adt);
3632
3633 /* flush effects of accumulating channels in NLA to the actual data they affect */
3634 nladata_flush_channels(ptr, &echannels, &echannels.eval_snapshot, flush_to_original);
3635 }
3636
3637 /* free temp data */
3638 nlaeval_free(&echannels);
3639
3640 return did_evaluate_something;
3641}
3642
3643/* ---------------------- */
3644
3646{
3647 for (int i = 0; i < snapshot->size; i++) {
3648 NlaEvalChannelSnapshot *necs = nlaeval_snapshot_get(snapshot, i);
3649 if (necs == nullptr) {
3650 continue;
3651 }
3652
3653 BLI_bitmap_set_all(necs->blend_domain.ptr, true, necs->length);
3654 }
3655}
3656
3658{
3659 LISTBASE_FOREACH (NlaEvalChannel *, nec, &eval_data->channels) {
3660 nlaeval_snapshot_ensure_channel(snapshot, nec);
3661 }
3662}
3663
3665 NlaEvalSnapshot *lower_snapshot,
3666 NlaEvalSnapshot *upper_snapshot,
3667 const short upper_blendmode,
3668 const float upper_influence,
3669 NlaEvalSnapshot *r_blended_snapshot)
3670{
3671 nlaeval_snapshot_ensure_size(r_blended_snapshot, eval_data->num_channels);
3672
3673 LISTBASE_FOREACH (NlaEvalChannel *, nec, &eval_data->channels) {
3674 NlaEvalChannelSnapshot *upper_necs = nlaeval_snapshot_get(upper_snapshot, nec->index);
3675 NlaEvalChannelSnapshot *lower_necs = nlaeval_snapshot_get(lower_snapshot, nec->index);
3676 if (upper_necs == nullptr && lower_necs == nullptr) {
3677 continue;
3678 }
3679
3681 if (lower_necs == nullptr) {
3682 lower_necs = nlaeval_snapshot_find_channel(lower_snapshot->base, nec);
3683 }
3684
3685 NlaEvalChannelSnapshot *result_necs = nlaeval_snapshot_ensure_channel(r_blended_snapshot, nec);
3687 lower_necs, upper_necs, upper_blendmode, upper_influence, result_necs);
3688 }
3689}
3690
3692 NlaEvalSnapshot *lower_snapshot,
3693 NlaEvalSnapshot *blended_snapshot,
3694 const short upper_blendmode,
3695 const float upper_influence,
3696 NlaEvalSnapshot *r_upper_snapshot)
3697{
3698 nlaeval_snapshot_ensure_size(r_upper_snapshot, eval_data->num_channels);
3699
3700 LISTBASE_FOREACH (NlaEvalChannel *, nec, &eval_data->channels) {
3701 NlaEvalChannelSnapshot *blended_necs = nlaeval_snapshot_get(blended_snapshot, nec->index);
3702 if (blended_necs == nullptr) {
3705 continue;
3706 }
3707
3708 NlaEvalChannelSnapshot *lower_necs = nlaeval_snapshot_get(lower_snapshot, nec->index);
3709 if (lower_necs == nullptr) {
3710 lower_necs = nlaeval_snapshot_find_channel(lower_snapshot->base, nec);
3711 }
3712
3713 NlaEvalChannelSnapshot *result_necs = nlaeval_snapshot_ensure_channel(r_upper_snapshot, nec);
3715 lower_necs, blended_necs, upper_blendmode, upper_influence, result_necs);
3716 }
3717}
3718
3720 NlaEvalSnapshot *blended_snapshot,
3721 NlaEvalSnapshot *upper_snapshot,
3722 const short upper_blendmode,
3723 const float upper_influence,
3724 NlaEvalSnapshot *r_lower_snapshot)
3725{
3726 nlaeval_snapshot_ensure_size(r_lower_snapshot, eval_data->num_channels);
3727
3728 LISTBASE_FOREACH (NlaEvalChannel *, nec, &eval_data->channels) {
3729 NlaEvalChannelSnapshot *blended_necs = nlaeval_snapshot_get(blended_snapshot, nec->index);
3730 if (blended_necs == nullptr) {
3731 /* We assume the caller only wants a subset of channels to be inverted, those that exist
3732 * within \a blended_snapshot. */
3733 continue;
3734 }
3735
3736 NlaEvalChannelSnapshot *upper_necs = nlaeval_snapshot_get(upper_snapshot, nec->index);
3737 NlaEvalChannelSnapshot *result_necs = nlaeval_snapshot_ensure_channel(r_lower_snapshot, nec);
3738
3740 blended_necs, upper_necs, upper_blendmode, upper_influence, result_necs);
3741 }
3742}
3743
3744/* ---------------------- */
3745
3747 ListBase *cache, PointerRNA *ptr, AnimData *adt, const AnimationEvalContext *anim_eval_context)
3748{
3749 /* The PointerRNA needs to point to an ID because animsys_evaluate_nla_for_keyframing uses
3750 * F-Curve paths to resolve properties. Since F-Curve paths are always relative to the ID this
3751 * would fail if the PointerRNA was e.g. a bone. */
3753
3754 /* No remapping needed if NLA is off or no action. */
3755 if ((adt == nullptr) || (adt->action == nullptr) || (adt->nla_tracks.first == nullptr) ||
3756 (adt->flag & ADT_NLA_EVAL_OFF))
3757 {
3758 return nullptr;
3759 }
3760
3761 /* No remapping if editing an ordinary Replace action with full influence and upper tracks not
3762 * evaluated. */
3763 if (!(adt->flag & ADT_NLA_EDIT_ON) &&
3764 (adt->act_blendmode == NLASTRIP_MODE_REPLACE && adt->act_influence == 1.0f) &&
3765 (adt->flag & ADT_NLA_EVAL_UPPER_TRACKS) == 0)
3766 {
3767 return nullptr;
3768 }
3769
3770 /* Try to find a cached context. */
3771 NlaKeyframingContext *ctx = static_cast<NlaKeyframingContext *>(
3772 BLI_findptr(cache, adt, offsetof(NlaKeyframingContext, adt)));
3773
3774 if (ctx == nullptr) {
3775 /* Allocate and evaluate a new context. */
3776 ctx = static_cast<NlaKeyframingContext *>(MEM_callocN(sizeof(*ctx), "NlaKeyframingContext"));
3777 ctx->adt = adt;
3778
3780 animsys_evaluate_nla_for_keyframing(ptr, adt, anim_eval_context, ctx);
3781
3782 BLI_assert(ELEM(ctx->strip.act, nullptr, adt->action));
3783 BLI_addtail(cache, ctx);
3784 }
3785
3786 return ctx;
3787}
3788
3790 PointerRNA *prop_ptr,
3791 PropertyRNA *prop,
3792 const blender::MutableSpan<float> values,
3793 int index,
3794 const AnimationEvalContext *anim_eval_context,
3795 bool *r_force_all,
3796 blender::BitVector<> &r_values_mask)
3797{
3798 const int count = values.size();
3799 r_values_mask.fill(false);
3800
3801 if (r_force_all != nullptr) {
3802 *r_force_all = false;
3803 }
3804
3805 blender::BitVector remap_domain(count, false);
3806 for (int i = 0; i < count; i++) {
3807 if (!ELEM(index, i, -1)) {
3808 continue;
3809 }
3810
3811 remap_domain[i].set();
3812 }
3813
3814 /* No context means no correction. */
3815 if (context == nullptr || context->strip.act == nullptr) {
3816 r_values_mask = remap_domain;
3817 return;
3818 }
3819
3820 /* If the strip is not evaluated, it is the same as zero influence. */
3821 if (context->eval_strip == nullptr) {
3822 return;
3823 }
3824
3825 /* Full influence Replace strips also require no correction if there are no upper tracks
3826 * evaluating. */
3827 int blend_mode = context->strip.blendmode;
3828 float influence = context->strip.influence;
3829
3830 if (blend_mode == NLASTRIP_MODE_REPLACE && influence == 1.0f &&
3831 BLI_listbase_is_empty(&context->upper_estrips))
3832 {
3833 r_values_mask = remap_domain;
3834 return;
3835 }
3836
3837 /* Zero influence is division by zero. */
3838 if (influence <= 0.0f) {
3839 return;
3840 }
3841
3843 NlaEvalData *eval_data = &context->lower_eval_data;
3844 NlaEvalSnapshot blended_snapshot;
3845 nlaeval_snapshot_init(&blended_snapshot, eval_data, nullptr);
3846
3847 NlaEvalChannelKey key{};
3848 key.ptr = *prop_ptr;
3849 key.prop = prop;
3850
3851 NlaEvalChannel *nec = nlaevalchan_verify_key(eval_data, nullptr, &key);
3852 BLI_assert(nec);
3853 if (nec->base_snapshot.length != count) {
3854 BLI_assert_msg(0, "invalid value count");
3855 nlaeval_snapshot_free_data(&blended_snapshot);
3856 return;
3857 }
3858
3859 NlaEvalChannelSnapshot *blended_necs = nlaeval_snapshot_ensure_channel(&blended_snapshot, nec);
3860 std::copy(values.begin(), values.end(), blended_necs->values);
3861
3862 /* Force all channels to be remapped for quaternions in a Combine or Replace strip, otherwise it
3863 * will always fail. See nlaevalchan_combine_quaternion_handle_undefined_blend_values().
3864 */
3865 const bool can_force_all = r_force_all != nullptr;
3866 if (blended_necs->channel->mix_mode == NEC_MIX_QUATERNION &&
3867 ELEM(blend_mode, NLASTRIP_MODE_COMBINE, NLASTRIP_MODE_REPLACE) && can_force_all)
3868 {
3869
3870 *r_force_all = true;
3871 index = -1;
3872 remap_domain.fill(true);
3873 }
3874
3875 for (const int i : remap_domain.index_range()) {
3876 BLI_BITMAP_SET(blended_necs->remap_domain.ptr, i, remap_domain[i]);
3877 }
3878
3879 /* Need to send id_ptr instead of prop_ptr so fcurve RNA paths resolve properly. */
3880 PointerRNA id_ptr = RNA_id_pointer_create(prop_ptr->owner_id);
3881
3882 /* Per iteration, remove effect of upper strip which gives output of nla stack below it. */
3883 LISTBASE_FOREACH_BACKWARD (NlaEvalStrip *, nes, &context->upper_estrips) {
3884 /* This will disable blended_necs->remap_domain bits if an upper strip is not invertible
3885 * (full replace, multiply zero, or transition). Then there is no remap solution. */
3887 &id_ptr, eval_data, nullptr, nes, &blended_snapshot, anim_eval_context);
3888 }
3889
3892 &context->lower_eval_data.eval_snapshot,
3893 &blended_snapshot,
3894 blend_mode,
3895 influence,
3896 &blended_snapshot);
3897
3898 /* Write results into \a values for successfully remapped values. */
3899 for (int i = 0; i < count; i++) {
3900 if (!BLI_BITMAP_TEST_BOOL(blended_necs->remap_domain.ptr, i)) {
3901 continue;
3902 }
3903 values[i] = blended_necs->values[i];
3904 }
3905
3906 for (int i = 0; i < blended_necs->length; i++) {
3907 r_values_mask[i].set(BLI_BITMAP_TEST_BOOL(blended_necs->remap_domain.ptr, i));
3908 }
3909
3910 nlaeval_snapshot_free_data(&blended_snapshot);
3911}
3912
3914{
3915 LISTBASE_FOREACH (NlaKeyframingContext *, ctx, cache) {
3916 MEM_SAFE_FREE(ctx->eval_strip);
3917 BLI_freelistN(&ctx->upper_estrips);
3918 nlaeval_free(&ctx->lower_eval_data);
3919 }
3920
3921 BLI_freelistN(cache);
3922}
3923
3924/* ***************************************** */
3925/* Overrides System - Public API */
3926
3927/* Evaluate Overrides */
3929{
3930 /* for each override, simply execute... */
3931 LISTBASE_FOREACH (AnimOverride *, aor, &adt->overrides) {
3932 PathResolvedRNA anim_rna;
3933 if (BKE_animsys_rna_path_resolve(ptr, aor->rna_path, aor->array_index, &anim_rna)) {
3934 BKE_animsys_write_to_rna_path(&anim_rna, aor->value);
3935 }
3936 }
3937}
3938
3939/* ***************************************** */
3940/* Evaluation System - Public API */
3941
3942/* Overview of how this system works:
3943 * 1) Depsgraph sorts data as necessary, so that data is in an order that means
3944 * that all dependencies are resolved before dependents.
3945 * 2) All normal animation is evaluated, so that drivers have some basis values to
3946 * work with
3947 * a. NLA stacks are done first, as the Active Actions act as 'tweaking' tracks
3948 * which modify the effects of the NLA-stacks
3949 * b. Active Action is evaluated as per normal, on top of the results of the NLA tracks
3950 *
3951 * --------------< often in a separate phase... >------------------
3952 *
3953 * 3) Drivers/expressions are evaluated on top of this, in an order where dependencies are
3954 * resolved nicely.
3955 * NOTE: it may be necessary to have some tools to handle the cases where some higher-level
3956 * drivers are added and cause some problematic dependencies that
3957 * didn't exist in the local levels...
3958 *
3959 * --------------< always executed >------------------
3960 *
3961 * Maintenance of editability of settings (XXX):
3962 * - In order to ensure that settings that are animated can still be manipulated in the UI without
3963 * requiring that keyframes are added to prevent these values from being overwritten,
3964 * we use 'overrides'.
3965 *
3966 * Unresolved things:
3967 * - Handling of multi-user settings (i.e. time-offset, group-instancing) -> big cache grids
3968 * or nodal system? but stored where?
3969 * - Multiple-block dependencies
3970 * (i.e. drivers for settings are in both local and higher levels) -> split into separate lists?
3971 *
3972 * Current Status:
3973 * - Currently (as of September 2009), overrides we haven't needed to (fully) implement overrides.
3974 * However, the code for this is relatively harmless, so is left in the code for now.
3975 */
3976
3978 AnimData *adt,
3979 const AnimationEvalContext *anim_eval_context,
3980 eAnimData_Recalc recalc,
3981 const bool flush_to_original)
3982{
3983
3984 /* sanity checks */
3985 if (ELEM(nullptr, id, adt)) {
3986 return;
3987 }
3988
3989 /* get pointer to ID-block for RNA to use */
3990 PointerRNA id_ptr = RNA_id_pointer_create(id);
3991
3992 /* recalculate keyframe data:
3993 * - NLA before Active Action, as Active Action behaves as 'tweaking track'
3994 * that overrides 'rough' work in NLA
3995 */
3996 /* TODO: need to double check that this all works correctly */
3997 if (recalc & ADT_RECALC_ANIM) {
3998 /* evaluate NLA data */
3999 bool did_nla_evaluate_anything = false;
4000 if ((adt->nla_tracks.first) && !(adt->flag & ADT_NLA_EVAL_OFF)) {
4001 /* evaluate NLA-stack
4002 * - active action is evaluated as part of the NLA stack as the last item
4003 */
4004 did_nla_evaluate_anything = animsys_calculate_nla(
4005 &id_ptr, adt, anim_eval_context, flush_to_original);
4006 }
4007
4008 if (!did_nla_evaluate_anything && adt->action) {
4009 blender::animrig::Action &action = adt->action->wrap();
4010 if (action.is_action_layered()) {
4012 id_ptr, action, adt->slot_handle, *anim_eval_context, flush_to_original);
4013 }
4014 else {
4016 &id_ptr, adt->action, animrig::Slot::unassigned, anim_eval_context, flush_to_original);
4017 }
4018 }
4019 }
4020
4021 /* recalculate drivers
4022 * - Drivers need to be evaluated afterwards, as they can either override
4023 * or be layered on top of existing animation data.
4024 * - Drivers should be in the appropriate order to be evaluated without problems...
4025 */
4026 if (recalc & ADT_RECALC_DRIVERS) {
4027 animsys_evaluate_drivers(&id_ptr, adt, anim_eval_context);
4028 }
4029
4030 /* always execute 'overrides'
4031 * - Overrides allow editing, by overwriting the value(s) set from animation-data, with the
4032 * value last set by the user (and not keyframed yet).
4033 * - Overrides are cleared upon frame change and/or keyframing
4034 * - It is best that we execute this every time, so that no errors are likely to occur.
4035 */
4036 animsys_evaluate_overrides(&id_ptr, adt);
4037}
4038
4040{
4041 ID *id;
4042
4043 if (G.debug & G_DEBUG) {
4044 printf("Evaluate all animation - %f\n", ctime);
4045 }
4046
4047 const bool flush_to_original = DEG_is_active(depsgraph);
4049 ctime);
4050
4051/* macros for less typing
4052 * - only evaluate animation data for id if it has users (and not just fake ones)
4053 * - whether animdata exists is checked for by the evaluation function, though taking
4054 * this outside of the function may make things slightly faster?
4055 */
4056#define EVAL_ANIM_IDS(first, aflag) \
4057 for (id = static_cast<ID *>(first); id; id = static_cast<ID *>(id->next)) { \
4058 if (ID_REAL_USERS(id) > 0) { \
4059 AnimData *adt = BKE_animdata_from_id(id); \
4060 BKE_animsys_evaluate_animdata(id, adt, &anim_eval_context, aflag, flush_to_original); \
4061 } \
4062 } \
4063 (void)0
4064
4065/* Another macro for the "embedded" node-tree cases
4066 * - This is like #EVAL_ANIM_IDS, but this handles the case "embedded node-trees"
4067 * (i.e. `scene/material/texture->nodetree`) which we need a special exception
4068 * for, otherwise they'd get skipped.
4069 * - `ntp` stands for "node tree parent" = data-block where node tree stuff resides.
4070 */
4071#define EVAL_ANIM_NODETREE_IDS(first, NtId_Type, aflag) \
4072 for (id = static_cast<ID *>(first); id; id = static_cast<ID *>(id->next)) { \
4073 if (ID_REAL_USERS(id) > 0) { \
4074 AnimData *adt = BKE_animdata_from_id(id); \
4075 NtId_Type *ntp = (NtId_Type *)id; \
4076 if (ntp->nodetree) { \
4077 AnimData *adt2 = BKE_animdata_from_id((ID *)ntp->nodetree); \
4078 BKE_animsys_evaluate_animdata( \
4079 &ntp->nodetree->id, adt2, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original); \
4080 } \
4081 BKE_animsys_evaluate_animdata(id, adt, &anim_eval_context, aflag, flush_to_original); \
4082 } \
4083 } \
4084 (void)0
4085
4086 /* optimization:
4087 * when there are no actions, don't go over database and loop over heaps of data-blocks,
4088 * which should ultimately be empty, since it is not possible for now to have any animation
4089 * without some actions, and drivers wouldn't get affected by any state changes
4090 *
4091 * however, if there are some curves, we will need to make sure that their 'ctime' property gets
4092 * set correctly, so this optimization must be skipped in that case...
4093 */
4094 if (BLI_listbase_is_empty(&main->actions) && BLI_listbase_is_empty(&main->curves)) {
4095 if (G.debug & G_DEBUG) {
4096 printf("\tNo Actions, so no animation needs to be evaluated...\n");
4097 }
4098
4099 return;
4100 }
4101
4102 /* nodes */
4103 EVAL_ANIM_IDS(main->nodetrees.first, ADT_RECALC_ANIM);
4104
4105 /* textures */
4107
4108 /* lights */
4110
4111 /* materials */
4113
4114 /* cameras */
4115 EVAL_ANIM_IDS(main->cameras.first, ADT_RECALC_ANIM);
4116
4117 /* shapekeys */
4118 EVAL_ANIM_IDS(main->shapekeys.first, ADT_RECALC_ANIM);
4119
4120 /* metaballs */
4121 EVAL_ANIM_IDS(main->metaballs.first, ADT_RECALC_ANIM);
4122
4123 /* curves */
4124 EVAL_ANIM_IDS(main->curves.first, ADT_RECALC_ANIM);
4125
4126 /* armatures */
4127 EVAL_ANIM_IDS(main->armatures.first, ADT_RECALC_ANIM);
4128
4129 /* lattices */
4130 EVAL_ANIM_IDS(main->lattices.first, ADT_RECALC_ANIM);
4131
4132 /* meshes */
4133 EVAL_ANIM_IDS(main->meshes.first, ADT_RECALC_ANIM);
4134
4135 /* particles */
4136 EVAL_ANIM_IDS(main->particles.first, ADT_RECALC_ANIM);
4137
4138 /* speakers */
4139 EVAL_ANIM_IDS(main->speakers.first, ADT_RECALC_ANIM);
4140
4141 /* movie clips */
4142 EVAL_ANIM_IDS(main->movieclips.first, ADT_RECALC_ANIM);
4143
4144 /* linestyles */
4145 EVAL_ANIM_IDS(main->linestyles.first, ADT_RECALC_ANIM);
4146
4147 /* grease pencil */
4148 EVAL_ANIM_IDS(main->gpencils.first, ADT_RECALC_ANIM);
4149
4150 /* palettes */
4151 EVAL_ANIM_IDS(main->palettes.first, ADT_RECALC_ANIM);
4152
4153 /* cache files */
4154 EVAL_ANIM_IDS(main->cachefiles.first, ADT_RECALC_ANIM);
4155
4156 /* Hair Curves. */
4157 EVAL_ANIM_IDS(main->hair_curves.first, ADT_RECALC_ANIM);
4158
4159 /* pointclouds */
4160 EVAL_ANIM_IDS(main->pointclouds.first, ADT_RECALC_ANIM);
4161
4162 /* volumes */
4163 EVAL_ANIM_IDS(main->volumes.first, ADT_RECALC_ANIM);
4164
4165 /* objects */
4166 /* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets
4167 * this tagged by Depsgraph on frame-change. This optimization means that objects
4168 * linked from other (not-visible) scenes will not need their data calculated.
4169 */
4170 EVAL_ANIM_IDS(main->objects.first, eAnimData_Recalc(0));
4171
4172 /* masks */
4173 EVAL_ANIM_IDS(main->masks.first, ADT_RECALC_ANIM);
4174
4175 /* worlds */
4177
4178 /* scenes */
4180}
4181
4182/* ***************************************** */
4183
4184/* ************** */
4185/* Evaluation API */
4186
4188{
4189 float ctime = DEG_get_ctime(depsgraph);
4190 AnimData *adt = BKE_animdata_from_id(id);
4191 /* XXX: this is only needed for flushing RNA updates,
4192 * which should get handled as part of the dependency graph instead. */
4193 DEG_debug_print_eval_time(depsgraph, __func__, id->name, id, ctime);
4194 const bool flush_to_original = DEG_is_active(depsgraph);
4195
4197 ctime);
4198 BKE_animsys_evaluate_animdata(id, adt, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original);
4199}
4200
4202{
4203 AnimData *adt = BKE_animdata_from_id(id);
4204
4205 /* Runtime driver map to avoid O(n^2) lookups in BKE_animsys_eval_driver.
4206 * Ideally the depsgraph could pass a pointer to the evaluated driver directly,
4207 * but this is difficult in the current design. */
4208 if (adt && adt->drivers.first) {
4209 BLI_assert(!adt->driver_array);
4210
4211 int num_drivers = BLI_listbase_count(&adt->drivers);
4212 adt->driver_array = static_cast<FCurve **>(
4213 MEM_mallocN(sizeof(FCurve *) * num_drivers, "adt->driver_array"));
4214
4215 int driver_index = 0;
4216 LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
4217 adt->driver_array[driver_index++] = fcu;
4218 }
4219 }
4220}
4221
4222void BKE_animsys_eval_driver(Depsgraph *depsgraph, ID *id, int driver_index, FCurve *fcu_orig)
4223{
4224 BLI_assert(fcu_orig != nullptr);
4225
4226 /* TODO(sergey): De-duplicate with BKE animsys. */
4227 bool ok = false;
4228
4229 /* Lookup driver, accelerated with driver array map. */
4230 const AnimData *adt = BKE_animdata_from_id(id);
4231 FCurve *fcu;
4232
4233 if (adt->driver_array) {
4234 fcu = adt->driver_array[driver_index];
4235 }
4236 else {
4237 fcu = static_cast<FCurve *>(BLI_findlink(&adt->drivers, driver_index));
4238 }
4239
4241 depsgraph, __func__, id->name, id, "fcu", fcu->rna_path, fcu, fcu->array_index);
4242
4243 PointerRNA id_ptr = RNA_id_pointer_create(id);
4244
4245 /* check if this driver's curve should be skipped */
4246 if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) {
4247 /* check if driver itself is tagged for recalculation */
4248 /* XXX driver recalc flag is not set yet by depsgraph! */
4249 ChannelDriver *driver_orig = fcu_orig->driver;
4250 if ((driver_orig) && !(driver_orig->flag & DRIVER_FLAG_INVALID)) {
4251 /* evaluate this using values set already in other places
4252 * NOTE: for 'layering' option later on, we should check if we should remove old value before
4253 * adding new to only be done when drivers only changed */
4254 // printf("\told val = %f\n", fcu->curval);
4255
4256 PathResolvedRNA anim_rna;
4257 if (BKE_animsys_rna_path_resolve(&id_ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
4258 /* Evaluate driver, and write results to copy-on-eval-domain destination */
4259 const float ctime = DEG_get_ctime(depsgraph);
4261 depsgraph, ctime);
4262 const float curval = calculate_fcurve(&anim_rna, fcu, &anim_eval_context);
4263 ok = BKE_animsys_write_to_rna_path(&anim_rna, curval);
4264
4265 /* Flush results & status codes to original data for UI (#59984) */
4266 if (ok && DEG_is_active(depsgraph)) {
4267 animsys_write_orig_anim_rna(&id_ptr, fcu->rna_path, fcu->array_index, curval);
4268
4269 /* curval is displayed in the UI, and flag contains error-status codes */
4270 fcu_orig->curval = fcu->curval;
4271 driver_orig->curval = fcu->driver->curval;
4272 driver_orig->flag = fcu->driver->flag;
4273
4274 DriverVar *dvar_orig = static_cast<DriverVar *>(driver_orig->variables.first);
4275 DriverVar *dvar = static_cast<DriverVar *>(fcu->driver->variables.first);
4276 for (; dvar_orig && dvar; dvar_orig = dvar_orig->next, dvar = dvar->next) {
4277 DriverTarget *dtar_orig = &dvar_orig->targets[0];
4278 DriverTarget *dtar = &dvar->targets[0];
4279 for (int i = 0; i < MAX_DRIVER_TARGETS; i++, dtar_orig++, dtar++) {
4280 dtar_orig->flag = dtar->flag;
4281 }
4282
4283 dvar_orig->curval = dvar->curval;
4284 dvar_orig->flag = dvar->flag;
4285 }
4286 }
4287 }
4288
4289 /* set error-flag if evaluation failed */
4290 if (ok == 0) {
4291 CLOG_WARN(&LOG, "invalid driver - %s[%d]", fcu->rna_path, fcu->array_index);
4292 driver_orig->flag |= DRIVER_FLAG_INVALID;
4293 }
4294 }
4295 }
4296}
Functions and classes to work with Actions.
Functions for backward compatibility with the legacy Action API.
Layered Action evaluation.
Blender kernel action and pose functionality.
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:89
eAnimData_Recalc
@ ADT_RECALC_ANIM
@ ADT_RECALC_DRIVERS
float evaluate_time_fmodifiers(FModifiersStackStorage *storage, const ListBase *modifiers, const FCurve *fcu, float cvalue, float evaltime)
uint evaluate_fmodifiers_storage_size_per_modifier(const ListBase *modifiers)
void evaluate_value_fmodifiers(FModifiersStackStorage *storage, const ListBase *modifiers, const FCurve *fcu, float *cvalue, float evaltime)
bool BKE_fcurve_is_empty(const FCurve *fcu)
float evaluate_fcurve(const FCurve *fcu, float evaltime)
float calculate_fcurve(PathResolvedRNA *anim_rna, FCurve *fcu, const AnimationEvalContext *anim_eval_context)
@ G_DEBUG
@ IDWALK_CB_NOP
#define BKE_LIB_FOREACHID_PROCESS_ID(data_, id_, cb_flag_)
General operations, lookup, etc. for materials.
void BKE_nla_clip_length_ensure_nonzero(const float *actstart, float *r_actend)
void BKE_nlastrip_recalculate_bounds_sync_action(NlaStrip *strip)
@ NLATIME_CONVERT_EVAL
Definition BKE_nla.hh:510
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
#define BLI_BITMAP_NEW(_num, _alloc_string)
Definition BLI_bitmap.h:41
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition BLI_bitmap.h:65
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition BLI_bitmap.h:82
#define BLI_BITMAP_DISABLE(_bitmap, _index)
Definition BLI_bitmap.h:89
#define BLI_BITMAP_SIZE(_num)
Definition BLI_bitmap.h:36
void BLI_bitmap_copy_all(BLI_bitmap *dst, const BLI_bitmap *src, size_t bits)
Definition bitmap.c:31
#define BLI_BITMAP_TEST_BOOL(_bitmap, _index)
Definition BLI_bitmap.h:75
void BLI_bitmap_set_all(BLI_bitmap *bitmap, bool set, size_t bits)
Definition bitmap.c:18
#define BLI_BITMAP_SET(_bitmap, _index, _set)
Definition BLI_bitmap.h:103
#define ATTR_FALLTHROUGH
A dynamically sized string ADT.
struct GSet GSet
Definition BLI_ghash.h:341
GSet * BLI_gset_ptr_new(const char *info)
unsigned int BLI_ghashutil_ptrhash(const void *key)
GHash * BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:686
GHash * BLI_ghash_str_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.c:860
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition BLI_ghash.c:1034
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:752
bool BLI_gset_add(GSet *gs, void *key)
Definition BLI_ghash.c:966
bool BLI_ghash_ensure_p_ex(GHash *gh, const void *key, void ***r_key, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:768
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:269
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
void void void void void void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void * BLI_findptr(const struct ListBase *listbase, const void *ptr, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void pow_qt_fl_normalized(float q[4], float fac)
void interp_qt_qtqt(float q[4], const float a[4], const float b[4], float t)
void invert_qt_normalized(float q[4])
float normalize_qt(float q[4])
void unit_qt(float q[4])
float normalize_qt_qt(float r[4], const float q[4])
void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
MINLINE void zero_v4(float r[4])
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.c:40
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define STRNCPY_UTF8(dst, src)
void BLI_uniquename(const struct ListBase *list, void *vlink, const char *defname, char delim, int name_offset, size_t name_maxncpy) ATTR_NONNULL(1
unsigned int uint
#define UNUSED_VARS_NDEBUG(...)
#define ELEM(...)
#define IS_EQF(a, b)
#define IN_RANGE_INCL(a, b, c)
#define STREQ(a, b)
#define CLAMP_MIN(a, b)
#define BLO_write_struct(writer, struct_name, data_ptr)
void BLO_read_string(BlendDataReader *reader, char **ptr_p)
Definition readfile.cc:4992
void BLO_write_string(BlendWriter *writer, const char *data_ptr)
#define BLO_read_struct_list(reader, struct_name, list)
#define DATA_(msgid)
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:182
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
void DEG_debug_print_eval_time(Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address, float time)
bool DEG_is_active(const Depsgraph *depsgraph)
Definition depsgraph.cc:318
void DEG_debug_print_eval_subdata_index(Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address, const char *subdata_comment, const char *subdata_name, const void *subdata_address, int subdata_index)
float DEG_get_ctime(const Depsgraph *graph)
@ AGRP_MUTED
#define MAX_DRIVER_TARGETS
@ NLASTRIP_FLAG_USR_INFLUENCE
@ NLASTRIP_FLAG_USR_TIME
@ NLASTRIP_FLAG_REVERSE
@ NLASTRIP_FLAG_MUTED
@ NLASTRIP_FLAG_USR_TIME_CYCLIC
@ NLASTRIP_FLAG_NO_TIME_MAP
@ NLASTRIP_FLAG_EDIT_TOUCHED
@ NLASTRIP_FLAG_SYNC_LENGTH
@ ADT_NLA_SOLO_TRACK
@ ADT_NLA_EVAL_OFF
@ ADT_NLA_EDIT_NOMAP
@ ADT_NLA_EVAL_UPPER_TRACKS
@ ADT_NLA_EDIT_ON
@ NLASTRIP_EXTEND_HOLD_FORWARD
@ NLASTRIP_EXTEND_NOTHING
@ NLASTRIP_EXTEND_HOLD
@ NLASTRIP_MODE_REPLACE
@ NLASTRIP_MODE_ADD
@ NLASTRIP_MODE_SUBTRACT
@ NLASTRIP_MODE_COMBINE
@ NLASTRIP_MODE_MULTIPLY
@ DRIVER_FLAG_INVALID
@ NLASTRIP_TYPE_META
@ NLASTRIP_TYPE_TRANSITION
@ NLASTRIP_TYPE_CLIP
@ FCURVE_DISABLED
@ FCURVE_MUTED
@ NLATRACK_SOLO
@ NLATRACK_MUTED
@ NLATRACK_DISABLED
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
@ PROP_FLOAT
Definition RNA_types.hh:67
@ PROP_BOOLEAN
Definition RNA_types.hh:65
@ PROP_ENUM
Definition RNA_types.hh:69
@ PROP_INT
Definition RNA_types.hh:66
@ PROP_PROPORTIONAL
Definition RNA_types.hh:250
PropertySubType
Definition RNA_types.hh:135
@ PROP_AXISANGLE
Definition RNA_types.hh:171
@ PROP_QUATERNION
Definition RNA_types.hh:170
static void nlaeval_init(NlaEvalData *nlaeval)
Definition anim_sys.cc:1347
static float nla_combine_value(const int mix_mode, float base_value, const float lower_value, const float strip_value, const float influence)
Definition anim_sys.cc:1830
static bool nla_combine_get_inverted_lower_value(const int mix_mode, float base_value, const float strip_value, const float blended_value, const float influence, float *r_lower_value)
Definition anim_sys.cc:1705
static void animsys_evaluate_fcurves(PointerRNA *ptr, Span< FCurve * > fcurves, const AnimationEvalContext *anim_eval_context, bool flush_to_original)
Definition anim_sys.cc:569
void nlasnapshot_enable_all_blend_domain(NlaEvalSnapshot *snapshot)
Definition anim_sys.cc:3645
void BKE_animsys_evaluate_animdata(ID *id, AnimData *adt, const AnimationEvalContext *anim_eval_context, eAnimData_Recalc recalc, const bool flush_to_original)
Definition anim_sys.cc:3977
static void animsys_write_orig_anim_rna(PointerRNA *ptr, const char *rna_path, int array_index, float value)
Definition anim_sys.cc:548
static void nlastrip_evaluate_meta(const int evaluation_mode, PointerRNA *ptr, NlaEvalData *channels, ListBase *modifiers, NlaEvalStrip *nes, NlaEvalSnapshot *snapshot, const AnimationEvalContext *anim_eval_context, const bool flush_to_original)
Definition anim_sys.cc:2931
static bool is_action_track_evaluated_without_nla(const AnimData *adt, const bool any_strip_evaluated)
Definition anim_sys.cc:3360
static NlaEvalChannel * nlaevalchan_verify_key(NlaEvalData *nlaeval, const char *path, NlaEvalChannelKey *key)
Definition anim_sys.cc:1509
AnimationEvalContext BKE_animsys_eval_context_construct(Depsgraph *depsgraph, float eval_time)
Definition anim_sys.cc:734
void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float ctime)
Definition anim_sys.cc:4039
void BKE_keyingsets_copy(ListBase *newlist, const ListBase *list)
Definition anim_sys.cc:243
static bool is_nlatrack_evaluatable(const AnimData *adt, const NlaTrack *nlt)
Definition anim_sys.cc:3330
static void nlaevalchan_free_data(NlaEvalChannel *nec)
Definition anim_sys.cc:1340
static void nlavalidmask_free(NlaValidMask *mask)
Definition anim_sys.cc:1178
static void nlastrip_evaluate_transition(const int evaluation_mode, PointerRNA *ptr, NlaEvalData *channels, ListBase *modifiers, NlaEvalStrip *nes, NlaEvalSnapshot *snapshot, const AnimationEvalContext *anim_eval_context, const bool flush_to_original)
Definition anim_sys.cc:2778
void nlasnapshot_ensure_channels(NlaEvalData *eval_data, NlaEvalSnapshot *snapshot)
Definition anim_sys.cc:3657
static void animsys_create_action_track_strip(const AnimData *adt, const bool keyframing_to_strip, NlaStrip *r_action_strip)
Definition anim_sys.cc:3276
static void nlaevalchan_assert_nonNull(const NlaEvalChannelSnapshot *necs)
Definition anim_sys.cc:2013
static void nlavalidmask_init(NlaValidMask *mask, int bits)
Definition anim_sys.cc:1167
void BKE_keyingset_free_paths(KeyingSet *ks)
Definition anim_sys.cc:267
static float nla_blend_value(const int blendmode, const float lower_value, const float strip_value, const float influence)
Definition anim_sys.cc:1794
static void nlaevalchan_combine_value_get_inverted_upper_evalchan(NlaEvalChannelSnapshot *lower_necs, NlaEvalChannelSnapshot *blended_necs, const float upper_influence, NlaEvalChannelSnapshot *r_upper_necs)
Definition anim_sys.cc:2296
bool BKE_animsys_rna_path_resolve(PointerRNA *ptr, const char *rna_path, const int array_index, PathResolvedRNA *r_result)
Definition anim_sys.cc:350
static bool nlaevalchan_blendOrcombine_try_copy_from_lower(const NlaEvalChannelSnapshot *lower_necs, const NlaEvalChannelSnapshot *upper_necs, const float upper_influence, NlaEvalChannelSnapshot *r_blended_necs)
Definition anim_sys.cc:2070
static void nlaeval_fmodifiers_join_stacks(ListBase *result, ListBase *list1, ListBase *list2)
Definition anim_sys.cc:2589
KeyingSet * BKE_keyingset_add(ListBase *list, const char idname[], const char name[], short flag, short keyingflag)
Definition anim_sys.cc:134
static void animsys_blend_fcurves_quaternion(PathResolvedRNA *anim_rna, Span< FCurve * > quaternion_fcurves, const AnimationEvalContext *anim_eval_context, const float blend_factor)
Definition anim_sys.cc:628
void BKE_keyingset_free_path(KeyingSet *ks, KS_Path *ksp)
Definition anim_sys.cc:227
void nlasnapshot_blend(NlaEvalData *eval_data, NlaEvalSnapshot *lower_snapshot, NlaEvalSnapshot *upper_snapshot, const short upper_blendmode, const float upper_influence, NlaEvalSnapshot *r_blended_snapshot)
Definition anim_sys.cc:3664
static uint nlaevalchan_keyhash(const void *ptr)
Definition anim_sys.cc:1188
void nlasnapshot_blend_get_inverted_upper_snapshot(NlaEvalData *eval_data, NlaEvalSnapshot *lower_snapshot, NlaEvalSnapshot *blended_snapshot, const short upper_blendmode, const float upper_influence, NlaEvalSnapshot *r_upper_snapshot)
Definition anim_sys.cc:3691
static void nlaevalchan_assert_blendOrcombine_compatible(const NlaEvalChannelSnapshot *lower_necs, const NlaEvalChannelSnapshot *upper_necs, const NlaEvalChannelSnapshot *blended_necs)
Definition anim_sys.cc:2020
static void nlaevalchan_combine_quaternion_get_inverted_upper_evalchan(NlaEvalChannelSnapshot *lower_necs, NlaEvalChannelSnapshot *blended_necs, const float upper_influence, NlaEvalChannelSnapshot *r_upper_necs)
Definition anim_sys.cc:2334
static void nlaevalchan_blendOrcombine_get_inverted_upper_evalchan(NlaEvalChannelSnapshot *lower_necs, NlaEvalChannelSnapshot *blended_necs, const int upper_blendmode, const float upper_influence, NlaEvalChannelSnapshot *r_upper_necs)
Definition anim_sys.cc:2366
KS_Path * BKE_keyingset_add_path(KeyingSet *ks, ID *id, const char group_name[], const char rna_path[], int array_index, short flag, short groupmode)
Definition anim_sys.cc:164
void BKE_animsys_nla_remap_keyframe_values(NlaKeyframingContext *context, PointerRNA *prop_ptr, PropertyRNA *prop, const blender::MutableSpan< float > values, int index, const AnimationEvalContext *anim_eval_context, bool *r_force_all, blender::BitVector<> &r_values_mask)
Definition anim_sys.cc:3789
void BKE_animsys_eval_animdata(Depsgraph *depsgraph, ID *id)
Definition anim_sys.cc:4187
static bool nla_combine_get_inverted_strip_value(const int mix_mode, float base_value, const float lower_value, const float blended_value, const float influence, float *r_strip_value)
Definition anim_sys.cc:1924
static void nlaevalchan_blend_value_get_inverted_upper_evalchan(NlaEvalChannelSnapshot *lower_necs, NlaEvalChannelSnapshot *blended_necs, const int upper_blendmode, const float upper_influence, NlaEvalChannelSnapshot *r_upper_necs)
Definition anim_sys.cc:2263
static void nlaevalchan_get_default_values(NlaEvalChannel *nec, float *r_values)
Definition anim_sys.cc:1411
static bool nlaevalchan_blendOrcombine_try_copy_to_lower(NlaEvalChannelSnapshot *blended_necs, NlaEvalChannelSnapshot *upper_necs, const float upper_influence, NlaEvalChannelSnapshot *r_lower_necs)
Definition anim_sys.cc:2093
static void nlaevalchan_combine_value_get_inverted_lower_evalchan(NlaEvalChannelSnapshot *blended_necs, NlaEvalChannelSnapshot *upper_necs, const float upper_influence, NlaEvalChannelSnapshot *r_lower_necs)
Definition anim_sys.cc:2454
static bool is_fcurve_evaluatable(const FCurve *fcu)
Definition anim_sys.cc:336
void nlasnapshot_blend_strip(PointerRNA *ptr, NlaEvalData *channels, ListBase *modifiers, NlaEvalStrip *nes, NlaEvalSnapshot *snapshot, const AnimationEvalContext *anim_eval_context, const bool flush_to_original)
Definition anim_sys.cc:3054
NlaKeyframingContext * BKE_animsys_get_nla_keyframing_context(ListBase *cache, PointerRNA *ptr, AnimData *adt, const AnimationEvalContext *anim_eval_context)
Definition anim_sys.cc:3746
static void nlaevalchan_blendOrcombine(NlaEvalChannelSnapshot *lower_necs, NlaEvalChannelSnapshot *upper_necs, const int upper_blendmode, const float upper_influence, NlaEvalChannelSnapshot *r_blended_necs)
Definition anim_sys.cc:2217
#define EVAL_ANIM_IDS(first, aflag)
static bool nlaevalchan_validate_index_ex(const NlaEvalChannel *nec, const int array_index)
Definition anim_sys.cc:1388
static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt)
Definition anim_sys.cc:3928
void BKE_animsys_free_nla_keyframing_context_cache(ListBase *cache)
Definition anim_sys.cc:3913
static void nlasnapshot_from_action(PointerRNA *ptr, NlaEvalData *channels, ListBase *modifiers, bAction *action, const animrig::slot_handle_t slot_handle, const float evaltime, NlaEvalSnapshot *r_snapshot)
Definition anim_sys.cc:2646
KS_Path * BKE_keyingset_find_path(KeyingSet *ks, ID *id, const char group_name[], const char rna_path[], int array_index, int)
Definition anim_sys.cc:84
static void nlaevalchan_blend_value(NlaEvalChannelSnapshot *lower_necs, NlaEvalChannelSnapshot *upper_necs, const int upper_blendmode, const float upper_influence, NlaEvalChannelSnapshot *r_blended_necs)
Definition anim_sys.cc:2118
static void nlaevalchan_snapshot_copy(NlaEvalChannelSnapshot *dst, const NlaEvalChannelSnapshot *src)
Definition anim_sys.cc:1233
void BKE_keyingsets_blend_write(BlendWriter *writer, ListBase *list)
Definition anim_sys.cc:302
bool BKE_animsys_read_from_rna_path(PathResolvedRNA *anim_rna, float *r_value)
Definition anim_sys.cc:399
void nlasnapshot_blend_get_inverted_lower_snapshot(NlaEvalData *eval_data, NlaEvalSnapshot *blended_snapshot, NlaEvalSnapshot *upper_snapshot, const short upper_blendmode, const float upper_influence, NlaEvalSnapshot *r_lower_snapshot)
Definition anim_sys.cc:3719
static bool nla_blend_get_inverted_lower_value(const int blendmode, const float strip_value, const float blended_value, const float influence, float *r_lower_value)
Definition anim_sys.cc:1609
static void nlaevalchan_blend_value_get_inverted_lower_evalchan(NlaEvalChannelSnapshot *blended_necs, NlaEvalChannelSnapshot *upper_necs, const int upper_blendmode, const float upper_influence, NlaEvalChannelSnapshot *r_lower_necs)
Definition anim_sys.cc:2413
void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup *agrp, const AnimationEvalContext *anim_eval_context)
Definition anim_sys.cc:836
static NlaEvalChannelSnapshot * nlaeval_snapshot_get(NlaEvalSnapshot *snapshot, int index)
Definition anim_sys.cc:1255
static NlaEvalChannel * nlaevalchan_verify(PointerRNA *ptr, NlaEvalData *nlaeval, const char *path)
Definition anim_sys.cc:1560
static void animsys_quaternion_evaluate_fcurves(PathResolvedRNA quat_rna, Span< FCurve * > quat_fcurves, const AnimationEvalContext *anim_eval_context, float r_quaternion[4])
Definition anim_sys.cc:597
NlaEvalStrip * nlastrips_ctime_get_strip(ListBase *list, ListBase *strips, short index, const AnimationEvalContext *anim_eval_context, const bool flush_to_original)
Definition anim_sys.cc:1001
static int nlaevalchan_validate_index(const NlaEvalChannel *nec, int index)
Definition anim_sys.cc:1376
static void animsys_blend_in_fcurves(PointerRNA *ptr, Span< FCurve * > fcurves, const AnimationEvalContext *anim_eval_context, const float blend_factor)
Definition anim_sys.cc:650
static NlaEvalStrip * nlastrips_ctime_get_strip_single(ListBase *dst_list, NlaStrip *single_strip, const AnimationEvalContext *anim_eval_context, const bool flush_to_original)
Definition anim_sys.cc:1151
static bool nla_blend_get_inverted_strip_value(const int blendmode, const float lower_value, const float blended_value, const float influence, float *r_strip_value)
Definition anim_sys.cc:1860
static void nlaeval_snapshot_ensure_size(NlaEvalSnapshot *snapshot, int size)
Definition anim_sys.cc:1261
static NlaEvalChannelSnapshot * nlaevalchan_snapshot_new(NlaEvalChannel *nec)
Definition anim_sys.cc:1206
void nlasnapshot_blend_strip_no_blend(PointerRNA *ptr, NlaEvalData *channels, ListBase *modifiers, NlaEvalStrip *nes, NlaEvalSnapshot *snapshot, const AnimationEvalContext *anim_eval_context)
Definition anim_sys.cc:3090
void BKE_keyingsets_blend_read_data(BlendDataReader *reader, ListBase *list)
Definition anim_sys.cc:320
static NlaEvalChannelSnapshot * nlaeval_snapshot_ensure_channel(NlaEvalSnapshot *snapshot, NlaEvalChannel *nec)
Definition anim_sys.cc:1299
#define ANIMSYS_FLOAT_AS_BOOL(value)
Definition anim_sys.cc:397
#define EVAL_ANIM_NODETREE_IDS(first, NtId_Type, aflag)
static void nlaevalchan_combine_quaternion_get_inverted_lower_evalchan(NlaEvalChannelSnapshot *blended_necs, NlaEvalChannelSnapshot *upper_necs, const float upper_influence, NlaEvalChannelSnapshot *r_lower_necs)
Definition anim_sys.cc:2497
static void nla_combine_quaternion(const float lower_values[4], const float strip_values[4], const float influence, float r_blended_value[4])
Definition anim_sys.cc:1970
void BKE_animsys_update_driver_array(ID *id)
Definition anim_sys.cc:4201
static bool nla_combine_quaternion_get_inverted_strip_values(const float lower_values[4], const float blended_values[4], const float influence, float r_strip_values[4])
Definition anim_sys.cc:1985
static void nlaevalchan_combine_quaternion(NlaEvalChannelSnapshot *lower_necs, NlaEvalChannelSnapshot *upper_necs, const float upper_influence, NlaEvalChannelSnapshot *r_blended_necs)
Definition anim_sys.cc:2183
static NlaTrack * nlatrack_find_tweaked(const AnimData *adt)
Definition anim_sys.cc:3388
static void nla_eval_domain_action(PointerRNA *ptr, NlaEvalData *channels, bAction *act, const animrig::slot_handle_t slot_handle, GSet *touched_actions)
Definition anim_sys.cc:3143
static void nlaeval_snapshot_init(NlaEvalSnapshot *snapshot, NlaEvalData *nlaeval, NlaEvalSnapshot *base)
Definition anim_sys.cc:1244
static bool animsys_calculate_nla(PointerRNA *ptr, AnimData *adt, const AnimationEvalContext *anim_eval_context, const bool flush_to_original)
Definition anim_sys.cc:3617
void animsys_evaluate_action(PointerRNA *ptr, bAction *act, const int32_t action_slot_handle, const AnimationEvalContext *anim_eval_context, const bool flush_to_original)
Definition anim_sys.cc:886
static void nlaeval_snapshot_free_data(NlaEvalSnapshot *snapshot)
Definition anim_sys.cc:1319
static void nla_combine_quaternion_get_inverted_lower_values(const float strip_values[4], const float blended_values[4], const float influence, float r_lower_value[4])
Definition anim_sys.cc:1767
static void nlaeval_free(NlaEvalData *nlaeval)
Definition anim_sys.cc:1356
void nlastrip_evaluate(const int evaluation_mode, PointerRNA *ptr, NlaEvalData *channels, ListBase *modifiers, NlaEvalStrip *nes, NlaEvalSnapshot *snapshot, const AnimationEvalContext *anim_eval_context, const bool flush_to_original)
Definition anim_sys.cc:2997
static void nlaevalchan_assert_blendOrcombine_compatible_quaternion(NlaEvalChannelSnapshot *lower_necs, NlaEvalChannelSnapshot *upper_necs, NlaEvalChannelSnapshot *blended_necs)
Definition anim_sys.cc:2052
static CLG_LogRef LOG
Definition anim_sys.cc:75
static float nlastrip_get_influence(NlaStrip *strip, float cframe)
Definition anim_sys.cc:936
static bool animsys_evaluate_nla_for_flush(NlaEvalData *echannels, PointerRNA *ptr, const AnimData *adt, const AnimationEvalContext *anim_eval_context, const bool flush_to_original)
Definition anim_sys.cc:3408
static bool nlaevalchan_keycmp(const void *a, const void *b)
Definition anim_sys.cc:1195
void BKE_animsys_eval_driver(Depsgraph *depsgraph, ID *id, int driver_index, FCurve *fcu_orig)
Definition anim_sys.cc:4222
static bool nlaevalchan_combine_quaternion_handle_undefined_blend_values(NlaEvalChannelSnapshot *blended_necs, NlaEvalChannelSnapshot *upper_or_lower_necs)
Definition anim_sys.cc:2038
void BKE_keyingsets_foreach_id(LibraryForeachIDData *data, const ListBase *keyingsets)
Definition anim_sys.cc:256
static void animsys_create_tweak_strip(const AnimData *adt, const bool keyframing_to_strip, NlaStrip *r_tweak_strip)
Definition anim_sys.cc:3241
void nlasnapshot_blend_strip_get_inverted_lower_snapshot(PointerRNA *ptr, NlaEvalData *channels, ListBase *modifiers, NlaEvalStrip *nes, NlaEvalSnapshot *snapshot, const AnimationEvalContext *anim_eval_context)
Definition anim_sys.cc:3072
static void nlaevalchan_snapshot_free(NlaEvalChannelSnapshot *nec_snapshot)
Definition anim_sys.cc:1223
void nladata_flush_channels(PointerRNA *ptr, NlaEvalData *channels, NlaEvalSnapshot *snapshot, const bool flush_to_original)
Definition anim_sys.cc:3101
static void action_idcode_patch_check(ID *id, bAction *act)
Definition anim_sys.cc:790
static void nlaeval_fmodifiers_split_stacks(ListBase *list1, ListBase *list2)
Definition anim_sys.cc:2622
static void nlaevalchan_copy_values(NlaEvalChannelSnapshot *dst, const NlaEvalChannelSnapshot *src)
Definition anim_sys.cc:2061
static char nlaevalchan_detect_mix_mode(NlaEvalChannelKey *key, int length)
Definition anim_sys.cc:1492
static bool animsys_construct_orig_pointer_rna(const PointerRNA *ptr, PointerRNA *ptr_orig)
Definition anim_sys.cc:524
static void animsys_evaluate_drivers(PointerRNA *ptr, AnimData *adt, const AnimationEvalContext *anim_eval_context)
Definition anim_sys.cc:749
static void animsys_evaluate_nla_domain(PointerRNA *ptr, NlaEvalData *channels, AnimData *adt)
Definition anim_sys.cc:3198
static void animsys_evaluate_nla_for_keyframing(PointerRNA *ptr, const AnimData *adt, const AnimationEvalContext *anim_eval_context, NlaKeyframingContext *r_context)
Definition anim_sys.cc:3477
static void nlaevalchan_combine_value(NlaEvalChannelSnapshot *lower_necs, NlaEvalChannelSnapshot *upper_necs, const float upper_influence, NlaEvalChannelSnapshot *r_blended_necs)
Definition anim_sys.cc:2149
static void nla_eval_domain_strips(PointerRNA *ptr, NlaEvalData *channels, ListBase *strips, GSet *touched_actions)
Definition anim_sys.cc:3177
static void nlastrip_evaluate_actionclip(const int evaluation_mode, PointerRNA *ptr, NlaEvalData *channels, ListBase *modifiers, NlaEvalStrip *nes, NlaEvalSnapshot *snapshot)
Definition anim_sys.cc:2697
static NlaEvalChannelSnapshot * nlaeval_snapshot_find_channel(NlaEvalSnapshot *snapshot, NlaEvalChannel *nec)
Definition anim_sys.cc:1283
static void nlaevalchan_blendOrCombine_get_inverted_lower_evalchan(NlaEvalChannelSnapshot *blended_necs, NlaEvalChannelSnapshot *upper_necs, const int upper_blendmode, const float upper_influence, NlaEvalChannelSnapshot *r_lower_necs)
Definition anim_sys.cc:2542
void animsys_blend_in_action(PointerRNA *ptr, bAction *act, const int32_t action_slot_handle, const AnimationEvalContext *anim_eval_context, const float blend_factor)
Definition anim_sys.cc:916
static void nlastrip_evaluate_controls(NlaStrip *strip, const AnimationEvalContext *anim_eval_context, const bool flush_to_original)
Definition anim_sys.cc:957
AnimationEvalContext BKE_animsys_eval_context_construct_at(const AnimationEvalContext *anim_eval_context, float eval_time)
Definition anim_sys.cc:742
static NlaEvalChannelSnapshot ** nlaeval_snapshot_ensure_slot(NlaEvalSnapshot *snapshot, NlaEvalChannel *nec)
Definition anim_sys.cc:1275
bool BKE_animsys_write_to_rna_path(PathResolvedRNA *anim_rna, const float value)
Definition anim_sys.cc:460
void BKE_keyingsets_free(ListBase *list)
Definition anim_sys.cc:283
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
float nlastrip_get_frame(NlaStrip *strip, float cframe, short mode)
float evaltime
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
Definition btVector3.h:257
constexpr Span slice_safe(const int64_t start, const int64_t size) const
Definition BLI_span.hh:155
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
int64_t size() const
void append(const T &value)
static constexpr slot_handle_t unassigned
void fill(const bool value)
IndexRange index_range() const
local_group_size(16, 16) .push_constant(Type b
#define printf
const Depsgraph * depsgraph
#define powf(x, y)
#define offsetof(t, d)
#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
int count
#define GS(x)
Definition iris.cc:202
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:45
void *(* MEM_recallocN_id)(void *vmemh, size_t len, const char *str)
Definition mallocn.cc:41
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
ccl_device_inline float2 fmod(const float2 a, const float b)
#define B
#define G(x, y, z)
int main()
Vector< FCurve * > fcurves_for_action_slot(bAction *action, slot_handle_t slot_handle)
Vector< const FCurve * > fcurves_all(const bAction *action)
bool action_treat_as_legacy(const bAction &action)
void evaluate_and_apply_action(PointerRNA &animated_id_ptr, Action &action, slot_handle_t slot_handle, const AnimationEvalContext &anim_eval_context, bool flush_to_original)
Definition evaluation.cc:73
Span< FCurve * > fcurves_for_action_slot(Action &action, slot_handle_t slot_handle)
decltype(::ActionSlot::handle) slot_handle_t
Vector< T * > listbase_to_vector(ListBase &list)
@ STRIP_EVAL_NOBLEND
@ STRIP_EVAL_BLEND_GET_INVERTED_LOWER_SNAPSHOT
@ STRIP_EVAL_BLEND
struct NlaEvalChannelSnapshot NlaEvalChannelSnapshot
struct NlaEvalChannelKey NlaEvalChannelKey
@ NEC_MIX_AXIS_ANGLE
Definition nla_private.h:91
@ NEC_MIX_ADD
Definition nla_private.h:88
@ NEC_MIX_MULTIPLY
Definition nla_private.h:89
@ NEC_MIX_QUATERNION
Definition nla_private.h:90
@ NES_TIME_TRANSITION_END
Definition nla_private.h:50
@ NES_TIME_TRANSITION_START
Definition nla_private.h:49
@ NES_TIME_AFTER
Definition nla_private.h:46
@ NES_TIME_BEFORE
Definition nla_private.h:44
@ NES_TIME_WITHIN
Definition nla_private.h:45
#define hash
Definition noise.c:154
float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_float_get_default_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, bool value)
void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
bool RNA_property_array_check(PropertyRNA *prop)
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
int RNA_property_int_clamp(PointerRNA *ptr, PropertyRNA *prop, int *value)
int RNA_property_float_clamp(PointerRNA *ptr, PropertyRNA *prop, float *value)
int RNA_property_int_get_default(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_struct_is_ID(const StructRNA *type)
int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, float value)
int RNA_property_enum_get_default(PointerRNA *, PropertyRNA *prop)
float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
bool RNA_property_animateable(const PointerRNA *ptr, PropertyRNA *prop_orig)
PropertyType RNA_property_type(PropertyRNA *prop)
void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_boolean_get_default_array(PointerRNA *ptr, PropertyRNA *prop, bool *values)
void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
float RNA_property_float_get_default(PointerRNA *ptr, PropertyRNA *prop)
int RNA_property_flag(PropertyRNA *prop)
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
void RNA_property_int_get_default_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
PropertySubType RNA_property_subtype(PropertyRNA *prop)
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
bool RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
bool RNA_property_boolean_get_default(PointerRNA *ptr, PropertyRNA *prop)
const char * RNA_property_identifier(const PropertyRNA *prop)
PointerRNA RNA_id_pointer_create(ID *id)
bool RNA_path_resolve_property(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
Definition rna_path.cc:553
signed int int32_t
Definition stdint.h:77
bAction * action
short act_blendmode
NlaStrip * actstrip
ListBase overrides
float act_influence
int32_t slot_handle
FCurve ** driver_array
NlaTrack * act_track
int32_t tmp_slot_handle
bAction * tmpact
short act_extendmode
ListBase drivers
ListBase nla_tracks
struct Depsgraph * depsgraph
Definition BKE_animsys.h:41
struct DriverVar * next
DriverTarget targets[8]
struct FCurve * next
bActionGroup * grp
float curval
char * rna_path
ChannelDriver * driver
int array_index
struct FModifier * next
struct FModifier * prev
Definition DNA_ID.h:413
struct ID * orig_id
Definition DNA_ID.h:466
char name[66]
Definition DNA_ID.h:425
struct KS_Path * next
char group[64]
short groupmode
char * rna_path
char name[64]
char idname[64]
struct KeyingSet * next
ListBase paths
short keyingoverride
void * last
void * first
struct PropertyRNA * prop
Definition nla_private.h:59
struct PointerRNA ptr
Definition nla_private.h:58
NlaValidMask remap_domain
Definition nla_private.h:77
NlaValidMask blend_domain
Definition nla_private.h:73
struct NlaEvalChannel * channel
Definition nla_private.h:70
struct NlaEvalData * owner
NlaEvalChannelSnapshot base_snapshot
const char * rna_path
NlaEvalChannelKey key
NlaValidMask domain
NlaEvalSnapshot eval_snapshot
GHash * path_hash
NlaEvalSnapshot base_snapshot
ListBase channels
GHash * key_hash
struct NlaEvalSnapshot * base
NlaEvalChannelSnapshot ** channels
NlaStrip * strip
Definition nla_private.h:30
short track_index
Definition nla_private.h:33
NlaTrack * track
Definition nla_private.h:28
short strip_mode
Definition nla_private.h:35
float strip_time
Definition nla_private.h:38
NlaStrip action_track_strip
struct AnimData * adt
NlaEvalData lower_eval_data
NlaEvalStrip * eval_strip
struct NlaStrip * next
short blendmode
ListBase fcurves
char name[64]
float influence
ListBase strips
int32_t action_slot_handle
ListBase modifiers
struct NlaStrip * prev
struct NlaStrip * orig_strip
short extendmode
bAction * act
float strip_time
ListBase strips
struct NlaTrack * next
BLI_bitmap * ptr
Definition nla_private.h:64
PointerRNA ptr
Definition RNA_types.hh:56
PropertyRNA * prop
Definition RNA_types.hh:57
ID * owner_id
Definition RNA_types.hh:40
StructRNA * type
Definition RNA_types.hh:41
void * data
Definition RNA_types.hh:42
PointerRNA * ptr
Definition wm_files.cc:4126
uint8_t flag
Definition wm_window.cc:138