From 6b75fe76580fc53d52b7e45e4e0c07457721936a Mon Sep 17 00:00:00 2001 From: Falk David Date: Mon, 6 Oct 2025 12:17:17 +0200 Subject: [PATCH] Fix #147106: VSE: Show keyframes of compositor node trees in dopesheet Any keyframes for properties inside the compositor node trees that were used by strips did not show up in the dopesheet. This was because the compositor tree is its own ID and needs to be manually added by the dopesheet code. This fix adds the node trees to the filtering code in `animdata_filter_dopesheet_scene`. Note that the dopesheet still uses the active scene as its context. So this means that if the sequencer scene differes from the active scene, the animation data from the sequencer scene will not be shown. This is currently expected behavior. Pull Request: https://projects.blender.org/blender/blender/pulls/147301 --- source/blender/blenkernel/intern/scene.cc | 2 ++ .../blender/editors/animation/anim_filter.cc | 20 +++++++++++++++++++ source/blender/sequencer/SEQ_modifier.hh | 6 ++++++ .../sequencer/intern/modifiers/modifier.cc | 15 ++++++++++++++ 4 files changed, 43 insertions(+) diff --git a/source/blender/blenkernel/intern/scene.cc b/source/blender/blenkernel/intern/scene.cc index d56ff37a098..f33f1ab5792 100644 --- a/source/blender/blenkernel/intern/scene.cc +++ b/source/blender/blenkernel/intern/scene.cc @@ -807,6 +807,8 @@ static bool strip_foreach_member_id_cb(Strip *strip, void *user_data) IDP_foreach_property(strip->system_properties, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) { BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data); }); + /* TODO: This could use `seq::foreach_strip_modifier_id`, but because `FOREACHID_PROCESS_IDSUPER` + * doesn't take IDs but "ID supers", it makes it a bit more cumbersome. */ LISTBASE_FOREACH (StripModifierData *, smd, &strip->modifiers) { FOREACHID_PROCESS_IDSUPER(data, smd->mask_id, IDWALK_CB_USER); if (smd->type == eSeqModifierType_Compositor) { diff --git a/source/blender/editors/animation/anim_filter.cc b/source/blender/editors/animation/anim_filter.cc index 05af9923b33..84b466148c2 100644 --- a/source/blender/editors/animation/anim_filter.cc +++ b/source/blender/editors/animation/anim_filter.cc @@ -88,6 +88,8 @@ #include "ED_anim_api.hh" #include "ED_markers.hh" +#include "SEQ_iterator.hh" +#include "SEQ_modifier.hh" #include "SEQ_sequencer.hh" #include "SEQ_utils.hh" @@ -3444,6 +3446,7 @@ static size_t animdata_filter_dopesheet_scene(bAnimContext *ac, BEGIN_ANIMFILTER_SUBCHANNELS (EXPANDED_SCEC(sce)) { bNodeTree *ntree = sce->compositing_node_group; World *wo = sce->world; + Editing *ed = sce->ed; /* Action, Drivers, or NLA for Scene */ if ((ac->ads->filterflag & ADS_FILTER_NOSCE) == 0) { @@ -3461,6 +3464,23 @@ static size_t animdata_filter_dopesheet_scene(bAnimContext *ac, ac, &tmp_data, reinterpret_cast(sce), ntree, filter_mode); } + /* Strip modifier node trees. */ + if (ed && !(ac->ads->filterflag & ADS_FILTER_NONTREE)) { + VectorSet node_trees; + seq::for_each_callback(&ed->seqbase, [&](Strip *strip) { + seq::foreach_strip_modifier_id(strip, [&](ID *id) { + if (GS(id->name) == ID_NT) { + node_trees.add(id); + } + }); + return true; + }); + for (ID *node_tree : node_trees) { + tmp_items += animdata_filter_ds_nodetree( + ac, &tmp_data, &sce->id, reinterpret_cast(node_tree), filter_mode); + } + } + /* line styles */ if ((ac->ads->filterflag & ADS_FILTER_NOLINESTYLE) == 0) { tmp_items += animdata_filter_ds_linestyle(ac, &tmp_data, sce, filter_mode); diff --git a/source/blender/sequencer/SEQ_modifier.hh b/source/blender/sequencer/SEQ_modifier.hh index df04dd9ce0c..a4b884e930a 100644 --- a/source/blender/sequencer/SEQ_modifier.hh +++ b/source/blender/sequencer/SEQ_modifier.hh @@ -8,6 +8,8 @@ * \ingroup sequencer */ +#include "BLI_function_ref.hh" + #include "DNA_sequence_types.h" struct ARegionType; @@ -17,6 +19,7 @@ struct ImBuf; struct ListBase; struct Strip; struct StripModifierData; +struct ID; namespace blender::seq { @@ -100,4 +103,7 @@ void modifier_set_active(Strip *strip, StripModifierData *smd); static constexpr char STRIP_MODIFIER_TYPE_PANEL_PREFIX[] = "STRIPMOD_PT_"; void modifier_type_panel_id(eStripModifierType type, char *r_idname); +/* Iterate over all the modifiers and call the callback function for every referenced ID. */ +void foreach_strip_modifier_id(Strip *strip, const FunctionRef fn); + } // namespace blender::seq diff --git a/source/blender/sequencer/intern/modifiers/modifier.cc b/source/blender/sequencer/intern/modifiers/modifier.cc index 085c0aaa8ff..36d72f67779 100644 --- a/source/blender/sequencer/intern/modifiers/modifier.cc +++ b/source/blender/sequencer/intern/modifiers/modifier.cc @@ -621,6 +621,21 @@ void modifier_type_panel_id(eStripModifierType type, char *r_idname) r_idname, sizeof(PanelType::idname), STRIP_MODIFIER_TYPE_PANEL_PREFIX, mti->idname); } +void foreach_strip_modifier_id(Strip *strip, const FunctionRef fn) +{ + LISTBASE_FOREACH (StripModifierData *, smd, &strip->modifiers) { + if (smd->mask_id) { + fn(reinterpret_cast(smd->mask_id)); + } + if (smd->type == eSeqModifierType_Compositor) { + auto *modifier_data = reinterpret_cast(smd); + if (modifier_data->node_group) { + fn(reinterpret_cast(modifier_data->node_group)); + } + } + } +} + /** \} */ /* -------------------------------------------------------------------- */