rigify
authorCampbell Barton <ideasman42@gmail.com>
Fri, 11 Dec 2009 16:30:27 +0000 (16:30 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 11 Dec 2009 16:30:27 +0000 (16:30 +0000)
* optional default blend argument, use for better leg & arm defaults
* way to define arbitrary options for bones that can then be passed to the generator function, only used to set elbow target parent at the moment.

release/scripts/modules/rigify/__init__.py
release/scripts/modules/rigify/arm_biped_generic.py
release/scripts/modules/rigify/copy.py
release/scripts/modules/rigify/delta.py
release/scripts/modules/rigify/finger_curl.py
release/scripts/modules/rigify/leg_biped_generic.py
release/scripts/modules/rigify/neck_flex.py
release/scripts/modules/rigify/palm_curl.py
release/scripts/modules/rigify/spine_pivot_flex.py
release/scripts/modules/rigify_utils.py

index 33a2f4c007e749d1e22207434fdbe91d14fe3a91..6ec90015d610bc62853b4fbbc2f3e271645b08a1 100644 (file)
@@ -41,19 +41,19 @@ def submodule_func_from_type(bone_type):
     if len(type_pair) == 1:
         type_pair = type_pair[0], "main"
 
-    submod_name, func_name = type_pair
+    type_name, func_name = type_pair
 
     # from rigify import leg
     try:
-        submod = __import__(name="%s.%s" % (__package__, submod_name), fromlist=[submod_name])
+        submod = __import__(name="%s.%s" % (__package__, type_name), fromlist=[type_name])
     except ImportError:
-        raise RigifyError("python module for type '%s' not found" % submod_name)
+        raise RigifyError("python module for type '%s' not found" % type_name)
         
     reload(submod)
-    return submod, getattr(submod, func_name)
+    return type_name, submod, getattr(submod, func_name)
 
 
-def submodule_types():
+def get_submodule_types():
     import os
     submodules = []
     files = os.listdir(os.path.dirname(__file__))
@@ -63,6 +63,17 @@ def submodule_types():
     
     return sorted(submodules)
 
+def get_bone_type_options(pbone, type_name):
+    options = {}
+    bone_name = pbone.name
+    for key, value in pbone.items():
+        key_pair = key.split(".")
+        if key_pair[0] == type_name:
+            if len(key_pair) != 2:
+                raise RigifyError("option error for bone '%s', property name was not a pair '%s'" % (bone_name, key_pair))
+            options[key_pair[1]] = value
+
+    return options
 
 def validate_rig(context, obj):
     '''
@@ -84,11 +95,13 @@ def validate_rig(context, obj):
             if bone_type.split(".")[0] in SPECIAL_TYPES:
                 continue
 
-            submod, type_func = submodule_func_from_type(bone_type)
+            type_name, submod, type_func = submodule_func_from_type(bone_type)
             reload(submod)
             submod.metarig_definition(obj, bone_name)
             type_found = True
-        
+
+            get_bone_type_options(pbone, bone_type)
+
         # missing, - check for duplicate root bone.
     
     if not type_found:
@@ -162,6 +175,7 @@ def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True):
     #   ...needed so we can override the root parent
     bone_genesis = {}
 
+
     # inspect all bones and assign their definitions before modifying
     for pbone in obj.pose.bones:
         bone_name = pbone.name
@@ -181,18 +195,17 @@ def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True):
             bone_type_list[:] = []
 
         for bone_type in bone_type_list:
-            submod, type_func = submodule_func_from_type(bone_type)
+            type_name, submod, type_func = submodule_func_from_type(bone_type)
             reload(submod)
-            submod_name = submod.__name__
             
             bone_def_dict = bone_definitions.setdefault(bone_name, {})
 
             # Only calculate bone definitions once
-            if submod_name not in bone_def_dict:
-                bone_def_dict[submod_name] = submod.metarig_definition(obj, bone_name)
+            if type_name not in bone_def_dict:
+                bone_def_dict[type_name] = submod.metarig_definition(obj, bone_name)
 
             bone_typeinfo = bone_typeinfos.setdefault(bone_name, [])
-            bone_typeinfo.append((submod_name, type_func))
+            bone_typeinfo.append((type_name, type_func))
 
 
     # sort bones, not needed but gives more pradictable execution which may be useful in rare cases
@@ -216,16 +229,17 @@ def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True):
         
         bone_names_pre = set([bone.name for bone in arm.bones])
 
-        for submod_name, type_func in bone_typeinfos[bone_name]:
+        for type_name, type_func in bone_typeinfos[bone_name]:
             # this bones definition of the current typeinfo
-            definition = bone_def_dict[submod_name]
+            definition = bone_def_dict[type_name]
+            options = get_bone_type_options(pbone, type_name)
 
             bpy.ops.object.mode_set(mode='EDIT')
-            ret = type_func(obj, definition, base_names)
+            ret = type_func(obj, definition, base_names, options)
             bpy.ops.object.mode_set(mode='OBJECT')
 
             if ret:
-                result_submod = results.setdefault(submod_name, [])
+                result_submod = results.setdefault(type_name, [])
 
                 if result_submod and len(result_submod[-1]) != len(ret):
                     raise Exception("bone lists not compatible: %s, %s" % (result_submod[-1], ret))
@@ -234,7 +248,7 @@ def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True):
 
         for result_submod in results.values():
             # blend 2 chains
-            definition = bone_def_dict[submod_name]
+            definition = bone_def_dict[type_name]
 
             if len(result_submod) == 2:
                 blend_bone_list(obj, definition, result_submod[0], result_submod[1], target_bone=bone_name)
@@ -325,11 +339,15 @@ def generate_test(context, metarig_type="", GENERATE_FINAL=True):
             obj.selected = False
         obj_new.selected = True
 
-    for module_name in submodule_types():
+    for module_name in get_submodule_types():
         if (metarig_type and module_name != metarig_type):
             continue
+
+        # XXX workaround!, problem with updating the pose matrix.
+        if module_name=="delta":
+            continue
         
-        submodule, func = submodule_func_from_type(module_name)
+        type_name, submodule, func = submodule_func_from_type(module_name)
 
         metarig_template = getattr(submodule, "metarig_template", None)
 
index e22857852ee304258854f4f9b40ebdbffee093e2..a9b5e62775e841462c296158e720e7a756436bf6 100644 (file)
@@ -93,7 +93,10 @@ def metarig_definition(obj, orig_bone_name):
     return mt.names()
 
 
-def ik(obj, definitions, base_names):
+def ik(obj, definitions, base_names, options):
+    print(options)
+    arm = obj.data
+    
     mt = bone_class_instance(obj, METARIG_NAMES)
     mt.shoulder, mt.arm, mt.forearm, mt.hand = definitions
     mt.update()
@@ -117,6 +120,17 @@ def ik(obj, definitions, base_names):
     ik.update()
     ik.pole_e.local_location = False
     
+    # option: elbow_parent
+    elbow_parent_name = options.get("elbow_parent", "")
+
+    if elbow_parent_name:
+        try:
+            elbow_parent_e = arm.edit_bones[elbow_parent_name]
+        except:
+            # TODO, old/new parent mapping
+            raise RigifyError("parent bone from property 'arm_biped_generic.elbow_parent' not found '%s'" % elbow_parent_name)
+        ik.pole_e.parent = elbow_parent_e
+    
     # update bones after this!
     ik.hand_vis = add_stretch_to(obj, mt.hand, ik_chain.hand, "VIS-%s_ik" % base_names[mt.hand])
     ik.pole_vis = add_stretch_to(obj, mt.forearm, ik.pole, "VIS-%s_ik" % base_names[mt.forearm])
@@ -162,7 +176,7 @@ def ik(obj, definitions, base_names):
     return [None] + ik_chain.names()
 
 
-def fk(obj, definitions, base_names):
+def fk(obj, definitions, base_names, options):
     
     arm = obj.data
     
@@ -254,9 +268,9 @@ def fk(obj, definitions, base_names):
     return None, fk_chain.arm, fk_chain.forearm, fk_chain.hand
 
 
-def main(obj, bone_definition, base_names):    
-    bones_ik = ik(obj, bone_definition, base_names)
-    bones_fk = fk(obj, bone_definition, base_names)
+def main(obj, bone_definition, base_names, options):    
+    bones_ik = ik(obj, bone_definition, base_names, options)
+    bones_fk = fk(obj, bone_definition, base_names, options)
 
     bpy.ops.object.mode_set(mode='OBJECT')
-    blend_bone_list(obj, bone_definition, bones_ik, bones_fk, target_bone=bone_definition[1])
+    blend_bone_list(obj, bone_definition, bones_ik, bones_fk, target_bone=bone_definition[1], blend_default=1.0)
index 21d0970234b1d49bf19dde0341b14d40d4b43f3e..70086b70907d8af555a6cc4df6cb987b4ddcdf74 100644 (file)
@@ -44,7 +44,7 @@ def metarig_definition(obj, orig_bone_name):
     return [orig_bone_name]
 
 
-def main(obj, bone_definition, base_names):
+def main(obj, bone_definition, base_names, options):
     arm = obj.data
     mt = bone_class_instance(obj, METARIG_NAMES)
     mt.cpy = bone_definition[0]
index 261e2b22479ce1b5b931d342d5e45447c05fe5a1..4e1d8ce4571b69b71bd80dc60c1f7e10df5555e5 100644 (file)
@@ -75,7 +75,7 @@ def metarig_definition(obj, orig_bone_name):
     return bone_definition
 
 
-def main(obj, bone_definition, base_names):
+def main(obj, bone_definition, base_names, options):
     '''
     Use this bone to define a delta thats applied to its child in pose mode.
     '''
index 7f21eecd7d3d7e766f2b4f8bc2fc6efca84cc91e..d260bb1a67af1d0ed82b7cc9ebe99fb26e99a8b5 100644 (file)
@@ -20,7 +20,7 @@
 
 import bpy
 from rigify import RigifyError
-from rigify_utils import copy_bone_simple, get_side_name, get_base_name, EMPTY_LAYER
+from rigify_utils import copy_bone_simple, get_side_name, get_base_name
 from rna_prop_ui import rna_idprop_ui_prop_get
 from functools import reduce
 
@@ -85,21 +85,17 @@ def metarig_definition(obj, orig_bone_name):
     return bone_definition
 
 
-def main(obj, bone_definition, base_names):
-
+def main(obj, bone_definition, base_names, options):
     # *** EDITMODE
 
     # get assosiated data
     arm = obj.data
-    orig_pbone = obj.pose.bones[bone_definition[0]]
     orig_ebone = arm.edit_bones[bone_definition[0]]
 
     obj.animation_data_create() # needed if its a new armature with no keys
 
-    arm.layer[0] = arm.layer[8] = True
-
-    children = orig_pbone.children_recursive
-    tot_len = reduce(lambda f, pbone: f + pbone.bone.length, children, orig_pbone.bone.length)
+    children = orig_ebone.children_recursive
+    tot_len = reduce(lambda f, ebone: f + ebone.length, children, orig_ebone.length)
 
     # FIXME, the line below is far too arbitrary
     base_name = base_names[bone_definition[0]].rsplit(".", 2)[0]
@@ -116,12 +112,7 @@ def main(obj, bone_definition, base_names):
     # now add bones inbetween this and its children recursively
 
     # switching modes so store names only!
-    children = [pbone.name for pbone in children]
-
-    # set an alternate layer for driver bones
-    other_layer = EMPTY_LAYER[:]
-    other_layer[8] = True
-
+    children = [ebone.name for ebone in children]
 
     driver_bone_pairs = []
 
@@ -134,7 +125,6 @@ def main(obj, bone_definition, base_names):
 
         driver_ebone = copy_bone_simple(arm, child_ebone.name, driver_bone_name)
         driver_ebone.length *= 0.5
-        driver_ebone.layer = other_layer
 
         # Insert driver_ebone in the chain without connected parents
         driver_ebone.connected = False
index 65fde79da6e9d3a0475093ce099583e0caa58f3f..4ce7352539a998a137176663ce088fc076f3926a 100644 (file)
@@ -125,7 +125,7 @@ def metarig_definition(obj, orig_bone_name):
     return bone_definition
 
 
-def ik(obj, bone_definition, base_names):
+def ik(obj, bone_definition, base_names, options):
     arm = obj.data
 
     # setup the existing bones
@@ -274,7 +274,7 @@ def ik(obj, bone_definition, base_names):
     return None, ik_chain.thigh, ik_chain.shin, ik_chain.foot, ik_chain.toe, None
 
 
-def fk(obj, bone_definition, base_names):
+def fk(obj, bone_definition, base_names, options):
     from Mathutils import Vector
     arm = obj.data
 
@@ -354,9 +354,9 @@ def fk(obj, bone_definition, base_names):
     return None, fk_chain.thigh, fk_chain.shin, fk_chain.foot, fk_chain.toe, None
 
 
-def main(obj, bone_definition, base_names):
-    bones_ik = ik(obj, bone_definition, base_names)
-    bones_fk = fk(obj, bone_definition, base_names)
+def main(obj, bone_definition, base_names, options):
+    bones_ik = ik(obj, bone_definition, base_names, options)
+    bones_fk = fk(obj, bone_definition, base_names, options)
 
     bpy.ops.object.mode_set(mode='OBJECT')
-    blend_bone_list(obj, bone_definition, bones_ik, bones_fk, target_bone=bone_definition[1])
+    blend_bone_list(obj, bone_definition, bones_ik, bones_fk, target_bone=bone_definition[1], blend_default=0.0)
index 9bb852b25b53600d1f94ccb5acdd7e1ef210f1c4..15efc2a6985219f968f4a146700af1dabdc71e81 100644 (file)
@@ -100,7 +100,7 @@ def metarig_definition(obj, orig_bone_name):
     return bone_definition
 
 
-def main(obj, bone_definition, base_names):
+def main(obj, bone_definition, base_names, options):
     from Mathutils import Vector
 
     arm = obj.data
index 867889b008464f93382115a3d8c845c1eefae215..4ad0cfe3675ead29a4cc4fc3ea7b86aed38aa10e 100644 (file)
@@ -96,7 +96,7 @@ def metarig_definition(obj, orig_bone_name):
     return [palm_parent.name] + bone_definition
 
 
-def main(obj, bone_definition, base_names):
+def main(obj, bone_definition, base_names, options):
     arm = obj.data
 
     children = bone_definition[1:]
@@ -163,22 +163,6 @@ def main(obj, bone_definition, base_names):
     driver = driver_fcurves[2].driver
     driver.expression = "(1.0-cos(x))-s"
 
-    def x_direction():
-        # NOTE: the direction of the Z rotation depends on which side the palm is on.
-        # we could do a simple side-of-x test but better to work out the direction
-        # the hand is facing.
-        from Mathutils import Vector, AngleBetweenVecs
-        from math import degrees
-        child_pbone_01 = obj.pose.bones[children[0]]
-        child_pbone_02 = obj.pose.bones[children[1]]
-
-        rel_vec = child_pbone_01.head - child_pbone_02.head
-        x_vec = child_pbone_01.matrix.rotationPart() * Vector(1.0, 0.0, 0.0)
-        return degrees(AngleBetweenVecs(rel_vec, x_vec)) > 90.0
-
-    if x_direction(): # flip
-        driver.expression = "-(%s)" % driver.expression
-    
     for fcurve in driver_fcurves:
         fcurve.modifiers.remove(0) # grr dont need a modifier
 
@@ -229,5 +213,23 @@ def main(obj, bone_definition, base_names):
     child_pbone = obj.pose.bones[children[-1]]
     child_pbone.rotation_mode = 'QUATERNION'
 
+    # fix at the end since there is some trouble with tx info not being updated otherwise
+    def x_direction():
+        # NOTE: the direction of the Z rotation depends on which side the palm is on.
+        # we could do a simple side-of-x test but better to work out the direction
+        # the hand is facing.
+        from Mathutils import Vector, AngleBetweenVecs
+        from math import degrees
+        child_pbone_01 = obj.pose.bones[children[0]].bone
+        child_pbone_02 = obj.pose.bones[children[1]].bone
+
+        rel_vec = child_pbone_01.head - child_pbone_02.head
+        x_vec = child_pbone_01.matrix.rotationPart() * Vector(1.0, 0.0, 0.0)
+        print(rel_vec, x_vec)
+        return degrees(AngleBetweenVecs(rel_vec, x_vec)) > 90.0
+
+    if x_direction(): # flip
+        driver.expression = "-(%s)" % driver.expression
+
     # no blending the result of this
     return None
index beeb5c68b7c6f98e01ea5c9f39f60af5576bbf67..f2608732c3726c92bdaae8d33ae863cbbe4f23f7 100644 (file)
@@ -121,7 +121,7 @@ def fk(*args):
     main(*args)
 
 
-def main(obj, bone_definition, base_names):
+def main(obj, bone_definition, base_names, options):
     from Mathutils import Vector, RotationMatrix
     from math import radians, pi
 
@@ -155,11 +155,9 @@ def main(obj, bone_definition, base_names):
     ex.ribcage_hinge = ex.ribcage_hinge_e.name
     ex.ribcage_hinge_e.translate(Vector(0.0, spine_chain_segment_length / 4.0, 0.0))
 
-    ex.spine_rotate_e = copy_bone_simple(arm, mt.pelvis, "MCH-%s_rotate" % spine_chain_basename)
+    ex.spine_rotate_e = copy_bone_simple(arm, mt.ribcage, "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.connected = False
     ex.spine_rotate_e.parent = ex.pelvis_copy_e
 
index a1fc54cb5bbe60ece4f3a524d91684b9d5a22387..6b15329c9920a4a946173aa6ca12b92f00c60257 100644 (file)
@@ -113,7 +113,7 @@ def copy_bone_simple_list(arm, from_bones, to_bones, parent=False):
     return copy_bones
 
 
-def blend_bone_list(obj, apply_bones, from_bones, to_bones, target_bone=None, target_prop="blend"):
+def blend_bone_list(obj, apply_bones, from_bones, to_bones, target_bone=None, target_prop="blend", blend_default=0.5):
 
     if obj.mode == 'EDIT':
         raise Exception("blending cant be called in editmode")
@@ -130,7 +130,7 @@ def blend_bone_list(obj, apply_bones, from_bones, to_bones, target_bone=None, ta
     prop_pbone = obj.pose.bones[target_bone]
     if prop_pbone.get(target_bone, None) is None:
         prop = rna_idprop_ui_prop_get(prop_pbone, target_prop, create=True)
-        prop_pbone[target_prop] = 0.5
+        prop_pbone[target_prop] = blend_default
         prop["soft_min"] = 0.0
         prop["soft_max"] = 1.0