[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [25238] trunk/blender: - rewrote arm rig so it creates 2 chains and blend them automatically ( like the leg)

Campbell Barton ideasman42 at gmail.com
Wed Dec 9 13:00:28 CET 2009


Revision: 25238
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=25238
Author:   campbellbarton
Date:     2009-12-09 13:00:28 +0100 (Wed, 09 Dec 2009)

Log Message:
-----------
- rewrote arm rig so it creates 2 chains and blend them automatically (like the leg)
- use reverse order for palm fingers (pointer first)
- allow copying bone class instances to exclude some bones
- doc generation had a python error (incedently updated online docs linked from the splash)

Modified Paths:
--------------
    trunk/blender/release/scripts/modules/rigify/__init__.py
    trunk/blender/release/scripts/modules/rigify/arm.py
    trunk/blender/release/scripts/modules/rigify/leg.py
    trunk/blender/release/scripts/modules/rigify/palm.py
    trunk/blender/source/blender/python/epy_doc_gen.py

Modified: trunk/blender/release/scripts/modules/rigify/__init__.py
===================================================================
--- trunk/blender/release/scripts/modules/rigify/__init__.py	2009-12-09 11:38:32 UTC (rev 25237)
+++ trunk/blender/release/scripts/modules/rigify/__init__.py	2009-12-09 12:00:28 UTC (rev 25238)
@@ -73,19 +73,23 @@
     setattr(self, attr, ebone.name)
 
 
-def _bone_class_instance_copy(self, from_prefix="", to_prefix=""):
+def _bone_class_instance_copy(self, from_fmt="%s", to_fmt="%s", exclude_attrs=(), base_names=None):
     from_name_ls = []
     new_name_ls = []
     new_slot_ls = []
 
     for attr in self.attr_names:
+        
+        if attr in exclude_attrs:
+            continue
+        
         bone_name_orig = getattr(self, attr)
         ebone = getattr(self, attr + "_e")
         # orig_names[attr] = bone_name_orig
 
-        # insert prefix
-        if from_prefix:
-            bone_name = from_prefix + bone_name_orig
+        # insert formatting
+        if from_fmt != "%s":
+            bone_name = from_fmt % bone_name_orig
             ebone.name = bone_name
             bone_name = ebone.name # cant be sure we get what we ask for
         else:
@@ -95,8 +99,9 @@
 
         new_slot_ls.append(attr)
         from_name_ls.append(bone_name)
-        bone_name_orig = bone_name_orig.replace("ORG-", "") # XXX - we need a better way to do this
-        new_name_ls.append(to_prefix + bone_name_orig)
+        if base_names:
+            bone_name_orig = base_names[bone_name_orig]
+        new_name_ls.append(to_fmt % bone_name_orig)
 
     new_bones = copy_bone_simple_list(self.obj.data, from_name_ls, new_name_ls, True)
     new_bc = bone_class_instance(self.obj, new_slot_ls)
@@ -134,6 +139,10 @@
 
 
 def bone_class_instance(obj, slots, name="BoneContainer"):
+    
+    if len(slots) != len(set(slots)):
+        raise Exception("duplicate entries found %s" % attr_names)
+
     attr_names = tuple(slots) # dont modify the original
     slots = list(slots) # dont modify the original
     for i in range(len(slots)):
@@ -210,6 +219,11 @@
     if obj.mode == 'EDIT':
         raise Exception("blending cant be called in editmode")
 
+    if len(apply_bones) != len(from_bones):
+        raise Exception("lists differ in length (from -> apply): \n\t%s\n\t%s" % (from_bones, apply_bones))
+    if len(apply_bones) != len(to_bones):
+        raise Exception("lists differ in length (to -> apply): \n\t%s\n\t%s" % (to_bones, apply_bones))
+
     # setup the blend property
     if target_bone is None:
         target_bone = apply_bones[-1] # default to the last bone
@@ -319,8 +333,9 @@
     con.volume = 'NO_VOLUME'
 
     bpy.ops.object.mode_set(mode=mode_orig)
+    
+    return stretch_name
 
-
 def add_pole_target_bone(obj, base_name, name, mode='CROSS'):
     '''
     Does not actually create a poll target, just the bone to use as a poll target

Modified: trunk/blender/release/scripts/modules/rigify/arm.py
===================================================================
--- trunk/blender/release/scripts/modules/rigify/arm.py	2009-12-09 11:38:32 UTC (rev 25237)
+++ trunk/blender/release/scripts/modules/rigify/arm.py	2009-12-09 12:00:28 UTC (rev 25238)
@@ -19,13 +19,15 @@
 # <pep8 compliant>
 
 import bpy
-from rigify import bone_class_instance, copy_bone_simple, add_pole_target_bone, add_stretch_to
+from rigify import bone_class_instance, copy_bone_simple, add_pole_target_bone, add_stretch_to, blend_bone_list
 from rna_prop_ui import rna_idprop_ui_prop_get
+from Mathutils import Vector
 
 METARIG_NAMES = "shoulder", "arm", "forearm", "hand"
 
 
 def metarig_template():
+    # generated by rigify.write_meta_rig
     bpy.ops.object.mode_set(mode='EDIT')
     obj = bpy.context.object
     arm = obj.data
@@ -66,8 +68,11 @@
     mt.shoulder_p = mt.arm_p.parent
 
     if not mt.shoulder_p:
-        raise Exception("could not find 'arm' parent, skipping:", orig_bone_name)
-    print(mt.shoulder_p)
+        raise Exception("could not find '%s' parent, skipping:" % orig_bone_name)
+        
+    if mt.arm_p.parent.bone.connected:
+        raise Exception("expected '%s' to be disconnected from its parent" % orig_bone_name)
+
     mt.shoulder = mt.shoulder_p.name
 
     # We could have some bones attached, find the bone that has this as its 2nd parent
@@ -90,232 +95,125 @@
     return mt.names()
 
 
-def main(obj, definitions, base_names):
-    """
-    the bone with the 'arm' property is the upper arm, this assumes a chain as follows.
-    [shoulder, upper_arm, forearm, hand]
-    ...where this bone is 'upper_arm'
-
-    there are 3 chains
-    - Original
-    - IK, MCH-%s_ik
-    - IKSwitch, MCH-%s ()
-
-
-    """
-
-    # Since there are 3 chains, this gets confusing so divide into 3 chains
-    # Initialize container classes for convenience
-    mt = bone_class_instance(obj, METARIG_NAMES) # meta
+def ik(obj, definitions, base_names):
+    mt = bone_class_instance(obj, METARIG_NAMES)
     mt.shoulder, mt.arm, mt.forearm, mt.hand = definitions
+    mt.update()
+    
+    ik = bone_class_instance(obj, ["pole", "pole_vis", "hand_vis"])
+    ik_chain = mt.copy(to_fmt="MCH-%s_ik", base_names=base_names, exclude_attrs=["shoulder"])
+    
+    # IK needs no parent_index
+    ik_chain.hand_e.connected = False
+    ik_chain.hand_e.parent = None
 
-    ik = bone_class_instance(obj, ["arm", "forearm", "pole", "hand"]) # ik
-    sw = bone_class_instance(obj, ["socket", "shoulder", "arm", "forearm", "hand"]) # hinge
-    ex = bone_class_instance(obj, ["arm_hinge"]) # hinge & extras
+    ik_chain.arm_e.connected = False
+    ik_chain.arm_e.parent = mt.shoulder_e
+    
+    # Add the bone used for the arms poll target
+    ik.pole = add_pole_target_bone(obj, mt.forearm, "elbow_poll", mode='+Z')
+    
+    # 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])
+    
+    ik.update()
+    ik.hand_vis_e.restrict_select = True
+    ik.pole_vis_e.restrict_select = True
+    
+    bpy.ops.object.mode_set(mode='OBJECT')
+    
+    mt.update()
+    ik.update()
+    ik_chain.update()
+    
+    con = ik_chain.forearm_p.constraints.new('IK')
+    con.target = obj
+    con.subtarget = ik_chain.hand
+    con.pole_target = obj
+    con.pole_subtarget = ik.pole
 
-    arm = obj.data
+    con.use_tail = True
+    con.use_stretch = True
+    con.use_target = True
+    con.use_rotation = False
+    con.chain_length = 2
+    con.pole_angle = -90.0 # XXX, RAD2DEG
 
-    def chain_ik(prefix="MCH-%s_ik"):
+    # ID Propery on the hand for IK/FK switch
 
-        mt.update()
+    prop = rna_idprop_ui_prop_get(ik_chain.hand_p, "ik", create=True)
+    ik_chain.hand_p["ik"] = 0.5
+    prop["soft_min"] = 0.0
+    prop["soft_max"] = 1.0
 
-        # Add the edit bones
-        ik.hand_e = copy_bone_simple(arm, mt.hand, prefix % base_names[mt.hand])
-        ik.hand = ik.hand_e.name
+    bpy.ops.object.mode_set(mode='EDIT')
+    
+    # don't blend the shoulder
+    return [None] + ik_chain.names()
 
-        ik.arm_e = copy_bone_simple(arm, mt.arm, prefix % base_names[mt.arm])
-        ik.arm = ik.arm_e.name
 
-        ik.forearm_e = copy_bone_simple(arm, mt.forearm, prefix % base_names[mt.forearm])
-        ik.forearm = ik.forearm_e.name
+def fk(obj, definitions, base_names):
+    
+    arm = obj.data
+    
+    mt = bone_class_instance(obj, METARIG_NAMES)
+    mt.shoulder, mt.arm, mt.forearm, mt.hand = definitions
+    mt.update()
 
-        ik.arm_e.parent = mt.arm_e.parent
-        ik.forearm_e.connected = mt.arm_e.connected
+    ex = bone_class_instance(obj, ["socket", "arm_hinge", "hand_delta"])
+    fk_chain = mt.copy(base_names=base_names)
 
-        ik.forearm_e.parent = ik.arm_e
-        ik.forearm_e.connected = True
+    # shoulder is used as a hinge
+    fk_chain.rename("shoulder", "MCH-%s_hinge" % base_names[mt.arm])
+    fk_chain.shoulder_e.translate(Vector(0.0, fk_chain.shoulder_e.length / 2, 0.0))
 
+    # upper arm constrains to this.
+    ex.socket_e = copy_bone_simple(arm, mt.arm, "MCH-%s_socket" % base_names[mt.arm])
+    ex.socket = ex.socket_e.name
+    ex.socket_e.connected = False
+    ex.socket_e.parent = mt.shoulder_e
+    ex.socket_e.tail = mt.shoulder_e.tail
+    
+    # insert the 'DLT-hand', between the forearm and the hand
+    # copies forarm rotation
+    ex.hand_delta_e = copy_bone_simple(arm, fk_chain.hand, "DLT-%s" % base_names[mt.hand], parent=True)
+    ex.hand_delta = ex.hand_delta_e.name
+    ex.hand_delta_e.length *= 0.5
+    ex.hand_delta_e.connected = False
+    
+    fk_chain.hand_e.connected = False
+    fk_chain.hand_e.parent = ex.hand_delta_e
 
-        # Add the bone used for the arms poll target
-        ik.pole = add_pole_target_bone(obj, mt.forearm, "elbow_poll", mode='+Z')
+    bpy.ops.object.mode_set(mode='OBJECT')
+    
+    mt.update()
+    ex.update()
+    fk_chain.update()
 
-        bpy.ops.object.mode_set(mode='OBJECT')
+    con = fk_chain.arm_p.constraints.new('COPY_LOCATION')
+    con.target = obj
+    con.subtarget = ex.socket
+    
+    fk_chain.hand_p.lock_location = True, True, True
+    con = ex.hand_delta_p.constraints.new('COPY_ROTATION')
+    con.target = obj
+    con.subtarget = fk_chain.forearm
 
-        ik.update()
-
-        con = ik.forearm_p.constraints.new('IK')
-        con.target = obj
-        con.subtarget = ik.hand
-        con.pole_target = obj
-        con.pole_subtarget = ik.pole
-
-        con.use_tail = True
-        con.use_stretch = True
-        con.use_target = True
-        con.use_rotation = False
-        con.chain_length = 2
-        con.pole_angle = -90.0 # XXX, RAD2DEG
-
-        # ID Propery on the hand for IK/FK switch
-
-        prop = rna_idprop_ui_prop_get(ik.hand_p, "ik", create=True)
-        ik.hand_p["ik"] = 0.5
-        prop["soft_min"] = 0.0
-        prop["soft_max"] = 1.0
-
-        bpy.ops.object.mode_set(mode='EDIT')
-
-    def chain_switch(prefix="MCH-%s"):
-        print(mt.obj.mode)
-        sw.update()
-        mt.update()
-
-        sw.shoulder_e = copy_bone_simple(arm, mt.shoulder, prefix % base_names[mt.shoulder])
-        sw.shoulder = sw.shoulder_e.name
-        sw.shoulder_e.parent = mt.shoulder_e.parent
-        sw.shoulder_e.connected = mt.shoulder_e.connected
-
-        sw.arm_e = copy_bone_simple(arm, mt.arm, prefix % base_names[mt.arm])

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list