Character Rig script help\advice?

I’m working on a rigging script and I’ve got most of my pseudocode ready, but I’m still fighting with some of the basic python/blender interaction. I just ran a test that generated empties and then drew bones to match their locations. The script runs but no bones appear to show up(the empties and an armature object do however). Can someone look at it and tell me what I did wrong? It was probably something simple.

import Blender
from Blender.Constraint import Type as T
from Blender.Constraint import Settings as S

def createEmpty(name, x, y, z):
	empty = None
	try:
		empty = Blender.Object.Get(name)
	except:
		empty = Blender.Object.New("Empty", name)
	empty.loc = (x, y, z)
	scene = Blender.Scene.GetCurrent()
	scene.link(empty)

guides = [
    ["Hip_R",        0,  0,  4],
    ["Knee_R",       0,  -2,  1],
    ["Ankle_R",     0,  0,  -2],
    ["Foot_R",     0,  -1,  -3],
	["Toes_R",		0,	-2, -3]
]

for guide in guides:
	createEmpty(guide[0], guide[1], guide[2], guide[3])
	Blender.Redraw()
	
newArmature =Blender.Armature.Armature("fna_Data")
newArmature.makeEditable()

Hip_R_Empty = Blender.Object.Get("Hip_R")
Knee_R_Empty = Blender.Object.Get("Knee_R")
Ankle_R_Empty = Blender.Object.Get("Ankle_R")
Foot_R_Empty = Blender.Object.Get("Foot_R")
Toes_R_Empty = Blender.Object.Get("Toes_R")

armatureObj = Blender.Object.New("Armature", "fna")
armatureObj.link(newArmature)    
newArmature.update()

scene = Blender.Scene.getCurrent()
scene.link(armatureObj)

newArmature.makeEditable()
newThighBone = Blender.Armature.Editbone()
newThighBone.head = Hip_R_Empty.getMatrix("worldspace").translationPart()
newThighBone.tail = Knee_R_Empty.getMatrix("worldspace").translationPart()
newArmature.bones["upperLeg"] = newThighBone

newLegBone = Blender.Armature.Editbone()
newLegBone.head = Knee_R_Empty.getMatrix("worldspace").translationPart()
newLegBone.tail = Ankle_R_Empty.getMatrix("worldspace").translationPart()
newLegBone.parent = newThighBone
newLegBone.options = [Blender.Armature.CONNECTED]
newArmature.bones["upperLeg"] = newLegBone

newAnkleBone = Blender.Armature.Editbone()
newAnkleBone.head = Ankle_R_Empty.getMatrix("worldspace").translationPart()
newAnkleBone.tail = Foot_R_Empty.getMatrix("worldspace").translationPart()
newAnkleBone.parent=newLegBone
newAnkleBone.options = [Blender.Armature.CONNECTED]
newArmature.bones["upperFoot"] = newAnkleBone

newToeBone = Blender.Armature.Editbone()
newToeBone.head = Foot_R_Empty.getMatrix("worldspace").translationPart()
newToeBone.tail = Toes_R_Empty.getMatrix("worldspace").translationPart()
newToeBone.parent=newAnkleBone
newToeBone.options = [Blender.Armature.CONNECTED]
newArmature.bones["lowerFoot"] = newToeBone

Also, on the mancandy dvds, he uses cntrl N a lot to Recalculate bone roll angles. Can anyone point me to the function or code for doing that? I couldn’t seem to find it in the library. Thanks for any help!

EDIT: forgot to post my script

There is 2 problems.

  1. When you add the first bone you have the line…
    newArmature.bones[“upperLeg”] = newThighBone

When you add the second bone you have…
newArmature.bones[“upperLeg”] = newLegBone

I’m sure this is a mistake, I changed the second one to
newArmature.bones[“lowerLeg”] = newLegBone

  1. The five lines

armatureObj = Blender.Object.New("Armature", "fna")
armatureObj.link(newArmature)    
newArmature.update()

scene = Blender.Scene.getCurrent()
scene.link(armatureObj)

should go at the END of your script.

When i changed those 2 things it worked (or i think it did what it was supposed to).

Let me know if this helps.

One other thing, in the function createEmpty, you do not want to do scene.link(empty) if
empty = Blender.Object.Get(name) succeeded.

Oh yeah, i looked for an equivalent to the Ctrl + N to clear the roll a few months ago and could not find any API call or way of doing it, you might have better luck.

Thanks that worked brilliantly! Do you mind telling me what the difference is between the armature data and the armature object and why the one goes at the beginning and the one at the end? I put it in the code that way because thats what a few examples that I saw did (and I can keep doing that if need be) but I’m curious as to why they aren’t the same thing.

Again, many thanks for the help.

Ok, one thing you have to keep in mind that EVERYTHING in the 3d view is an object. Lamps,cameras,meshes,curves,metaballs,armatures, and so on. Each object needs the appropriate data linked to it.

We need to create the armature data (i.e. bones,setting…) before we can have an armature object. We create the armature data structure, by doing …

Blender.Armature.Armature("fna_Data")

Once we have that we can put bones, adjust locations, change settings and so on.

Once we have done that then you can create an armature object by doing…

Blender.Object.New("Armature", "fna")

Now we have an armature object, but the object has no armature data inside it. So what we do next is link the armature object to the armature data. In the code it was done by doing…

armatureObj.link(newArmature)

Now the armature object has the armature data inside it. Now the next problem is that the current scene does not have the armature object inside it, so we put the armature object inside the scene by doing…

scene.link(armatureObj)

Now the armature object is inside the scene.

Im not really sure but the only explaination i can give to why you have to link the armature data to the armature object at the end of the script is because you have to modify the armature data FIRST, then add it to the armature object.

A good way of thinking about it is that we build a chain
Scene —> ArmatureObject —> ArmatureData

Or if we had a lamp you would have
Scene —> LampObject —> LampData

Or whatever type of object you need. To build the chain we work backwards, create and adjust the data, create the object, link the object to the data, and finally link the scene to the object.

Keep this in mind while working with any type of object in blender! I hope i have been able to shed some light on this. If you have any other questions, just ask and i’ll try to answer them.