0
import bpy

ob = bpy.data.objects
child = ob['cube']
parent = ob['armature']
bone = parent.pose.bones['bone']

child.parent = parent
child.parent_type = 'BONE'
child.parent_bone = bone

I wrote the script above to carry out bone parenting with Python.
The parenting setting works correctly, but at the end, the child object's transformation will have an offset.
How can I achieve bone parenting without offset?


Additional questions about batFINGER's answers.
I tested the script. But I still get the offset. Did I make a mistake?
I recorded two GIF to clarify the question.
In the case of the parenting using operator, the cube's transform is maintained, but in the case of parenting using script, the cube's transform changed.

Bone parenting using operator Bone Parenting by Operator

Bone parenting using script Bone Parenting by Script


  1. After creating an armature, change the bone transforms in pose mode.
  2. Operate bone parenting with cube & bone of armature.
  3. The ops method keeps the cube in place, but the script method changes the cube by the bone transform
  4. I want to achieve ops result using python script.

Result by ops (Ctrl+P/Bone after select cube and armature) enter image description here

Result by script enter image description here

J. SungHoon
  • 2,196
  • 11
  • 36
  • 1
    Could you please clarify.... is this a dupe of https://blender.stackexchange.com/questions/112776/parent-object-to-a-bone-and-object-becomes-offsets-how-do-i-prevent-object-from Answered below based on my understanding of no offset resulting in child at the origin of parent when location is (0,0,0) . In the link posted OP sees "no offset" as the object not moving when the parent is set. – batFINGER Sep 17 '20 at 14:51

1 Answers1

3

Set basis and parent inverse to identity.

One of the simplest ways to do this is to set both the basis matrix and parent inverse matrix to identity, to ensure all transforms are those inherited directly.

Getting no feedback re what parenting "without offset" is, have included link to https://blender.stackexchange.com/a/112856/15543 which has a number of methods to parent, either keeping current global location, (the operator result in question EDIT) or snapping to the transform of the parent as shown here..

The confusion is over the term offset. Code below puts an object at its parents transform with no "offset" from it, no local transforms.

Parenting, while maintaining the object in place, could be considered as setting the offset from child to parent, before parenting. If turned on relationship lines are a visual rep'n of the parent to child offset.

Code below is same as 'SNAP_IDENTITY'

import bpy
from mathutils import Matrix

ob = bpy.data.objects child = ob['Cube'] parent = ob['Armature'] bone = parent.pose.bones['Bone']

child.parent = parent child.parent_type = 'BONE' child.parent_bone = bone.name

child.matrix_basis = Matrix() child.matrix_parent_inverse = Matrix()

Please also notice that the parent bone setting requires the name of the bone, not the bone itself.

batFINGER
  • 84,216
  • 10
  • 108
  • 233
  • I tested the code and wrote the additional content. Please check. – J. SungHoon Sep 22 '20 at 03:46
  • IMO What is still unclear is which is the one you want. The script posted in link does both. AFAIC in the new examples given the parent with operator is keeping offset, parenting with identity (as above) is with no offset. – batFINGER Sep 22 '20 at 03:51
  • I'm sorry. I'm trying to explain my intentions. I added a new image and work order. Still, isn't it clear what I'm trying to achieve? – J. SungHoon Sep 22 '20 at 05:14
  • Have marked as dupe. – batFINGER Sep 22 '20 at 05:32
  • I went to dupe and tried the script suggested as a solution, but the result was the same. The cube doesn't keep its transform and follow along the slope of the bone :( – J. SungHoon Sep 22 '20 at 05:43
  • 1
    If you mean my script then change type of parenting desired from 'SNAP' to 'KEEP_WORLD_AND_BASIS' (Have done this for you just in case there are more issues) to (as mentioned in the answer "Blenders default parenting would be akin to 'KEEP_WORLD_AND_BASIS' below") match using the operator Ie the object not move when parented or reparented. – batFINGER Sep 22 '20 at 05:55
  • It works very well now when the code on line 49 is modified from If op == "KEEP": to if op ==" KEEP_WORLD_AND_BASIS":. – J. SungHoon Sep 22 '20 at 06:09
  • The idea is to use op = 'KEEP' for that option. And take note of different options. Everything has been explained here and there. The result gif in question is exactly as expected. The cube, once parented has no offset from parent. As noted here same as 'SNAP_IDENTITY' there. After running it with 'SNAP' you comment to say its the same as 'SNAP_IDENTITY' above.. once again expected. The answer there clearly states if you wish to have a result like default parenting use 'KEEP_WORLD_AND_BASIS'.. (reiterated in comment) ... Please in future read questions and comments more thoroughly. – batFINGER Sep 22 '20 at 07:19