pep8 edits and fix some warnings
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
# internal blender C module
|
||||
import _bpy
|
||||
from _bpy import types, props
|
||||
@@ -38,8 +40,8 @@ def load_scripts(reload_scripts=False):
|
||||
import os
|
||||
import traceback
|
||||
import time
|
||||
|
||||
|
||||
|
||||
|
||||
t_main = time.time()
|
||||
|
||||
def test_import(module_name):
|
||||
@@ -52,7 +54,7 @@ def load_scripts(reload_scripts=False):
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return None
|
||||
|
||||
|
||||
|
||||
for base_path in utils.script_paths():
|
||||
for path_subdir in ("ui", "op", "io"):
|
||||
|
||||
@@ -59,7 +59,7 @@ class bpy_ops(object):
|
||||
|
||||
def add(self, pyop):
|
||||
op_add(pyop)
|
||||
|
||||
|
||||
def add_macro(self, pyop):
|
||||
op_add_macro(pyop)
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
import os
|
||||
|
||||
@@ -58,7 +60,7 @@ _scripts = (os.path.normpath(_scripts), )
|
||||
|
||||
def script_paths(*args):
|
||||
scripts = list(_scripts)
|
||||
|
||||
|
||||
# add user scripts dir
|
||||
user_script_path = bpy.context.user_preferences.filepaths.python_scripts_directory
|
||||
|
||||
@@ -84,11 +86,11 @@ def script_paths(*args):
|
||||
return script_paths
|
||||
|
||||
|
||||
_presets = os.path.join(_scripts[0], "presets") # FIXME - multiple paths
|
||||
_presets = os.path.join(_scripts[0], "presets") # FIXME - multiple paths
|
||||
|
||||
def preset_paths(subdir):
|
||||
'''
|
||||
Returns a list of paths for a spesific preset.
|
||||
'''
|
||||
|
||||
return (os.path.join(_presets, subdir), )
|
||||
'''
|
||||
Returns a list of paths for a spesific preset.
|
||||
'''
|
||||
|
||||
return (os.path.join(_presets, subdir), )
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
from _bpy import types as bpy_types
|
||||
|
||||
StructRNA = bpy_types.Struct.__bases__[0]
|
||||
@@ -57,7 +60,7 @@ class _GenericBone:
|
||||
'''
|
||||
# use the name so different types can be tested.
|
||||
name = parent_test.name
|
||||
|
||||
|
||||
parent = self.parent
|
||||
i = 1
|
||||
while parent:
|
||||
@@ -65,7 +68,7 @@ class _GenericBone:
|
||||
return i
|
||||
parent = parent.parent
|
||||
i += 1
|
||||
|
||||
|
||||
return 0
|
||||
|
||||
@property
|
||||
@@ -76,19 +79,19 @@ class _GenericBone:
|
||||
def parent_recursive(self):
|
||||
parent_list = []
|
||||
parent = self.parent
|
||||
|
||||
|
||||
while parent:
|
||||
if parent:
|
||||
parent_list.append(parent)
|
||||
|
||||
|
||||
parent = parent.parent
|
||||
|
||||
|
||||
return parent_list
|
||||
|
||||
@property
|
||||
def length(self):
|
||||
return (self.head - self.tail).length
|
||||
|
||||
|
||||
@length.setter
|
||||
def length(self, value):
|
||||
"""The distance from head to tail"""
|
||||
@@ -105,7 +108,7 @@ class _GenericBone:
|
||||
index = bone.parent_index(self)
|
||||
if index:
|
||||
bones_children.append((index, bone))
|
||||
|
||||
|
||||
# sort by distance to parent
|
||||
bones_children.sort(key=lambda bone_pair: bone_pair[0])
|
||||
return [bone for index, bone in bones_children]
|
||||
@@ -136,21 +139,21 @@ class _GenericBone:
|
||||
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)
|
||||
|
||||
|
||||
if id_data_type == bpy_types.Object:
|
||||
bones = id_data.pose.bones
|
||||
elif id_data_type == bpy_types.Armature:
|
||||
bones = id_data.edit_bones
|
||||
if not bones: # not in editmode
|
||||
bones = id_data.bones
|
||||
|
||||
|
||||
return bones
|
||||
|
||||
|
||||
@@ -166,34 +169,36 @@ class EditBone(StructRNA, _GenericBone):
|
||||
pass
|
||||
|
||||
|
||||
def ord_ind(i1,i2):
|
||||
if i1<i2: return i1,i2
|
||||
return i2,i1
|
||||
def ord_ind(i1, i2):
|
||||
if i1 < i2:
|
||||
return i1, i2
|
||||
return i2, i1
|
||||
|
||||
|
||||
class Mesh(bpy_types.ID):
|
||||
|
||||
|
||||
def from_pydata(self, verts, edges, faces):
|
||||
'''
|
||||
Make a mesh from a list of verts/edges/faces
|
||||
Until we have a nicer way to make geometry, use this.
|
||||
'''
|
||||
self.add_geometry(len(verts), len(edges), len(faces))
|
||||
|
||||
|
||||
verts_flat = [f for v in verts for f in v]
|
||||
self.verts.foreach_set("co", verts_flat)
|
||||
del verts_flat
|
||||
|
||||
|
||||
edges_flat = [i for e in edges for i in e]
|
||||
self.edges.foreach_set("verts", edges_flat)
|
||||
del edges_flat
|
||||
|
||||
|
||||
def treat_face(f):
|
||||
if len(f) == 3:
|
||||
return f[0], f[1], f[2], 0
|
||||
elif f[3] == 0:
|
||||
return f[3], f[0], f[1], f[2]
|
||||
return f
|
||||
|
||||
|
||||
faces_flat = [v for f in faces for v in treat_face(f)]
|
||||
self.faces.foreach_set("verts_raw", faces_flat)
|
||||
del faces_flat
|
||||
@@ -233,17 +238,21 @@ class MeshFace(StructRNA):
|
||||
@property
|
||||
def edge_keys(self):
|
||||
verts = tuple(self.verts)
|
||||
if len(verts)==3:
|
||||
return ord_ind(verts[0], verts[1]), ord_ind(verts[1], verts[2]), ord_ind(verts[2], verts[0])
|
||||
if len(verts) == 3:
|
||||
return ord_ind(verts[0], verts[1]), ord_ind(verts[1], verts[2]), ord_ind(verts[2], verts[0])
|
||||
|
||||
return ord_ind(verts[0], verts[1]), ord_ind(verts[1], verts[2]), ord_ind(verts[2], verts[3]), ord_ind(verts[3], verts[0])
|
||||
return ord_ind(verts[0], verts[1]), ord_ind(verts[1], verts[2]), ord_ind(verts[2], verts[3]), ord_ind(verts[3], verts[0])
|
||||
|
||||
|
||||
import collections
|
||||
|
||||
|
||||
class OrderedMeta(type):
|
||||
|
||||
def __init__(cls, name, bases, attributes):
|
||||
super(OrderedMeta, cls).__init__(name, bases, attributes)
|
||||
cls.order = list(attributes.keys())
|
||||
|
||||
def __prepare__(name, bases, **kwargs):
|
||||
return collections.OrderedDict()
|
||||
|
||||
@@ -252,32 +261,35 @@ class OrderedMeta(type):
|
||||
class Operator(StructRNA, metaclass=OrderedMeta):
|
||||
pass
|
||||
|
||||
|
||||
class Macro(StructRNA, metaclass=OrderedMeta):
|
||||
# bpy_types is imported before ops is defined
|
||||
# so we have to do a local import on each run
|
||||
|
||||
@classmethod
|
||||
def define(self, opname):
|
||||
from _bpy import ops
|
||||
return ops.macro_define(self, opname)
|
||||
|
||||
|
||||
class Menu(StructRNA):
|
||||
|
||||
|
||||
def path_menu(self, searchpaths, operator):
|
||||
layout = self.layout
|
||||
# hard coded to set the operators 'path' to the filename.
|
||||
|
||||
|
||||
import os
|
||||
|
||||
def path_to_name(f):
|
||||
''' Only capitalize all lowercase names, mixed case use them as is.
|
||||
'''
|
||||
f_base = os.path.splitext(f)[0]
|
||||
|
||||
|
||||
# string replacements
|
||||
f_base = f_base.replace("_colon_", ":")
|
||||
|
||||
|
||||
f_base = f_base.replace("_", " ")
|
||||
|
||||
|
||||
if f_base.lower() == f_base:
|
||||
return ' '.join([w[0].upper() + w[1:] for w in f_base.split()])
|
||||
else:
|
||||
@@ -298,7 +310,7 @@ class Menu(StructRNA):
|
||||
continue
|
||||
|
||||
layout.operator(operator, text=path_to_name(f)).path = path
|
||||
|
||||
|
||||
def draw_preset(self, context):
|
||||
'''Define these on the subclass
|
||||
- preset_operator
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
|
||||
|
||||
def collect_baseclasses(_class, bases):
|
||||
|
||||
if _class is type or _class is object:
|
||||
@@ -29,6 +32,7 @@ def collect_baseclasses(_class, bases):
|
||||
|
||||
return bases
|
||||
|
||||
|
||||
def collect_subclasses(_class, subs):
|
||||
|
||||
if _class is type or _class is object:
|
||||
@@ -40,6 +44,7 @@ def collect_subclasses(_class, subs):
|
||||
|
||||
return subs
|
||||
|
||||
|
||||
class DynMenu(bpy.types.Menu):
|
||||
|
||||
def draw(self, context):
|
||||
@@ -61,6 +66,7 @@ class DynMenu(bpy.types.Menu):
|
||||
subclass.internal_draw(self, context)
|
||||
# print("subclass.internal_draw", subclass.internal_draw)
|
||||
|
||||
|
||||
def setup(menu_class):
|
||||
'''
|
||||
Setup subclasses (not needed when self.add() is used)
|
||||
@@ -88,6 +94,7 @@ def setup(menu_class):
|
||||
|
||||
root_class.draw = DynMenu.draw
|
||||
|
||||
|
||||
def add(menu_class, func):
|
||||
'''
|
||||
Add a single function directly without having to make a class
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
|
||||
header = '''
|
||||
@@ -28,6 +30,7 @@ footer = '''
|
||||
}
|
||||
'''
|
||||
|
||||
|
||||
def compat_str(text, line_length=0):
|
||||
|
||||
if line_length:
|
||||
@@ -35,28 +38,29 @@ def compat_str(text, line_length=0):
|
||||
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
|
||||
|
||||
|
||||
def graph_armature(obj, path, FAKE_PARENT=True, CONSTRAINTS=True, DRIVERS=True, XTRA_INFO=False):
|
||||
CONSTRAINTS = DRIVERS = True
|
||||
|
||||
file = open(path, "w")
|
||||
fw = file.write
|
||||
|
||||
fileobject = open(path, "w")
|
||||
fw = fileobject.write
|
||||
fw(header)
|
||||
fw('label = "%s::%s" ;' % (bpy.data.filename.split("/")[-1].split("\\")[-1], obj.name))
|
||||
|
||||
|
||||
arm = obj.data
|
||||
|
||||
|
||||
bones = [bone.name for bone in arm.bones]
|
||||
bones.sort()
|
||||
print("")
|
||||
@@ -65,37 +69,37 @@ def graph_armature(obj, path, FAKE_PARENT=True, CONSTRAINTS=True, DRIVERS=True,
|
||||
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
|
||||
|
||||
|
||||
if type(value) == float:
|
||||
value = "%.3f" % value
|
||||
elif type(value) == str:
|
||||
value = compat_str(value)
|
||||
|
||||
|
||||
label.append("%s = %s" % (key, value))
|
||||
|
||||
|
||||
opts = ["shape=box", "regular=1", "style=filled", "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)))
|
||||
|
||||
|
||||
fw('\n\n# Hierarchy:\n')
|
||||
|
||||
|
||||
# Root node.
|
||||
if FAKE_PARENT:
|
||||
fw('"Object::%s" [];\n' % obj.name)
|
||||
|
||||
|
||||
for bone in bones:
|
||||
bone = arm.bones[bone]
|
||||
|
||||
|
||||
parent = bone.parent
|
||||
if parent:
|
||||
parent_name = parent.name
|
||||
@@ -105,14 +109,14 @@ def graph_armature(obj, path, FAKE_PARENT=True, CONSTRAINTS=True, DRIVERS=True,
|
||||
connected = False
|
||||
else:
|
||||
continue
|
||||
|
||||
|
||||
opts = ["dir=forward", "weight=2", "arrowhead=normal"]
|
||||
if not connected:
|
||||
opts.append("style=dotted")
|
||||
|
||||
|
||||
fw('"%s" -> "%s" [%s] ;\n' % (bone.name, parent_name, ','.join(opts)))
|
||||
del bone
|
||||
|
||||
del bone
|
||||
|
||||
# constraints
|
||||
if CONSTRAINTS:
|
||||
fw('\n\n# Constraints:\n')
|
||||
@@ -128,10 +132,11 @@ def graph_armature(obj, path, FAKE_PARENT=True, CONSTRAINTS=True, DRIVERS=True,
|
||||
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
|
||||
if DRIVERS:
|
||||
fw('\n\n# Drivers:\n')
|
||||
|
||||
def rna_path_as_pbone(rna_path):
|
||||
if not rna_path.startswith("pose.bones["):
|
||||
return None
|
||||
@@ -140,33 +145,33 @@ def graph_armature(obj, path, FAKE_PARENT=True, CONSTRAINTS=True, DRIVERS=True,
|
||||
#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:
|
||||
|
||||
|
||||
fcurve_drivers = [fcurve_driver for fcurve_driver in animation_data.drivers]
|
||||
fcurve_drivers.sort(key=lambda fcurve_driver: fcurve_driver.rna_path)
|
||||
|
||||
|
||||
for fcurve_driver in fcurve_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"] # ,
|
||||
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", "")
|
||||
if XTRA_INFO:
|
||||
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()
|
||||
|
||||
fileobject.close()
|
||||
|
||||
'''
|
||||
print(".", end='')
|
||||
import sys
|
||||
@@ -176,8 +181,7 @@ def graph_armature(obj, path, FAKE_PARENT=True, CONSTRAINTS=True, DRIVERS=True,
|
||||
return True
|
||||
|
||||
if __name__ == "__main__":
|
||||
import bpy
|
||||
import os
|
||||
path ="/tmp/test.dot"
|
||||
graph_armature(bpy.context.object, path, CONSTRAINTS=True, DRIVERS=True)
|
||||
os.system("dot -Tpng %s > %s; eog %s &" % (path, path + '.png', path + '.png'))
|
||||
tmppath = "/tmp/test.dot"
|
||||
graph_armature(bpy.context.object, tmppath, CONSTRAINTS=True, DRIVERS=True)
|
||||
os.system("dot -Tpng %s > %s; eog %s &" % (tmppath, tmppath + '.png', tmppath + '.png'))
|
||||
|
||||
@@ -118,7 +118,7 @@ class Hub(object):
|
||||
return faces
|
||||
|
||||
|
||||
class Spline:
|
||||
class Spline(object):
|
||||
__slots__ = "points", "hubs", "length"
|
||||
|
||||
def __init__(self, points):
|
||||
@@ -170,13 +170,15 @@ def get_points(stroke):
|
||||
|
||||
|
||||
def get_splines(gp):
|
||||
l = None
|
||||
for l in gp.layers:
|
||||
if l.active: # XXX - should be layers.active
|
||||
break
|
||||
|
||||
frame = l.active_frame
|
||||
|
||||
return [Spline(get_points(stroke)) for stroke in frame.strokes]
|
||||
if l:
|
||||
frame = l.active_frame
|
||||
return [Spline(get_points(stroke)) for stroke in frame.strokes]
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
def xsect_spline(sp_a, sp_b, _hubs):
|
||||
|
||||
@@ -16,25 +16,29 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
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
|
||||
from rna_prop_ui import rna_idprop_ui_prop_get
|
||||
|
||||
empty_layer = [False] * 32
|
||||
|
||||
|
||||
def auto_class(slots, name="ContainerClass", class_dict=None):
|
||||
|
||||
|
||||
if class_dict:
|
||||
class_dict = class_dict.copy()
|
||||
else:
|
||||
class_dict = {}
|
||||
|
||||
class_dict["__slots__"] = tuple(slots)
|
||||
|
||||
|
||||
return type(name, (object,), class_dict)
|
||||
|
||||
|
||||
|
||||
def auto_class_instance(slots, name="ContainerClass", class_dict=None):
|
||||
return auto_class(slots, name, class_dict)()
|
||||
|
||||
@@ -46,7 +50,7 @@ def _bone_class_instance_update(self):
|
||||
bbones = arm.bones
|
||||
pbones = self.obj.pose.bones
|
||||
ebones = arm.edit_bones
|
||||
|
||||
|
||||
for member in self.attr_names:
|
||||
name = getattr(self, member, None)
|
||||
if name is not None:
|
||||
@@ -58,16 +62,16 @@ def _bone_class_instance_update(self):
|
||||
def _bone_class_instance_rename(self, attr, new_name):
|
||||
''' Rename bones, editmode only
|
||||
'''
|
||||
|
||||
|
||||
if self.obj.mode != 'EDIT':
|
||||
raise Exception("Only rename in editmode supported")
|
||||
|
||||
|
||||
ebone = getattr(self, attr + "_e")
|
||||
ebone.name = new_name
|
||||
|
||||
|
||||
# we may not get what is asked for so get the name from the editbone
|
||||
setattr(self, attr, ebone.name)
|
||||
|
||||
|
||||
|
||||
def _bone_class_instance_copy(self, from_prefix="", to_prefix=""):
|
||||
from_name_ls = []
|
||||
@@ -78,7 +82,7 @@ def _bone_class_instance_copy(self, from_prefix="", to_prefix=""):
|
||||
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
|
||||
@@ -86,14 +90,14 @@ def _bone_class_instance_copy(self, from_prefix="", to_prefix=""):
|
||||
bone_name = ebone.name # cant be sure we get what we ask for
|
||||
else:
|
||||
bone_name = bone_name_orig
|
||||
|
||||
|
||||
setattr(self, attr, bone_name)
|
||||
|
||||
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)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
@@ -104,28 +108,31 @@ def _bone_class_instance_copy(self, from_prefix="", to_prefix=""):
|
||||
|
||||
return new_bc
|
||||
|
||||
|
||||
def _bone_class_instance_names(self):
|
||||
return [getattr(self, attr) for attr in self.attr_names]
|
||||
|
||||
|
||||
def _bone_class_instance_blend(self, from_bc, to_bc, target_bone=None, target_prop="blend"):
|
||||
'''
|
||||
Use for blending bone chains.
|
||||
|
||||
|
||||
blend_target = (bone_name, bone_property)
|
||||
default to the last bone, blend prop
|
||||
|
||||
|
||||
XXX - toggles editmode, need to re-validate all editbones :(
|
||||
'''
|
||||
|
||||
if self.attr_names != from_bc.attr_names or self.attr_names != to_bc.attr_names:
|
||||
raise Exception("can only blend between matching chains")
|
||||
|
||||
|
||||
apply_bones = [getattr(self, attr) for attr in self.attr_names]
|
||||
from_bones = [getattr(from_bc, attr) for attr in from_bc.attr_names]
|
||||
to_bones = [getattr(to_bc, attr) for attr in to_bc.attr_names]
|
||||
|
||||
|
||||
blend_bone_list(self.obj, apply_bones, from_bones, to_bones, target_bone, target_prop)
|
||||
|
||||
|
||||
def bone_class_instance(obj, slots, name="BoneContainer"):
|
||||
attr_names = tuple(slots) # dont modify the original
|
||||
slots = list(slots) # dont modify the original
|
||||
@@ -136,20 +143,18 @@ def bone_class_instance(obj, slots, name="BoneContainer"):
|
||||
slots.append(member + "_e") # edit bone
|
||||
|
||||
class_dict = { \
|
||||
"obj":obj, \
|
||||
"attr_names":attr_names, \
|
||||
"update":_bone_class_instance_update, \
|
||||
"rename":_bone_class_instance_rename, \
|
||||
"names":_bone_class_instance_names, \
|
||||
"copy":_bone_class_instance_copy, \
|
||||
"blend":_bone_class_instance_blend, \
|
||||
"obj": obj, \
|
||||
"attr_names": attr_names, \
|
||||
"update": _bone_class_instance_update, \
|
||||
"rename": _bone_class_instance_rename, \
|
||||
"names": _bone_class_instance_names, \
|
||||
"copy": _bone_class_instance_copy, \
|
||||
"blend": _bone_class_instance_blend, \
|
||||
}
|
||||
|
||||
instance = auto_class_instance(slots, name, class_dict)
|
||||
return instance
|
||||
|
||||
def gen_none(obj, orig_bone_name):
|
||||
pass
|
||||
|
||||
def get_bone_data(obj, bone_name):
|
||||
arm = obj.data
|
||||
@@ -158,9 +163,10 @@ def get_bone_data(obj, bone_name):
|
||||
bone = arm.edit_bones[bone_name]
|
||||
else:
|
||||
bone = arm.bones[bone_name]
|
||||
|
||||
|
||||
return arm, pbone, bone
|
||||
|
||||
|
||||
def copy_bone_simple(arm, from_bone, name, parent=False):
|
||||
ebone = arm.edit_bones[from_bone]
|
||||
ebone_new = arm.edit_bones.new(name)
|
||||
@@ -168,7 +174,7 @@ def copy_bone_simple(arm, from_bone, name, parent=False):
|
||||
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
|
||||
@@ -176,11 +182,10 @@ def copy_bone_simple(arm, from_bone, name, parent=False):
|
||||
|
||||
|
||||
def copy_bone_simple_list(arm, from_bones, to_bones, parent=False):
|
||||
dup_bones = {}
|
||||
|
||||
|
||||
if len(from_bones) != len(to_bones):
|
||||
raise Exception("bone list sizes must match")
|
||||
|
||||
|
||||
copy_bones = [copy_bone_simple(arm, bone_name, to_bones[i], True) for i, bone_name in enumerate(from_bones)]
|
||||
|
||||
# now we need to re-parent
|
||||
@@ -196,14 +201,15 @@ def copy_bone_simple_list(arm, from_bones, to_bones, parent=False):
|
||||
ebone.parent = None
|
||||
else:
|
||||
ebone.parent = copy_bones[i]
|
||||
|
||||
|
||||
return copy_bones
|
||||
|
||||
|
||||
def blend_bone_list(obj, apply_bones, from_bones, to_bones, target_bone=None, target_prop="blend"):
|
||||
|
||||
|
||||
if obj.mode == 'EDIT':
|
||||
raise Exception("blending cant be called in editmode")
|
||||
|
||||
|
||||
# setup the blend property
|
||||
if target_bone is None:
|
||||
target_bone = apply_bones[-1] # default to the last bone
|
||||
@@ -223,7 +229,7 @@ def blend_bone_list(obj, apply_bones, from_bones, to_bones, target_bone=None, ta
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = driver_path
|
||||
|
||||
|
||||
def blend_location(new_pbone, from_bone_name, to_bone_name):
|
||||
con = new_pbone.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
@@ -232,7 +238,7 @@ def blend_bone_list(obj, apply_bones, from_bones, to_bones, target_bone=None, ta
|
||||
con = new_pbone.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = to_bone_name
|
||||
|
||||
|
||||
fcurve = con.driver_add("influence", 0)
|
||||
driver = fcurve.driver
|
||||
driver.type = 'AVERAGE'
|
||||
@@ -248,7 +254,7 @@ def blend_bone_list(obj, apply_bones, from_bones, to_bones, target_bone=None, ta
|
||||
con = new_pbone.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = to_bone_name
|
||||
|
||||
|
||||
fcurve = con.driver_add("influence", 0)
|
||||
driver = fcurve.driver
|
||||
driver.type = 'AVERAGE'
|
||||
@@ -259,7 +265,7 @@ def blend_bone_list(obj, apply_bones, from_bones, to_bones, target_bone=None, ta
|
||||
for i, new_bone_name in enumerate(apply_bones):
|
||||
from_bone_name = from_bones[i]
|
||||
to_bone_name = to_bones[i]
|
||||
|
||||
|
||||
# allow skipping some bones by having None in the list
|
||||
if None in (new_bone_name, from_bone_name, to_bone_name):
|
||||
continue
|
||||
@@ -268,7 +274,7 @@ def blend_bone_list(obj, apply_bones, from_bones, to_bones, target_bone=None, ta
|
||||
|
||||
if not new_pbone.bone.connected:
|
||||
blend_location(new_pbone, from_bone_name, to_bone_name)
|
||||
|
||||
|
||||
blend_rotation(new_pbone, from_bone_name, to_bone_name)
|
||||
|
||||
|
||||
@@ -276,7 +282,7 @@ 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')
|
||||
|
||||
@@ -284,10 +290,10 @@ def add_stretch_to(obj, from_name, to_name, name):
|
||||
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:
|
||||
@@ -296,18 +302,16 @@ def add_stretch_to(obj, from_name, to_name, name):
|
||||
|
||||
# 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.subtarget = to_name
|
||||
con.original_length = (head - tail).length
|
||||
con.keep_axis = 'PLANE_X'
|
||||
con.volume = 'NO_VOLUME'
|
||||
@@ -321,41 +325,41 @@ def add_pole_target_bone(obj, base_name, name, mode='CROSS'):
|
||||
'''
|
||||
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]=="+":
|
||||
offset = Vector(0, 0, 0)
|
||||
if mode[0] == "+":
|
||||
val = distance
|
||||
else:
|
||||
val = -distance
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -366,8 +370,8 @@ def generate_rig(context, obj_orig, prefix="ORG-"):
|
||||
context.user_preferences.edit.global_undo = False
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
|
||||
|
||||
|
||||
# copy object and data
|
||||
obj_orig.selected = False
|
||||
obj = obj_orig.copy()
|
||||
@@ -376,30 +380,30 @@ def generate_rig(context, obj_orig, prefix="ORG-"):
|
||||
scene.objects.link(obj)
|
||||
scene.objects.active = obj
|
||||
obj.selected = True
|
||||
|
||||
|
||||
arm = obj.data
|
||||
|
||||
|
||||
# original name mapping
|
||||
base_names = {}
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
for bone in arm.edit_bones:
|
||||
bone_name = bone.name
|
||||
bone.name = prefix + bone_name
|
||||
base_names[bone.name] = bone_name # new -> old mapping
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
|
||||
# key: bone name
|
||||
# value: {type:definition, ...}
|
||||
# where type is the submodule name - leg, arm etc
|
||||
# and definition is a list of bone names
|
||||
# and definition is a list of bone names
|
||||
bone_definitions = {}
|
||||
|
||||
|
||||
# key: bone name
|
||||
# value: [functions, ...]
|
||||
# each function is from the module. eg leg.ik, arm.main
|
||||
bone_typeinfos = {}
|
||||
|
||||
|
||||
# inspect all bones and assign their definitions before modifying
|
||||
for pbone in obj.pose.bones:
|
||||
bone_name = pbone.name
|
||||
@@ -408,79 +412,79 @@ def generate_rig(context, obj_orig, prefix="ORG-"):
|
||||
|
||||
for bone_type in bone_type_list:
|
||||
type_pair = bone_type.split(".")
|
||||
|
||||
|
||||
# 'leg.ik' will look for an ik function in the leg module
|
||||
# 'leg' will look up leg.main
|
||||
if len(type_pair) == 1:
|
||||
type_pair = type_pair[0], "main"
|
||||
|
||||
|
||||
submod_name, func_name = type_pair
|
||||
|
||||
|
||||
# from rigify import leg
|
||||
submod = __import__(name="%s.%s" % (__package__, submod_name), fromlist=[submod_name])
|
||||
reload(submod)
|
||||
|
||||
|
||||
bone_def_dict = bone_definitions.setdefault(bone_name, {})
|
||||
|
||||
# Only calculate bone definitions once
|
||||
if submod_name not in bone_def_dict:
|
||||
metarig_definition_func = getattr(submod, "metarig_definition")
|
||||
bone_def_dict[submod_name] = metarig_definition_func(obj, bone_name)
|
||||
|
||||
|
||||
|
||||
|
||||
bone_typeinfo = bone_typeinfos.setdefault(bone_name, [])
|
||||
|
||||
type_func = getattr(submod, func_name)
|
||||
bone_typeinfo.append((submod_name, type_func))
|
||||
|
||||
|
||||
|
||||
# now we have all the info about bones we can start operating on them
|
||||
|
||||
|
||||
for pbone in obj.pose.bones:
|
||||
bone_name = pbone.name
|
||||
|
||||
|
||||
if bone_name not in bone_typeinfos:
|
||||
continue
|
||||
|
||||
|
||||
bone_def_dict = bone_definitions[bone_name]
|
||||
|
||||
|
||||
# Only blend results from the same submodule, eg.
|
||||
# leg.ik and arm.fk could not be blended.
|
||||
results = OrderedDict()
|
||||
|
||||
|
||||
for submod_name, type_func in bone_typeinfos[bone_name]:
|
||||
# this bones definition of the current typeinfo
|
||||
definition = bone_def_dict[submod_name]
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
ret = type_func(obj, definition, base_names)
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
if ret:
|
||||
if ret:
|
||||
result_submod = results.setdefault(submod_name, [])
|
||||
|
||||
|
||||
if result_submod and len(result_submod[-1]) != len(ret):
|
||||
raise Exception("bone lists not compatible: %s, %s" % (result_submod[-1], ret))
|
||||
|
||||
result_submod.append(ret)
|
||||
|
||||
|
||||
for result_submod in results.values():
|
||||
# blend 2 chains
|
||||
definition = bone_def_dict[submod_name]
|
||||
|
||||
|
||||
if len(result_submod) == 2:
|
||||
blend_bone_list(obj, definition, result_submod[0], result_submod[1])
|
||||
|
||||
|
||||
# needed to update driver deps
|
||||
# context.scene.update()
|
||||
|
||||
|
||||
# Only for demo'ing
|
||||
|
||||
|
||||
# obj.restrict_view = True
|
||||
obj.data.draw_axes = False
|
||||
|
||||
|
||||
context.user_preferences.edit.global_undo = global_undo
|
||||
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
@@ -503,8 +507,7 @@ def write_meta_rig(obj, func_name="metarig_template"):
|
||||
bones.sort(key=lambda item: item[0])
|
||||
bones = [item[1] for item in bones]
|
||||
|
||||
|
||||
|
||||
|
||||
for bone_name in bones:
|
||||
bone = arm.edit_bones[bone_name]
|
||||
code.append(" bone = arm.edit_bones.new('%s')" % bone.name)
|
||||
@@ -514,15 +517,15 @@ def write_meta_rig(obj, func_name="metarig_template"):
|
||||
code.append(" bone.connected = %s" % str(bone.connected))
|
||||
if bone.parent:
|
||||
code.append(" bone.parent = arm.edit_bones['%s']" % bone.parent.name)
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
code.append("")
|
||||
code.append(" bpy.ops.object.mode_set(mode='OBJECT')")
|
||||
|
||||
|
||||
for bone_name in bones:
|
||||
pbone = obj.pose.bones[bone_name]
|
||||
pbone_written = False
|
||||
|
||||
|
||||
# Only 1 level of props, simple types supported
|
||||
for key, value in pbone.items():
|
||||
if key.startswith("_"):
|
||||
@@ -534,20 +537,21 @@ def write_meta_rig(obj, func_name="metarig_template"):
|
||||
|
||||
if type(value) == str:
|
||||
value = "'" + value + "'"
|
||||
|
||||
|
||||
if not pbone_written: # only write bones we need
|
||||
code.append(" pbone = obj.pose.bones['%s']" % bone_name)
|
||||
|
||||
|
||||
code.append(" pbone['%s'] = %s" % (key, value))
|
||||
|
||||
|
||||
return "\n".join(code)
|
||||
|
||||
|
||||
def generate_test(context):
|
||||
import os
|
||||
new_objects = []
|
||||
|
||||
|
||||
scene = context.scene
|
||||
|
||||
def create_empty_armature(name):
|
||||
obj_new = bpy.data.add_object('ARMATURE', name)
|
||||
armature = bpy.data.add_armature(name)
|
||||
@@ -573,11 +577,11 @@ def generate_test(context):
|
||||
metarig_template()
|
||||
obj = context.object
|
||||
obj_new = generate_rig(context, obj)
|
||||
|
||||
|
||||
new_objects.append((obj, obj_new))
|
||||
else:
|
||||
print("note: rig type '%s' has no metarig_template(), can't test this", module_name)
|
||||
|
||||
|
||||
return new_objects
|
||||
|
||||
|
||||
@@ -587,14 +591,14 @@ def generate_test_all(context):
|
||||
import os
|
||||
reload(rigify)
|
||||
reload(graphviz_export)
|
||||
|
||||
|
||||
new_objects = rigify.generate_test(context)
|
||||
|
||||
|
||||
base_name = os.path.splitext(bpy.data.filename)[0]
|
||||
for obj, obj_new in new_objects:
|
||||
for obj in (obj, obj_new):
|
||||
fn = base_name + "-" + bpy.utils.clean_name(obj.name)
|
||||
|
||||
|
||||
path_dot = fn + ".dot"
|
||||
path_png = fn + ".png"
|
||||
saved = graphviz_export.graph_armature(obj, path_dot, CONSTRAINTS=True, DRIVERS=True)
|
||||
@@ -610,8 +614,7 @@ def generate_test_all(context):
|
||||
obj_new.selected = False
|
||||
obj.selected = True
|
||||
i += 4
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate_rig(bpy.context, bpy.context.object)
|
||||
|
||||
|
||||
@@ -16,12 +16,15 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
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
|
||||
from rna_prop_ui import rna_idprop_ui_prop_get
|
||||
|
||||
METARIG_NAMES = "shoulder", "arm", "forearm", "hand"
|
||||
|
||||
|
||||
def metarig_template():
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
obj = bpy.context.object
|
||||
@@ -59,10 +62,10 @@ def metarig_definition(obj, orig_bone_name):
|
||||
mt = bone_class_instance(obj, METARIG_NAMES) # meta
|
||||
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:
|
||||
raise Exception("could not find 'arm' parent, skipping:", orig_bone_name)
|
||||
|
||||
@@ -82,7 +85,7 @@ def metarig_definition(obj, orig_bone_name):
|
||||
|
||||
mt.forearm_p = mt.hand_p.parent
|
||||
mt.forearm = mt.forearm_p.name
|
||||
|
||||
|
||||
return mt.names()
|
||||
|
||||
|
||||
@@ -91,35 +94,34 @@ 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
|
||||
mt.shoulder, mt.arm, mt.forearm, mt.hand = definitions
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
arm = obj.data
|
||||
|
||||
|
||||
|
||||
def chain_ik(prefix="MCH-%s_ik"):
|
||||
|
||||
|
||||
mt.update()
|
||||
|
||||
|
||||
# Add the edit bones
|
||||
ik.hand_e = copy_bone_simple(arm, mt.hand, prefix % mt.hand)
|
||||
ik.hand = ik.hand_e.name
|
||||
|
||||
|
||||
ik.arm_e = copy_bone_simple(arm, mt.arm, prefix % mt.arm)
|
||||
ik.arm = ik.arm_e.name
|
||||
|
||||
@@ -128,50 +130,50 @@ def main(obj, definitions, base_names):
|
||||
|
||||
ik.arm_e.parent = mt.arm_e.parent
|
||||
ik.forearm_e.connected = mt.arm_e.connected
|
||||
|
||||
|
||||
ik.forearm_e.parent = ik.arm_e
|
||||
ik.forearm_e.connected = True
|
||||
|
||||
|
||||
|
||||
|
||||
# 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')
|
||||
|
||||
|
||||
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.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')
|
||||
|
||||
|
||||
ik.arm = ik.arm
|
||||
ik.forearm = ik.forearm
|
||||
ik.hand = ik.hand
|
||||
ik.pole = ik.pole
|
||||
|
||||
|
||||
def chain_switch(prefix="MCH-%s"):
|
||||
|
||||
|
||||
sw.update()
|
||||
mt.update()
|
||||
|
||||
|
||||
sw.shoulder_e = copy_bone_simple(arm, mt.shoulder, prefix % mt.shoulder)
|
||||
sw.shoulder = sw.shoulder_e.name
|
||||
sw.shoulder_e.parent = mt.shoulder_e.parent
|
||||
@@ -181,7 +183,7 @@ def main(obj, definitions, base_names):
|
||||
sw.arm = sw.arm_e.name
|
||||
sw.arm_e.parent = sw.shoulder_e
|
||||
sw.arm_e.connected = arm.edit_bones[mt.shoulder].connected
|
||||
|
||||
|
||||
sw.forearm_e = copy_bone_simple(arm, mt.forearm, prefix % mt.forearm)
|
||||
sw.forearm = sw.forearm_e.name
|
||||
sw.forearm_e.parent = sw.arm_e
|
||||
@@ -191,25 +193,24 @@ def main(obj, definitions, base_names):
|
||||
sw.hand = sw.hand_e.name
|
||||
sw.hand_e.parent = sw.forearm_e
|
||||
sw.hand_e.connected = arm.edit_bones[mt.hand].connected
|
||||
|
||||
|
||||
# The sw.hand_e needs to own all the children on the metarig's hand
|
||||
for child in mt.hand_e.children:
|
||||
child.parent = sw.hand_e
|
||||
|
||||
|
||||
|
||||
|
||||
# These are made the children of sw.shoulder_e
|
||||
|
||||
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
|
||||
# Add constraints
|
||||
sw.update()
|
||||
|
||||
|
||||
#dummy, ik.arm, ik.forearm, ik.hand, ik.pole = ik_chain_tuple
|
||||
|
||||
|
||||
ik_driver_path = obj.pose.bones[ik.hand].path_to_id() + '["ik"]'
|
||||
|
||||
|
||||
|
||||
def ik_fk_driver(con):
|
||||
'''
|
||||
3 bones use this for ik/fk switching
|
||||
@@ -235,7 +236,7 @@ def main(obj, definitions, base_names):
|
||||
con.subtarget = ik.arm
|
||||
con.influence = 0.5
|
||||
ik_fk_driver(con)
|
||||
|
||||
|
||||
# ***********
|
||||
con = sw.forearm_p.constraints.new('COPY_ROTATION')
|
||||
con.name = "FK"
|
||||
@@ -248,7 +249,7 @@ def main(obj, definitions, base_names):
|
||||
con.subtarget = ik.forearm
|
||||
con.influence = 0.5
|
||||
ik_fk_driver(con)
|
||||
|
||||
|
||||
# ***********
|
||||
con = sw.hand_p.constraints.new('COPY_ROTATION')
|
||||
con.name = "FK"
|
||||
@@ -261,52 +262,51 @@ def main(obj, definitions, base_names):
|
||||
con.subtarget = ik.hand
|
||||
con.influence = 0.5
|
||||
ik_fk_driver(con)
|
||||
|
||||
|
||||
|
||||
|
||||
add_stretch_to(obj, sw.forearm, ik.pole, "VIS-elbow_ik_poll")
|
||||
add_stretch_to(obj, sw.hand, ik.hand, "VIS-hand_ik")
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
def chain_shoulder(prefix="MCH-%s"):
|
||||
|
||||
sw.socket_e = copy_bone_simple(arm, mt.arm, (prefix % mt.arm) + "_socket")
|
||||
sw.socket = sw.socket_e.name
|
||||
sw.socket_e.tail = arm.edit_bones[mt.shoulder].tail
|
||||
|
||||
|
||||
|
||||
|
||||
# Set the shoulder as parent
|
||||
ik.update()
|
||||
sw.update()
|
||||
mt.update()
|
||||
|
||||
|
||||
sw.socket_e.parent = sw.shoulder_e
|
||||
ik.arm_e.parent = sw.shoulder_e
|
||||
|
||||
|
||||
|
||||
|
||||
# ***** add the shoulder hinge
|
||||
# yes this is correct, the shoulder copy gets the arm's name
|
||||
ex.arm_hinge_e = copy_bone_simple(arm, mt.shoulder, (prefix % mt.arm) + "_hinge")
|
||||
ex.arm_hinge = ex.arm_hinge_e.name
|
||||
offset = ex.arm_hinge_e.length / 2.0
|
||||
|
||||
|
||||
ex.arm_hinge_e.head.y += offset
|
||||
ex.arm_hinge_e.tail.y += offset
|
||||
|
||||
|
||||
# Note: meta arm becomes child of hinge
|
||||
mt.arm_e.parent = ex.arm_hinge_e
|
||||
|
||||
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
|
||||
ex.update()
|
||||
|
||||
|
||||
con = mt.arm_p.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = sw.socket
|
||||
|
||||
|
||||
|
||||
|
||||
# Hinge constraint & driver
|
||||
con = ex.arm_hinge_p.constraints.new('COPY_ROTATION')
|
||||
con.name = "hinge"
|
||||
@@ -315,35 +315,35 @@ def main(obj, definitions, base_names):
|
||||
driver_fcurve = con.driver_add("influence", 0)
|
||||
driver = driver_fcurve.driver
|
||||
|
||||
|
||||
|
||||
controller_path = mt.arm_p.path_to_id()
|
||||
# add custom prop
|
||||
mt.arm_p["hinge"] = 0.0
|
||||
prop = rna_idprop_ui_prop_get(mt.arm_p, "hinge", create=True)
|
||||
prop["soft_min"] = 0.0
|
||||
prop["soft_max"] = 1.0
|
||||
|
||||
|
||||
|
||||
|
||||
# *****
|
||||
driver = driver_fcurve.driver
|
||||
driver.type = 'AVERAGE'
|
||||
|
||||
|
||||
tar = driver.targets.new()
|
||||
tar.name = "hinge"
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = controller_path + '["hinge"]'
|
||||
|
||||
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
# remove the shoulder and re-parent
|
||||
|
||||
# remove the shoulder and re-parent
|
||||
|
||||
chain_ik()
|
||||
chain_switch()
|
||||
chain_shoulder()
|
||||
|
||||
|
||||
# Shoulder with its delta and hinge.
|
||||
|
||||
|
||||
# TODO - return a list for fk and IK
|
||||
return None
|
||||
|
||||
@@ -16,12 +16,15 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from rigify import get_bone_data
|
||||
|
||||
# not used, defined for completeness
|
||||
METARIG_NAMES = tuple()
|
||||
|
||||
|
||||
def metarig_definition(obj, orig_bone_name):
|
||||
'''
|
||||
The bone given is the head, its parent is the body,
|
||||
@@ -32,68 +35,69 @@ def metarig_definition(obj, orig_bone_name):
|
||||
arm = obj.data
|
||||
delta = arm.bones[orig_bone_name]
|
||||
children = delta.children
|
||||
|
||||
|
||||
if len(children) != 1:
|
||||
print("only 1 child supported for delta")
|
||||
|
||||
|
||||
bone_definition = [delta.name, children[0].name]
|
||||
|
||||
|
||||
return bone_definition
|
||||
|
||||
|
||||
def main(obj, bone_definition, base_names):
|
||||
'''
|
||||
Use this bone to define a delta thats applied to its child in pose mode.
|
||||
'''
|
||||
|
||||
|
||||
mode_orig = obj.mode
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
|
||||
delta_name, child_name = bone_definition
|
||||
|
||||
|
||||
delta_pbone = obj.pose.bones[delta_name]
|
||||
|
||||
arm, child_pbone, child_bone = get_bone_data(obj, child_name)
|
||||
|
||||
|
||||
delta_phead = delta_pbone.head.copy()
|
||||
delta_ptail = delta_pbone.tail.copy()
|
||||
delta_pmatrix = delta_pbone.matrix.copy()
|
||||
|
||||
|
||||
child_phead = child_pbone.head.copy()
|
||||
child_ptail = child_pbone.tail.copy()
|
||||
child_pmatrix = child_pbone.matrix.copy()
|
||||
|
||||
|
||||
|
||||
|
||||
children = delta_pbone.children
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
|
||||
delta_ebone = arm.edit_bones[delta_name]
|
||||
child_ebone = arm.edit_bones[child_name]
|
||||
|
||||
|
||||
delta_head = delta_ebone.head.copy()
|
||||
delta_tail = delta_ebone.tail.copy()
|
||||
|
||||
delta_tail = delta_ebone.tail.copy()
|
||||
|
||||
# arm, parent_pbone, parent_bone = get_bone_data(obj, delta_name)
|
||||
child_head = child_ebone.head.copy()
|
||||
child_tail = child_ebone.tail.copy()
|
||||
|
||||
|
||||
arm.edit_bones.remove(delta_ebone)
|
||||
del delta_ebone # cant use this
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
|
||||
|
||||
|
||||
# Move the child bone to the deltas location
|
||||
obj.animation_data_create()
|
||||
child_pbone = obj.pose.bones[child_name]
|
||||
|
||||
|
||||
# ------------------- drivers
|
||||
|
||||
|
||||
child_pbone.rotation_mode = 'XYZ'
|
||||
|
||||
rot = delta_pmatrix.invert().rotationPart() * child_pmatrix.rotationPart()
|
||||
|
||||
rot = delta_pmatrix.invert().rotationPart() * child_pmatrix.rotationPart()
|
||||
rot = rot.invert().toEuler()
|
||||
|
||||
|
||||
fcurve_drivers = child_pbone.driver_add("rotation_euler", -1)
|
||||
for i, fcurve_driver in enumerate(fcurve_drivers):
|
||||
driver = fcurve_driver.driver
|
||||
@@ -103,10 +107,10 @@ def main(obj, bone_definition, base_names):
|
||||
mod.poly_order = 1
|
||||
mod.coefficients[0] = rot[i]
|
||||
mod.coefficients[1] = 0.0
|
||||
|
||||
|
||||
# tricky, find the transform to drive the bone to this location.
|
||||
delta_head_offset = child_pmatrix.rotationPart() * (delta_phead - child_phead)
|
||||
|
||||
delta_head_offset = child_pmatrix.rotationPart() * (delta_phead - child_phead)
|
||||
|
||||
fcurve_drivers = child_pbone.driver_add("location", -1)
|
||||
for i, fcurve_driver in enumerate(fcurve_drivers):
|
||||
driver = fcurve_driver.driver
|
||||
@@ -116,13 +120,12 @@ def main(obj, bone_definition, base_names):
|
||||
mod.poly_order = 1
|
||||
mod.coefficients[0] = delta_head_offset[i]
|
||||
mod.coefficients[1] = 0.0
|
||||
|
||||
|
||||
|
||||
|
||||
# arm, parent_pbone, parent_bone = get_bone_data(obj, delta_name)
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode=mode_orig)
|
||||
|
||||
# no blendeing
|
||||
return None
|
||||
|
||||
@@ -16,13 +16,16 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from rigify import get_bone_data, empty_layer, copy_bone_simple
|
||||
from rna_prop_ui import rna_idprop_ui_get, rna_idprop_ui_prop_get
|
||||
from rna_prop_ui import rna_idprop_ui_prop_get
|
||||
from functools import reduce
|
||||
|
||||
METARIG_NAMES = "finger_01", "finger_02", "finger_03"
|
||||
|
||||
|
||||
def metarig_template():
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
obj = bpy.context.object
|
||||
@@ -49,6 +52,7 @@ def metarig_template():
|
||||
pbone = obj.pose.bones['finger.01']
|
||||
pbone['type'] = 'finger'
|
||||
|
||||
|
||||
def metarig_definition(obj, orig_bone_name):
|
||||
'''
|
||||
The bone given is the first in a chain
|
||||
@@ -56,13 +60,13 @@ def metarig_definition(obj, orig_bone_name):
|
||||
eg.
|
||||
finger -> finger_01 -> finger_02
|
||||
'''
|
||||
|
||||
|
||||
bone_definition = []
|
||||
|
||||
orig_bone = obj.data.bones[orig_bone_name]
|
||||
|
||||
bone_definition.append(orig_bone.name)
|
||||
|
||||
|
||||
bone = orig_bone
|
||||
chain = 0
|
||||
while chain < 2: # first 2 bones only have 1 child
|
||||
@@ -73,102 +77,102 @@ def metarig_definition(obj, orig_bone_name):
|
||||
bone = children[0]
|
||||
bone_definition.append(bone.name) # finger_02, finger_03
|
||||
chain += 1
|
||||
|
||||
|
||||
if len(bone_definition) != len(METARIG_NAMES):
|
||||
raise Exception("internal problem, expected %d bones" % len(METARIG_NAMES))
|
||||
|
||||
|
||||
return bone_definition
|
||||
|
||||
|
||||
|
||||
def main(obj, bone_definition, base_names):
|
||||
|
||||
|
||||
# *** EDITMODE
|
||||
|
||||
# get assosiated data
|
||||
|
||||
# get assosiated data
|
||||
arm, orig_pbone, orig_ebone = get_bone_data(obj, bone_definition[0])
|
||||
|
||||
|
||||
obj.animation_data_create() # needed if its a new armature with no keys
|
||||
|
||||
|
||||
arm.layer[0] = arm.layer[8] = True
|
||||
|
||||
|
||||
children = orig_pbone.children_recursive
|
||||
tot_len = reduce(lambda f, pbone: f + pbone.bone.length, children, orig_pbone.bone.length)
|
||||
|
||||
|
||||
base_name = base_names[bone_definition[0]].rsplit(".", 1)[0]
|
||||
|
||||
|
||||
# first make a new bone at the location of the finger
|
||||
#control_ebone = arm.edit_bones.new(base_name)
|
||||
control_ebone = copy_bone_simple(arm, bone_definition[0], base_name)
|
||||
control_bone_name = control_ebone.name # we dont know if we get the name requested
|
||||
|
||||
|
||||
control_ebone.connected = orig_ebone.connected
|
||||
control_ebone.parent = orig_ebone.parent
|
||||
control_ebone.length = tot_len
|
||||
|
||||
|
||||
# now add bones inbetween this and its children recursively
|
||||
|
||||
|
||||
# switching modes so store names only!
|
||||
children = [pbone.name for pbone in children]
|
||||
|
||||
# set an alternate layer for driver bones
|
||||
other_layer = empty_layer[:]
|
||||
other_layer[8] = True
|
||||
|
||||
|
||||
|
||||
driver_bone_pairs = []
|
||||
|
||||
for child_bone_name in children:
|
||||
arm, pbone_child, child_ebone = get_bone_data(obj, child_bone_name)
|
||||
|
||||
child_ebone = arm.edit_bones[child_bone_name]
|
||||
|
||||
# finger.02 --> finger_driver.02
|
||||
driver_bone_name = child_bone_name.split('.')
|
||||
driver_bone_name = driver_bone_name[0] + "_driver." + ".".join(driver_bone_name[1:])
|
||||
|
||||
|
||||
driver_ebone = copy_bone_simple(arm, child_ebone.name, driver_bone_name)
|
||||
driver_ebone.length *= 0.5
|
||||
driver_ebone.layer = other_layer
|
||||
|
||||
|
||||
# Insert driver_ebone in the chain without connected parents
|
||||
driver_ebone.connected = False
|
||||
driver_ebone.parent = child_ebone.parent
|
||||
|
||||
|
||||
child_ebone.connected = False
|
||||
child_ebone.parent = driver_ebone
|
||||
|
||||
|
||||
# Add the drivers to these when in posemode.
|
||||
driver_bone_pairs.append((child_bone_name, driver_bone_name))
|
||||
|
||||
|
||||
del control_ebone
|
||||
|
||||
|
||||
|
||||
# *** POSEMODE
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
|
||||
arm, orig_pbone, orig_bone = get_bone_data(obj, bone_definition[0])
|
||||
arm, control_pbone, control_bone= get_bone_data(obj, control_bone_name)
|
||||
|
||||
|
||||
|
||||
|
||||
orig_pbone = obj.pose.bones[bone_definition[0]]
|
||||
control_pbone = obj.pose.bones[control_bone_name]
|
||||
|
||||
|
||||
# only allow Y scale
|
||||
control_pbone.lock_scale = (True, False, True)
|
||||
|
||||
|
||||
control_pbone["bend_ratio"] = 0.4
|
||||
prop = rna_idprop_ui_prop_get(control_pbone, "bend_ratio", create=True)
|
||||
prop["soft_min"] = 0.0
|
||||
prop["soft_max"] = 1.0
|
||||
|
||||
|
||||
con = orig_pbone.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = control_bone_name
|
||||
|
||||
|
||||
con = orig_pbone.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = control_bone_name
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# setup child drivers on each new smaller bone added. assume 2 for now.
|
||||
|
||||
|
||||
# drives the bones
|
||||
controller_path = control_pbone.path_to_id() # 'pose.bones["%s"]' % control_bone_name
|
||||
|
||||
@@ -176,18 +180,18 @@ def main(obj, bone_definition, base_names):
|
||||
for child_bone_name, driver_bone_name in driver_bone_pairs:
|
||||
|
||||
# XXX - todo, any number
|
||||
if i==2:
|
||||
if i == 2:
|
||||
break
|
||||
|
||||
arm, driver_pbone, driver_bone = get_bone_data(obj, driver_bone_name)
|
||||
|
||||
|
||||
driver_pbone = obj.pose.bones[driver_bone_name]
|
||||
|
||||
driver_pbone.rotation_mode = 'YZX'
|
||||
fcurve_driver = driver_pbone.driver_add("rotation_euler", 0)
|
||||
|
||||
|
||||
#obj.driver_add('pose.bones["%s"].scale', 1)
|
||||
#obj.animation_data.drivers[-1] # XXX, WATCH THIS
|
||||
driver = fcurve_driver.driver
|
||||
|
||||
|
||||
# scale target
|
||||
tar = driver.targets.new()
|
||||
tar.name = "scale"
|
||||
@@ -203,17 +207,17 @@ def main(obj, bone_definition, base_names):
|
||||
tar.rna_path = controller_path + '["bend_ratio"]'
|
||||
|
||||
# XXX - todo, any number
|
||||
if i==0:
|
||||
if i == 0:
|
||||
driver.expression = '(-scale+1.0)*pi*2.0*(1.0-br)'
|
||||
elif i==1:
|
||||
elif i == 1:
|
||||
driver.expression = '(-scale+1.0)*pi*2.0*br'
|
||||
|
||||
arm, child_pbone, child_bone = get_bone_data(obj, child_bone_name)
|
||||
|
||||
child_pbone = obj.pose.bones[child_bone_name]
|
||||
|
||||
# only allow X rotation
|
||||
driver_pbone.lock_rotation = child_pbone.lock_rotation = (False, True, True)
|
||||
|
||||
|
||||
i += 1
|
||||
|
||||
|
||||
# no blending the result of this
|
||||
return None
|
||||
|
||||
@@ -16,12 +16,15 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from rigify import bone_class_instance, copy_bone_simple, copy_bone_simple_list, add_pole_target_bone, add_stretch_to, blend_bone_list
|
||||
from rna_prop_ui import rna_idprop_ui_get, rna_idprop_ui_prop_get
|
||||
from rigify import bone_class_instance, copy_bone_simple, blend_bone_list
|
||||
from rna_prop_ui import rna_idprop_ui_prop_get
|
||||
|
||||
METARIG_NAMES = "hips", "thigh", "shin", "foot", "toe", "heel"
|
||||
|
||||
|
||||
def metarig_template():
|
||||
# generated by rigify.write_meta_rig
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
@@ -67,6 +70,7 @@ def metarig_template():
|
||||
pbone = obj.pose.bones['thigh']
|
||||
pbone['type'] = 'leg'
|
||||
|
||||
|
||||
def metarig_definition(obj, orig_bone_name):
|
||||
'''
|
||||
The bone given is the first in a chain
|
||||
@@ -74,7 +78,7 @@ def metarig_definition(obj, orig_bone_name):
|
||||
eg.
|
||||
thigh -> shin -> foot -> [toe, heel]
|
||||
'''
|
||||
|
||||
|
||||
bone_definition = []
|
||||
|
||||
orig_bone = obj.data.bones[orig_bone_name]
|
||||
@@ -85,8 +89,8 @@ def metarig_definition(obj, orig_bone_name):
|
||||
|
||||
bone_definition.append(orig_bone_parent.name)
|
||||
bone_definition.append(orig_bone.name)
|
||||
|
||||
|
||||
|
||||
|
||||
bone = orig_bone
|
||||
chain = 0
|
||||
while chain < 2: # first 2 bones only have 1 child
|
||||
@@ -97,7 +101,7 @@ def metarig_definition(obj, orig_bone_name):
|
||||
bone = children[0]
|
||||
bone_definition.append(bone.name) # shin, foot
|
||||
chain += 1
|
||||
|
||||
|
||||
children = bone.children
|
||||
# Now there must be 2 children, only one connected
|
||||
if len(children) != 2:
|
||||
@@ -105,25 +109,24 @@ def metarig_definition(obj, orig_bone_name):
|
||||
|
||||
if children[0].connected == children[1].connected:
|
||||
raise Exception("expected one bone to be connected")
|
||||
|
||||
|
||||
toe, heel = children
|
||||
if heel.connected:
|
||||
toe, heel = heel, toe
|
||||
|
||||
|
||||
|
||||
|
||||
bone_definition.append(toe.name)
|
||||
bone_definition.append(heel.name)
|
||||
|
||||
|
||||
if len(bone_definition) != len(METARIG_NAMES):
|
||||
raise Exception("internal problem, expected %d bones" % len(METARIG_NAMES))
|
||||
|
||||
|
||||
return bone_definition
|
||||
|
||||
|
||||
def ik(obj, bone_definition, base_names):
|
||||
from Mathutils import Vector
|
||||
arm = obj.data
|
||||
|
||||
|
||||
# setup the existing bones
|
||||
mt_chain = bone_class_instance(obj, ["thigh", "shin", "foot", "toe"])
|
||||
mt = bone_class_instance(obj, ["hips", "heel"])
|
||||
@@ -131,7 +134,7 @@ def ik(obj, bone_definition, base_names):
|
||||
ex = bone_class_instance(obj, ["thigh_socket", "thigh_hinge", "foot_roll_1", "foot_roll_2", "foot_roll_3"])
|
||||
# children of ik_foot
|
||||
ik = bone_class_instance(obj, ["foot", "foot_roll", "foot_roll_01", "foot_roll_02", "knee_target"])
|
||||
|
||||
|
||||
# XXX - duplicate below
|
||||
for bone_class in (mt, mt_chain):
|
||||
for attr in bone_class.attr_names:
|
||||
@@ -155,13 +158,13 @@ def ik(obj, bone_definition, base_names):
|
||||
ik.foot = ik.foot_e.name
|
||||
ik.foot_e.tail.z = ik.foot_e.head.z
|
||||
ik.foot_e.roll = 0.0
|
||||
|
||||
|
||||
# heel pointing backwards, half length
|
||||
ik.foot_roll_e = copy_bone_simple(arm, mt.heel, "%s_roll" % base_foot_name)
|
||||
ik.foot_roll = ik.foot_roll_e.name
|
||||
ik.foot_roll_e.tail = ik.foot_roll_e.head + (ik.foot_roll_e.head - ik.foot_roll_e.tail) / 2.0
|
||||
ik.foot_roll_e.parent = ik.foot_e # heel is disconnected
|
||||
|
||||
|
||||
# heel pointing forwards to the toe base, parent of the following 2 bones
|
||||
ik.foot_roll_01_e = copy_bone_simple(arm, mt.heel, "MCH-%s_roll.01" % base_foot_name)
|
||||
ik.foot_roll_01 = ik.foot_roll_01_e.name
|
||||
@@ -174,20 +177,20 @@ def ik(obj, bone_definition, base_names):
|
||||
ik.foot_roll_02_e.parent = ik.foot_roll_01_e # heel is disconnected
|
||||
ik.foot_roll_02_e.head = mt_chain.foot_e.tail
|
||||
ik.foot_roll_02_e.tail = mt.heel_e.head
|
||||
|
||||
|
||||
del base_foot_name
|
||||
|
||||
|
||||
# rename 'MCH-toe' --> to 'toe_ik' and make the child of ik.foot_roll_01
|
||||
# ------------------ FK or IK?
|
||||
ik_chain.rename("toe", base_names[mt_chain.toe] + "_ik")
|
||||
ik_chain.toe_e.connected = False
|
||||
ik_chain.toe_e.parent = ik.foot_roll_01_e
|
||||
|
||||
# re-parent ik_chain.foot to the
|
||||
|
||||
# re-parent ik_chain.foot to the
|
||||
ik_chain.foot_e.connected = False
|
||||
ik_chain.foot_e.parent = ik.foot_roll_02_e
|
||||
|
||||
|
||||
|
||||
|
||||
# knee target is the heel moved up and forward on its local axis
|
||||
ik.knee_target_e = copy_bone_simple(arm, mt.heel, "knee_target")
|
||||
ik.knee_target = ik.knee_target_e.name
|
||||
@@ -209,7 +212,7 @@ def ik(obj, bone_definition, base_names):
|
||||
ex.update()
|
||||
mt_chain.update()
|
||||
ik_chain.update()
|
||||
|
||||
|
||||
# IK
|
||||
con = ik_chain.shin_p.constraints.new('IK')
|
||||
con.chain_length = 2
|
||||
@@ -220,52 +223,51 @@ def ik(obj, bone_definition, base_names):
|
||||
con.use_target = True
|
||||
con.use_rotation = False
|
||||
con.weight = 1.0
|
||||
|
||||
|
||||
con.target = obj
|
||||
con.subtarget = ik.foot
|
||||
|
||||
|
||||
con.pole_target = obj
|
||||
con.pole_subtarget = ik.knee_target
|
||||
|
||||
|
||||
# foot roll
|
||||
cons = [ \
|
||||
(ik.foot_roll_01_p.constraints.new('COPY_ROTATION'), ik.foot_roll_01_p.constraints.new('LIMIT_ROTATION')), \
|
||||
(ik.foot_roll_02_p.constraints.new('COPY_ROTATION'), ik.foot_roll_02_p.constraints.new('LIMIT_ROTATION'))
|
||||
]
|
||||
|
||||
(ik.foot_roll_02_p.constraints.new('COPY_ROTATION'), ik.foot_roll_02_p.constraints.new('LIMIT_ROTATION'))]
|
||||
|
||||
for con, con_l in cons:
|
||||
con.target = obj
|
||||
con.subtarget = ik.foot_roll
|
||||
con.use_x, con.use_y, con.use_z = True, False, False
|
||||
con.target_space = con.owner_space = 'LOCAL'
|
||||
|
||||
|
||||
con = con_l
|
||||
con.use_limit_x, con.use_limit_y, con.use_limit_z = True, False, False
|
||||
con.owner_space = 'LOCAL'
|
||||
|
||||
|
||||
if con_l is cons[-1][-1]:
|
||||
con.minimum_x = 0.0
|
||||
con.maximum_x = 180.0 # XXX -deg
|
||||
else:
|
||||
con.minimum_x = -180.0 # XXX -deg
|
||||
con.maximum_x = 0.0
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
|
||||
return None, ik_chain.thigh, ik_chain.shin, ik_chain.foot, ik_chain.toe, None
|
||||
|
||||
|
||||
def fk(obj, bone_definition, base_names):
|
||||
from Mathutils import Vector
|
||||
arm = obj.data
|
||||
|
||||
|
||||
# these account for all bones in METARIG_NAMES
|
||||
mt_chain = bone_class_instance(obj, ["thigh", "shin", "foot", "toe"])
|
||||
mt = bone_class_instance(obj, ["hips", "heel"])
|
||||
|
||||
|
||||
# new bones
|
||||
ex = bone_class_instance(obj, ["thigh_socket", "thigh_hinge"])
|
||||
|
||||
|
||||
for bone_class in (mt, mt_chain):
|
||||
for attr in bone_class.attr_names:
|
||||
i = METARIG_NAMES.index(attr)
|
||||
@@ -280,11 +282,11 @@ def fk(obj, bone_definition, base_names):
|
||||
ex.thigh_hinge_e = copy_bone_simple(arm, mt_chain.thigh, "MCH-%s_hinge" % base_names[mt_chain.thigh], parent=True)
|
||||
ex.thigh_hinge = ex.thigh_hinge_e.name
|
||||
ex.thigh_hinge_e.tail = ex.thigh_hinge_e.head + Vector(0.0, 0.0, mt_chain.thigh_e.head.length)
|
||||
ex.thigh_hinge_e.translate(Vector(-(mt.hips_e.head.x - mt_chain.thigh_e.head.x), 0.0, 0.0))
|
||||
ex.thigh_hinge_e.translate(Vector( - (mt.hips_e.head.x - mt_chain.thigh_e.head.x), 0.0, 0.0))
|
||||
ex.thigh_hinge_e.length = mt.hips_e.length
|
||||
|
||||
|
||||
fk_chain = mt_chain.copy() # fk has no prefix!
|
||||
|
||||
|
||||
fk_chain.thigh_e.connected = False
|
||||
fk_chain.thigh_e.parent = ex.thigh_hinge_e
|
||||
|
||||
@@ -303,14 +305,14 @@ def fk(obj, bone_definition, base_names):
|
||||
fk_chain.thigh_p["hinge"] = 0.5
|
||||
prop["soft_min"] = 0.0
|
||||
prop["soft_max"] = 1.0
|
||||
|
||||
|
||||
con = ex.thigh_hinge_p.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = mt.hips
|
||||
|
||||
|
||||
# add driver
|
||||
hinge_driver_path = fk_chain.thigh_p.path_to_id() + '["hinge"]'
|
||||
|
||||
|
||||
fcurve = con.driver_add("influence", 0)
|
||||
driver = fcurve.driver
|
||||
tar = driver.targets.new()
|
||||
@@ -324,15 +326,16 @@ def fk(obj, bone_definition, base_names):
|
||||
mod.poly_order = 1
|
||||
mod.coefficients[0] = 1.0
|
||||
mod.coefficients[1] = -1.0
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
|
||||
# dont blend the hips or heel
|
||||
return None, fk_chain.thigh, fk_chain.shin, fk_chain.foot, fk_chain.toe, None
|
||||
|
||||
|
||||
def main(obj, bone_definition, base_names):
|
||||
bones_ik = ik(obj, bone_definition, base_names)
|
||||
bones_fk = fk(obj, bone_definition, base_names)
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
blend_bone_list(obj, bone_definition, bones_ik, bones_fk)
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from rigify import bone_class_instance, copy_bone_simple
|
||||
from rna_prop_ui import rna_idprop_ui_prop_get
|
||||
@@ -23,6 +25,7 @@ from rna_prop_ui import rna_idprop_ui_prop_get
|
||||
# not used, defined for completeness
|
||||
METARIG_NAMES = ("body", "head")
|
||||
|
||||
|
||||
def metarig_template():
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
obj = bpy.context.object
|
||||
@@ -84,7 +87,7 @@ def metarig_definition(obj, orig_bone_name):
|
||||
arm = obj.data
|
||||
head = arm.bones[orig_bone_name]
|
||||
body = head.parent
|
||||
|
||||
|
||||
children = head.children
|
||||
if len(children) != 1:
|
||||
print("expected the head to have only 1 child.")
|
||||
@@ -97,7 +100,7 @@ def metarig_definition(obj, orig_bone_name):
|
||||
|
||||
def main(obj, bone_definition, base_names):
|
||||
from Mathutils import Vector
|
||||
|
||||
|
||||
arm = obj.data
|
||||
|
||||
# Initialize container classes for convenience
|
||||
@@ -115,12 +118,12 @@ def main(obj, bone_definition, base_names):
|
||||
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
@@ -128,7 +131,7 @@ def main(obj, bone_definition, base_names):
|
||||
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
|
||||
@@ -137,7 +140,7 @@ def main(obj, bone_definition, base_names):
|
||||
|
||||
# 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
|
||||
@@ -145,60 +148,60 @@ def main(obj, bone_definition, base_names):
|
||||
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, attr in enumerate(mt_chain.attr_names):
|
||||
neck_e = getattr(mt_chain, attr + "_e")
|
||||
|
||||
|
||||
# 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()
|
||||
@@ -207,36 +210,36 @@ def main(obj, bone_definition, base_names):
|
||||
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, attr in enumerate(mt_chain.attr_names):
|
||||
neck_p = getattr(mt_chain, attr + "_p")
|
||||
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"
|
||||
@@ -244,7 +247,7 @@ def main(obj, bone_definition, base_names):
|
||||
con.subtarget = ex.head
|
||||
con.owner_space = 'LOCAL'
|
||||
con.target_space = 'LOCAL'
|
||||
|
||||
|
||||
fcurve = con.driver_add("influence", 0)
|
||||
driver = fcurve.driver
|
||||
driver.type = 'SCRIPTED'
|
||||
@@ -258,6 +261,6 @@ def main(obj, bone_definition, base_names):
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = head_driver_path + ('["bend_%.2d"]' % (j + 1))
|
||||
|
||||
|
||||
# no blending the result of this
|
||||
return None
|
||||
|
||||
@@ -16,13 +16,16 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from rigify import get_bone_data, copy_bone_simple
|
||||
from rna_prop_ui import rna_idprop_ui_get, rna_idprop_ui_prop_get
|
||||
from rna_prop_ui import rna_idprop_ui_prop_get
|
||||
|
||||
# not used, defined for completeness
|
||||
METARIG_NAMES = tuple()
|
||||
|
||||
|
||||
def metarig_template():
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
obj = bpy.context.object
|
||||
@@ -84,73 +87,73 @@ def metarig_definition(obj, orig_bone_name):
|
||||
arm = obj.data
|
||||
bone_definition = [orig_bone_name]
|
||||
palm_ebone = arm.bones[orig_bone_name]
|
||||
|
||||
|
||||
children = [ebone.name for ebone in palm_ebone.children]
|
||||
children.sort() # simply assume the pinky has the lowest name
|
||||
bone_definition.extend(children)
|
||||
|
||||
|
||||
return bone_definition
|
||||
|
||||
|
||||
def main(obj, bone_definition, base_names):
|
||||
arm, palm_pbone, palm_ebone = get_bone_data(obj, bone_definition[0])
|
||||
children = bone_definition[1:]
|
||||
|
||||
|
||||
# Make a copy of the pinky
|
||||
# simply assume the pinky has the lowest name
|
||||
pinky_ebone = arm.edit_bones[children[0]]
|
||||
ring_ebone = arm.edit_bones[children[1]]
|
||||
|
||||
|
||||
control_ebone = copy_bone_simple(arm, pinky_ebone.name, "palm_control", parent=True)
|
||||
control_name = control_ebone.name
|
||||
|
||||
control_name = control_ebone.name
|
||||
|
||||
offset = (pinky_ebone.head - ring_ebone.head)
|
||||
|
||||
|
||||
control_ebone.translate(offset)
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
|
||||
|
||||
|
||||
arm, control_pbone, control_ebone = get_bone_data(obj, control_name)
|
||||
arm, pinky_pbone, pinky_ebone = get_bone_data(obj, children[0])
|
||||
|
||||
|
||||
control_pbone.rotation_mode = 'YZX'
|
||||
control_pbone.lock_rotation = False, True, True
|
||||
|
||||
|
||||
driver_fcurves = pinky_pbone.driver_add("rotation_euler")
|
||||
|
||||
|
||||
|
||||
|
||||
controller_path = control_pbone.path_to_id()
|
||||
|
||||
|
||||
# add custom prop
|
||||
control_pbone["spread"] = 0.0
|
||||
prop = rna_idprop_ui_prop_get(control_pbone, "spread", create=True)
|
||||
prop["soft_min"] = -1.0
|
||||
prop["soft_max"] = 1.0
|
||||
|
||||
|
||||
|
||||
|
||||
# *****
|
||||
driver = driver_fcurves[0].driver
|
||||
driver.type = 'AVERAGE'
|
||||
|
||||
|
||||
tar = driver.targets.new()
|
||||
tar.name = "x"
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = controller_path + ".rotation_euler[0]"
|
||||
|
||||
|
||||
|
||||
|
||||
# *****
|
||||
driver = driver_fcurves[1].driver
|
||||
driver.expression = "-x/4.0"
|
||||
|
||||
|
||||
tar = driver.targets.new()
|
||||
tar.name = "x"
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = controller_path + ".rotation_euler[0]"
|
||||
|
||||
|
||||
|
||||
|
||||
# *****
|
||||
driver = driver_fcurves[2].driver
|
||||
driver.expression = "(1.0-cos(x))-s"
|
||||
@@ -159,7 +162,7 @@ def main(obj, bone_definition, base_names):
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = controller_path + ".rotation_euler[0]"
|
||||
|
||||
|
||||
tar = driver.targets.new()
|
||||
tar.name = "s"
|
||||
tar.id_type = 'OBJECT'
|
||||
@@ -170,17 +173,17 @@ def main(obj, bone_definition, base_names):
|
||||
for i, child_name in enumerate(children):
|
||||
child_pbone = obj.pose.bones[child_name]
|
||||
child_pbone.rotation_mode = 'YZX'
|
||||
|
||||
|
||||
if child_name != children[-1] and child_name != children[0]:
|
||||
|
||||
|
||||
# this is somewhat arbitrary but seems to look good
|
||||
inf = i / (len(children)+1)
|
||||
inf = i / (len(children) + 1)
|
||||
inf = 1.0 - inf
|
||||
inf = ((inf * inf) + inf) / 2.0
|
||||
|
||||
|
||||
# used for X/Y constraint
|
||||
inf_minor = inf * inf
|
||||
|
||||
|
||||
con = child_pbone.constraints.new('COPY_ROTATION')
|
||||
con.name = "Copy Z Rot"
|
||||
con.target = obj
|
||||
@@ -200,6 +203,6 @@ def main(obj, bone_definition, base_names):
|
||||
|
||||
child_pbone = obj.pose.bones[children[-1]]
|
||||
child_pbone.rotation_mode = 'QUATERNION'
|
||||
|
||||
|
||||
# no blending the result of this
|
||||
return None
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from rigify import bone_class_instance, copy_bone_simple
|
||||
from rna_prop_ui import rna_idprop_ui_prop_get
|
||||
@@ -23,6 +25,7 @@ from rna_prop_ui import rna_idprop_ui_prop_get
|
||||
# not used, defined for completeness
|
||||
METARIG_NAMES = ("pelvis", "ribcage")
|
||||
|
||||
|
||||
def metarig_template():
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
obj = bpy.context.object
|
||||
@@ -98,7 +101,7 @@ def metarig_definition(obj, orig_bone_name):
|
||||
arm = obj.data
|
||||
ribcage = arm.bones[orig_bone_name]
|
||||
pelvis = ribcage.parent
|
||||
|
||||
|
||||
children = ribcage.children
|
||||
if len(children) != 1:
|
||||
print("expected the ribcage to have only 1 child.")
|
||||
@@ -108,11 +111,13 @@ def metarig_definition(obj, orig_bone_name):
|
||||
bone_definition.extend([child.name for child in child.children_recursive_basename])
|
||||
return bone_definition
|
||||
|
||||
|
||||
def fk(*args):
|
||||
main(*args)
|
||||
|
||||
|
||||
def main(obj, bone_definition, base_names):
|
||||
from Mathutils import Vector, Matrix, RotationMatrix
|
||||
from Mathutils import Vector, RotationMatrix
|
||||
from math import radians, pi
|
||||
|
||||
arm = obj.data
|
||||
@@ -138,11 +143,11 @@ def main(obj, bone_definition, base_names):
|
||||
spine_chain = [child] + child.children_recursive_basename
|
||||
spine_chain_orig = [child.name for child in spine_chain]
|
||||
'''
|
||||
|
||||
|
||||
child = spine_chain[0]
|
||||
spine_chain_segment_length = child.length
|
||||
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
|
||||
@@ -153,33 +158,33 @@ def main(obj, bone_definition, base_names):
|
||||
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))
|
||||
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.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))
|
||||
|
||||
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.translate(Vector(0.0, - ex.ribcage_e.length / 2.0, 0.0))
|
||||
ex.ribcage_e.parent = mt.ribcage_e
|
||||
|
||||
spine_chain = [child.name for child in spine_chain]
|
||||
@@ -194,7 +199,7 @@ def main(obj, bone_definition, base_names):
|
||||
rv_chain = bone_class_instance(obj, spine_chain_attrs) # *
|
||||
ex_chain = bone_class_instance(obj, spine_chain_attrs) # MCH-rev_*
|
||||
del spine_chain_attrs
|
||||
|
||||
|
||||
for i, child_name in enumerate(spine_chain):
|
||||
child_name_orig = base_names[spine_chain_orig[i]]
|
||||
|
||||
@@ -208,37 +213,37 @@ def main(obj, bone_definition, base_names):
|
||||
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):
|
||||
for i, child_name in enumerate(spine_chain_orig):
|
||||
attr = ex_chain.attr_names[i] + "_e"
|
||||
|
||||
|
||||
if i == 0:
|
||||
getattr(ex_chain, attr).parent = mt.pelvis_e
|
||||
else:
|
||||
attr_parent = ex_chain.attr_names[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, spine_chain_len): # similar to neck
|
||||
child_name_orig = spine_chain_orig[i]
|
||||
spine_e = getattr(mt_chain, mt_chain.attr_names[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, ex_chain.attr_names[i] + "_e")
|
||||
orig_parent = spine_e.parent
|
||||
spine_e.connected = False
|
||||
@@ -246,7 +251,7 @@ def main(obj, bone_definition, base_names):
|
||||
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
|
||||
@@ -259,10 +264,10 @@ def main(obj, bone_definition, base_names):
|
||||
spine_e.tail = ((spine_e.tail - pivot) * matrix) + pivot
|
||||
spine_e.roll += pi # 180d roll
|
||||
del spine_e
|
||||
|
||||
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
|
||||
# refresh pose bones
|
||||
mt.update()
|
||||
ex.update()
|
||||
@@ -270,41 +275,41 @@ def main(obj, bone_definition, base_names):
|
||||
mt_chain.update()
|
||||
ex_chain.update()
|
||||
rv_chain.update()
|
||||
|
||||
|
||||
# df.pelvis_p / DEF-wgt_pelvis
|
||||
con = df.pelvis_p.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = ex.pelvis
|
||||
con.owner_space = 'LOCAL'
|
||||
con.target_space = 'LOCAL'
|
||||
|
||||
|
||||
con = df.pelvis_p.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = ex.pelvis
|
||||
con.owner_space = 'LOCAL'
|
||||
con.target_space = 'LOCAL'
|
||||
|
||||
|
||||
# df.ribcage_p / DEF-wgt_rib_cage
|
||||
con = df.ribcage_p.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = ex.ribcage
|
||||
con.owner_space = 'LOCAL'
|
||||
con.target_space = 'LOCAL'
|
||||
|
||||
|
||||
con = df.ribcage_p.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = ex.ribcage
|
||||
con.owner_space = 'LOCAL'
|
||||
con.target_space = 'LOCAL'
|
||||
|
||||
|
||||
con = ex.ribcage_hinge_p.constraints.new('COPY_ROTATION')
|
||||
con.name = "hinge"
|
||||
con.target = obj
|
||||
con.subtarget = mt.pelvis
|
||||
|
||||
|
||||
# add driver
|
||||
hinge_driver_path = mt.ribcage_p.path_to_id() + '["hinge"]'
|
||||
|
||||
|
||||
fcurve = con.driver_add("influence", 0)
|
||||
driver = fcurve.driver
|
||||
tar = driver.targets.new()
|
||||
@@ -313,14 +318,13 @@ def main(obj, bone_definition, base_names):
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = hinge_driver_path
|
||||
|
||||
|
||||
mod = fcurve.modifiers[0]
|
||||
mod.poly_order = 1
|
||||
mod.coefficients[0] = 1.0
|
||||
mod.coefficients[1] = -1.0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
con = ex.spine_rotate_p.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = mt.ribcage
|
||||
@@ -338,7 +342,7 @@ def main(obj, bone_definition, base_names):
|
||||
con.subtarget = mt_chain.spine_01
|
||||
con.owner_space = 'WORLD'
|
||||
con.target_space = 'WORLD'
|
||||
|
||||
|
||||
# ex.ribcage_p / MCH-wgt_rib_cage
|
||||
con = ex.ribcage_p.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
@@ -347,57 +351,57 @@ def main(obj, bone_definition, base_names):
|
||||
|
||||
con = ex.ribcage_p.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = getattr(mt_chain, mt_chain.attr_names[-1])
|
||||
|
||||
con.subtarget = getattr(mt_chain, mt_chain.attr_names[-1])
|
||||
|
||||
# mt.pelvis_p / rib_cage
|
||||
con = mt.ribcage_p.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = mt.pelvis
|
||||
con.head_tail = 0.0
|
||||
|
||||
|
||||
# This stores all important ID props
|
||||
prop = rna_idprop_ui_prop_get(mt.ribcage_p, "hinge", create=True)
|
||||
mt.ribcage_p["hinge"] = 1.0
|
||||
prop["soft_min"] = 0.0
|
||||
prop["soft_max"] = 1.0
|
||||
|
||||
|
||||
prop = rna_idprop_ui_prop_get(mt.ribcage_p, "pivot_slide", create=True)
|
||||
mt.ribcage_p["pivot_slide"] = 0.5
|
||||
prop["soft_min"] = 1.0 / spine_chain_len
|
||||
prop["soft_max"] = 1.0
|
||||
|
||||
|
||||
for i in range(spine_chain_len - 1):
|
||||
prop_name = "bend_%.2d" % (i + 1)
|
||||
prop = rna_idprop_ui_prop_get(mt.ribcage_p, prop_name, create=True)
|
||||
mt.ribcage_p[prop_name] = 1.0
|
||||
prop["soft_min"] = 0.0
|
||||
prop["soft_max"] = 1.0
|
||||
|
||||
|
||||
# Create a fake connected parent/child relationship with bone location constraints
|
||||
# positioned at the tip.
|
||||
|
||||
|
||||
# reverse bones / MCH-rev_spine.##
|
||||
for i in range(1, spine_chain_len):
|
||||
spine_p = getattr(rv_chain, rv_chain.attr_names[i] + "_p")
|
||||
spine_fake_parent_name = getattr(rv_chain, rv_chain.attr_names[i - 1])
|
||||
|
||||
|
||||
con = spine_p.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = spine_fake_parent_name
|
||||
con.head_tail = 1.0
|
||||
del spine_p, spine_fake_parent_name, con
|
||||
|
||||
|
||||
|
||||
|
||||
# Constrain 'inbetween' bones
|
||||
|
||||
|
||||
# b01/max(0.001,b01+b02+b03+b04+b05)
|
||||
target_names = [("b%.2d" % (i + 1)) for i in range(spine_chain_len - 1)]
|
||||
expression_suffix = "/max(0.001,%s)" % "+".join(target_names)
|
||||
|
||||
|
||||
rib_driver_path = mt.ribcage_p.path_to_id()
|
||||
|
||||
|
||||
for i in range(1, spine_chain_len):
|
||||
|
||||
|
||||
spine_p = getattr(ex_chain, ex_chain.attr_names[i] + "_p")
|
||||
spine_p_parent = spine_p.parent # interlaced bone
|
||||
|
||||
@@ -407,7 +411,7 @@ def main(obj, bone_definition, base_names):
|
||||
con.owner_space = 'LOCAL'
|
||||
con.target_space = 'LOCAL'
|
||||
del spine_p
|
||||
|
||||
|
||||
# add driver
|
||||
fcurve = con.driver_add("influence", 0)
|
||||
driver = fcurve.driver
|
||||
@@ -422,37 +426,37 @@ def main(obj, bone_definition, base_names):
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = rib_driver_path + ('["bend_%.2d"]' % (j + 1))
|
||||
|
||||
|
||||
|
||||
|
||||
# original bone drivers
|
||||
# note: the first bone has a lot more constraints, but also this simple one is first.
|
||||
for i, attr in enumerate(mt_chain.attr_names):
|
||||
spine_p = getattr(mt_chain, attr + "_p")
|
||||
|
||||
|
||||
con = spine_p.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = getattr(ex_chain, attr) # lock to the copy's rotation
|
||||
del spine_p
|
||||
|
||||
|
||||
# pivot slide: - lots of copy location constraints.
|
||||
|
||||
|
||||
con = mt_chain.spine_01_p.constraints.new('COPY_LOCATION')
|
||||
con.name = "base"
|
||||
con.target = obj
|
||||
con.subtarget = rv_chain.spine_01 # lock to the reverse location
|
||||
|
||||
|
||||
for i in range(1, spine_chain_len + 1):
|
||||
con = mt_chain.spine_01_p.constraints.new('COPY_LOCATION')
|
||||
con.name = "slide_%d" % i
|
||||
con.target = obj
|
||||
|
||||
|
||||
if i == spine_chain_len:
|
||||
attr = mt_chain.attr_names[i - 1]
|
||||
else:
|
||||
attr = mt_chain.attr_names[i]
|
||||
|
||||
con.subtarget = getattr(rv_chain, attr) # lock to the reverse location
|
||||
|
||||
|
||||
if i == spine_chain_len:
|
||||
con.head_tail = 1.0
|
||||
|
||||
@@ -464,12 +468,11 @@ def main(obj, bone_definition, base_names):
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = rib_driver_path + '["pivot_slide"]'
|
||||
|
||||
|
||||
mod = fcurve.modifiers[0]
|
||||
mod.poly_order = 1
|
||||
mod.coefficients[0] = - (i - 1)
|
||||
mod.coefficients[1] = spine_chain_len
|
||||
|
||||
|
||||
# no support for blending chains
|
||||
return None
|
||||
|
||||
|
||||
@@ -211,28 +211,6 @@ class WM_OT_properties_edit(bpy.types.Operator):
|
||||
self.properties.max = prop_ui.get("max", 1000000000)
|
||||
self.properties.description = prop_ui.get("description", "")
|
||||
|
||||
if 0:
|
||||
_message = "PyConsole, press Ctrl+D to unlock the BGE"
|
||||
import sys
|
||||
|
||||
# evaluate commands in current namespace
|
||||
frame = sys._getframe()
|
||||
namespace = frame.f_globals.copy()
|
||||
namespace.update(frame.f_locals)
|
||||
|
||||
import code
|
||||
|
||||
# Autocomp in python, not as comprehensive as IPython
|
||||
import rlcompleter
|
||||
|
||||
try: # ick, some pythons dont have this
|
||||
import readline
|
||||
readline.parse_and_bind("tab: complete")
|
||||
except:
|
||||
pass
|
||||
|
||||
code.interact(banner=_message, local=namespace)
|
||||
|
||||
wm = context.manager
|
||||
wm.invoke_props_popup(self, event)
|
||||
return ('RUNNING_MODAL',)
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from bpy.props import *
|
||||
|
||||
@@ -61,11 +63,11 @@ class SelectPattern(bpy.types.Operator):
|
||||
wm = context.manager
|
||||
wm.invoke_props_popup(self, event)
|
||||
return ('RUNNING_MODAL',)
|
||||
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
props = self.properties
|
||||
|
||||
|
||||
layout.prop(props, "pattern")
|
||||
row = layout.row()
|
||||
row.prop(props, "case_sensitive")
|
||||
|
||||
@@ -793,7 +793,6 @@ static void delete_graph_keys (bAnimContext *ac)
|
||||
/* loop through filtered data and delete selected keys */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
FCurve *fcu= (FCurve *)ale->key_data;
|
||||
AnimData *adt= ale->adt;
|
||||
|
||||
/* delete selected keyframes only */
|
||||
delete_fcurve_keys(fcu);
|
||||
|
||||
Reference in New Issue
Block a user