Anim: change RNA Action.id_root to have backwards-compatible behavior
Most of the old Animato properties on an Action (e.g. FCurve list, Channel Groups) already act as proxies for the data for the first slot in the first strip of the first layer. (Say that three times fast!) However, this was not yet the case for `Action.id_root`. This PR changes `Action.id_root` to act as a proxy for the first Slot's `target_id_type` property, both for reading and writing. If the Action has no Slots, then reading always returns 'UNSPECIFIED', and writing will create a Slot and set its `target_id_type`. Note that the ability to write to the first Slot's `target_id_type` via `Action.id_root` conflicts with `target_id_type` supposedly only being writable when it's still 'UNSPECIFIED' (#133883). Although that's certainly a little weird, practically speaking this doesn't break anything for now, and is a temporary kludge to keep `id_root` working until we can remove it in Blender 5.0. `id_root` will be removed entirely in 5.0, resolving this inconsistency. Pull Request: https://projects.blender.org/blender/blender/pulls/133823
This commit is contained in:
committed by
Nathan Vegdahl
parent
aa535f1a5f
commit
eda2f11f7a
@@ -324,7 +324,7 @@ class LegacyAPIOnLayeredActionTest(unittest.TestCase):
|
||||
- curve_frame_range
|
||||
- fcurves
|
||||
- groups
|
||||
- id_root (should always be 0 for layered Actions)
|
||||
- id_root
|
||||
- flip_with_pose(object)
|
||||
"""
|
||||
|
||||
@@ -450,6 +450,68 @@ class LegacyAPIOnLayeredActionTest(unittest.TestCase):
|
||||
|
||||
self.assertEqual([group], channelbag.groups[:])
|
||||
|
||||
def test_id_root_on_layered_action(self) -> None:
|
||||
# When there's at least one slot, action.id_root should simply act as a
|
||||
# proxy for the first slot's target_id_type. This should work for both
|
||||
# reading and writing.
|
||||
|
||||
slot_1 = self.action.slots.new('OBJECT', "Slot 1")
|
||||
slot_2 = self.action.slots.new('CAMERA', "Slot 2")
|
||||
bpy.data.objects['Cube'].animation_data_create()
|
||||
bpy.data.objects['Cube'].animation_data.action = self.action
|
||||
bpy.data.objects['Cube'].animation_data.action_slot = slot_1
|
||||
|
||||
self.assertEqual(self.action.id_root, 'OBJECT')
|
||||
self.assertEqual(self.action.slots[0].target_id_type, 'OBJECT')
|
||||
self.assertEqual(self.action.slots[0].identifier, 'OBSlot 1')
|
||||
self.assertEqual(self.action.slots[1].target_id_type, 'CAMERA')
|
||||
self.assertEqual(self.action.slots[1].identifier, 'CASlot 2')
|
||||
self.assertEqual(bpy.data.objects['Cube'].animation_data.last_slot_identifier, 'OBSlot 1')
|
||||
|
||||
self.action.id_root = 'MATERIAL'
|
||||
|
||||
self.assertEqual(self.action.id_root, 'MATERIAL')
|
||||
self.assertEqual(self.action.slots[0].target_id_type, 'MATERIAL')
|
||||
self.assertEqual(self.action.slots[0].identifier, 'MASlot 1')
|
||||
self.assertEqual(self.action.slots[1].target_id_type, 'CAMERA')
|
||||
self.assertEqual(self.action.slots[1].identifier, 'CASlot 2')
|
||||
self.assertEqual(bpy.data.objects['Cube'].animation_data.last_slot_identifier, 'MASlot 1')
|
||||
|
||||
def test_id_root_on_layered_action_for_identifier_uniqueness(self) -> None:
|
||||
# When setting id_root such that the first slot's identifier would
|
||||
# become a duplicate, the name portion of the identifier should be
|
||||
# automatically renamed to be unique.
|
||||
|
||||
slot_1 = self.action.slots.new('OBJECT', "Foo")
|
||||
slot_2 = self.action.slots.new('CAMERA', "Foo")
|
||||
|
||||
self.assertEqual(self.action.id_root, 'OBJECT')
|
||||
self.assertEqual(self.action.slots[0].target_id_type, 'OBJECT')
|
||||
self.assertEqual(self.action.slots[0].identifier, 'OBFoo')
|
||||
self.assertEqual(self.action.slots[1].target_id_type, 'CAMERA')
|
||||
self.assertEqual(self.action.slots[1].identifier, 'CAFoo')
|
||||
|
||||
self.action.id_root = 'CAMERA'
|
||||
|
||||
self.assertEqual(self.action.id_root, 'CAMERA')
|
||||
self.assertEqual(self.action.slots[0].target_id_type, 'CAMERA')
|
||||
self.assertEqual(self.action.slots[0].identifier, 'CAFoo.001')
|
||||
self.assertEqual(self.action.slots[1].target_id_type, 'CAMERA')
|
||||
self.assertEqual(self.action.slots[1].identifier, 'CAFoo')
|
||||
|
||||
def test_id_root_on_empty_action(self) -> None:
|
||||
# When there are no slots, setting action.id_root should create a legacy
|
||||
# slot and set its target_id_type.
|
||||
|
||||
self.assertEqual(self.action.id_root, 'UNSPECIFIED')
|
||||
self.assertEqual(len(self.action.slots), 0)
|
||||
|
||||
self.action.id_root = 'OBJECT'
|
||||
|
||||
self.assertEqual(self.action.id_root, 'OBJECT')
|
||||
self.assertEqual(len(self.action.slots), 1)
|
||||
self.assertEqual(self.action.slots[0].target_id_type, 'OBJECT')
|
||||
|
||||
|
||||
class ChannelbagsTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
|
||||
Reference in New Issue
Block a user