- modify for Cessens updated spine

- Neck example didnt account for some possible problems when linking to the body
- foot IK were referencing the wrong bones
- updated some example rigs
- graph constraint arrow direction was incorrect
This commit is contained in:
Campbell Barton 2009-12-08 17:00:53 +00:00
parent 7235e681b9
commit ee74e720a8
4 changed files with 64 additions and 52 deletions

@ -51,7 +51,7 @@ def compat_str(text, line_length=0):
return "* " + text
def graph_armature(obj, path, FAKE_PARENT=True, CONSTRAINTS=True, DRIVERS=True, XTRA_INFO=False):
def graph_armature(obj, path, FAKE_PARENT=True, CONSTRAINTS=True, DRIVERS=True, XTRA_INFO=True):
CONSTRAINTS = DRIVERS = True
fileobject = open(path, "w")
@ -131,7 +131,7 @@ def graph_armature(obj, path, FAKE_PARENT=True, CONSTRAINTS=True, DRIVERS=True,
if XTRA_INFO:
label = "%s\n%s" % (constraint.type, constraint.name)
opts.append('label="%s"' % compat_str(label))
fw('"%s" -> "%s" [%s] ;\n' % (subtarget, pbone.name, ','.join(opts)))
fw('"%s" -> "%s" [%s] ;\n' % (pbone.name, subtarget, ','.join(opts)))
# Drivers
if DRIVERS:

@ -77,8 +77,8 @@ def metarig_definition(obj, orig_bone_name):
if index == 2:
hands.append(pbone)
if len(hands) > 1:
raise Exception("more then 1 hand found on:", orig_bone_name)
if len(hands) != 1:
raise Exception("Expected more then 1 hand found on:", orig_bone_name)
# first add the 2 new bones
mt.hand_p = hands[0]

@ -27,19 +27,20 @@ METARIG_NAMES = ("body", "head")
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.object
arm = obj.data
bone = arm.edit_bones.new('body')
bone.head[:] = -0.0000, -0.2771, -1.3345
bone.tail[:] = -0.0000, -0.1708, -0.3984
bone.tail[:] = -0.0000, -0.1708, -0.1984
bone.roll = 0.0000
bone.connected = False
bone = arm.edit_bones.new('head')
bone.head[:] = -0.0000, -0.1708, -0.1984
bone.tail[:] = 0.0000, -0.1708, 1.6016
bone.roll = -0.0000
bone.connected = False
bone.tail[:] = 0.0000, 0.7292, 1.3604
bone.roll = 0.0000
bone.connected = True
bone.parent = arm.edit_bones['body']
bone = arm.edit_bones.new('neck.01')
bone.head[:] = 0.0000, -0.1708, -0.1984
@ -116,7 +117,7 @@ def main(obj, bone_definition, base_names):
setattr(mt_chain, attr, neck_chain[i])
mt_chain.update()
neck_chain_basename = mt_chain.neck_01_e.basename
neck_chain_basename = base_names[mt_chain.neck_01_e.name].split(".")[0]
neck_chain_segment_length = mt_chain.neck_01_e.length
ex = bone_class_instance(obj, ["body", "head", "head_hinge", "neck_socket"]) # hinge & extras
@ -125,7 +126,8 @@ def main(obj, bone_definition, base_names):
# Copy the head bone and offset
ex.head_e = copy_bone_simple(arm, mt.head, "MCH_%s" % mt.head, parent=True)
ex.head_e = copy_bone_simple(arm, mt.head, "MCH_%s" % base_names[mt.head], parent=True)
ex.head_e.connected = False
ex.head = ex.head_e.name
# offset
head_length = ex.head_e.length
@ -133,17 +135,20 @@ def main(obj, bone_definition, base_names):
ex.head_e.tail.y += head_length / 2.0
# Yes, use the body bone but call it a head hinge
ex.head_hinge_e = copy_bone_simple(arm, mt.body, "MCH_%s_hinge" % mt.head, parent=True)
ex.head_hinge_e = copy_bone_simple(arm, mt.body, "MCH_%s_hinge" % base_names[mt.head], parent=True)
ex.head_hinge_e.connected = False
ex.head_hinge = ex.head_hinge_e.name
ex.head_hinge_e.head.y += head_length / 4.0
ex.head_hinge_e.tail.y += head_length / 4.0
# reparent the head, assume its not connected
mt.head_e.connected = False
mt.head_e.parent = ex.head_hinge_e
# Insert the neck socket, the head copys this loation
ex.neck_socket_e = arm.edit_bones.new("MCH-%s_socked" % neck_chain_basename)
ex.neck_socket = ex.neck_socket_e.name
ex.neck_socket_e.connected = False
ex.neck_socket_e.parent = mt.body_e
ex.neck_socket_e.head = mt.head_e.head
ex.neck_socket_e.tail = mt.head_e.head - Vector(0.0, neck_chain_segment_length / 2.0, 0.0)
@ -157,7 +162,7 @@ def main(obj, bone_definition, base_names):
neck_e = getattr(mt_chain, attr + "_e")
# dont store parent names, re-reference as each chain bones parent.
neck_e_parent = arm.edit_bones.new("MCH-rot_%s" % neck_e.name)
neck_e_parent = arm.edit_bones.new("MCH-rot_%s" % base_names[neck_e.name])
neck_e_parent.head = neck_e.head
neck_e_parent.tail = neck_e.head + ((mt.head_e.tail - mt.head_e.head).normalize() * neck_chain_segment_length / 2.0)
neck_e_parent.roll = mt.head_e.roll

@ -27,6 +27,7 @@ METARIG_NAMES = ("pelvis", "ribcage")
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.object
arm = obj.data
@ -86,7 +87,7 @@ def metarig_template():
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['rib_cage']
pbone['type'] = 'spine'
pbone['type'] = 'spine.fk'
def metarig_definition(obj, orig_bone_name):
@ -139,47 +140,55 @@ def main(obj, bone_definition, base_names):
child = spine_chain[0]
spine_chain_segment_length = child.length
child.parent = mt.pelvis_e # was mt.ribcage
#child.parent = mt.pelvis_e # was mt.ribcage
# The first bone in the chain happens to be the basis of others, create them now
ex = bone_class_instance(obj, ["pelvis", "ribcage", "ribcage_hinge", "spine_rotate"])
ex = bone_class_instance(obj, ["pelvis", "pelvis_copy", "ribcage", "ribcage_hinge", "ribcage_copy", "spine_rotate"])
df = bone_class_instance(obj, ["pelvis", "ribcage"]) # DEF-wgt_pelvis, DEF-wgt_rib_cage
ex.pelvis_copy_e = copy_bone_simple(arm, mt.pelvis, base_names[mt.pelvis]) # no parent
ex.pelvis_copy = ex.pelvis_copy_e.name
# copy the pelvis, offset to make MCH-spine_rotate and MCH-ribcage_hinge
ex.ribcage_hinge_e = copy_bone_simple(arm, mt.pelvis, "MCH-%s_hinge" % mt.ribcage)
ex.ribcage_hinge_e = copy_bone_simple(arm, mt.pelvis, "MCH-%s_hinge" % base_names[mt.ribcage])
ex.ribcage_hinge = ex.ribcage_hinge_e.name
ex.ribcage_hinge_e.translate(Vector(0.0, spine_chain_segment_length / 4.0, 0.0))
mt.ribcage_e.parent = ex.ribcage_hinge_e
ex.spine_rotate_e = copy_bone_simple(arm, mt.pelvis, "MCH-%s_rotate" % spine_chain_basename)
ex.spine_rotate = ex.spine_rotate_e.name
ex.spine_rotate_e.translate(Vector(0.0, spine_chain_segment_length / 2.0, 0.0))
# swap head/tail
ex.spine_rotate_e.head, ex.spine_rotate_e.tail = ex.spine_rotate_e.tail.copy(), ex.spine_rotate_e.head.copy()
ex.spine_rotate_e.parent = mt.pelvis_e
ex.spine_rotate_e.connected = False
ex.spine_rotate_e.parent = ex.pelvis_copy_e
df.pelvis_e = copy_bone_simple(arm, child.name, "DEF-wgt_%s" % mt.pelvis)
df.pelvis_e = copy_bone_simple(arm, child.name, "DEF-wgt_%s" % base_names[mt.pelvis])
df.pelvis = df.pelvis_e.name
df.pelvis_e.translate(Vector(spine_chain_segment_length * 2.0, - spine_chain_segment_length, 0.0))
ex.pelvis_e = copy_bone_simple(arm, child.name, "MCH-wgt_%s" % mt.pelvis)
ex.pelvis_e = copy_bone_simple(arm, child.name, "MCH-wgt_%s" % base_names[mt.pelvis])
ex.pelvis = ex.pelvis_e.name
ex.pelvis_e.translate(Vector(0.0, - spine_chain_segment_length, 0.0))
ex.pelvis_e.parent = mt.pelvis_e
ex.pelvis_e.connected = False
ex.pelvis_e.parent = ex.pelvis_copy_e
# Copy the last bone now
child = spine_chain[-1]
df.ribcage_e = copy_bone_simple(arm, child.name, "DEF-wgt_%s" % mt.ribcage)
df.ribcage_e = copy_bone_simple(arm, child.name, "DEF-wgt_%s" % base_names[mt.ribcage])
df.ribcage = df.ribcage_e.name
df.ribcage_e.translate(Vector(spine_chain_segment_length * 2.0, - df.ribcage_e.length / 2.0, 0.0))
ex.ribcage_e = copy_bone_simple(arm, child.name, "MCH-wgt_%s" % mt.ribcage)
ex.ribcage_e = copy_bone_simple(arm, child.name, "MCH-wgt_%s" % base_names[mt.ribcage])
ex.ribcage = ex.ribcage_e.name
ex.ribcage_e.translate(Vector(0.0, - ex.ribcage_e.length / 2.0, 0.0))
ex.ribcage_e.parent = mt.ribcage_e
ex.ribcage_copy_e = copy_bone_simple(arm, child.name, base_names[mt.ribcage])
ex.ribcage_copy = ex.ribcage_copy_e.name
ex.ribcage_copy_e.connected = False
ex.ribcage_copy_e.parent = ex.ribcage_hinge_e
spine_chain = [child.name for child in spine_chain]
# We have 3 spine chains
@ -214,21 +223,22 @@ def main(obj, bone_definition, base_names):
# Now we need to re-parent these chains
for i, child_name in enumerate(spine_chain_orig):
attr = ex_chain.attr_names[i] + "_e"
ebone = getattr(ex_chain, attr)
if i == 0:
getattr(ex_chain, attr).parent = mt.pelvis_e
ebone.connected = False
ebone.parent = ex.pelvis_copy_e
else:
attr_parent = ex_chain.attr_names[i-1] + "_e"
getattr(ex_chain, attr).parent = getattr(ex_chain, attr_parent)
attr_parent = ex_chain.attr_names[i - 1] + "_e"
ebone.parent = getattr(ex_chain, attr_parent)
# intentional! get the parent from the other paralelle chain member
getattr(rv_chain, attr).parent = getattr(ex_chain, attr)
getattr(rv_chain, attr).parent = ebone
# ex_chain needs to interlace bones!
# Note, skip the first bone
for i in range(1, spine_chain_len): # similar to neck
child_name_orig = spine_chain_orig[i]
child_name_orig = base_names[spine_chain_orig[i]]
spine_e = getattr(mt_chain, mt_chain.attr_names[i] + "_e")
# dont store parent names, re-reference as each chain bones parent.
@ -299,11 +309,9 @@ def main(obj, bone_definition, base_names):
con = ex.ribcage_hinge_p.constraints.new('COPY_ROTATION')
con.name = "hinge"
con.target = obj
con.subtarget = mt.pelvis
con.subtarget = ex.pelvis_copy
# add driver
hinge_driver_path = mt.ribcage_p.path_to_id() + '["hinge"]'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
tar = driver.targets.new()
@ -311,7 +319,7 @@ def main(obj, bone_definition, base_names):
tar.name = "var"
tar.id_type = 'OBJECT'
tar.id = obj
tar.rna_path = hinge_driver_path
tar.rna_path = ex.ribcage_copy_p.path_to_id() + '["hinge"]'
mod = fcurve.modifiers[0]
mod.poly_order = 1
@ -347,20 +355,20 @@ def main(obj, bone_definition, base_names):
con.target = obj
con.subtarget = getattr(mt_chain, mt_chain.attr_names[-1])
# mt.pelvis_p / rib_cage
con = mt.ribcage_p.constraints.new('COPY_LOCATION')
# ex.pelvis_copy_p / rib_cage
con = ex.ribcage_copy_p.constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = mt.pelvis
con.subtarget = ex.pelvis_copy
con.head_tail = 0.0
# This stores all important ID props
prop = rna_idprop_ui_prop_get(mt.ribcage_p, "hinge", create=True)
mt.ribcage_p["hinge"] = 1.0
prop = rna_idprop_ui_prop_get(ex.ribcage_copy_p, "hinge", create=True)
ex.ribcage_copy_p["hinge"] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop = rna_idprop_ui_prop_get(mt.ribcage_p, "pivot_slide", create=True)
mt.ribcage_p["pivot_slide"] = 1.0 / spine_chain_len
prop = rna_idprop_ui_prop_get(ex.ribcage_copy_p, "pivot_slide", create=True)
ex.ribcage_copy_p["pivot_slide"] = 1.0 / spine_chain_len
prop["soft_min"] = 1.0 / spine_chain_len
prop["soft_max"] = 1.0
@ -382,10 +390,10 @@ def main(obj, bone_definition, base_names):
# Constrain 'inbetween' bones
target_names = [("b%.2d" % (i + 1)) for i in range(spine_chain_len - 1)]
rib_driver_path = mt.ribcage_p.path_to_id()
rib_driver_path = ex.ribcage_copy_p.path_to_id()
mt.ribcage_p["bend_tot"] = 0.0
fcurve = mt.ribcage_p.driver_add('["bend_tot"]', 0)
ex.ribcage_copy_p["bend_tot"] = 0.0
fcurve = ex.ribcage_copy_p.driver_add('["bend_tot"]', 0)
driver = fcurve.driver
driver.type = 'SUM'
fcurve.modifiers.remove(0) # grr dont need a modifier
@ -396,14 +404,13 @@ def main(obj, bone_definition, base_names):
tar.id_type = 'OBJECT'
tar.id = obj
tar.rna_path = rib_driver_path + ('["bend_%.2d"]' % (i + 1))
print(rib_driver_path)
for i in range(1, spine_chain_len):
# Add bend prop
prop_name = "bend_%.2d" % i
prop = rna_idprop_ui_prop_get(mt.ribcage_p, prop_name, create=True)
mt.ribcage_p[prop_name] = 1.0
prop = rna_idprop_ui_prop_get(ex.ribcage_copy_p, prop_name, create=True)
ex.ribcage_copy_p[prop_name] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0