Anim: add ensure parameter to KeyframeStrip.channels(...) RNA function

Add `ensure` boolean parameter to the `ActionKeyframeStrip.channels()` RNA
function. Passing `ensure=True` will ensure the channelbag for the given
action slot handle exists. This makes it more straight-forward to create
F-Curves for a slot regardless of whether there already was a channelbag
for those F-Cuves:

```python
strip = action.layers[0].strips[0]
slot = action.slots[0]

# Old:
channelbag = strip.channels(slot.handle)
if not channelbag:
    channelbag = strip.channelbags.new(action_slot)
ob_loc_x = channelbag.fcurves.new('location', index=0)

# New:
channelbag = strip.channels(slot.handle, ensure=True)
ob_loc_x = channelbag.fcurves.new('location', index=0)
```

Pull Request: https://projects.blender.org/blender/blender/pulls/133678
This commit is contained in:
Sybren A. Stüvel
2025-01-31 15:16:10 +01:00
parent 7f5c803a8b
commit 815337a7da
4 changed files with 23 additions and 3 deletions
+1
View File
@@ -971,6 +971,7 @@ class StripKeyframeData : public ::ActionStripKeyframeData {
* Find the channelbag for the given slot, or if none exists, create it.
*/
Channelbag &channelbag_for_slot_ensure(const Slot &slot);
Channelbag &channelbag_for_slot_ensure(slot_handle_t slot_handle);
/**
* Remove the given channelbag from this strip data.
+7 -2
View File
@@ -1774,11 +1774,16 @@ Channelbag &StripKeyframeData::channelbag_for_slot_add(const slot_handle_t slot_
Channelbag &StripKeyframeData::channelbag_for_slot_ensure(const Slot &slot)
{
Channelbag *channelbag = this->channelbag_for_slot(slot);
return this->channelbag_for_slot_ensure(slot.handle);
}
Channelbag &StripKeyframeData::channelbag_for_slot_ensure(const slot_handle_t slot_handle)
{
Channelbag *channelbag = this->channelbag_for_slot(slot_handle);
if (channelbag != nullptr) {
return *channelbag;
}
return this->channelbag_for_slot_add(slot);
return this->channelbag_for_slot_add(slot_handle);
}
static void channelbag_ptr_destructor(ActionChannelbag **dna_channelbag_ptr)
+11 -1
View File
@@ -721,10 +721,15 @@ static void rna_Channelbag_group_remove(ActionChannelbag *dna_channelbag,
static ActionChannelbag *rna_ActionStrip_channels(ID *dna_action_id,
ActionStrip *self,
const animrig::slot_handle_t slot_handle)
const animrig::slot_handle_t slot_handle,
const bool ensure)
{
animrig::Action &action = reinterpret_cast<bAction *>(dna_action_id)->wrap();
animrig::StripKeyframeData &strip_data = self->wrap().data<animrig::StripKeyframeData>(action);
if (ensure) {
return &strip_data.channelbag_for_slot_ensure(slot_handle);
}
return strip_data.channelbag_for_slot(slot_handle);
}
@@ -2233,6 +2238,11 @@ static void rna_def_action_keyframe_strip(BlenderRNA *brna)
0,
INT_MAX);
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
RNA_def_boolean(func,
"ensure",
false,
"Create if necessary",
"Ensure the channelbag exists for this slot handle, creating it if necessary");
parm = RNA_def_pointer(func, "channels", "ActionChannelbag", "Channels", "");
RNA_def_function_return(func, parm);
+4
View File
@@ -395,6 +395,10 @@ class ChannelbagsTest(unittest.TestCase):
self.strip.channelbags.remove(channelbag)
self.assertEqual([], list(self.strip.channelbags))
def test_ensure_channelbag(self):
channelbag = self.strip.channels(self.slot.handle, ensure=True)
self.assertEqual([channelbag], list(self.strip.channelbags))
def test_create_remove_fcurves(self):
channelbag = self.strip.channelbags.new(self.slot)