[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [25026] trunk/blender/release/scripts/ modules: convert rigify into a package.

Campbell Barton ideasman42 at gmail.com
Mon Nov 30 13:31:11 CET 2009


Revision: 25026
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=25026
Author:   campbellbarton
Date:     2009-11-30 13:31:11 +0100 (Mon, 30 Nov 2009)

Log Message:
-----------
convert rigify into a package. advantage is new types can be added into the package without modifying any existing files, the bone 'type' property will find the matching submodule

Added Paths:
-----------
    trunk/blender/release/scripts/modules/rigify/
    trunk/blender/release/scripts/modules/rigify/__init__.py
    trunk/blender/release/scripts/modules/rigify/arm.py
    trunk/blender/release/scripts/modules/rigify/delta.py
    trunk/blender/release/scripts/modules/rigify/finger.py
    trunk/blender/release/scripts/modules/rigify/palm.py

Removed Paths:
-------------
    trunk/blender/release/scripts/modules/rigify.py

Copied: trunk/blender/release/scripts/modules/rigify/__init__.py (from rev 25022, trunk/blender/release/scripts/modules/rigify.py)
===================================================================
--- trunk/blender/release/scripts/modules/rigify/__init__.py	                        (rev 0)
+++ trunk/blender/release/scripts/modules/rigify/__init__.py	2009-11-30 12:31:11 UTC (rev 25026)
@@ -0,0 +1,236 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+import bpy
+from Mathutils import Vector
+
+# TODO, have these in a more general module
+from rna_prop_ui import rna_idprop_ui_get, rna_idprop_ui_prop_get
+
+empty_layer = [False] * 32
+
+def auto_class(slots, name="ContainerClass"):
+    return type(name, (object,), {"__slots__":tuple(slots)})
+    
+def auto_class_instance(slots, name="ContainerClass"):
+    return auto_class(slots, name)()
+
+def bone_class_instance(obj, slots, name="BoneContainer"):
+    for member in slots[:]:
+        slots.append(member + "_b") # bone bone
+        slots.append(member + "_p") # pose bone
+        slots.append(member + "_e") # edit bone
+    
+    slots.extend(["obj", "update"])
+    
+    instance = auto_class_instance(slots, name)
+    
+    def update():
+        '''
+        Re-Assigns bones from the blender data
+        '''
+        arm = obj.data
+        
+        bbones = arm.bones
+        pbones = obj.pose.bones
+        ebones = arm.edit_bones
+        
+        for member in slots:
+            
+            if member in ("update", "obj"):
+                continue
+            
+            if not member[-2] == "_":
+                name = getattr(instance, member, None)
+                if name is not None:
+                    setattr(instance, member + "_b", bbones.get(name, None))
+                    setattr(instance, member + "_p", pbones.get(name, None))
+                    setattr(instance, member + "_e", ebones.get(name, None))
+        
+    instance.update = update
+    
+    return instance
+
+def gen_none(obj, orig_bone_name):
+    pass
+
+def get_bone_data(obj, bone_name):
+    arm = obj.data
+    pbone = obj.pose.bones[bone_name]
+    if obj.mode == 'EDIT':
+        bone = arm.edit_bones[bone_name]
+    else:
+        bone = arm.bones[bone_name]
+    
+    return arm, pbone, bone
+
+def bone_basename(name):
+    return name.split(".")[0]
+
+def copy_bone_simple(arm, from_bone, name, parent=False):
+    ebone = arm.edit_bones[from_bone]
+    ebone_new = arm.edit_bones.new(name)
+    
+    if parent:
+        ebone_new.connected = ebone.connected
+        ebone_new.parent = ebone.parent
+    
+    ebone_new.head = ebone.head
+    ebone_new.tail = ebone.tail
+    ebone_new.roll = ebone.roll
+    return ebone_new
+
+
+def add_stretch_to(obj, from_name, to_name, name):
+    '''
+    Adds a bone that stretches from one to another
+    '''
+    
+    mode_orig = obj.mode
+    bpy.ops.object.mode_set(mode='EDIT')
+
+    arm = obj.data
+    stretch_ebone = arm.edit_bones.new(name)
+    stretch_name = stretch_ebone.name
+    del name
+    
+    head = stretch_ebone.head = arm.edit_bones[from_name].head.copy()
+    #tail = stretch_ebone.tail = arm.edit_bones[to_name].head.copy()
+    
+    # annoying exception for zero length bones, since its using stretch_to the rest pose doesnt really matter
+    #if (head - tail).length < 0.1:
+    if 1:
+        tail = stretch_ebone.tail = arm.edit_bones[from_name].tail.copy()
+
+
+    # Now for the constraint
+    bpy.ops.object.mode_set(mode='OBJECT')
+    from_pbone = obj.pose.bones[from_name]
+    to_pbone = obj.pose.bones[to_name]
+    
+    stretch_pbone = obj.pose.bones[stretch_name]
+    
+    con = stretch_pbone.constraints.new('COPY_LOCATION')
+    con.target = obj
+    con.subtarget = from_name
+    
+    con = stretch_pbone.constraints.new('STRETCH_TO')
+    con.target = obj
+    con.subtarget = to_name   
+    con.original_length = (head - tail).length
+    con.keep_axis = 'PLANE_X'
+    con.volume = 'NO_VOLUME'
+
+    bpy.ops.object.mode_set(mode=mode_orig)
+
+
+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
+    '''
+    mode_orig = obj.mode
+    bpy.ops.object.mode_set(mode='EDIT')
+    
+    arm = obj.data
+    
+    poll_ebone = arm.edit_bones.new(base_name + "_poll")
+    base_ebone = arm.edit_bones[base_name]
+    poll_name = poll_ebone.name
+    parent_ebone = base_ebone.parent
+    
+    base_head = base_ebone.head.copy()
+    base_tail = base_ebone.tail.copy()
+    base_dir = base_head - base_tail
+    
+    parent_head = parent_ebone.head.copy()
+    parent_tail = parent_ebone.tail.copy()
+    parent_dir = parent_head - parent_tail
+    
+    distance = (base_dir.length + parent_dir.length)
+    
+    if mode == 'CROSS':
+        offset = base_dir.copy().normalize() - parent_dir.copy().normalize()
+        offset.length = distance
+    else:
+        offset = Vector(0,0,0)
+        if mode[0]=="+":
+            val = distance
+        else:
+            val = -distance
+        
+        setattr(offset, mode[1].lower(), val)
+    
+    poll_ebone.head = base_head + offset
+    poll_ebone.tail = base_head + (offset * (1.0 - (1.0 / 4.0)))
+    
+    bpy.ops.object.mode_set(mode=mode_orig)
+    
+    return poll_name
+
+
+def generate_rig(context, ob):
+    
+    global_undo = context.user_preferences.edit.global_undo
+    context.user_preferences.edit.global_undo = False
+    
+    # add_stretch_to(ob, "a", "b", "c")
+
+    bpy.ops.object.mode_set(mode='OBJECT')
+    
+    
+    # copy object and data
+    ob.selected = False
+    ob_new = ob.copy()
+    ob_new.data = ob.data.copy()
+    scene = context.scene
+    scene.objects.link(ob_new)
+    scene.objects.active = ob_new
+    ob_new.selected = True
+    
+    # enter armature editmode
+    
+    
+    for pbone_name in ob_new.pose.bones.keys():
+        bone_type = ob_new.pose.bones[pbone_name].get("type", "")
+
+        if bone_type == "":
+        	continue
+
+        # submodule = getattr(self, bone_type)
+        # exec("from rigify import %s as submodule")
+        submodule = __import__(name="%s.%s" % (__package__, bone_type), fromlist=[bone_type])
+
+        reload(submodule) # XXX, dev only
+
+        
+        # Toggle editmode so the pose data is always up to date
+        bpy.ops.object.mode_set(mode='EDIT')
+        submodule.main(ob_new, pbone_name)
+        bpy.ops.object.mode_set(mode='OBJECT')
+    
+    # needed to update driver deps
+    # context.scene.update()
+    
+    # Only for demo'ing
+    ob.restrict_view = True
+    ob_new.data.draw_axes = False
+    
+    context.user_preferences.edit.global_undo = global_undo
+
+if __name__ == "__main__":
+    generate_rig(bpy.context, bpy.context.object)


Property changes on: trunk/blender/release/scripts/modules/rigify/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Author Date Id Revision
Name: svn:mergeinfo
   + 
Name: svn:eol-style
   + native

Added: trunk/blender/release/scripts/modules/rigify/arm.py
===================================================================
--- trunk/blender/release/scripts/modules/rigify/arm.py	                        (rev 0)
+++ trunk/blender/release/scripts/modules/rigify/arm.py	2009-11-30 12:31:11 UTC (rev 25026)
@@ -0,0 +1,315 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+import bpy
+from rigify import bone_class_instance, copy_bone_simple, add_pole_target_bone, add_stretch_to
+from rna_prop_ui import rna_idprop_ui_get, rna_idprop_ui_prop_get
+
+
+def main(obj, orig_bone_name):
+    """
+    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, ["shoulder", "arm", "forearm", "hand"]) # meta
+    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
+    
+    
+    def chain_init():
+        '''
+        Sanity check and return the arm as a list of bone names.
+        '''
+        # do a sanity check
+        mt.arm = orig_bone_name
+        mt.update()
+        
+        mt.shoulder_p = mt.arm_p.parent
+        mt.shoulder = mt.shoulder_p.name
+        
+        if not mt.shoulder_p:
+            print("could not find 'arm' parent, skipping:", orig_bone_name)
+            return
+
+        # We could have some bones attached, find the bone that has this as its 2nd parent
+        hands = []
+        for pbone in obj.pose.bones:

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list