Fix #110650: Drivers not removed if removing their container
This applies to modifiers, constraints and shape keys. Any driver on such data was not removed with it, leaving invalid drivers on objects. With this patch, the drivers are removed, but animation is left untouched. This is because animation might be reused somewhere else and we don't want to introduce potential side effects there. This also adds unit tests for the fixed cases Pull Request: https://projects.blender.org/blender/blender/pulls/134511
This commit is contained in:
committed by
Christoph Lendenfeld
parent
ba149680a2
commit
5100a80f7f
@@ -194,6 +194,68 @@ class ContextViewLayerDriverTest(AbstractEmptyDriverTest, unittest.TestCase):
|
||||
self.assertPropValue('test_fallback', 321)
|
||||
|
||||
|
||||
class SubDataDriverRemovalTest(AbstractEmptyDriverTest, unittest.TestCase):
|
||||
|
||||
def test_remove_object_modifier(self):
|
||||
# Removing a modifier with a driver should also delete the driver
|
||||
modifier = self.obj.modifiers.new("test", 'ARRAY')
|
||||
# No animation data means no drivers.
|
||||
self.assertEqual(self.obj.animation_data, None)
|
||||
self.obj.driver_add('modifiers["test"].count')
|
||||
self.assertEqual(len(self.obj.animation_data.drivers), 1)
|
||||
self.obj.modifiers.remove(modifier)
|
||||
self.assertEqual(len(self.obj.modifiers), 0)
|
||||
self.assertEqual(len(self.obj.animation_data.drivers), 0,
|
||||
"Removing the modifier should remove the driver on it")
|
||||
|
||||
def test_remove_object_constraint(self):
|
||||
# Using limit distance constraint because that has a property that can have a driver.
|
||||
constraint = self.obj.constraints.new('LIMIT_DISTANCE')
|
||||
constraint.name = "test"
|
||||
# No animation data means no drivers.
|
||||
self.assertEqual(self.obj.animation_data, None)
|
||||
self.obj.driver_add('constraints["test"].distance')
|
||||
self.assertEqual(len(self.obj.animation_data.drivers), 1)
|
||||
self.obj.constraints.remove(constraint)
|
||||
self.assertEqual(len(self.obj.constraints), 0)
|
||||
self.assertEqual(len(self.obj.animation_data.drivers), 0,
|
||||
"Removing the constraint should remove the driver on it")
|
||||
|
||||
def test_remove_bone_constraint(self):
|
||||
arm = bpy.data.armatures.new('Armature')
|
||||
arm_ob = bpy.data.objects.new('ArmObject', arm)
|
||||
bpy.context.scene.collection.objects.link(arm_ob)
|
||||
bpy.context.view_layer.objects.active = arm_ob
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
ebone = arm.edit_bones.new(name="test")
|
||||
ebone.tail = (1, 0, 0)
|
||||
bpy.ops.object.mode_set(mode='POSE')
|
||||
pose_bone = arm_ob.pose.bones["test"]
|
||||
constraint = pose_bone.constraints.new('LIMIT_DISTANCE')
|
||||
constraint.name = "test"
|
||||
self.assertEqual(len(pose_bone.constraints), 1)
|
||||
arm_ob.driver_add('pose.bones["test"].constraints["test"].distance')
|
||||
self.assertEqual(len(arm_ob.animation_data.drivers), 1)
|
||||
pose_bone.constraints.remove(constraint)
|
||||
self.assertEqual(len(pose_bone.constraints), 0)
|
||||
self.assertEqual(len(arm_ob.animation_data.drivers), 0,
|
||||
"Removing the constraint should remove the driver on it")
|
||||
|
||||
def test_remove_shapekey(self):
|
||||
self.obj.shape_key_add(name="base")
|
||||
test_key = self.obj.shape_key_add(name="test")
|
||||
# Due to the weirdness of shapekeys, this is an ID.
|
||||
shape_key_id = self.obj.data.shape_keys
|
||||
self.assertEqual(len(shape_key_id.key_blocks), 2)
|
||||
shape_key_id.driver_add('key_blocks["test"].value')
|
||||
self.assertEqual(len(shape_key_id.animation_data.drivers), 1)
|
||||
|
||||
self.obj.shape_key_remove(test_key)
|
||||
self.assertEqual(len(shape_key_id.key_blocks), 1)
|
||||
self.assertEqual(len(shape_key_id.animation_data.drivers), 0,
|
||||
"Removing the shape key should remove any driver on it")
|
||||
|
||||
|
||||
def main():
|
||||
global args
|
||||
import argparse
|
||||
|
||||
Reference in New Issue
Block a user