From 33b9d54abb02747c74fac3e44b1d0837fcfec2c5 Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Tue, 4 Feb 2025 17:39:03 +0100 Subject: [PATCH] Anim: add RNA `Channelbag.slot` property This allows Python scripts to easily determine what Slot a Channelbag is for. This is particularly important because we're trying to discourage the use of Slot handles in the Python APIs, and before this the only way to identify which Slot a Channelbag was for was via the Channelbag's `slot_handle` property. Pull Request: https://projects.blender.org/blender/blender/pulls/134053 --- source/blender/makesrna/intern/rna_action.cc | 16 ++++++++++++++++ tests/python/bl_animation_action.py | 20 ++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/source/blender/makesrna/intern/rna_action.cc b/source/blender/makesrna/intern/rna_action.cc index 32f59dac25c..823e9117ff0 100644 --- a/source/blender/makesrna/intern/rna_action.cc +++ b/source/blender/makesrna/intern/rna_action.cc @@ -601,6 +601,16 @@ static std::optional rna_Channelbag_path(const PointerRNA *ptr) return std::nullopt; } +static PointerRNA rna_Channelbag_slot_get(PointerRNA *ptr) +{ + animrig::Action &action = rna_action(ptr); + animrig::Channelbag &channelbag = rna_data_channelbag(ptr); + animrig::Slot *slot = action.slot_for_handle(channelbag.slot_handle); + BLI_assert(slot); + + return rna_pointer_inherit_refine(ptr, &RNA_ActionSlot, slot); +} + static void rna_iterator_Channelbag_fcurves_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { @@ -2493,6 +2503,12 @@ static void rna_def_action_channelbag(BlenderRNA *brna) prop = RNA_def_property(srna, "slot_handle", PROP_INT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); + prop = RNA_def_property(srna, "slot", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "ActionSlot"); + RNA_def_property_ui_text(prop, "Slot", "The Slot that the Channelbag's animation data is for"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_pointer_funcs(prop, "rna_Channelbag_slot_get", nullptr, nullptr, nullptr); + /* Channelbag.fcurves */ prop = RNA_def_property(srna, "fcurves", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_funcs(prop, diff --git a/tests/python/bl_animation_action.py b/tests/python/bl_animation_action.py index 7f1af80544d..19072174418 100644 --- a/tests/python/bl_animation_action.py +++ b/tests/python/bl_animation_action.py @@ -559,6 +559,7 @@ class ChannelbagsTest(unittest.TestCase): self.strip.key_insert(self.slot, "location", 1, 47.0, 327.0) self.assertEqual("location", channelbag.fcurves[0].data_path, "Keys for the channelbag's slot should go into the channelbag") + self.assertEqual(self.slot, channelbag.slot) self.strip.channelbags.remove(channelbag) self.assertEqual([], list(self.strip.channelbags)) @@ -570,6 +571,7 @@ class ChannelbagsTest(unittest.TestCase): channelbag = self.strip.channelbag(self.slot, ensure=True) self.assertEqual([channelbag], list(self.strip.channelbags)) + self.assertEqual(self.slot, channelbag.slot) def test_create_remove_fcurves(self): channelbag = self.strip.channelbags.new(self.slot) @@ -676,6 +678,24 @@ class ChannelbagsTest(unittest.TestCase): self.assertEquals([fcurve5, fcurve3], group1.channels[:]) self.assertEquals([fcurve5, fcurve3, fcurve2, fcurve4, fcurve0, fcurve1], channelbag.fcurves[:]) + def test_channelbag_slot_properties(self): + slot_1 = self.slot + slot_2 = self.action.slots.new('MATERIAL', "Test2") + slot_3 = self.action.slots.new('CAMERA', "Test3") + + channelbag_1 = self.strip.channelbags.new(slot_1) + channelbag_2 = self.strip.channelbags.new(slot_2) + channelbag_3 = self.strip.channelbags.new(slot_3) + + self.assertEqual(slot_1.handle, channelbag_1.slot_handle) + self.assertEqual(slot_1, channelbag_1.slot) + + self.assertEqual(slot_2.handle, channelbag_2.slot_handle) + self.assertEqual(slot_2, channelbag_2.slot) + + self.assertEqual(slot_3.handle, channelbag_3.slot_handle) + self.assertEqual(slot_3, channelbag_3.slot) + class DataPathTest(unittest.TestCase): def setUp(self):