[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [2034] trunk/py/scripts/addons/rigify: Rigify: new spine rig!

Nathan Vegdahl cessen at cessen.com
Wed Jun 15 03:55:58 CEST 2011


Revision: 2034
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=2034
Author:   cessen
Date:     2011-06-15 01:55:53 +0000 (Wed, 15 Jun 2011)
Log Message:
-----------
Rigify: new spine rig!

This rig replaces the old spine rig, and has a super-set of the old spine's
features.  The main new features are:
1. A separate over-all control for translation.  Due to the pivot slide
   feature of the spine, it didn't really make sense to have one of the
   spine bones be the control for translation, so I broke that out
   into a separate control.  This control also acts as a root of the
   spine in general, including for scaling and rotation.  If you
   want to grab the entire spine as one unit, this is how to do it.
2. The spine can now have more than two control bones.  The rigger
   can specify an arbitrary number of the spine bones to be
   turned into controls upon rig generation.
   Controls that are not at the end points of the spine
   are optionally (via an animatable switch) auto-rotated by the
   the end point controls, so animators can ignore them when they
   do not require that level of control.

Modified Paths:
--------------
    trunk/py/scripts/addons/rigify/metarigs/human.py
    trunk/py/scripts/addons/rigify/rigs/spine.py
    trunk/py/scripts/addons/rigify/utils.py

Modified: trunk/py/scripts/addons/rigify/metarigs/human.py
===================================================================
--- trunk/py/scripts/addons/rigify/metarigs/human.py	2011-06-14 00:23:05 UTC (rev 2033)
+++ trunk/py/scripts/addons/rigify/metarigs/human.py	2011-06-15 01:55:53 UTC (rev 2034)
@@ -470,6 +470,8 @@
     bpy.ops.object.mode_set(mode='OBJECT')
     pbone = obj.pose.bones[bones['hips']]
     pbone.rigify_type = 'spine'
+    pbone.rigify_parameters.add()
+    pbone.rigify_parameters[0].chain_bone_controls = "1, 2, 3"
     pbone.lock_location = (False, False, False)
     pbone.lock_rotation = (False, False, False)
     pbone.lock_rotation_w = False

Modified: trunk/py/scripts/addons/rigify/rigs/spine.py
===================================================================
--- trunk/py/scripts/addons/rigify/rigs/spine.py	2011-06-14 00:23:05 UTC (rev 2033)
+++ trunk/py/scripts/addons/rigify/rigs/spine.py	2011-06-15 01:55:53 UTC (rev 2034)
@@ -16,23 +16,31 @@
 #
 #======================= END GPL LICENSE BLOCK ========================
 
+""" TODO:
+    - Add parameters for bone transform alphas.
+"""
+
+from math import floor
+
 import bpy
 from mathutils import Vector
 from rigify.utils import MetarigError
-from rigify.utils import copy_bone, flip_bone, put_bone
+from rigify.utils import copy_bone, new_bone, flip_bone, put_bone
 from rigify.utils import connected_children_names
 from rigify.utils import strip_org, make_mechanism_name, make_deformer_name
-from rigify.utils import obj_to_bone, create_circle_widget
+from rigify.utils import obj_to_bone, create_circle_widget, create_compass_widget
 from rna_prop_ui import rna_idprop_ui_prop_get
 
 
 script = """
-hips = "%s"
-ribs = "%s"
-if is_selected([hips, ribs]):
-    layout.prop(pose_bones[ribs], '["pivot_slide"]', text="Pivot Slide (" + ribs + ")", slider=True)
-if is_selected(ribs):
-    layout.prop(pose_bones[ribs], '["isolate"]', text="Isolate Rotation (" + ribs + ")", slider=True)
+main = "%s"
+spine = [%s]
+if is_selected([main]+ spine):
+    layout.prop(pose_bones[main], '["pivot_slide"]', text="Pivot Slide (" + main + ")", slider=True)
+
+for name in spine[1:-1]:
+    if is_selected(name):
+        layout.prop(pose_bones[name], '["auto_rotate"]', text="Auto Rotate (" + name + ")", slider=True)
 """
 
 
@@ -49,6 +57,23 @@
         self.org_bones = [bone_name] + connected_children_names(obj, bone_name)
         self.params = params
 
+        # Collect control bone indices
+        self.control_indices = [0, len(self.org_bones) - 1]
+        temp = self.params.chain_bone_controls.split(",")
+        for i in temp:
+            try:
+                j = int(i) - 1
+            except ValueError:
+                pass
+            else:
+                if (j > 0) and (j < len(self.org_bones)) and (j not in self.control_indices):
+                    self.control_indices += [j]
+        self.control_indices.sort()
+
+        self.pivot_rest = self.params.rest_pivot_slide
+        self.pivot_rest = max(self.pivot_rest, 1.0/len(self.org_bones))
+        self.pivot_rest = min(self.pivot_rest, 1.0-(1.0/len(self.org_bones)))
+
         if len(self.org_bones) <= 1:
             raise MetarigError("RIGIFY ERROR: Bone '%s': input to rig type must be a chain of 2 or more bones." % (strip_org(bone)))
 
@@ -83,215 +108,200 @@
         """ Generate the control rig.
 
         """
-        #---------------------------------
-        # Create the hip and rib controls
         bpy.ops.object.mode_set(mode='EDIT')
+        eb = self.obj.data.edit_bones
+        #-------------------------
+        # Get rest slide position
+        a = self.pivot_rest * len(self.org_bones)
+        i = floor(a)
+        a -= i
+        if i == len(self.org_bones):
+            i -= 1
+            a = 1.0
 
-        # Copy org bones
-        hip_control = copy_bone(self.obj, self.org_bones[0], strip_org(self.org_bones[0]))
-        rib_control = copy_bone(self.obj, self.org_bones[-1], strip_org(self.org_bones[-1]))
-        rib_mch = copy_bone(self.obj, self.org_bones[-1], make_mechanism_name(strip_org(self.org_bones[-1] + ".follow")))
-        hinge = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(self.org_bones[-1]) + ".hinge"))
+        pivot_rest_pos = eb[self.org_bones[i]].head.copy()
+        pivot_rest_pos += eb[self.org_bones[i]].vector * a
 
