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