[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [25039] trunk/blender/release/scripts/ modules: added autorig neck type

Campbell Barton ideasman42 at gmail.com
Tue Dec 1 01:45:36 CET 2009


Revision: 25039
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=25039
Author:   campbellbarton
Date:     2009-12-01 01:44:53 +0100 (Tue, 01 Dec 2009)

Log Message:
-----------
added autorig neck type

new bone properties
- bone.basename (name without the extension), "Some.Bone.001" --> "Some.Bone"
- bone.children_recursive_basename, gives a chain of children that have the same basename

Modified Paths:
--------------
    trunk/blender/release/scripts/modules/bpy_types.py
    trunk/blender/release/scripts/modules/rigify/__init__.py
    trunk/blender/release/scripts/modules/rigify/finger.py

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

Modified: trunk/blender/release/scripts/modules/bpy_types.py
===================================================================
--- trunk/blender/release/scripts/modules/bpy_types.py	2009-11-30 22:32:04 UTC (rev 25038)
+++ trunk/blender/release/scripts/modules/bpy_types.py	2009-12-01 00:44:53 UTC (rev 25039)
@@ -46,6 +46,7 @@
     functions for bones, common between Armature/Pose/Edit bones.
     internal subclassing use only.
     '''
+    
     def parent_index(self, parent_test):
         '''
         The same as 'bone in other_bone.parent_recursive' but saved generating a list.
@@ -64,6 +65,10 @@
         return 0
 
     @property
+    def basename(self):
+        return self.name.rsplit(".", 1)[0]
+
+    @property
     def parent_recursive(self):
         parent_list = []
         parent = self.parent
@@ -97,6 +102,35 @@
         return [bone for index, bone in bones_children]
 
     @property
+    def children_recursive_basename(self):
+        '''
+        Returns a chain of children with the same base name as this bone
+        Only direct chains are supported, forks caused by multiple children with matching basenames will.
+        '''
+        basename = self.basename
+        chain = []
+
+        child = self
+        while True:
+            children = child.children
+            children_basename = []
+
+            for child in children:
+                if basename == child.basename:
+                    children_basename.append(child)
+
+            if len(children_basename) == 1:
+                child = children_basename[0]
+                chain.append(child)
+            else:
+                if len(children_basename):
+                    print("multiple basenames found, this is probably not what you want!", bone.name, children_basename)
+
+                break
+        
+        return chain
+
+    @property
     def _other_bones(self):
         id_data = self.id_data
         id_data_type = type(id_data)

Modified: trunk/blender/release/scripts/modules/rigify/__init__.py
===================================================================
--- trunk/blender/release/scripts/modules/rigify/__init__.py	2009-11-30 22:32:04 UTC (rev 25038)
+++ trunk/blender/release/scripts/modules/rigify/__init__.py	2009-12-01 00:44:53 UTC (rev 25039)
@@ -79,9 +79,6 @@
     
     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)

Modified: trunk/blender/release/scripts/modules/rigify/finger.py
===================================================================
--- trunk/blender/release/scripts/modules/rigify/finger.py	2009-11-30 22:32:04 UTC (rev 25038)
+++ trunk/blender/release/scripts/modules/rigify/finger.py	2009-12-01 00:44:53 UTC (rev 25039)
@@ -17,7 +17,7 @@
 # ##### END GPL LICENSE BLOCK #####
 
 import bpy
-from rigify import get_bone_data, bone_basename, empty_layer
+from rigify import get_bone_data, empty_layer
 from rna_prop_ui import rna_idprop_ui_get, rna_idprop_ui_prop_get
 from functools import reduce
 
@@ -35,7 +35,7 @@
     children = orig_pbone.children_recursive
     tot_len = reduce(lambda f, pbone: f + pbone.bone.length, children, orig_pbone.bone.length)
     
-    base_name = bone_basename(orig_pbone.name)
+    base_name = orig_pbone.basename
     
     # first make a new bone at the location of the finger
     control_ebone = arm.edit_bones.new(base_name)