+        #----------------------
+        # Create controls
+
+        # Create control bones
+        controls = []
+        for i in self.control_indices:
+            name = copy_bone(self.obj, self.org_bones[i], strip_org(self.org_bones[i]))
+            controls += [name]
+
+        # Create control parents
+        control_parents = []
+        for i in self.control_indices[1:-1]:
+            name = new_bone(self.obj, make_mechanism_name("par_" + strip_org(self.org_bones[i])))
+            control_parents += [name]
+
+        # Create sub-control bones
+        subcontrols = []
+        for i in self.control_indices:
+            name = new_bone(self.obj, make_mechanism_name("sub_" + strip_org(self.org_bones[i])))
+            subcontrols += [name]
+
+        # Create main control bone
+        main_control = new_bone(self.obj, self.params.spine_main_control_name)
+
+        # Create main control WGT bones
+        main_wgt1 = new_bone(self.obj, make_mechanism_name(self.params.spine_main_control_name + ".01"))
+        main_wgt2 = new_bone(self.obj, make_mechanism_name(self.params.spine_main_control_name + ".02"))
+
         eb = self.obj.data.edit_bones
 
-        hip_control_e = eb[hip_control]
-        rib_control_e = eb[rib_control]
-        rib_mch_e = eb[rib_mch]
-        hinge_e = eb[hinge]
+        # Parent the main control
+        eb[main_control].use_connect = False
+        eb[main_control].parent = eb[self.org_bones[0]].parent
 
-        # Parenting
-        hip_control_e.use_connect = False
-        rib_control_e.use_connect = False
-        rib_mch_e.use_connect = False
-        hinge_e.use_connect = False
+        # Parent the main WGTs
+        eb[main_wgt1].use_connect = False
+        eb[main_wgt1].parent = eb[main_control]
+        eb[main_wgt2].use_connect = False
+        eb[main_wgt2].parent = eb[main_wgt1]
 
-        hinge_e.parent = None
-        rib_control_e.parent = hinge_e
-        rib_mch_e.parent = rib_control_e
+        # Parent the controls and sub-controls
+        for name, subname in zip(controls, subcontrols):
+            eb[name].use_connect = False
+            eb[name].parent = eb[main_control]
+            eb[subname].use_connect = False
+            eb[subname].parent = eb[name]
 
