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