Added: trunk/blender/release/scripts/modules/rigify/neck.py
===================================================================
--- trunk/blender/release/scripts/modules/rigify/neck.py	                        (rev 0)
+++ trunk/blender/release/scripts/modules/rigify/neck.py	2009-12-01 00:44:53 UTC (rev 25039)
@@ -0,0 +1,194 @@
+# ##### 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
+from rna_prop_ui import rna_idprop_ui_prop_get
+
+
+def main(obj, orig_bone_name):
+    from Mathutils import Vector
+    
+    arm = obj.data
+
+    # Initialize container classes for convenience
+    mt = bone_class_instance(obj, ["body", "head"]) # meta
+    mt.head = orig_bone_name
+    mt.update()
+    mt.body = mt.head_e.parent.name
+    mt.update()
+
+    # child chain of the 'head'
+    children = mt.head_e.children
+    if len(children) != 1:
+        print("expected the head to have only 1 child.")
+
+    child = children[0]
+    neck_chain = [child] + child.children_recursive_basename
+    neck_chain = [child.name for child in neck_chain]
+    
+    mt_chain = bone_class_instance(obj, [("neck_%.2d" % (i + 1)) for i in range(len(neck_chain))]) # 99 bones enough eh?
+    for i, child_name in enumerate(neck_chain):
+        setattr(mt_chain, ("neck_%.2d" % (i + 1)), child_name)
+    mt_chain.update()
+
+    neck_chain_basename = mt_chain.neck_01_e.basename
+    neck_chain_segment_length = mt_chain.neck_01_e.length
+    
+    ex = bone_class_instance(obj, ["body", "head", "head_hinge","neck_socket"]) # hinge & extras
+    
+    # Add the head hinge at the bodys location, becomes the parent of the original head
+    
+    
+    # Copy the head bone and offset
+    ex.head_e = copy_bone_simple(arm, mt.head, "MCH_%s" % mt.head, parent=True)
+    ex.head = ex.head_e.name
+    # offset
+    head_length = ex.head_e.length
+    ex.head_e.head.y += head_length / 2.0
+    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 = 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.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.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)
+    ex.neck_socket_e.roll = 0.0
+    
+    # offset the head, not really needed since it has a copyloc constraint
+    mt.head_e.head.y += head_length / 4.0
+    mt.head_e.tail.y += head_length / 4.0
+
+    for i in range(len(neck_chain)):
+        neck_e = getattr(mt_chain, "neck_%.2d_e" % (i + 1))
+        
+        # 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.head = neck_e.head
+        neck_e_parent.tail = neck_e.head + Vector(0.0, 0.0, neck_chain_segment_length / 2.0)
+        neck_e_parent.roll = 0.0
+        
+        orig_parent = neck_e.parent
+        neck_e.connected = False
+        neck_e.parent = neck_e_parent
+        neck_e_parent.connected = False
+        
+        if i == 0:
+            neck_e_parent.parent = mt.body_e
+        else:
+            neck_e_parent.parent = orig_parent
+    
+    
+    bpy.ops.object.mode_set(mode='OBJECT')
+    
+    mt.update()
+    mt_chain.update()
+    ex.update()
+    
+    # Simple one off constraints, no drivers
+    con = mt.head_p.constraints.new('COPY_LOCATION')
+    con.target = obj
+    con.subtarget = ex.neck_socket
+    
+    con = ex.head_p.constraints.new('COPY_ROTATION')
+    con.target = obj
+    con.subtarget = mt.head
+    
+    # driven hinge
+    prop = rna_idprop_ui_prop_get(mt.head_p, "hinge", create=True)
+    mt.head_p["hinge"] = 0.0
+    prop["soft_min"] = 0.0
+    prop["soft_max"] = 1.0
+    
+    con = ex.head_hinge_p.constraints.new('COPY_ROTATION')
+    con.name = "hinge"
+    con.target = obj
+    con.subtarget = mt.body
+    
+    # add driver
+    hinge_driver_path = mt.head_p.path_to_id() + '["hinge"]'
+    
+    fcurve = con.driver_add("influence", 0)
+    driver = fcurve.driver
+    tar = driver.targets.new()
+    driver.type = 'AVERAGE'
+    tar.name = "var"
+    tar.id_type = 'OBJECT'
+    tar.id = obj
+    tar.rna_path = hinge_driver_path
+    
+    #mod = fcurve_driver.modifiers.new('GENERATOR')
+    mod = fcurve.modifiers[0]
+    mod.poly_order = 1
+    mod.coefficients[0] = 1.0
+    mod.coefficients[1] = -1.0
+    
+    head_driver_path = mt.head_p.path_to_id()
+    
+    # b01/max(0.001,b01+b02+b03+b04+b05)
+    target_names = [("b%.2d" % (i + 1)) for i in range(len(neck_chain))]
+    expression_suffix = "/max(0.001,%s)" % "+".join(target_names)
+    
+    
+    for i in range(len(neck_chain)):
+        neck_p = getattr(mt_chain, "neck_%.2d_p" % (i + 1))
+        neck_p.lock_location = True, True, True
+        neck_p.lock_location = True, True, True
+        neck_p.lock_rotations_4d = True
+        
+        # Add bend prop
+        prop_name = "bend_%.2d" % (i + 1)
+        prop = rna_idprop_ui_prop_get(mt.head_p, prop_name, create=True)
+        mt.head_p[prop_name] = 1.0
+        prop["soft_min"] = 0.0
+        prop["soft_max"] = 1.0
+        
+        # add parent constraint
+        neck_p_parent = neck_p.parent
+        
+        # add constraint
+        con = neck_p_parent.constraints.new('COPY_ROTATION')
+        con.name = "Copy Rotation"
+        con.target = obj
+        con.subtarget = ex.head
+        con.owner_space = 'LOCAL'
+        con.target_space = 'LOCAL'
+        
+        fcurve = con.driver_add("influence", 0)
+        driver = fcurve.driver
+        driver.type = 'SCRIPTED'
+        # b01/max(0.001,b01+b02+b03+b04+b05)
+        driver.expression = target_names[i] + expression_suffix

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list