Anim: make RNA property bone_collection.parent writable

Moving a bone collection to another parent is now possible in Python by
assigning to `bone_collection.parent`.

Thanks to Sergey for the implementation.
This commit is contained in:
Sybren A. Stüvel
2024-01-04 15:33:18 +01:00
parent b165b20cef
commit 29be81ec23
2 changed files with 62 additions and 2 deletions

View File

@@ -266,6 +266,34 @@ static PointerRNA rna_BoneCollection_parent_get(PointerRNA *ptr)
return RNA_pointer_create(&arm->id, &RNA_BoneCollection, parent);
}
static void rna_BoneCollection_parent_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *reports)
{
using namespace blender::animrig;
BoneCollection *self = (BoneCollection *)ptr->data;
BoneCollection *to_parent = (BoneCollection *)value.data;
bArmature *armature = (bArmature *)ptr->owner_id;
const int from_bcoll_index = armature_bonecoll_find_index(armature, self);
const int from_parent_index = armature_bonecoll_find_parent_index(armature, from_bcoll_index);
const int to_parent_index = armature_bonecoll_find_index(armature, to_parent);
if (to_parent_index == from_bcoll_index ||
armature_bonecoll_is_decendent_of(armature, from_bcoll_index, to_parent_index))
{
BKE_report(reports, RPT_ERROR, "Cannot make a bone collection a decendent of itself");
return;
}
armature_bonecoll_move_to_parent(
armature, from_bcoll_index, -1, from_parent_index, to_parent_index);
WM_main_add_notifier(NC_OBJECT | ND_BONE_COLLECTION, nullptr);
}
static int rna_BoneCollections_active_index_get(PointerRNA *ptr)
{
bArmature *arm = (bArmature *)ptr->data;
@@ -2269,8 +2297,9 @@ static void rna_def_bonecollection(BlenderRNA *brna)
prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "BoneCollection");
RNA_def_property_pointer_funcs(prop, "rna_BoneCollection_parent_get", nullptr, nullptr, nullptr);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_pointer_funcs(
prop, "rna_BoneCollection_parent_get", "rna_BoneCollection_parent_set", nullptr, nullptr);
RNA_def_property_ui_text(prop,
"Parent",
"Parent bone collection. Note that accessing this requires a scan of "

View File

@@ -111,6 +111,37 @@ class BoneCollectionTest(unittest.TestCase):
# Check the array order.
self.assertEqual([root1, r1_child1, root2, r1_child1_001, r2_child1, r2_child2], list(bcolls.all))
def test_parent_property(self):
# Just to keep the rest of the code shorter.
bcolls = self.arm.collections
self.assertEqual([], list(bcolls), "By default an Armature should have no collections")
# Build a hierarchy.
root1 = bcolls.new('root1')
r1_child1 = bcolls.new('r1_child1', parent=root1)
r1_child2 = bcolls.new('r1_child2', parent=root1)
root2 = bcolls.new('root2')
r2_child1 = bcolls.new('r2_child1', parent=root2)
r2_child2 = bcolls.new('r2_child2', parent=root2)
# Check getting the parent.
self.assertEqual(root1, r1_child1.parent)
self.assertEqual(root1, r1_child2.parent)
self.assertEqual(root2, r2_child1.parent)
self.assertEqual(root2, r2_child2.parent)
# Move r1_child1 to be a child of root2 by assigning the parent.
r1_child1.parent = root2
self.assertEqual(root2, r1_child1.parent)
# Check the sibling order.
self.assertEqual([r2_child1, r2_child2, r1_child1], list(root2.children))
# Make r1_child1 a root.
r1_child1.parent = None
self.assertIsNone(r1_child1.parent)
def test_bone_collection_bones(self):
# Build a hierarchy on the armature.
bcolls = self.arm.collections