8
$\begingroup$

I have automated the task of parenting in Blender with Python. The code affects the relation parent according to the two last characters of the names of the objects. example:

obj1.name = Cube.01
obj2.name = Suzanne.01

If obj1 is in the group "children" and obj2 is not in the group "children" : obj2 is the parent of obj1. My code works, but without keeping children's transformation. How can I do to keep the children's transformation?

import bpy

for obj1 in bpy.context.selected_objects:    
    if obj1.name in  bpy.data.groups["Children"].objects:
    a = obj1.name[-2:]

    for obj2 in bpy.context.selected_objects:
            if obj2.name not in  bpy.data.groups["Children"].objects:
                b = obj2.name[-2:]
                if a == b:                       
                   obj1.parent= obj2
$\endgroup$

3 Answers 3

19
$\begingroup$

You have to set the inverse matrix of the child to clear the initial transformation of the parent at parenting moment :

obj1.parent= obj2
obj1.matrix_parent_inverse = obj2.matrix_world.inverted()
$\endgroup$
2
  • $\begingroup$ This doesn't seem to work for clearing the scale. Any thoughts on how to do that? $\endgroup$ Commented Aug 16, 2022 at 22:04
  • $\begingroup$ this will not keep transform, at least in blender 3.1 when your parent is a curve. if you find the solution could you please post it here blender.stackexchange.com/questions/273079/… $\endgroup$
    – Harry McKenzie
    Commented Aug 27, 2022 at 2:18
3
$\begingroup$

An additional note to Chebhou's answer and for other community members searching for answers related to keeping the child's transform when the parent object is a Curve. The solution comes from this thread: If your parent object is a Curve, you need to set the use_path property of the curve's data to False.

curve.data.use_path = False
obj.parent = curve
obj.matrix_parent_inverse = curve.matrix_world.inverted()
$\endgroup$
1
$\begingroup$

I tried Chebhou's method but it didn't work as expected. To keep an object's position, rotation, and scale unchanged when changing its parent, you need to multiply the new parent's inverse matrix with the object's world matrix. This ensures the object maintains its world space transform after reparenting.

    # First, calculate the inverse of the parent's world matrix
    parent_inverse_world_matrix = parent.matrix_world.inverted()

    # Now, set the parent 
    obj.parent = parent
    
    obj.matrix_parent_inverse =  parent_inverse_world_matrix @ obj.matrix_world
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .