Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2009-12-02 01:45:56 +0300
committerCampbell Barton <ideasman42@gmail.com>2009-12-02 01:45:56 +0300
commitc27f3adadcec0855fe15a059851551e0500d588a (patch)
treee1050542bfdcbd965da7f56caa6e5e08011441cf /release
parentce13cded15bb8429d495c3976eeab2e2d46dd104 (diff)
- rig spine type WIP, editmode done, still needs pose constraints and drivers.
- bone.translate(vec) utility function
Diffstat (limited to 'release')
-rw-r--r--release/scripts/modules/bpy_types.py6
-rw-r--r--release/scripts/modules/graphviz_export.py111
-rw-r--r--release/scripts/modules/rigify/spine.py187
3 files changed, 262 insertions, 42 deletions
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index 7727d30328f..4351ee7579b 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -46,7 +46,11 @@ class _GenericBone:
functions for bones, common between Armature/Pose/Edit bones.
internal subclassing use only.
'''
-
+
+ def translate(self, vec):
+ self.head += vec
+ self.tail += vec
+
def parent_index(self, parent_test):
'''
The same as 'bone in other_bone.parent_recursive' but saved generating a list.
diff --git a/release/scripts/modules/graphviz_export.py b/release/scripts/modules/graphviz_export.py
index c69a74f3d11..1e6d9ffe95b 100644
--- a/release/scripts/modules/graphviz_export.py
+++ b/release/scripts/modules/graphviz_export.py
@@ -26,12 +26,26 @@ footer = '''
}
'''
-def compat_str(text):
+def compat_str(text, line_length=22):
+
+ if line_length:
+ text_ls = []
+ while len(text) > line_length:
+ text_ls.append(text[:line_length])
+ text = text[line_length:]
+
+ if text:
+ text_ls.append(text)
+ text = '\n '.join(text_ls)
+
+
+ #text = text.replace('.', '.\n')
+ #text = text.replace(']', ']\n')
text = text.replace("\n", "\\n")
text = text.replace('"', '\\"')
- return text
+ return "* " + text
-def graph_armature(obj, path, FAKE_PARENT=True):
+def graph_armature(obj, path, FAKE_PARENT=True, CONSTRAINTS=True, DRIVERS=True):
file = open(path, "w")
fw = file.write
@@ -40,8 +54,15 @@ def graph_armature(obj, path, FAKE_PARENT=True):
arm = obj.data
- for bone in arm.bones:
- label = [bone.name]
+ bones = [bone.name for bone in arm.bones]
+ bones.sort()
+ print("")
+ for bone in bones:
+ b = arm.bones[bone]
+ print(">>", bone, ["*>", "->"][b.connected], getattr(getattr(b, "parent", ""), "name", ""))
+ label = [bone]
+ bone = arm.bones[bone]
+
for key, value in obj.pose.bones[bone.name].items():
if key.startswith("_"):
continue
@@ -53,7 +74,13 @@ def graph_armature(obj, path, FAKE_PARENT=True):
label.append("%s = %s" % (key, value))
- opts = ["shape=box", "regular=1", "style=filled", "fillcolor=white", 'width="2.33"', 'height="0.35"', "fixedsize=false", 'label="%s"' % compat_str('\n'.join(label))]
+ opts = ["shape=box", "regular=1", "style=filled", 'width="2.33"', 'height="0.35"', "fixedsize=false", 'label="%s"' % compat_str('\n'.join(label))]
+
+ if bone.name.startswith('ORG'):
+ opts.append("fillcolor=yellow")
+ else:
+ opts.append("fillcolor=white")
+
fw('"%s" [%s];\n' % (bone.name, ','.join(opts)))
@@ -80,43 +107,45 @@ def graph_armature(obj, path, FAKE_PARENT=True):
del bone
# constraints
- for pbone in obj.pose.bones:
- for constraint in pbone.constraints:
- subtarget = constraint.subtarget
- if subtarget:
- # TODO, not internal links
- opts = ['dir=forward', "weight=1", "arrowhead=normal", "arrowtail=none", "constraint=false", 'color="red"', 'labelfontsize=8']
- label = "%s\n%s" % (constraint.type, constraint.name)
- opts.append('label="%s"' % compat_str(label))
- fw('"%s" -> "%s" [%s] ;\n' % (subtarget, pbone.name, ','.join(opts)))
+ if CONSTRAINTS:
+ for pbone in obj.pose.bones:
+ for constraint in pbone.constraints:
+ subtarget = constraint.subtarget
+ if subtarget:
+ # TODO, not internal links
+ opts = ['dir=forward', "weight=1", "arrowhead=normal", "arrowtail=none", "constraint=false", 'color="red"', 'labelfontsize=4']
+ label = "%s\n%s" % (constraint.type, constraint.name)
+ opts.append('label="%s"' % compat_str(label))
+ fw('"%s" -> "%s" [%s] ;\n' % (subtarget, pbone.name, ','.join(opts)))
# Drivers
- def rna_path_as_pbone(rna_path):
- if not rna_path.startswith("pose.bones["):
- return None
+ if DRIVERS:
+ def rna_path_as_pbone(rna_path):
+ if not rna_path.startswith("pose.bones["):
+ return None
- #rna_path_bone = rna_path[:rna_path.index("]") + 1]
- #return obj.path_resolve(rna_path_bone)
- bone_name = rna_path.split("[")[1].split("]")[0]
- return obj.pose.bones[bone_name[1:-1]]
-
- animation_data = obj.animation_data
- if animation_data:
- for fcurve_driver in animation_data.drivers:
- rna_path = fcurve_driver.rna_path
- pbone = rna_path_as_pbone(rna_path)
-
- if pbone:
- for target in fcurve_driver.driver.targets:
- pbone_target = rna_path_as_pbone(target.rna_path)
- rna_path_target = target.rna_path
- if pbone_target:
- opts = ['dir=forward', "weight=1", "arrowhead=normal", "arrowtail=none", "constraint=false", 'color="blue"', "labelfontsize=8"] # ,
- display_source = rna_path.replace("pose.bones", "")
- display_target = rna_path_target.replace("pose.bones", "")
- label = "%s\\n%s" % (display_source, display_target)
- opts.append('label="%s"' % compat_str(label))
- fw('"%s" -> "%s" [%s] ;\n' % (pbone_target.name, pbone.name, ','.join(opts)))
+ #rna_path_bone = rna_path[:rna_path.index("]") + 1]
+ #return obj.path_resolve(rna_path_bone)
+ bone_name = rna_path.split("[")[1].split("]")[0]
+ return obj.pose.bones[bone_name[1:-1]]
+
+ animation_data = obj.animation_data
+ if animation_data:
+ for fcurve_driver in animation_data.drivers:
+ rna_path = fcurve_driver.rna_path
+ pbone = rna_path_as_pbone(rna_path)
+
+ if pbone:
+ for target in fcurve_driver.driver.targets:
+ pbone_target = rna_path_as_pbone(target.rna_path)
+ rna_path_target = target.rna_path
+ if pbone_target:
+ opts = ['dir=forward', "weight=1", "arrowhead=normal", "arrowtail=none", "constraint=false", 'color="blue"', "labelfontsize=4"] # ,
+ display_source = rna_path.replace("pose.bones", "")
+ display_target = rna_path_target.replace("pose.bones", "")
+ label = "%s\\n%s" % (display_source, display_target)
+ opts.append('label="%s"' % compat_str(label))
+ fw('"%s" -> "%s" [%s] ;\n' % (pbone_target.name, pbone.name, ','.join(opts)))
fw(footer)
file.close()
@@ -129,5 +158,5 @@ if __name__ == "__main__":
import bpy
import os
path ="/tmp/test.dot"
- graph_armature(bpy.context.object, path)
+ graph_armature(bpy.context.object, path, CONSTRAINTS=False, DRIVERS=False)
os.system("dot -Tpng %s > %s; eog %s &" % (path, path + '.png', path + '.png'))
diff --git a/release/scripts/modules/rigify/spine.py b/release/scripts/modules/rigify/spine.py
new file mode 100644
index 00000000000..ebc8b6ccdc0
--- /dev/null
+++ b/release/scripts/modules/rigify/spine.py
@@ -0,0 +1,187 @@
+# ##### 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 validate(obj, orig_bone_name):
+ '''
+ The bone given is the second in a chain.
+ Expects at least 1 parent and a chain of children withe the same basename
+ eg.
+ pelvis -> rib_cage -> spine.01 -> spine.02 -> spine.03
+ '''
+ orig_bone = obj.data.bones[orig_bone_name]
+ if not orig_bone.parent:
+ return "expected spine bone '%s' to have a parent" % orig_bone_name
+
+ children = orig_bone.children
+
+ if len(children) != 1:
+ return "expected spine bone '%s' to have only 1 child for the sine chain" % orig_bone_name
+
+ children_spine = children[0].children_recursive_basename
+
+ if len(children_spine) == 0:
+ return "expected '%s' to define a chain of children with its basename (2 or more)" % children[0]
+
+ return ''
+
+def main(obj, orig_bone_name):
+ from Mathutils import Vector, Matrix, RotationMatrix
+ from math import radians, pi
+
+ arm = obj.data
+
+ # Initialize container classes for convenience
+ mt = bone_class_instance(obj, ["pelvis", "ribcage"]) # meta
+ mt.ribcage = orig_bone_name
+ mt.update()
+ mt.pelvis = mt.ribcage_e.parent.name
+ mt.update()
+
+ children = mt.ribcage_e.children
+ child = children[0] # validate checks for 1 only.
+ spine_chain_basename = child.basename # probably 'spine'
+ spine_chain_segment_length = child.length
+ spine_chain = [child] + child.children_recursive_basename
+ spine_chain_orig = [child.name for child in spine_chain]
+ child.parent = mt.pelvis_e # was mt.ribcage
+
+ # The first bone in the chain happens to be the basis of others, create them now
+ ex = bone_class_instance(obj, ["pelvis", "ribcage", "ribcage_hinge", "spine_rotate"])
+ df = bone_class_instance(obj, ["pelvis", "ribcage"]) # DEF-wgt_pelvis, DEF-wgt_rib_cage
+
+
+ # copy the pelvis, offset to make MCH-spine_rotate and MCH-ribcage_hinge
+ ex.ribcage_hinge_e = copy_bone_simple(arm, mt.pelvis, "MCH-%s_hinge" % mt.ribcage)
+ ex.ribcage_hinge = ex.ribcage_hinge_e.name
+ ex.ribcage_hinge_e.translate(Vector(0.0, spine_chain_segment_length / 4.0, 0.0))
+ mt.ribcage_e.parent = ex.ribcage_hinge_e
+
+ ex.spine_rotate_e = copy_bone_simple(arm, mt.pelvis, "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.parent = mt.pelvis_e
+
+ df.pelvis_e = copy_bone_simple(arm, child.name, "DEF-wgt_%s" % mt.pelvis)
+ df.pelvis = df.pelvis_e.name
+ df.pelvis_e.translate(Vector(spine_chain_segment_length * 2.0, -spine_chain_segment_length, 0.0))
+
+ ex.pelvis_e = copy_bone_simple(arm, child.name, "MCH-wgt_%s" % mt.pelvis)
+ ex.pelvis = ex.pelvis_e.name
+ ex.pelvis_e.translate(Vector(0.0, -spine_chain_segment_length, 0.0))
+ ex.pelvis_e.parent = mt.pelvis_e
+
+ # Copy the last bone now
+ child = spine_chain[-1]
+
+ df.ribcage_e = copy_bone_simple(arm, child.name, "DEF-wgt_%s" % mt.ribcage)
+ df.ribcage = df.ribcage_e.name
+ df.ribcage_e.translate(Vector(spine_chain_segment_length * 2.0, -df.ribcage_e.length / 2.0, 0.0))
+
+ ex.ribcage_e = copy_bone_simple(arm, child.name, "MCH-wgt_%s" % mt.ribcage)
+ ex.ribcage = ex.ribcage_e.name
+ ex.ribcage_e.translate(Vector(0.0, -ex.ribcage_e.length / 2.0, 0.0))
+ ex.ribcage_e.parent = mt.ribcage_e
+
+ # rename!
+ for child in spine_chain:
+ child.name = "ORG-" + child.name
+
+ spine_chain = [child.name for child in spine_chain]
+
+ # We have 3 spine chains
+ # - original (ORG_*)
+ # - copy (*use original name*)
+ # - reverse (MCH-rev_*)
+ spine_chain_attrs = [("spine_%.2d" % (i + 1)) for i in range(len(spine_chain_orig))]
+ mt_chain = bone_class_instance(obj, spine_chain_attrs) # ORG_*
+ rv_chain = bone_class_instance(obj, spine_chain_attrs) # *
+ ex_chain = bone_class_instance(obj, spine_chain_attrs) # MCH-rev_*
+
+ for i, child_name in enumerate(spine_chain):
+ child_name_orig = spine_chain_orig[i]
+
+ attr = spine_chain_attrs[i] # eg. spine_04
+
+ setattr(mt_chain, attr, spine_chain[i]) # use the new name
+
+ ebone = copy_bone_simple(arm, child_name, child_name_orig) # use the original name
+ setattr(ex_chain, attr, ebone.name)
+
+ ebone = copy_bone_simple(arm, child_name, "MCH-rev_%s" % child_name_orig)
+ setattr(rv_chain, attr, ebone.name)
+ ebone.connected = False
+
+ mt_chain.update()
+ ex_chain.update()
+ rv_chain.update()
+
+ # Now we need to re-parent these chains
+ for i, child_name in enumerate(spine_chain_orig):
+ attr = spine_chain_attrs[i] + "_e"
+
+ if i == 0:
+ getattr(ex_chain, attr).parent = mt.pelvis_e
+ else:
+ attr_parent = spine_chain_attrs[i-1] + "_e"
+ getattr(ex_chain, attr).parent = getattr(ex_chain, attr_parent)
+
+ # intentional! get the parent from the other paralelle chain member
+ getattr(rv_chain, attr).parent = getattr(ex_chain, attr)
+
+
+ # ex_chain needs to interlace bones!
+ # Note, skip the first bone
+ for i in range(1, len(spine_chain_orig)): # similar to neck
+ child_name_orig = spine_chain_orig[i]
+ spine_e = getattr(mt_chain, spine_chain_attrs[i] + "_e")
+
+ # dont store parent names, re-reference as each chain bones parent.
+ spine_e_parent = arm.edit_bones.new("MCH-rot_%s" % child_name_orig)
+ spine_e_parent.head = spine_e.head
+ spine_e_parent.tail = spine_e.head + Vector(0.0, 0.0, spine_chain_segment_length / 2.0)
+ spine_e_parent.roll = 0.0
+
+ spine_e = getattr(ex_chain, spine_chain_attrs[i] + "_e")
+ orig_parent = spine_e.parent
+ spine_e.connected = False
+ spine_e.parent = spine_e_parent
+ spine_e_parent.connected = False
+
+ spine_e_parent.parent = orig_parent
+
+
+ # Rotate the rev chain 180 about the by the first bones center point
+ pivot = (rv_chain.spine_01_e.head + rv_chain.spine_01_e.tail) * 0.5
+ matrix = RotationMatrix(radians(180), 3, 'X')
+ for i in range(len(spine_chain_orig)): # similar to neck
+ spine_e = getattr(rv_chain, spine_chain_attrs[i] + "_e")
+ # use the first bone as the pivot
+
+ spine_e.head = ((spine_e.head - pivot) * matrix) + pivot
+ spine_e.tail = ((spine_e.tail - pivot) * matrix) + pivot
+ spine_e.roll += pi # 180d roll
+
+ # done with editmode
+ # TODO, posemode
+ \ No newline at end of file