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
8
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
848 action_idcode_patch_check(ptr->owner_id, act);
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()) {
900 action_idcode_patch_check(ptr->owner_id, act);
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()) {
925 action_idcode_patch_check(ptr->owner_id, act);
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. */
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. */
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)) {
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
1539
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 */
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
2648 ListBase *modifiers,
2649 bAction *action,
2650 const animrig::slot_handle_t slot_handle,
2651 const float evaltime,
2652 NlaEvalSnapshot *r_snapshot)
2653{
2654 action_idcode_patch_check(ptr->owner_id, action);
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,
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,
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
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,
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,
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 */
3052}
3053
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,
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
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
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
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
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)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
@ 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 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...
int main(int argc, char *argv[])
float nlastrip_get_frame(NlaStrip *strip, float cframe, short mode)
#define A
float evaltime
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
constexpr int64_t size() const
Definition BLI_span.hh:494
constexpr T * end() const
Definition BLI_span.hh:549
constexpr T * begin() const
Definition BLI_span.hh:545
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
#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
#define LOG(severity)
Definition log.h:33
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)
ccl_device_inline float4 mask(const int4 mask, const float4 a)
#define B
#define G(x, y, z)
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 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
void * data
Definition RNA_types.hh:42
PointerRNA * ptr
Definition wm_files.cc:4126
uint8_t flag
Definition wm_window.cc:138