-        # Position
-        flip_bone(self.obj, hip_control)
-        flip_bone(self.obj, hinge)
+        # Parent the control parents
+        for name, par_name in zip(controls[1:-1], control_parents):
+            eb[par_name].use_connect = False
+            eb[par_name].parent = eb[main_control]
+            eb[name].parent = eb[par_name]
 
-        hinge_e.length /= 2
-        rib_mch_e.length /= 2
+        # Position the main bone
+        put_bone(self.obj, main_control, pivot_rest_pos)
+        eb[main_control].length = sum([eb[b].length for b in self.org_bones]) / 2
 
-        put_bone(self.obj, rib_control, hip_control_e.head)
-        put_bone(self.obj, rib_mch, hip_control_e.head)
+        # Position the main WGTs
+        eb[main_wgt1].tail = (0.0, 0.0, sum([eb[b].length for b in self.org_bones]) / 4)
+        eb[main_wgt2].length = sum([eb[b].length for b in self.org_bones]) / 4
+        put_bone(self.obj, main_wgt1, pivot_rest_pos)
+        put_bone(self.obj, main_wgt2, pivot_rest_pos)
 
-        bpy.ops.object.mode_set(mode='POSE')
-        bpy.ops.object.mode_set(mode='EDIT')
-        eb = self.obj.data.edit_bones
+        # Position the controls and sub-controls
+        pos = eb[controls[0]].head.copy()
+        for name, subname in zip(controls, subcontrols):
+            put_bone(self.obj, name, pivot_rest_pos)
+            put_bone(self.obj, subname, pivot_rest_pos)
+            eb[subname].length = eb[name].length / 3
 
-        # Switch to object mode
+        # Position the control parents
+        for name, par_name in zip(controls[1:-1], control_parents):
+            put_bone(self.obj, par_name, pivot_rest_pos)
+            eb[par_name].length = eb[name].length / 2
+
+        #-----------------------------------------
+        # Control bone constraints and properties
         bpy.ops.object.mode_set(mode='OBJECT')
         pb = self.obj.pose.bones
-        hip_control_p = pb[hip_control]
-        rib_control_p = pb[rib_control]
-        hinge_p = pb[hinge]
 
-        # No translation on rib control
-        rib_control_p.lock_location = [True, True, True]
+        # Lock control locations
+        for name in controls:
+            bone = pb[name]
+            bone.lock_location = True, True, True
 
-        # Hip does not use local location
-        hip_control_p.bone.use_local_location = False
+        # Main control doesn't use local location
+        pb[main_control].bone.use_local_location = False
 
-        # Custom hinge property
-        prop = rna_idprop_ui_prop_get(rib_control_p, "isolate", create=True)
-        rib_control_p["isolate"] = 1.0
-        prop["soft_min"] = prop["min"] = 0.0
-        prop["soft_max"] = prop["max"] = 1.0
+        
 
-        # Constraints
-        con = hinge_p.constraints.new('COPY_LOCATION')
-        con.name = "copy_location"
-        con.target = self.obj
-        con.subtarget = hip_control
+        # Intermediate controls follow hips and spine
+        for name, par_name, i in zip(controls[1:-1], control_parents, self.control_indices[1:-1]):
+            bone = pb[par_name]
 
-        con1 = hinge_p.constraints.new('COPY_ROTATION')
-        con1.name = "isolate_off.01"
-        con1.target = self.obj
-        con1.subtarget = hip_control
+            # Custom bend_alpha property
+            prop = rna_idprop_ui_prop_get(pb[name], "bend_alpha", create=True)
+            pb[name]["bend_alpha"] = i / (len(self.org_bones) - 1)  # set bend alpha
+            prop["min"] = 0.0
+            prop["max"] = 1.0
+            prop["soft_min"] = 0.0
+            prop["soft_max"] = 1.0
 
-        con2 = rib_control_p.constraints.new('COPY_SCALE')
-        con2.name = "isolate_off.02"
-        con2.target = self.obj
-        con2.subtarget = hip_control
-        con2.use_offset = True

@@ Diff output truncated at 10240 characters. @@


More information about the Bf-extensions-cvs mailing list