I need to modify an armature so each parent bone which has only one child bone will connect to it (it’s tip would move to the child bones base and merge). How would you do that? I failed after hours of trying.
PS: using 2.4.x API.
what I have so far:
for i in skeleton.bones.keys():
if len(skeleton.bones[i].getAllChildren()) < 2:
# children not available for editBone for whatever reason
child = skeleton.bones[i].children[0]
skeleton.makeEditable()
skeleton.bones[i].tail = skeleton.bones[child.name].head
skeleton.bones[i].options = [Blender.Armature.CONNECTED]
skeleton.update()
Is a difficult question because I do not exactly understand what you want. But you can do the following:
Read out all the bones Matricies in Armaturespace and write them to a dictionary.
Append a childlist as well. Then rebuild the Skeleton by unparenting all the bones, setting the ArmSpaceMat.translationPart() as the head Position
and applying the childs ArmSpaceMat.translationPart() (while len(childlist) == 1) as the tail position of your bone. Then redo the parenting. Hope it helps.
for bone in skeleton.bones:
if len(yourchildlist) == 1:
skeleton.makeEditable()
skeleton.bones[yourchildlist[0]].parent = skeleton.bones[bone]
skeleton.update()
if you know the parent:
for bone in skeleton.bones:
parent = yourparentbonename # where ever you get it from
skeleton.makeEditable()
skeleton.bones[bone].parent = skeleton.bones[parent]
skeleton.update()
If you work with bones you have to connect the child to its parent and not as it seems logic the parent to its child.
I need to connect parent to child, which means “connect parent tip to the child’s head”. Its the usual case. If you extrude one bone from another, thats what happens, and you usually build your armature like that.
Is that what you meant?
You have to connect the childbone to the parentbone. That does not mean “connect” parent tip to childs head. It only means connect one bone to another where it doesn’t matter how the bone is oriented. If you have your skeleton done, you can set the parents tail position to the first childs head position to make your armature look fine. Thats what I told you in the first reply. Apply the first childs headposition to the parent bone’s tail position before you connect your bones. You can get the headposition with
what?
No, I don’t want to connect the childbone to parentbone, I need to connect the parentbone to the childbone (as in what I explained above). Open Blender, make an armature with 2 bones, click one bone and then the other, press Ctrl + P, choose “Connected”. The childbone will move to the paren bone’s position. And thats obviously not what I want.
And I don’t connect a parent to its first child, if parent has more than 1 child, it should not connect to anything.
Thats not how it works if you use python. In python you have to choose the bone that its child and have to tell em witch parent that it hase. There is no other method. There some differences between the way you build up your armature manualy and the way it is done with python. If you work with ordinary “Objects” the method “Hey! I’m the parent of these other Objects” is right. But if you work with armatures you have to tell a bone who is its parent. Telling it who is its child is not implemented in python.
Well yeah, I know that you can’t access a child of EditBone, unlike (object) Bone, for whatever reason. Thats why Im in object mode in my example snippet when getting a handle to the child bone and then switch to edit mode.
Did you try out my snippet?
If you would, youd probably get a “list index out of range”, even though the index is 0. Thats my issue.
However, the bones don’t connect as expected. I dont know how to explain this,could you please try it with an example scene? I can only guess that it might have something to do with the order in which the bones are processed.
does not mean that your bone became a parent or child.
These option is an IK related thing.
As far as i can see your snippet means that you already have a parent children relation in your armature and the bones are already “connected”. All you have to do now is set the parents bone tail to the first or only childs head position.
Hint 1:
A parent child relation does not mean that the parents bone tail automaticaly points to its child.
Hint 2:
If you can see doted lines in your armature while in edit mode your bones already have its parents.
I know that, the parent-child info is already set before running the script.
You should check out what CONNECTED does. Ill try to explain it with words: basically if the parent tip and child head are in the same x,y,z position, then CONNECTED makes the head and tip become “one”, it is rendered is 1 sphere instead of two and by moving it, you move them both.
The issue Im encountering is that some bones dont connect, even though they should and some seem to connect to the child’s child istead.
for i in skeleton.bones.keys():
if len(skeleton.bones[i].getAllChildren()) < 2:
# children not available for editBone for whatever reason
child = skeleton.bones[i].children[0]
skeleton.makeEditable()
skeleton.bones[i].tail = skeleton.bones[child.name].head
skeleton.bones[i].options = [Blender.Armature.CONNECTED]
skeleton.update()
will become
for bone in skeleton.bones.keys():
if len(skeleton.bones[bone].children) == 1:
# children not available for editBone for whatever reason
child = skeleton.bones[bone].children[0]
skeleton.makeEditable()
#no need for the next line cause parents tip and childs head
#are already at the same postion or will jump automaticaly there
#skeleton.bones[i].tail = skeleton.bones[child.name].head
editbone = skeleton.bones[<b>child</b>.<b>name</b>] #most importend thing here
editbone.options = [Blender.Armature.CONNECTED]
skeleton.update()
Its because the option CONNECTED is related to the parentbone not to the childs.
Now your bones tip should jump to the childs head. Leave the rest as I have told you.
In Armatures all bone relationships are relative to its parents. You can only set the CONNECTED
statement to the bones parent and not to the bones child. The key ‘ARMATURESPACE’ is needed cause the Armature.bones values came in BONESPACE by default if they have a parent child relationship as far as I know.