From 62c21a0800a59de3acd455b48b35311d1b9cb210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Fri, 14 Feb 2025 13:55:44 +0100 Subject: [PATCH] Fix: NLA Track Solo flag handling, in depsgraph and F-Curve iteration This fixes the (unreported) issue where solo'ing an NLA track would only play back animation when _any_ of the tracks were unmuted. Some code considered a track to be muted when its `NLATRACK_MUTED` flag was set regardless of the `NLATRACK_SOLO` flag, whereas other code did consider the `NLATRACK_SOLO` flag. Now all the code is consistent with what actual animation evaluation is doing. Pull Request: https://projects.blender.org/blender/blender/pulls/134500 --- source/blender/blenkernel/BKE_nla.hh | 8 +++++ source/blender/blenkernel/intern/anim_data.cc | 2 +- source/blender/blenkernel/intern/anim_sys.cc | 32 ++----------------- source/blender/blenkernel/intern/nla.cc | 9 ++++++ .../intern/builder/deg_builder_nodes.cc | 3 +- .../intern/builder/deg_builder_relations.cc | 3 +- 6 files changed, 25 insertions(+), 32 deletions(-) diff --git a/source/blender/blenkernel/BKE_nla.hh b/source/blender/blenkernel/BKE_nla.hh index 4ce39b5cdda..cc064fe6734 100644 --- a/source/blender/blenkernel/BKE_nla.hh +++ b/source/blender/blenkernel/BKE_nla.hh @@ -141,6 +141,14 @@ void BKE_nlatrack_remove(ListBase *tracks, NlaTrack *nlt); */ void BKE_nlatrack_remove_and_free(ListBase *tracks, NlaTrack *nlt, bool do_id_user); +/** + * Return whether this NLA track is enabled. + * + * If any track is solo'ed: returns true when this is the solo'ed one. + * If no track is solo'ed: returns true when this track is not muted. + */ +bool BKE_nlatrack_is_enabled(const AnimData &adt, const NlaTrack &nlt); + /** * Compute the length of the passed strip's clip, unless the clip length * is zero in which case a non-zero value is returned. diff --git a/source/blender/blenkernel/intern/anim_data.cc b/source/blender/blenkernel/intern/anim_data.cc index 45a2a0614ce..fb1052bba08 100644 --- a/source/blender/blenkernel/intern/anim_data.cc +++ b/source/blender/blenkernel/intern/anim_data.cc @@ -1272,7 +1272,7 @@ static void adt_apply_all_fcurves_cb(ID *id, /* NLA Data - Animation Data for Strips */ LISTBASE_FOREACH (NlaTrack *, nlt, &adt->nla_tracks) { - if (nlt->flag & NLATRACK_MUTED) { + if (!BKE_nlatrack_is_enabled(*adt, *nlt)) { continue; } nlastrips_apply_all_curves_cb(id, &nlt->strips, func); diff --git a/source/blender/blenkernel/intern/anim_sys.cc b/source/blender/blenkernel/intern/anim_sys.cc index 568f99ee36d..3c6b83979b6 100644 --- a/source/blender/blenkernel/intern/anim_sys.cc +++ b/source/blender/blenkernel/intern/anim_sys.cc @@ -3200,21 +3200,9 @@ static void animsys_evaluate_nla_domain(PointerRNA *ptr, NlaEvalData *channels, /* NLA Data - Animation Data for Strips */ LISTBASE_FOREACH (NlaTrack *, nlt, &adt->nla_tracks) { - /* solo and muting are mutually exclusive... */ - if (adt->flag & ADT_NLA_SOLO_TRACK) { - /* skip if there is a solo track, but this isn't it */ - if ((nlt->flag & NLATRACK_SOLO) == 0) { - continue; - } - /* else - mute doesn't matter */ + if (!BKE_nlatrack_is_enabled(*adt, *nlt)) { + continue; } - else { - /* no solo tracks - skip track if muted */ - if (nlt->flag & NLATRACK_MUTED) { - continue; - } - } - nla_eval_domain_strips(ptr, channels, &nlt->strips, touched_actions); } @@ -3325,21 +3313,7 @@ static bool is_nlatrack_evaluatable(const AnimData *adt, const NlaTrack *nlt) return false; } - /* Solo and muting are mutually exclusive. */ - if (adt->flag & ADT_NLA_SOLO_TRACK) { - /* Skip if there is a solo track, but this isn't it. */ - if ((nlt->flag & NLATRACK_SOLO) == 0) { - return false; - } - } - else { - /* Skip track if muted. */ - if (nlt->flag & NLATRACK_MUTED) { - return false; - } - } - - return true; + return BKE_nlatrack_is_enabled(*adt, *nlt); } /** diff --git a/source/blender/blenkernel/intern/nla.cc b/source/blender/blenkernel/intern/nla.cc index 365bb520261..1b39f070c5e 100644 --- a/source/blender/blenkernel/intern/nla.cc +++ b/source/blender/blenkernel/intern/nla.cc @@ -667,6 +667,15 @@ void BKE_nlatrack_remove_and_free(ListBase *tracks, NlaTrack *nlt, bool do_id_us BKE_nlatrack_free(nlt, do_id_user); } +bool BKE_nlatrack_is_enabled(const AnimData &adt, const NlaTrack &nlt) +{ + if (adt.flag & ADT_NLA_SOLO_TRACK) { + return (nlt.flag & NLATRACK_SOLO); + } + + return !(nlt.flag & NLATRACK_MUTED); +} + /* *************************************************** */ /* NLA Evaluation <-> Editing Stuff */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 572777e98d1..59e61030410 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -77,6 +77,7 @@ #include "BKE_mesh.hh" #include "BKE_modifier.hh" #include "BKE_movieclip.h" +#include "BKE_nla.hh" #include "BKE_node.hh" #include "BKE_node_runtime.hh" #include "BKE_object.hh" @@ -1253,7 +1254,7 @@ void DepsgraphNodeBuilder::build_animdata(ID *id) } /* NLA strips contain actions. */ LISTBASE_FOREACH (NlaTrack *, nlt, &adt->nla_tracks) { - if (nlt->flag & NLATRACK_MUTED) { + if (!BKE_nlatrack_is_enabled(*adt, *nlt)) { continue; } build_animdata_nlastrip_targets(&nlt->strips); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index f72458bbff7..05154ef674f 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -75,6 +75,7 @@ #include "BKE_material.hh" #include "BKE_mball.hh" #include "BKE_modifier.hh" +#include "BKE_nla.hh" #include "BKE_node.hh" #include "BKE_node_runtime.hh" #include "BKE_object.hh" @@ -1616,7 +1617,7 @@ void DepsgraphRelationBuilder::build_animdata_curves(ID *id) build_animdata_action_targets(id, adt->slot_handle, adt_key, operation_from, adt->action); } LISTBASE_FOREACH (NlaTrack *, nlt, &adt->nla_tracks) { - if (nlt->flag & NLATRACK_MUTED) { + if (!BKE_nlatrack_is_enabled(*adt, *nlt)) { continue; } build_animdata_nlastrip_targets(id, adt_key, operation_from, &nlt->strips);