Removed old rigify code, as it is starting to interfere with the newer Rigify addon.

The newer addon currently resides here: bzr://bzr.cessen.com/rigify
But will eventually be included in svn.
This commit is contained in:
Nathan Vegdahl 2010-10-26 05:07:09 +00:00
parent 05abc0d3eb
commit 30b4fa2aa8
26 changed files with 0 additions and 8979 deletions

View File

@ -1,564 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### 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_prop_get
SPECIAL_TYPES = "root",
LAYER_TYPES = "main", "extra", "ik", "fk"
ORG_LAYERS = [n == 31 for n in range(0, 32)]
MCH_LAYERS = [n == 30 for n in range(0, 32)]
DEF_LAYERS = [n == 29 for n in range(0, 32)]
ROOT_LAYERS = [n == 28 for n in range(0, 32)]
ORG_PREFIX = "ORG-"
MCH_PREFIX = "MCH-"
DEF_PREFIX = "DEF-"
WGT_PREFIX = "WGT-"
class RigifyError(Exception):
"""Exception raised for errors in the metarig.
"""
def __init__(self, message):
self.message = message
def __str__(self):
return repr(self.message)
def submodule_func_from_type(bone_type):
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"
type_name, func_name = type_pair
# from rigify import leg
try:
submod = __import__(name="%s.%s" % (__package__, type_name), fromlist=[type_name])
except ImportError:
raise RigifyError("python module for type '%s' not found" % type_name)
reload(submod)
return type_name, submod, getattr(submod, func_name)
def get_submodule_types():
import os
submodules = []
files = os.listdir(os.path.dirname(__file__))
for f in files:
if not f.startswith("_") and f.endswith(".py"):
submodules.append(f[:-3])
return sorted(submodules)
def get_bone_type_options(pbone, type_name):
options = {}
bone_name = pbone.name
for key, value in pbone.items():
key_pair = key.rsplit(".")
# get all bone properties
""""
if key_pair[0] == type_name:
if len(key_pair) != 2:
raise RigifyError("option error for bone '%s', property name was not a pair '%s'" % (bone_name, key_pair))
options[key_pair[1]] = value
"""
options[key] = value
return options
def get_layer_dict(options):
'''
Extracts layer info from a bone options dict
defaulting to the layer index if not set.
'''
layer_default = [False] * 32
result = {}
for i, layer_type in enumerate(LAYER_TYPES):
# no matter if its not defined
layer_index = options.get("layer_" + layer_type, i + 2)
layer = layer_default[:]
layer[layer_index-1] = True
result[layer_type] = layer
return result
def validate_rig(context, obj):
'''
Makes no changes
only runs the metarig definitions and reports errors
'''
type_found = False
for pbone in obj.pose.bones:
bone_name = pbone.name
bone_type = pbone.get("type", "")
if bone_type:
bone_type_list = [bt for bt in bone_type.replace(",", " ").split()]
else:
bone_type_list = []
for bone_type in bone_type_list:
if bone_type.split(".")[0] in SPECIAL_TYPES:
continue
type_name, submod, type_func = submodule_func_from_type(bone_type)
reload(submod)
submod.metarig_definition(obj, bone_name)
type_found = True
get_bone_type_options(pbone, bone_type)
# missing, - check for duplicate root bone.
if not type_found:
raise RigifyError("This rig has no 'type' properties defined on any pose bones, nothing to do")
def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True):
'''
Main function for generating
'''
from collections import OrderedDict
import rigify_utils
reload(rigify_utils)
print("Begin...")
# Not needed but catches any errors before duplicating
validate_rig(context, obj_orig)
use_global_undo = context.user_preferences.edit.use_global_undo
context.user_preferences.edit.use_global_undo = False
mode_orig = context.mode
rest_backup = obj_orig.data.pose_position
obj_orig.data.pose_position = 'REST'
bpy.ops.object.mode_set(mode='OBJECT')
scene = context.scene
# Check if the generated rig already exists, so we can
# regenerate in the same object. If not, create a new
# object to generate the rig in.
print("Fetch rig.")
try:
name = obj_orig["rig_object_name"]
except KeyError:
name = "rig"
try:
obj = scene.objects[name]
except KeyError:
obj = bpy.data.objects.new(name, bpy.data.armatures.new(name))
scene.objects.link(obj)
obj.data.pose_position = 'POSE'
# Get rid of anim data in case the rig already existed
print("Clear rig animation data.")
obj.animation_data_clear()
# Select generated rig object
obj_orig.select = False
obj.select = True
scene.objects.active = obj
# Remove all bones from the generated rig armature.
bpy.ops.object.mode_set(mode='EDIT')
for bone in obj.data.edit_bones:
obj.data.edit_bones.remove(bone)
bpy.ops.object.mode_set(mode='OBJECT')
# Create temporary duplicates for merging
temp_rig_1 = obj_orig.copy()
temp_rig_1.data = obj_orig.data.copy()
scene.objects.link(temp_rig_1)
temp_rig_2 = obj_orig.copy()
temp_rig_2.data = obj.data
scene.objects.link(temp_rig_2)
# Select the temp rigs for merging
for objt in scene.objects:
objt.select = False # deselect all objects
temp_rig_1.select = True
temp_rig_2.select = True
scene.objects.active = temp_rig_2
# Merge the temporary rigs
bpy.ops.object.join(context)
# Delete the second temp rig
bpy.ops.object.delete()
# Select the generated rig
for objt in scene.objects:
objt.select = False # deselect all objects
obj.select = True
scene.objects.active = obj
# Copy over the pose_bone properties
for bone in obj_orig.pose.bones:
bone_gen = obj.pose.bones[bone.name]
# Rotation mode and transform locks
bone_gen.rotation_mode = bone.rotation_mode
bone_gen.lock_rotation = tuple(bone.lock_rotation)
bone_gen.lock_rotation_w = bone.lock_rotation_w
bone_gen.lock_rotations_4d = bone.lock_rotations_4d
bone_gen.lock_location = tuple(bone.lock_location)
bone_gen.lock_scale = tuple(bone.lock_scale)
# Custom properties
for prop in bone.keys():
bone_gen[prop] = bone[prop]
# Copy over bone properties
for bone in obj_orig.data.bones:
bone_gen = obj.data.bones[bone.name]
# B-bone stuff
bone_gen.bbone_segments = bone.bbone_segments
bone_gen.bbone_in = bone.bbone_in
bone_gen.bbone_out = bone.bbone_out
# Create proxy deformation rig
# TODO: remove this
if META_DEF:
obj_def = obj_orig.copy()
obj_def.data = obj_orig.data.copy()
scene.objects.link(obj_def)
scene.update()
print("On to the real work.")
arm = obj.data
# prepend the ORG prefix to the bones, and create the base_names mapping
base_names = {}
bpy.ops.object.mode_set(mode='EDIT')
for bone in arm.edit_bones:
bone_name = bone.name
bone.name = ORG_PREFIX + bone_name
base_names[bone.name] = bone_name
# create root_bone
bpy.ops.object.mode_set(mode='EDIT')
edit_bone = obj.data.edit_bones.new("root")
root_bone = edit_bone.name
edit_bone.head = (0.0, 0.0, 0.0)
edit_bone.tail = (0.0, 1.0, 0.0)
edit_bone.roll = 0.0
edit_bone.layers = ROOT_LAYERS
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
bone_definitions = {}
# key: bone name
# value: [functions, ...]
# each function is from the module. eg leg.ik, arm.main
bone_typeinfos = {}
# key: bone name
# value: [new_bone_name, ...]
# where each bone with a 'type' stores a list of bones that it created
# ...needed so we can override the root parent
bone_genesis = {}
# inspect all bones and assign their definitions before modifying
for pbone in obj.pose.bones:
bone_name = pbone.name
bone_type = pbone.get("type", "")
if bone_type:
bone_type_list = [bt for bt in bone_type.replace(",", " ").split()]
# not essential but means running autorig again wont do anything
del pbone["type"]
else:
bone_type_list = []
for bone_type in bone_type_list:
type_name, submod, type_func = submodule_func_from_type(bone_type)
reload(submod)
bone_def_dict = bone_definitions.setdefault(bone_name, {})
# Only calculate bone definitions once
if type_name not in bone_def_dict:
bone_def_dict[type_name] = submod.metarig_definition(obj, bone_name)
bone_typeinfo = bone_typeinfos.setdefault(bone_name, [])
bone_typeinfo.append((type_name, type_func))
# sort bones, not needed but gives more pradictable execution which may be useful in rare cases
bones_sorted = obj.pose.bones.values()
bones_sorted.sort(key=lambda pbone: pbone.name) # first sort by names
bones_sorted.sort(key=lambda pbone: len(pbone.parent_recursive)) # parents before children
# now we have all the info about bones we can start operating on them
# for pbone in obj.pose.bones:
for pbone in bones_sorted:
bone_name = pbone.name
print(bone_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()
bone_names_pre = {bone.name for bone in arm.bones}
for type_name, type_func in bone_typeinfos[bone_name]:
print(" " + type_name)
# this bones definition of the current typeinfo
definition = bone_def_dict[type_name]
options = get_bone_type_options(pbone, type_name)
bpy.ops.object.mode_set(mode='EDIT')
ret = type_func(obj, definition, base_names, options)
bpy.ops.object.mode_set(mode='OBJECT')
if ret:
result_submod = results.setdefault(type_name, [])
if result_submod and len(result_submod[-1]) != len(ret):
raise RigifyError("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[type_name]
if len(result_submod) == 2:
blend_bone_list(obj, definition, result_submod[0], result_submod[1], target_bone=bone_name)
bone_names_post = {bone.name for bone in arm.bones}
# Store which bones were created from this one
bone_genesis[bone_name] = list(bone_names_post - bone_names_pre)
# need a reverse lookup on bone_genesis so as to know immediately
# where a bone comes from
bone_genesis_reverse = {}
'''
for bone_name, bone_children in bone_genesis.items():
for bone_child_name in bone_children:
bone_genesis_reverse[bone_child_name] = bone_name
'''
if root_bone:
# assign all new parentless bones to this
bpy.ops.object.mode_set(mode='EDIT')
root_ebone = arm.edit_bones[root_bone]
for ebone in arm.edit_bones:
bone_name = ebone.name
if ebone.parent is None:
ebone.parent = root_ebone
'''
if ebone.parent is None and bone_name not in base_names:
# check for override
bone_creator = bone_genesis_reverse[bone_name]
pbone_creator = obj.pose.bones[bone_creator]
root_bone_override = pbone_creator.get("root", "")
if root_bone_override:
root_ebone_tmp = arm.edit_bones[root_bone_override]
else:
root_ebone_tmp = root_ebone
ebone.use_connect = False
ebone.parent = root_ebone_tmp
'''
bpy.ops.object.mode_set(mode='OBJECT')
if META_DEF:
# for pbone in obj_def.pose.bones:
for bone_name, bone_name_new in base_names.items():
#pbone_from = bone_name
pbone = obj_def.pose.bones[bone_name_new]
con = pbone.constraints.new('COPY_ROTATION')
con.target = obj
con.subtarget = bone_name
if not pbone.bone.use_connect:
con = pbone.constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = bone_name
# would be 'REST' from when copied
obj_def.data.pose_position = 'POSE'
# todo - make a more generic system?
layer_tot = [False] * 32
layer_last = layer_tot[:]
layer_last[31] = True
layer_second_last = layer_tot[:]
layer_second_last[30] = True
for bone_name, bone in arm.bones.items():
bone.use_deform = False # Non DEF bones shouldn't deform
if bone_name.startswith(ORG_PREFIX):
bone.layers = ORG_LAYERS
elif bone_name.startswith(MCH_PREFIX): # XXX fixme
bone.layers = MCH_LAYERS
elif bone_name.startswith(DEF_PREFIX): # XXX fixme
bone.layers = DEF_LAYERS
bone.use_deform = True
else:
# Assign bone appearance if there is a widget for it
obj.pose.bones[bone_name].custom_shape = context.scene.objects.get(WGT_PREFIX + bone_name)
layer_tot[:] = [max(lay) for lay in zip(layer_tot, bone.layers)]
# Only for demo'ing
layer_show = [a and not (b or c or d) for a, b, c, d in zip(layer_tot, ORG_LAYERS, MCH_LAYERS, DEF_LAYERS)]
arm.layers = layer_show
# obj.hide = True
obj.data.show_axes = False
bpy.ops.object.mode_set(mode=mode_orig)
obj_orig.data.pose_position = rest_backup
obj.data.pose_position = 'POSE'
obj_orig.data.pose_position = 'POSE'
context.user_preferences.edit.use_global_undo = use_global_undo
print("Done.\n")
return obj
def generate_test(context, metarig_type="", GENERATE_FINAL=True):
import os
new_objects = []
scene = context.scene
def create_empty_armature(name):
armature = bpy.data.armatures.new(name)
obj_new = bpy.data.objects.new(name, armature)
scene.objects.link(obj_new)
scene.objects.active = obj_new
for obj in scene.objects:
obj.select = False
obj_new.select = True
for module_name in get_submodule_types():
if (metarig_type and module_name != metarig_type):
continue
# XXX workaround!, problem with updating the pose matrix.
if module_name == "delta":
continue
type_name, submodule, func = submodule_func_from_type(module_name)
metarig_template = getattr(submodule, "metarig_template", None)
if metarig_template:
create_empty_armature("meta_" + module_name) # sets active
metarig_template()
obj = context.active_object
obj.location = scene.cursor_location
if GENERATE_FINAL:
obj_new = generate_rig(context, obj)
new_objects.append((obj, obj_new))
else:
new_objects.append((obj, None))
else:
print("note: rig type '%s' has no metarig_template(), can't test this" % module_name)
return new_objects
def generate_test_all(context, GRAPH=False):
import rigify
import rigify_utils
import graphviz_export
import os
reload(rigify)
reload(rigify_utils)
reload(graphviz_export)
new_objects = rigify.generate_test(context)
if GRAPH:
if(bpy.data.filepath):
base_name = os.path.splitext(bpy.data.filepath)[0]
else:
import tempfile
base_name = tempfile.mktemp(prefix=bpy.app.tempdir)
for obj, obj_new in new_objects:
for obj in (obj, obj_new):
fn = base_name + "-" + bpy.path.clean_name(obj.name)
path_dot = fn + ".dot"
path_png = fn + ".png"
saved = graphviz_export.graph_armature(obj, path_dot, CONSTRAINTS=True, DRIVERS=True)
#if saved:
# os.system("dot -Tpng %s > %s; eog %s" % (path_dot, path_png, path_png))
i = 0
for obj, obj_new in new_objects:
obj.data.draw_type = 'STICK'
obj.location[1] += i
obj_new.location[1] += i
obj_new.select = False
obj.select = True
i += 4
if __name__ == "__main__":
generate_rig(bpy.context, bpy.context.active_object)

View File

@ -1,396 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from math import radians, pi
from rigify import RigifyError, ORG_PREFIX
from rigify_utils import bone_class_instance, copy_bone_simple, add_pole_target_bone, add_stretch_to, blend_bone_list, get_side_name, get_base_name
from rna_prop_ui import rna_idprop_ui_prop_get
from mathutils import Vector
METARIG_NAMES = "shoulder", "arm", "forearm", "hand"
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('shoulder')
bone.head[:] = 0.0000, -0.0425, 0.0000
bone.tail[:] = 0.0942, -0.0075, 0.0333
bone.roll = -0.2227
bone.use_connect = False
bone = arm.edit_bones.new('upper_arm')
bone.head[:] = 0.1066, -0.0076, -0.0010
bone.tail[:] = 0.2855, 0.0206, -0.0104
bone.roll = 1.6152
bone.use_connect = False
bone.parent = arm.edit_bones['shoulder']
bone = arm.edit_bones.new('forearm')
bone.head[:] = 0.2855, 0.0206, -0.0104
bone.tail[:] = 0.4550, -0.0076, -0.0023
bone.roll = 1.5153
bone.use_connect = True
bone.parent = arm.edit_bones['upper_arm']
bone = arm.edit_bones.new('hand')
bone.head[:] = 0.4550, -0.0076, -0.0023
bone.tail[:] = 0.5423, -0.0146, -0.0131
bone.roll = -3.0083
bone.use_connect = True
bone.parent = arm.edit_bones['forearm']
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['upper_arm']
pbone['type'] = 'arm_biped'
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
if not mt.shoulder_p:
raise RigifyError("could not find '%s' parent, skipping:" % orig_bone_name)
mt.shoulder = mt.shoulder_p.name
# We could have some bones attached, find the bone that has this as its 2nd parent
hands = []
for pbone in obj.pose.bones:
index = pbone.parent_index(mt.arm_p)
if index == 2 and pbone.bone.use_connect and pbone.bone.parent.use_connect:
hands.append(pbone)
if len(hands) != 1:
raise RigifyError("Found %s possible hands attached to this arm, expected 1 from bone: %s" % ([pbone.name for pbone in hands], orig_bone_name))
# first add the 2 new bones
mt.hand_p = hands[0]
mt.hand = mt.hand_p.name
mt.forearm_p = mt.hand_p.parent
mt.forearm = mt.forearm_p.name
return mt.names()
def ik(obj, definitions, base_names, options):
arm = obj.data
mt = bone_class_instance(obj, METARIG_NAMES)
mt.shoulder, mt.arm, mt.forearm, mt.hand = definitions
mt.update()
ik = bone_class_instance(obj, ["pole", "pole_vis", "hand_vis"])
ik_chain = mt.copy(to_fmt="MCH-%s_ik", base_names=base_names, exclude_attrs=["shoulder"])
# IK needs no parent_index
ik_chain.hand_e.use_connect = False
ik_chain.hand_e.parent = None
ik_chain.hand_e.use_local_location = False
ik_chain.rename("hand", get_base_name(base_names[mt.hand]) + "_ik" + get_side_name(mt.hand))
ik_chain.arm_e.use_connect = False
ik_chain.arm_e.parent = mt.shoulder_e
# Add the bone used for the arms poll target
#ik.pole = add_pole_target_bone(obj, mt.forearm, get_base_name(base_names[mt.forearm]) + "_target" + get_side_name(mt.forearm), mode='ZAVERAGE')
ik.pole = add_pole_target_bone(obj, mt.forearm, "elbow_target" + get_side_name(mt.forearm), mode='ZAVERAGE')
ik.update()
ik.pole_e.use_local_location = False
# option: elbow_parent
elbow_parent_name = options.get("elbow_parent", "")
if elbow_parent_name:
try:
elbow_parent_e = arm.edit_bones[ORG_PREFIX + elbow_parent_name]
except:
# TODO, old/new parent mapping
raise RigifyError("parent bone from property 'arm_biped_generic.elbow_parent' not found '%s'" % elbow_parent_name)
ik.pole_e.parent = elbow_parent_e
# update bones after this!
ik.hand_vis = add_stretch_to(obj, mt.hand, ik_chain.hand, "VIS-%s_ik" % base_names[mt.hand])
ik.pole_vis = add_stretch_to(obj, mt.forearm, ik.pole, "VIS-%s_ik" % base_names[mt.forearm])
ik.update()
ik.hand_vis_e.hide_select = True
ik.pole_vis_e.hide_select = True
bpy.ops.object.mode_set(mode='OBJECT')
mt.update()
ik.update()
ik_chain.update()
# Set IK dof
ik_chain.forearm_p.lock_ik_x = False
ik_chain.forearm_p.lock_ik_y = True
ik_chain.forearm_p.lock_ik_z = True
con = ik_chain.forearm_p.constraints.new('IK')
con.target = obj
con.subtarget = ik_chain.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.chain_count = 2
con.pole_angle = -pi/2
# last step setup layers
if "ik_layer" in options:
layer = [n==options["ik_layer"] for n in range(0,32)]
else:
layer = list(mt.arm_b.layers)
ik_chain.hand_b.layers = layer
ik.hand_vis_b.layers = layer
ik.pole_b.layers = layer
ik.pole_vis_b.layers = layer
bpy.ops.object.mode_set(mode='EDIT')
# don't blend the shoulder
return [None] + ik_chain.names()
def fk(obj, definitions, base_names, options):
arm = obj.data
mt = bone_class_instance(obj, METARIG_NAMES)
mt.shoulder, mt.arm, mt.forearm, mt.hand = definitions
mt.update()
ex = bone_class_instance(obj, ["socket", "hand_delta"])
fk_chain = mt.copy(base_names=base_names)
# shoulder is used as a hinge
fk_chain.rename("shoulder", "MCH-%s_hinge" % base_names[mt.arm])
fk_chain.shoulder_e.translate(Vector((0.0, fk_chain.shoulder_e.length / 2, 0.0)))
# upper arm constrains to this.
ex.socket_e = copy_bone_simple(arm, mt.arm, "MCH-%s_socket" % base_names[mt.arm])
ex.socket = ex.socket_e.name
ex.socket_e.use_connect = False
ex.socket_e.parent = mt.shoulder_e
ex.socket_e.length *= 0.5
# insert the 'MCH-delta_hand', between the forearm and the hand
# copies forarm rotation
ex.hand_delta_e = copy_bone_simple(arm, fk_chain.hand, "MCH-delta_%s" % base_names[mt.hand], parent=True)
ex.hand_delta = ex.hand_delta_e.name
ex.hand_delta_e.length *= 0.5
ex.hand_delta_e.use_connect = False
if "hand_roll" in options:
ex.hand_delta_e.roll += radians(options["hand_roll"])
fk_chain.hand_e.use_connect = False
fk_chain.hand_e.parent = ex.hand_delta_e
bpy.ops.object.mode_set(mode='OBJECT')
mt.update()
ex.update()
fk_chain.update()
# Set rotation modes and axis locks
fk_chain.forearm_p.rotation_mode = 'XYZ'
fk_chain.forearm_p.lock_rotation = (False, True, True)
fk_chain.hand_p.rotation_mode = 'ZXY'
fk_chain.arm_p.lock_location = True, True, True
con = fk_chain.arm_p.constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = ex.socket
fk_chain.hand_p.lock_location = True, True, True
con = ex.hand_delta_p.constraints.new('COPY_ROTATION')
con.target = obj
con.subtarget = fk_chain.forearm
def hinge_setup():
# Hinge constraint & driver
con = fk_chain.shoulder_p.constraints.new('COPY_ROTATION')
con.name = "hinge"
con.target = obj
con.subtarget = mt.shoulder
driver_fcurve = con.driver_add("influence")
driver = driver_fcurve.driver
controller_path = fk_chain.arm_p.path_from_id()
# add custom prop
fk_chain.arm_p["hinge"] = 0.0
prop = rna_idprop_ui_prop_get(fk_chain.arm_p, "hinge", create=True)
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
# *****
driver = driver_fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.name = "hinge"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = controller_path + '["hinge"]'
mod = driver_fcurve.modifiers[0]
mod.poly_order = 1
mod.coefficients[0] = 1.0
mod.coefficients[1] = -1.0
hinge_setup()
# last step setup layers
if "fk_layer" in options:
layer = [n==options["fk_layer"] for n in range(0,32)]
else:
layer = list(mt.arm_b.layers)
fk_chain.arm_b.layers = layer
fk_chain.forearm_b.layers = layer
fk_chain.hand_b.layers = layer
# Forearm was getting wrong roll somehow. Hack to fix that.
bpy.ops.object.mode_set(mode='EDIT')
fk_chain.update()
mt.update()
fk_chain.forearm_e.roll = mt.forearm_e.roll
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.mode_set(mode='EDIT')
return None, fk_chain.arm, fk_chain.forearm, fk_chain.hand
def deform(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
# Create upper arm bones: two bones, each half of the upper arm.
uarm1 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.01" % base_names[definitions[1]], parent=True)
uarm2 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.02" % base_names[definitions[1]], parent=True)
uarm1.use_connect = False
uarm2.use_connect = False
uarm2.parent = uarm1
center = uarm1.center
uarm1.tail = center
uarm2.head = center
# Create forearm bones: two bones, each half of the forearm.
farm1 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.01" % base_names[definitions[2]], parent=True)
farm2 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.02" % base_names[definitions[2]], parent=True)
farm1.use_connect = False
farm2.use_connect = False
farm2.parent = farm1
center = farm1.center
farm1.tail = center
farm2.head = center
# Create twist bone
twist = copy_bone_simple(obj.data, definitions[2], "MCH-arm_twist")
twist.use_connect = False
twist.parent = obj.data.edit_bones[definitions[3]]
twist.length /= 2
# Create hand bone
hand = copy_bone_simple(obj.data, definitions[3], "DEF-%s" % base_names[definitions[3]], parent=True)
# Store names before leaving edit mode
uarm1_name = uarm1.name
uarm2_name = uarm2.name
farm1_name = farm1.name
farm2_name = farm2.name
twist_name = twist.name
hand_name = hand.name
# Leave edit mode
bpy.ops.object.mode_set(mode='OBJECT')
# Get the pose bones
uarm1 = obj.pose.bones[uarm1_name]
uarm2 = obj.pose.bones[uarm2_name]
farm1 = obj.pose.bones[farm1_name]
farm2 = obj.pose.bones[farm2_name]
twist = obj.pose.bones[twist_name]
hand = obj.pose.bones[hand_name]
# Upper arm constraints
con = uarm1.constraints.new('DAMPED_TRACK')
con.name = "trackto"
con.target = obj
con.subtarget = definitions[2]
con = uarm1.constraints.new('COPY_SCALE')
con.name = "trackto"
con.target = obj
con.subtarget = definitions[1]
con = uarm2.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[1]
# Forearm constraints
con = farm1.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[2]
con = farm1.constraints.new('COPY_SCALE')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[2]
con = farm2.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = twist.name
con = farm2.constraints.new('DAMPED_TRACK')
con.name = "trackto"
con.target = obj
con.subtarget = definitions[3]
# Hand constraint
con = hand.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[3]
bpy.ops.object.mode_set(mode='EDIT')
return (uarm1_name, uarm2_name, farm1_name, farm2_name, hand_name)
def main(obj, bone_definition, base_names, options):
bones_fk = fk(obj, bone_definition, base_names, options)
bones_ik = ik(obj, bone_definition, base_names, options)
bones_deform = deform(obj, bone_definition, base_names, options)
bpy.ops.object.mode_set(mode='OBJECT')
blend_bone_list(obj, bone_definition, bones_fk, bones_ik, target_bone=bones_ik[3], target_prop="ik", blend_default=0.0)

View File

@ -1,112 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rigify_utils import bone_class_instance, copy_bone_simple
METARIG_NAMES = ("cpy",)
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('Bone')
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 1.0000
bone.roll = 0.0000
bone.use_connect = False
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['Bone']
pbone['type'] = 'copy'
def metarig_definition(obj, orig_bone_name):
return (orig_bone_name,)
def deform(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
# Create deform bone.
bone = copy_bone_simple(obj.data, definitions[0], "DEF-%s" % base_names[definitions[0]], parent=True)
# Store name before leaving edit mode
bone_name = bone.name
# Leave edit mode
bpy.ops.object.mode_set(mode='OBJECT')
# Get the pose bone
bone = obj.pose.bones[bone_name]
# Constrain to the original bone
con = bone.constraints.new('COPY_TRANSFORMS')
con.name = "copy_loc"
con.target = obj
con.subtarget = definitions[0]
return (bone_name,)
def control(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
arm = obj.data
mt = bone_class_instance(obj, METARIG_NAMES)
mt.cpy = definitions[0]
mt.update()
cp = bone_class_instance(obj, ["cpy"])
cp.cpy_e = copy_bone_simple(arm, mt.cpy, base_names[mt.cpy], parent=True)
cp.cpy = cp.cpy_e.name
bpy.ops.object.mode_set(mode='OBJECT')
cp.update()
mt.update()
con = mt.cpy_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = cp.cpy
# Rotation mode and axis locks
cp.cpy_p.rotation_mode = mt.cpy_p.rotation_mode
cp.cpy_p.lock_location = tuple(mt.cpy_p.lock_location)
cp.cpy_p.lock_rotations_4d = mt.cpy_p.lock_rotations_4d
cp.cpy_p.lock_rotation = tuple(mt.cpy_p.lock_rotation)
cp.cpy_p.lock_rotation_w = mt.cpy_p.lock_rotation_w
cp.cpy_p.lock_scale = tuple(mt.cpy_p.lock_scale)
# Layers
cp.cpy_b.layers = list(mt.cpy_b.layers)
return (mt.cpy,)
def main(obj, bone_definition, base_names, options):
# Create control bone
cpy = control(obj, bone_definition, base_names, options)[0]
# Create deform bone
deform(obj, bone_definition, base_names, options)
return (cpy,)

View File

@ -1,162 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rigify import RigifyError
# not used, defined for completeness
METARIG_NAMES = tuple()
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('bonesker')
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = -0.0000, 0.7382, 0.1895
bone.roll = -0.0000
bone.use_connect = False
bone = arm.edit_bones.new('delta')
bone.head[:] = -0.0497, 0.8414, 0.3530
bone.tail[:] = -0.2511, 1.1588, 0.9653
bone.roll = 2.6044
bone.use_connect = False
bone.parent = arm.edit_bones['bonesker']
bone = arm.edit_bones.new('boney')
bone.head[:] = 0.7940, 2.5592, 0.4134
bone.tail[:] = 0.7940, 3.3975, 0.4890
bone.roll = 3.1416
bone.use_connect = False
bone.parent = arm.edit_bones['delta']
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['delta']
pbone['type'] = 'delta'
def metarig_definition(obj, orig_bone_name):
'''
The bone given is the head, its parent is the body,
# its only child the first of a chain with matching basenames.
eg.
body -> head -> neck_01 -> neck_02 -> neck_03.... etc
'''
arm = obj.data
delta = arm.bones[orig_bone_name]
children = delta.children
if len(children) != 1:
raise RigifyError("only 1 child supported for delta on bone '%s'" % delta.name)
if delta.use_connect:
raise RigifyError("bone cannot be connected to its parent '%s'" % delta.name)
bone_definition = [delta.name, children[0].name]
return bone_definition
def main(obj, bone_definition, base_names, options):
'''
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 = obj.data
child_pbone = obj.pose.bones[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()
child_head = child_ebone.head.copy()
child_tail = child_ebone.tail.copy()
#arm.edit_bones.remove(delta_ebone)
#del delta_ebone # cant use this
del child_pbone
bpy.ops.object.mode_set(mode='OBJECT')
# Move the child bone to the deltas location
obj.animation_data_create()
delta_pbone = obj.pose.bones[delta_name]
# child_pbone = obj.pose.bones[child_name]
# ------------------- drivers
delta_pbone.rotation_mode = 'XYZ'
rot = delta_pmatrix.invert().rotation_part() * child_pmatrix.rotation_part()
rot = rot.invert().to_euler()
fcurve_drivers = delta_pbone.driver_add("rotation_euler", -1)
for i, fcurve_driver in enumerate(fcurve_drivers):
driver = fcurve_driver.driver
driver.type = 'AVERAGE'
#mod = fcurve_driver.modifiers.new('GENERATOR')
mod = fcurve_driver.modifiers[0]
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.rotation_part() * (delta_phead - child_phead)
fcurve_drivers = delta_pbone.driver_add("location", -1)
for i, fcurve_driver in enumerate(fcurve_drivers):
driver = fcurve_driver.driver
driver.type = 'AVERAGE'
#mod = fcurve_driver.modifiers.new('GENERATOR')
mod = fcurve_driver.modifiers[0]
mod.poly_order = 1
mod.coefficients[0] = delta_head_offset[i]
mod.coefficients[1] = 0.0
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.object.mode_set(mode=mode_orig)
# no blendeing
return None

View File

@ -1,405 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rna_prop_ui import rna_idprop_ui_prop_get
from mathutils import Vector
from rigify import RigifyError
from rigify_utils import copy_bone_simple
#METARIG_NAMES = ("cpy",)
RIG_TYPE = "eye_balls"
def addget_shape_key(obj, name="Key"):
""" Fetches a shape key, or creates it if it doesn't exist
"""
# Create a shapekey set if it doesn't already exist
if obj.data.shape_keys is None:
shape = obj.add_shape_key(name="Basis", from_mix=False)
obj.active_shape_key_index = 0
# Get the shapekey, or create it if it doesn't already exist
if name in obj.data.shape_keys.keys:
shape_key = obj.data.shape_keys.keys[name]
else:
shape_key = obj.add_shape_key(name=name, from_mix=False)
return shape_key
def addget_shape_key_driver(obj, name="Key"):
""" Fetches the driver for the shape key, or creates it if it doesn't
already exist.
"""
driver_path = 'keys["' + name + '"].value'
fcurve = None
driver = None
new = False
if obj.data.shape_keys.animation_data is not None:
for driver_s in obj.data.shape_keys.animation_data.drivers:
if driver_s.data_path == driver_path:
fcurve = driver_s
if fcurve is None:
fcurve = obj.data.shape_keys.keys[name].driver_add("value")
fcurve.driver.type = 'AVERAGE'
new = True
return fcurve, new
def create_shape_and_driver(obj, bone, meshes, shape_name, var_name, var_path, expression):
""" Creates/gets a shape key and sets up a driver for it.
obj = armature object
bone = driving bone name
meshes = list of meshes to create the shapekey/driver on
shape_name = name of the shape key
var_name = name of the driving variable
var_path = path to the property on the bone to drive with
expression = python expression for the driver
"""
pb = obj.pose.bones
bpy.ops.object.mode_set(mode='OBJECT')
for mesh_name in meshes:
mesh_obj = bpy.data.objects[mesh_name]
# Add/get the shape key
shape = addget_shape_key(mesh_obj, name=shape_name)
# Add/get the shape key driver
fcurve, a = addget_shape_key_driver(mesh_obj, name=shape_name)
# Set up the driver
driver = fcurve.driver
driver.type = 'SCRIPTED'
driver.expression = expression
# Get the variable, or create it if it doesn't already exist
if var_name in driver.variables:
var = driver.variables[var_name]
else:
var = driver.variables.new()
var.name = var_name
# Set up the variable
var.type = "SINGLE_PROP"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = 'pose.bones["' + bone + '"]' + var_path
def mark_actions():
for action in bpy.data.actions:
action.tag = True
def get_unmarked_action():
for action in bpy.data.actions:
if action.tag != True:
return action
return None
def add_action(name=None):
mark_actions()
bpy.ops.action.new()
action = get_unmarked_action()
if name is not None:
action.name = name
return action
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('Bone')
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 1.0000
bone.roll = 0.0000
bone.use_connect = False
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['Bone']
pbone['type'] = 'copy'
def metarig_definition(obj, orig_bone_name):
bone = obj.data.bones[orig_bone_name]
chain = []
try:
chain += [bone.parent.name, bone.name]
except AttributeError:
raise RigifyError("'%s' rig type requires a parent (bone: %s)" % (RIG_TYPE, orig_bone_name))
return chain
def deform(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
eb = obj.data.edit_bones
pb = obj.pose.bones
# Get list of eyes
if "eyes" in options:
eye_base_names = options["eyes"].replace(" ", "").split(",")
else:
eye_base_names = []
# Get their ORG- names
eyes = []
for name in eye_base_names:
eyes += ["ORG-"+name]
# Duplicate the eyes to make deformation bones
def_eyes = [] # def/org pairs
for eye in eyes:
def_eyes += [(copy_bone_simple(obj.data, eye, "DEF-"+base_names[eye], parent=True).name, eye)]
bpy.ops.object.mode_set(mode='OBJECT')
# Constraints
for eye in def_eyes:
con = pb[eye[0]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = eye[1]
return (None,)
def control(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
eb = obj.data.edit_bones
bb = obj.data.bones
pb = obj.pose.bones
head = definitions[0]
eye_target = definitions[1]
# Get list of pupil mesh objects
if "mesh" in options:
pupil_meshes = options["mesh"].replace(" ", "").split(",")
else:
pupil_meshes = []
# Get list of eyes
if "eyes" in options:
eye_base_names = options["eyes"].replace(" ", "").split(",")
else:
eye_base_names = []
# Get their ORG- names
eyes = []
for name in eye_base_names:
eyes += ["ORG-"+name]
# Get the average position of the eyes
center = Vector((0, 0, 0))
for eye in eyes:
center += eb[eye].head
if len(eyes) != 0:
center /= len(eyes)
# Get the average length of the eyes
length = 0.0
for eye in eyes:
length += eb[eye].length
if len(eyes) == 0:
length = 1.0
else:
length /= len(eyes)
# Make the mind's eye
minds_eye = copy_bone_simple(obj.data, eye_target, "MCH-"+base_names[eye_target]+".mind", parent=True).name
eb[minds_eye].head = center
eb[minds_eye].tail = eb[eye_target].head
eb[minds_eye].roll = 0.0
eb[minds_eye].length = length
# Create org/copy/control eye sets
eye_sets = []
for eye in eyes:
copy = copy_bone_simple(obj.data, minds_eye, "MCH-"+base_names[eye]+".cpy", parent=True).name
eb[copy].translate(eb[eye].head - eb[copy].head)
eb[copy].parent = eb[eye].parent
control = copy_bone_simple(obj.data, eye, base_names[eye], parent=True).name
eb[control].parent = eb[copy]
eye_sets += [(eye, copy, control)]
# Bones for parent/free switch for eye target
target_ctrl = copy_bone_simple(obj.data, eye_target, base_names[eye_target], parent=True).name
parent = copy_bone_simple(obj.data, head, "MCH-eye_target_parent", parent=False).name
eb[target_ctrl].parent = eb[parent]
bpy.ops.object.mode_set(mode='OBJECT')
# Axis locks
pb[target_ctrl].lock_scale = False, True, True
# Add eye_spread action if it doesn't already exist
action_name = "eye_spread"
if action_name in bpy.data.actions:
spread_action = bpy.data.actions[action_name]
else:
spread_action = add_action(name=action_name)
# Add free property
prop_name = "free"
prop = rna_idprop_ui_prop_get(pb[target_ctrl], prop_name, create=True)
pb[target_ctrl][prop_name] = 0.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop["min"] = 0.0
prop["max"] = 1.0
free_driver_path = pb[target_ctrl].path_from_id() + '["free"]'
# Constraints
# Mind's eye tracks eye target control
con = pb[minds_eye].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = target_ctrl
# Parent copies transforms of head
con = pb[parent].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = head
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
mod = fcurve.modifiers[0]
mod.coefficients[0] = 1.0
mod.coefficients[1] = -1.0
var = driver.variables.new()
var.name = "free"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = free_driver_path
# Eye set's constraints
for eye in eye_sets:
# Org copies transforms of control
con = pb[eye[0]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = eye[2]
# Copy copies rotation of mind's eye
con = pb[eye[1]].constraints.new('COPY_ROTATION')
con.target = obj
con.subtarget = minds_eye
# Control gets action constraint for eye spread
con = pb[eye[2]].constraints.new('ACTION')
con.target = obj
con.subtarget = target_ctrl
con.action = spread_action
con.transform_channel = 'SCALE_X'
con.frame_start = -20
con.frame_end = 20
con.min = 0.0
con.max = 2.0
con.target_space = 'LOCAL'
# Get/create the shape keys and drivers for pupil dilation
shape_names = ["PUPILS-dilate_wide", "PUPILS-dilate_narrow"]
slider_name = "pupil_dilate"
# Set up the custom property on the bone
prop = rna_idprop_ui_prop_get(pb[target_ctrl], slider_name, create=True)
pb[target_ctrl][slider_name] = 0.0
prop["min"] = 0.0
prop["max"] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
if len(shape_names) > 1:
prop["min"] = -1.0
prop["soft_min"] = -1.0
# Add the shape drivers
# Positive
if shape_names[0] != "":
# Set up the variables for creating the shape key driver
shape_name = shape_names[0]
var_name = slider_name.replace(".", "_").replace("-", "_")
var_path = '["' + slider_name + '"]'
if slider_name + "_fac" in options:
fac = options[slider_name + "_fac"]
else:
fac = 1.0
expression = var_name + " * " + str(fac)
# Create the shape key driver
create_shape_and_driver(obj, target_ctrl, pupil_meshes, shape_name, var_name, var_path, expression)
# Negative
if shape_names[0] != "" and len(shape_names) > 1:
# Set up the variables for creating the shape key driver
shape_name = shape_names[1]
var_name = slider_name.replace(".", "_").replace("-", "_")
var_path = '["' + slider_name + '"]'
if slider_name + "_fac" in options:
fac = options[slider_name + "_fac"]
else:
fac = 1.0
expression = var_name + " * " + str(fac) + " * -1"
# Create the shape key driver
create_shape_and_driver(obj, target_ctrl, pupil_meshes, shape_name, var_name, var_path, expression)
# Set layers
#layer = list(bb[definitions[2]].layers)
#bb[lid1].layers = layer
#bb[lid2].layers = layer
#bb[lid3].layers = layer
#bb[lid4].layers = layer
#bb[lid5].layers = layer
#bb[lid6].layers = layer
#bb[lid7].layers = layer
#bb[lid8].layers = layer
return (None,)
def main(obj, bone_definition, base_names, options):
# Create control rig
control(obj, bone_definition, base_names, options)
# Create deform rig
deform(obj, bone_definition, base_names, options)
return (None,)

View File

@ -1,687 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rna_prop_ui import rna_idprop_ui_prop_get
from math import acos
from mathutils import Vector
from rigify import RigifyError
from rigify_utils import copy_bone_simple
#METARIG_NAMES = ("cpy",)
RIG_TYPE = "eye_lid"
def mark_actions():
for action in bpy.data.actions:
action.tag = True
def get_unmarked_action():
for action in bpy.data.actions:
if action.tag != True:
return action
return None
def add_action(name=None):
mark_actions()
bpy.ops.action.new()
action = get_unmarked_action()
if name is not None:
action.name = name
return action
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('Bone')
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 1.0000
bone.roll = 0.0000
bone.use_connect = False
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['Bone']
pbone['type'] = 'copy'
def metarig_definition(obj, orig_bone_name):
bb = obj.data.bones
bone = bb[orig_bone_name]
chain = []
try:
chain += [bone.parent.parent.name, bone.parent.name, bone.name]
except AttributeError:
raise RigifyError("'%s' rig type requires a chain of two parents (bone: %s)" % (RIG_TYPE, orig_bone_name))
chain += [child.name for child in bone.children_recursive_basename]
if len(chain) < 10:
raise RigifyError("'%s' rig type requires a chain of 10 bones (bone: %s)" % (RIG_TYPE, orig_bone_name))
chain = chain[:10]
try:
chain += [bb[chain[9]].children[0].name]
chain += [bb[chain[10]].children[0].name]
except IndexError:
raise RigifyError("'%s' rig type requires a chain of 10 bones (bone: %s)" % (RIG_TYPE, orig_bone_name))
return chain
def deform(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
eb = obj.data.edit_bones
pb = obj.pose.bones
# Upper lid MCH
lid1 = make_lid_stretch_bone(obj, "MCH-lid", definitions[2], definitions[3], 1.0)
lid2 = make_lid_stretch_bone(obj, "MCH-lid", definitions[3], definitions[4], 1.0)
lid22 = make_lid_stretch_bone(obj, "MCH-lid", definitions[4], definitions[5], 1.0)
lid33 = make_lid_stretch_bone(obj, "MCH-lid", definitions[4], definitions[3], 1.0)
lid3 = make_lid_stretch_bone(obj, "MCH-lid", definitions[5], definitions[4], 1.0)
lid4 = make_lid_stretch_bone(obj, "MCH-lid", definitions[6], definitions[5], 1.0)
dlid22 = copy_bone_simple(obj.data, lid22, "MCH-lid", parent=True).name
dlid33 = copy_bone_simple(obj.data, lid33, "MCH-lid", parent=True).name
eb[dlid22].bbone_segments = 8
eb[dlid33].bbone_segments = 8
eb[lid1].parent = eb[definitions[2]]
eb[lid2].parent = eb[definitions[3]]
eb[lid22].parent = eb[definitions[4]]
eb[lid33].parent = eb[definitions[4]]
eb[lid3].parent = eb[definitions[5]]
eb[lid4].parent = eb[definitions[6]]
# Lower lid MCH
lid5 = make_lid_stretch_bone(obj, "MCH-lid", definitions[6], definitions[7], 1.0)
lid6 = make_lid_stretch_bone(obj, "MCH-lid", definitions[7], definitions[8], 1.0)
lid66 = make_lid_stretch_bone(obj, "MCH-lid", definitions[8], definitions[9], 1.0)
lid77 = make_lid_stretch_bone(obj, "MCH-lid", definitions[8], definitions[7], 1.0)
lid7 = make_lid_stretch_bone(obj, "MCH-lid", definitions[9], definitions[8], 1.0)
lid8 = make_lid_stretch_bone(obj, "MCH-lid", definitions[2], definitions[9], 1.0)
dlid66 = copy_bone_simple(obj.data, lid66, "MCH-lid", parent=True).name
dlid77 = copy_bone_simple(obj.data, lid77, "MCH-lid", parent=True).name
eb[dlid66].bbone_segments = 8
eb[dlid77].bbone_segments = 8
eb[lid5].parent = eb[definitions[6]]
eb[lid6].parent = eb[definitions[7]]
eb[lid66].parent = eb[definitions[8]]
eb[lid77].parent = eb[definitions[8]]
eb[lid7].parent = eb[definitions[9]]
eb[lid8].parent = eb[definitions[2]]
# Upper lid DEF
dlid1 = copy_bone_simple(obj.data, lid1, "DEF-" + base_names[definitions[2]], parent=True).name
dlid2 = copy_bone_simple(obj.data, lid2, "DEF-" + base_names[definitions[3]], parent=True).name
dlid3 = copy_bone_simple(obj.data, lid3, "DEF-" + base_names[definitions[4]], parent=True).name
dlid4 = copy_bone_simple(obj.data, lid4, "DEF-" + base_names[definitions[5]], parent=True).name
eb[dlid2].parent = eb[dlid1]
eb[dlid22].parent = eb[dlid2]
eb[dlid3].parent = eb[dlid4]
eb[dlid33].parent = eb[dlid3]
eb[dlid2].use_connect = True
eb[dlid22].use_connect = True
eb[dlid3].use_connect = True
eb[dlid33].use_connect = True
eb[dlid1].bbone_segments = 8
eb[dlid2].bbone_segments = 8
eb[dlid3].bbone_segments = 8
eb[dlid4].bbone_segments = 8
# Lower lid DEF
dlid5 = copy_bone_simple(obj.data, lid5, "DEF-" + base_names[definitions[6]], parent=True).name
dlid6 = copy_bone_simple(obj.data, lid6, "DEF-" + base_names[definitions[7]], parent=True).name
dlid7 = copy_bone_simple(obj.data, lid7, "DEF-" + base_names[definitions[8]], parent=True).name
dlid8 = copy_bone_simple(obj.data, lid8, "DEF-" + base_names[definitions[9]], parent=True).name
eb[dlid6].parent = eb[dlid5]
eb[dlid66].parent = eb[dlid6]
eb[dlid7].parent = eb[dlid8]
eb[dlid77].parent = eb[dlid7]
eb[dlid6].use_connect = True
eb[dlid66].use_connect = True
eb[dlid7].use_connect = True
eb[dlid77].use_connect = True
eb[dlid5].bbone_segments = 8
eb[dlid6].bbone_segments = 8
eb[dlid7].bbone_segments = 8
eb[dlid8].bbone_segments = 8
bpy.ops.object.mode_set(mode='OBJECT')
# Constraints
con = pb[dlid1].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid1
con = pb[dlid22].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid22
con = pb[dlid33].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid33
con = pb[dlid2].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid2
con = pb[dlid3].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid3
con = pb[dlid4].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid4
con = pb[dlid5].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid5
con = pb[dlid6].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid6
con = pb[dlid66].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid66
con = pb[dlid77].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid77
con = pb[dlid7].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid7
con = pb[dlid8].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lid8
return (None,)
def control(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
eb = obj.data.edit_bones
bb = obj.data.bones
pb = obj.pose.bones
head_e = eb[definitions[0]]
eye_e = eb[definitions[1]]
# Make eye "flower"
flo1 = copy_bone_simple(obj.data, definitions[1], "MCH-"+base_names[definitions[2]]+".flower", parent=True).name
flo2 = copy_bone_simple(obj.data, definitions[1], "MCH-"+base_names[definitions[3]]+".flower", parent=True).name
flo3 = copy_bone_simple(obj.data, definitions[1], "MCH-"+base_names[definitions[4]]+".flower", parent=True).name
flo4 = copy_bone_simple(obj.data, definitions[1], "MCH-"+base_names[definitions[5]]+".flower", parent=True).name
flo5 = copy_bone_simple(obj.data, definitions[1], "MCH-"+base_names[definitions[6]]+".flower", parent=True).name
flo6 = copy_bone_simple(obj.data, definitions[1], "MCH-"+base_names[definitions[7]]+".flower", parent=True).name
flo7 = copy_bone_simple(obj.data, definitions[1], "MCH-"+base_names[definitions[8]]+".flower", parent=True).name
flo8 = copy_bone_simple(obj.data, definitions[1], "MCH-"+base_names[definitions[9]]+".flower", parent=True).name
eb[flo1].tail = eb[definitions[2]].head
eb[flo2].tail = eb[definitions[3]].head
eb[flo3].tail = eb[definitions[4]].head
eb[flo4].tail = eb[definitions[5]].head
eb[flo5].tail = eb[definitions[6]].head
eb[flo6].tail = eb[definitions[7]].head
eb[flo7].tail = eb[definitions[8]].head
eb[flo8].tail = eb[definitions[9]].head
# Make eye lids on tips of flowers
flid1 = copy_bone_simple(obj.data, definitions[2], "MCH-"+base_names[definitions[2]]).name
flid2 = copy_bone_simple(obj.data, definitions[3], "MCH-"+base_names[definitions[3]]).name
flid3 = copy_bone_simple(obj.data, definitions[4], "MCH-"+base_names[definitions[4]]).name
flid4 = copy_bone_simple(obj.data, definitions[5], "MCH-"+base_names[definitions[5]]).name
flid5 = copy_bone_simple(obj.data, definitions[6], "MCH-"+base_names[definitions[6]]).name
flid6 = copy_bone_simple(obj.data, definitions[7], "MCH-"+base_names[definitions[7]]).name
flid7 = copy_bone_simple(obj.data, definitions[8], "MCH-"+base_names[definitions[8]]).name
flid8 = copy_bone_simple(obj.data, definitions[9], "MCH-"+base_names[definitions[9]]).name
eb[flid1].parent = eb[flo1]
eb[flid2].parent = eb[flo2]
eb[flid3].parent = eb[flo3]
eb[flid4].parent = eb[flo4]
eb[flid5].parent = eb[flo5]
eb[flid6].parent = eb[flo6]
eb[flid7].parent = eb[flo7]
eb[flid8].parent = eb[flo8]
# Make eye lid controls
lid1 = copy_bone_simple(obj.data, definitions[2], base_names[definitions[2]]).name
lid2 = copy_bone_simple(obj.data, definitions[3], base_names[definitions[3]]).name
lid3 = copy_bone_simple(obj.data, definitions[4], base_names[definitions[4]]).name
lid4 = copy_bone_simple(obj.data, definitions[5], base_names[definitions[5]]).name
lid5 = copy_bone_simple(obj.data, definitions[6], base_names[definitions[6]]).name
lid6 = copy_bone_simple(obj.data, definitions[7], base_names[definitions[7]]).name
lid7 = copy_bone_simple(obj.data, definitions[8], base_names[definitions[8]]).name
lid8 = copy_bone_simple(obj.data, definitions[9], base_names[definitions[9]]).name
size = eb[lid1].length
size_y = Vector(0.0, size, 0.0)
eb[lid1].tail = eb[lid1].head + size_y
eb[lid2].tail = eb[lid2].head + size_y
eb[lid3].tail = eb[lid3].head + size_y
eb[lid4].tail = eb[lid4].head + size_y
eb[lid5].tail = eb[lid5].head + size_y
eb[lid6].tail = eb[lid6].head + size_y
eb[lid7].tail = eb[lid7].head + size_y
eb[lid8].tail = eb[lid8].head + size_y
eb[lid1].roll = 0
eb[lid2].roll = 0
eb[lid3].roll = 0
eb[lid4].roll = 0
eb[lid5].roll = 0
eb[lid6].roll = 0
eb[lid7].roll = 0
eb[lid8].roll = 0
eb[lid1].parent = head_e
eb[lid2].parent = head_e
eb[lid3].parent = head_e
eb[lid4].parent = head_e
eb[lid5].parent = head_e
eb[lid6].parent = head_e
eb[lid7].parent = head_e
eb[lid8].parent = head_e
lower_lid_ctrl = copy_bone_simple(obj.data, definitions[10], base_names[definitions[10]]).name
upper_lid_ctrl = copy_bone_simple(obj.data, definitions[11], base_names[definitions[11]]).name
eb[lower_lid_ctrl].parent = head_e
eb[upper_lid_ctrl].parent = head_e
distance = (eb[lower_lid_ctrl].head - eb[upper_lid_ctrl].head).length
bpy.ops.object.mode_set(mode='OBJECT')
# Axis locks
pb[lower_lid_ctrl].lock_location = True, False, True
pb[upper_lid_ctrl].lock_location = True, False, True
# Add eye close action if it doesn't already exist
action_name = "eye_close"
if action_name in bpy.data.actions:
close_action = bpy.data.actions[action_name]
else:
close_action = add_action(name=action_name)
# Add close property (useful when making the animation in the action)
prop_name = "close_action"
prop = rna_idprop_ui_prop_get(pb[upper_lid_ctrl], prop_name, create=True)
pb[upper_lid_ctrl][prop_name] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop["min"] = 0.0
prop["max"] = 1.0
close_driver_path = pb[upper_lid_ctrl].path_from_id() + '["close_action"]'
# Constraints
# Flowers track lid controls
con = pb[flo1].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = lid1
con = pb[flo2].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = lid2
con = pb[flo3].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = lid3
con = pb[flo4].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = lid4
con = pb[flo5].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = lid5
con = pb[flo6].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = lid6
con = pb[flo7].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = lid7
con = pb[flo8].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = lid8
# ORG bones to flower lids
con = pb[definitions[2]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = flid1
con = pb[definitions[3]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = flid2
con = pb[definitions[4]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = flid3
con = pb[definitions[5]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = flid4
con = pb[definitions[6]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = flid5
con = pb[definitions[7]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = flid6
con = pb[definitions[8]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = flid7
con = pb[definitions[9]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = flid8
# Action constraints, upper lid
con = pb[lid1].constraints.new('ACTION')
con.target = obj
con.subtarget = upper_lid_ctrl
con.action = close_action
con.transform_channel = 'LOCATION_Y'
con.frame_start = -30
con.frame_end = 30
con.min = -distance*2
con.max = distance
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = close_driver_path
con = pb[lid2].constraints.new('ACTION')
con.target = obj
con.subtarget = upper_lid_ctrl
con.action = close_action
con.transform_channel = 'LOCATION_Y'
con.frame_start = -30
con.frame_end = 30
con.min = -distance*2
con.max = distance
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = close_driver_path
con = pb[lid3].constraints.new('ACTION')
con.target = obj
con.subtarget = upper_lid_ctrl
con.action = close_action
con.transform_channel = 'LOCATION_Y'
con.frame_start = -30
con.frame_end = 30
con.min = -distance*2
con.max = distance
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = close_driver_path
con = pb[lid4].constraints.new('ACTION')
con.target = obj
con.subtarget = upper_lid_ctrl
con.action = close_action
con.transform_channel = 'LOCATION_Y'
con.frame_start = -30
con.frame_end = 30
con.min = -distance*2
con.max = distance
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = close_driver_path
con = pb[lid5].constraints.new('ACTION')
con.target = obj
con.subtarget = upper_lid_ctrl
con.action = close_action
con.transform_channel = 'LOCATION_Y'
con.frame_start = -30
con.frame_end = 30
con.min = -distance*2
con.max = distance
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = close_driver_path
# Action constraints, lower lid
con = pb[lid5].constraints.new('ACTION')
con.target = obj
con.subtarget = lower_lid_ctrl
con.action = close_action
con.transform_channel = 'LOCATION_Y'
con.frame_start = -30
con.frame_end = 30
con.min = -distance
con.max = distance*2
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = close_driver_path
con = pb[lid6].constraints.new('ACTION')
con.target = obj
con.subtarget = lower_lid_ctrl
con.action = close_action
con.transform_channel = 'LOCATION_Y'
con.frame_start = -30
con.frame_end = 30
con.min = -distance
con.max = distance*2
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = close_driver_path
con = pb[lid7].constraints.new('ACTION')
con.target = obj
con.subtarget = lower_lid_ctrl
con.action = close_action
con.transform_channel = 'LOCATION_Y'
con.frame_start = -30
con.frame_end = 30
con.min = -distance
con.max = distance*2
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = close_driver_path
con = pb[lid8].constraints.new('ACTION')
con.target = obj
con.subtarget = lower_lid_ctrl
con.action = close_action
con.transform_channel = 'LOCATION_Y'
con.frame_start = -30
con.frame_end = 30
con.min = -distance
con.max = distance*2
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = close_driver_path
con = pb[lid1].constraints.new('ACTION')
con.target = obj
con.subtarget = lower_lid_ctrl
con.action = close_action
con.transform_channel = 'LOCATION_Y'
con.frame_start = -30
con.frame_end = 30
con.min = -distance
con.max = distance*2
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = close_driver_path
# Set layers
layer = list(bb[definitions[2]].layers)
bb[lid1].layers = layer
bb[lid2].layers = layer
bb[lid3].layers = layer
bb[lid4].layers = layer
bb[lid5].layers = layer
bb[lid6].layers = layer
bb[lid7].layers = layer
bb[lid8].layers = layer
return (None,)
def main(obj, bone_definition, base_names, options):
# Create control rig
control(obj, bone_definition, base_names, options)
# Create deform rig
deform(obj, bone_definition, base_names, options)
return (None,)
def make_lid_stretch_bone(obj, name, bone1, bone2, roll_alpha):
eb = obj.data.edit_bones
pb = obj.pose.bones
# Create the bone, pointing from bone1 to bone2
bone_e = copy_bone_simple(obj.data, bone1, name, parent=True)
bone_e.use_connect = False
bone_e.tail = eb[bone2].head
bone = bone_e.name
# Align the bone roll with the average direction of bone1 and bone2
vec = bone_e.y_axis.cross(((1.0-roll_alpha)*eb[bone1].y_axis) + (roll_alpha*eb[bone2].y_axis)).normalize()
ang = acos(vec * bone_e.x_axis)
bone_e.roll += ang
c1 = vec * bone_e.x_axis
bone_e.roll -= (ang*2)
c2 = vec * bone_e.x_axis
if c1 > c2:
bone_e.roll += (ang*2)
bpy.ops.object.mode_set(mode='OBJECT')
bone_p = pb[bone]
# Constrains
con = bone_p.constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = bone1
con = bone_p.constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = bone2
con = bone_p.constraints.new('STRETCH_TO')
con.target = obj
con.subtarget = bone2
con.volume = 'NO_VOLUME'
bpy.ops.object.mode_set(mode='EDIT')
return bone

View File

@ -1,378 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rigify import RigifyError
from rigify_utils import copy_bone_simple, get_side_name
from rna_prop_ui import rna_idprop_ui_prop_get
METARIG_NAMES = "finger_01", "finger_02", "finger_03"
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('finger.01')
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0353, -0.0184, -0.0053
bone.roll = -2.8722
bone.use_connect = False
bone = arm.edit_bones.new('finger.02')
bone.head[:] = 0.0353, -0.0184, -0.0053
bone.tail[:] = 0.0702, -0.0364, -0.0146
bone.roll = -2.7099
bone.use_connect = True
bone.parent = arm.edit_bones['finger.01']
bone = arm.edit_bones.new('finger.03')
bone.head[:] = 0.0702, -0.0364, -0.0146
bone.tail[:] = 0.0903, -0.0461, -0.0298
bone.roll = -2.1709
bone.use_connect = True
bone.parent = arm.edit_bones['finger.02']
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['finger.01']
pbone['type'] = 'finger_curl'
def metarig_definition(obj, orig_bone_name):
'''
The bone given is the first in a chain
Expects a chain with at least 1 child of the same base name.
eg.
finger_01 -> finger_02
'''
orig_bone = obj.data.bones[orig_bone_name]
bone_definition = [orig_bone.name]
bone_definition.extend([child.name for child in orig_bone.children_recursive_basename])
if len(bone_definition) < 2:
raise RigifyError("expected the chain to have at least 1 child from bone '%s' without the same base name" % orig_bone_name)
return bone_definition
def deform(obj, definitions, base_names, options):
""" Creates the deform rig.
"""
bpy.ops.object.mode_set(mode='EDIT')
three_digits = True if len(definitions) > 2 else False
# Create base digit bones: two bones, each half of the base digit.
f1a = copy_bone_simple(obj.data, definitions[0], "DEF-%s.01" % base_names[definitions[0]], parent=True)
f1b = copy_bone_simple(obj.data, definitions[0], "DEF-%s.02" % base_names[definitions[0]], parent=True)
f1a.use_connect = False
f1b.use_connect = False
f1b.parent = f1a
center = f1a.center
f1a.tail = center
f1b.head = center
# Create the other deform bones.
f2 = copy_bone_simple(obj.data, definitions[1], "DEF-%s" % base_names[definitions[1]], parent=True)
if three_digits:
f3 = copy_bone_simple(obj.data, definitions[2], "DEF-%s" % base_names[definitions[2]], parent=True)
# Store names before leaving edit mode
f1a_name = f1a.name
f1b_name = f1b.name
f2_name = f2.name
if three_digits:
f3_name = f3.name
# Leave edit mode
bpy.ops.object.mode_set(mode='OBJECT')
# Get the pose bones
f1a = obj.pose.bones[f1a_name]
f1b = obj.pose.bones[f1b_name]
f2 = obj.pose.bones[f2_name]
if three_digits:
f3 = obj.pose.bones[f3_name]
# Constrain the base digit's bones
con = f1a.constraints.new('DAMPED_TRACK')
con.name = "trackto"
con.target = obj
con.subtarget = definitions[1]
con = f1a.constraints.new('COPY_SCALE')
con.name = "copy_scale"
con.target = obj
con.subtarget = definitions[0]
con = f1b.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[0]
# Constrain the other digit's bones
con = f2.constraints.new('COPY_TRANSFORMS')
con.name = "copy_transforms"
con.target = obj
con.subtarget = definitions[1]
if three_digits:
con = f3.constraints.new('COPY_TRANSFORMS')
con.name = "copy_transforms"
con.target = obj
con.subtarget = definitions[2]
def main(obj, bone_definition, base_names, options):
# *** EDITMODE
bpy.ops.object.mode_set(mode='EDIT')
three_digits = True if len(bone_definition) > 2 else False
# get assosiated data
arm = obj.data
bb = obj.data.bones
eb = obj.data.edit_bones
pb = obj.pose.bones
org_f1 = bone_definition[0] # Original finger bone 01
org_f2 = bone_definition[1] # Original finger bone 02
if three_digits:
org_f3 = bone_definition[2] # Original finger bone 03
# Check options
if "bend_ratio" in options:
bend_ratio = options["bend_ratio"]
else:
bend_ratio = 0.4
yes = [1, 1.0, True, "True", "true", "Yes", "yes"]
make_hinge = False
if ("hinge" in options) and (eb[org_f1].parent is not None):
if options["hinge"] in yes:
make_hinge = True
# Needed if its a new armature with no keys
obj.animation_data_create()
# Create the control bone
base_name = base_names[bone_definition[0]].split(".", 1)[0]
if three_digits:
tot_len = eb[org_f1].length + eb[org_f2].length + eb[org_f3].length
else:
tot_len = eb[org_f1].length + eb[org_f2].length
control = copy_bone_simple(arm, bone_definition[0], base_name + get_side_name(base_names[bone_definition[0]]), parent=True).name
eb[control].use_connect = eb[org_f1].use_connect
eb[control].parent = eb[org_f1].parent
eb[control].length = tot_len
# Create secondary control bones
f1 = copy_bone_simple(arm, bone_definition[0], base_names[bone_definition[0]]).name
f2 = copy_bone_simple(arm, bone_definition[1], base_names[bone_definition[1]]).name
if three_digits:
f3 = copy_bone_simple(arm, bone_definition[2], base_names[bone_definition[2]]).name
# Create driver bones
df1 = copy_bone_simple(arm, bone_definition[0], "MCH-" + base_names[bone_definition[0]]).name
eb[df1].length /= 2
df2 = copy_bone_simple(arm, bone_definition[1], "MCH-" + base_names[bone_definition[1]]).name
eb[df2].length /= 2
if three_digits:
df3 = copy_bone_simple(arm, bone_definition[2], "MCH-" + base_names[bone_definition[2]]).name
eb[df3].length /= 2
# Set parents of the bones, interleaving the driver bones with the secondary control bones
if three_digits:
eb[f3].use_connect = False
eb[df3].use_connect = False
eb[f2].use_connect = False
eb[df2].use_connect = False
eb[f1].use_connect = False
eb[df1].use_connect = eb[org_f1].use_connect
if three_digits:
eb[f3].parent = eb[df3]
eb[df3].parent = eb[f2]
eb[f2].parent = eb[df2]
eb[df2].parent = eb[f1]
eb[f1].parent = eb[df1]
eb[df1].parent = eb[org_f1].parent
# Set up bones for hinge
if make_hinge:
socket = copy_bone_simple(arm, org_f1, "MCH-socket_"+control, parent=True).name
hinge = copy_bone_simple(arm, eb[org_f1].parent.name, "MCH-hinge_"+control).name
eb[control].use_connect = False
eb[control].parent = eb[hinge]
# Create the deform rig while we're still in edit mode
deform(obj, bone_definition, base_names, options)
# *** POSEMODE
bpy.ops.object.mode_set(mode='OBJECT')
# Set rotation modes and axis locks
pb[control].rotation_mode = obj.pose.bones[bone_definition[0]].rotation_mode
pb[control].lock_location = True, True, True
pb[control].lock_scale = True, False, True
pb[f1].rotation_mode = 'YZX'
pb[f2].rotation_mode = 'YZX'
if three_digits:
pb[f3].rotation_mode = 'YZX'
pb[f1].lock_location = True, True, True
pb[f2].lock_location = True, True, True
if three_digits:
pb[f3].lock_location = True, True, True
pb[df2].rotation_mode = 'YZX'
if three_digits:
pb[df3].rotation_mode = 'YZX'
# Add the bend_ratio property to the control bone
pb[control]["bend_ratio"] = bend_ratio
prop = rna_idprop_ui_prop_get(pb[control], "bend_ratio", create=True)
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
# Add hinge property to the control bone
if make_hinge:
pb[control]["hinge"] = 0.0
prop = rna_idprop_ui_prop_get(pb[control], "hinge", create=True)
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
# Constraints
con = pb[df1].constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = control
con = pb[df1].constraints.new('COPY_ROTATION')
con.target = obj
con.subtarget = control
con = pb[org_f1].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = f1
con = pb[org_f2].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = f2
if three_digits:
con = pb[org_f3].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = f3
if make_hinge:
con = pb[hinge].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = bb[org_f1].parent.name
hinge_driver_path = pb[control].path_from_id() + '["hinge"]'
fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = hinge_driver_path
mod = fcurve.modifiers[0]
mod.poly_order = 1
mod.coefficients[0] = 1.0
mod.coefficients[1] = -1.0
con = pb[control].constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = socket
# Create the drivers for the driver bones (control bone scale rotates driver bones)
controller_path = pb[control].path_from_id() # 'pose.bones["%s"]' % control_bone_name
if three_digits:
finger_digits = [df2, df3]
else:
finger_digits = [df2]
i = 0
for bone in finger_digits:
# XXX - todo, any number
if i == 2:
break
pbone = pb[bone]
pbone.rotation_mode = 'YZX'
fcurve_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
var = driver.variables.new()
var.name = "scale"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = controller_path + '.scale[1]'
# bend target
var = driver.variables.new()
var.name = "br"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = controller_path + '["bend_ratio"]'
# XXX - todo, any number
if three_digits:
if i == 0:
driver.expression = '(-scale+1.0)*pi*2.0*(1.0-br)'
elif i == 1:
driver.expression = '(-scale+1.0)*pi*2.0*br'
else:
driver.expression = driver.expression = '(-scale+1.0)*pi*2.0'
i += 1
# Last step setup layers
if "ex_layer" in options:
layer = [n==options["ex_layer"] for n in range(0,32)]
else:
layer = list(arm.bones[bone_definition[0]].layers)
#for bone_name in [f1, f2, f3]:
# arm.bones[bone_name].layers = layer
arm.bones[f1].layers = layer
arm.bones[f2].layers = layer
if three_digits:
arm.bones[f3].layers = layer
layer = list(arm.bones[bone_definition[0]].layers)
bb[control].layers = layer
# no blending the result of this
return None

View File

@ -1,501 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from math import pi
from rigify import RigifyError
from rigify_utils import bone_class_instance, copy_bone_simple, blend_bone_list, get_side_name, get_base_name
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')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('hips')
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 0.2506
bone.roll = 0.0000
bone.use_connect = False
bone = arm.edit_bones.new('thigh')
bone.head[:] = 0.1253, 0.0000, -0.0000
bone.tail[:] = 0.0752, -0.0251, -0.4260
bone.roll = 0.1171
bone.use_connect = False
bone.parent = arm.edit_bones['hips']
bone = arm.edit_bones.new('shin')
bone.head[:] = 0.0752, -0.0251, -0.4260
bone.tail[:] = 0.0752, 0.0000, -0.8771
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones['thigh']
bone = arm.edit_bones.new('foot')
bone.head[:] = 0.0752, 0.0000, -0.8771
bone.tail[:] = 0.1013, -0.1481, -0.9773
bone.roll = -0.4662
bone.use_connect = True
bone.parent = arm.edit_bones['shin']
bone = arm.edit_bones.new('toe')
bone.head[:] = 0.1013, -0.1481, -0.9773
bone.tail[:] = 0.1100, -0.2479, -0.9773
bone.roll = 3.1416
bone.use_connect = True
bone.parent = arm.edit_bones['foot']
bone = arm.edit_bones.new('heel')
bone.head[:] = 0.0652, 0.0501, -1.0024
bone.tail[:] = 0.0927, -0.1002, -1.0024
bone.roll = 0.0000
bone.use_connect = False
bone.parent = arm.edit_bones['foot']
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['thigh']
pbone['type'] = 'leg_biped'
def metarig_definition(obj, orig_bone_name):
'''
The bone given is the first in a chain
Expects a chain of at least 3 children.
eg.
thigh -> shin -> foot -> [toe, heel]
'''
bone_definition = []
orig_bone = obj.data.bones[orig_bone_name]
orig_bone_parent = orig_bone.parent
if orig_bone_parent is None:
raise RigifyError("expected the thigh bone to have a parent hip bone")
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
children = bone.children
if len(children) != 1:
raise RigifyError("expected the thigh bone to have 3 children without a fork")
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:
raise RigifyError("expected the foot bone:'%s' to have 2 children" % bone.name)
if children[0].use_connect == children[1].use_connect:
raise RigifyError("expected one bone to be connected")
toe, heel = children
if heel.use_connect:
toe, heel = heel, toe
bone_definition.append(toe.name)
bone_definition.append(heel.name)
if len(bone_definition) != len(METARIG_NAMES):
raise RigifyError("internal problem, expected %d bones" % len(METARIG_NAMES))
return bone_definition
def ik(obj, bone_definition, base_names, options):
arm = obj.data
# setup the existing bones, use names from METARIG_NAMES
mt_chain = bone_class_instance(obj, ["thigh", "shin", "foot", "toe"])
mt = bone_class_instance(obj, ["hips", "heel"])
mt.attr_initialize(METARIG_NAMES, bone_definition)
mt_chain.attr_initialize(METARIG_NAMES, bone_definition)
# children of ik_foot
ik = bone_class_instance(obj, ["foot", "foot_roll", "foot_roll_01", "foot_roll_02", "knee_target"])
# Make a new chain
ik_chain = mt_chain.copy(to_fmt="MCH-%s", base_names=base_names)
# simple rename
ik_chain.rename("thigh", ik_chain.thigh + "_ik")
ik_chain.rename("shin", ik_chain.shin + "_ik")
# make sure leg is child of hips
ik_chain.thigh_e.parent = mt.hips_e
# ik foot: no parents
base_foot_name = get_base_name(base_names[mt_chain.foot])
ik.foot_e = copy_bone_simple(arm, mt.heel, base_foot_name + "_ik" + get_side_name(base_names[mt_chain.foot]))
ik.foot = ik.foot_e.name
ik.foot_e.translate(mt_chain.foot_e.head - ik.foot_e.head)
ik.foot_e.use_local_location = False
# foot roll: heel pointing backwards, half length
ik.foot_roll_e = copy_bone_simple(arm, mt.heel, base_foot_name + "_roll" + get_side_name(base_names[mt_chain.foot]))
ik.foot_roll = ik.foot_roll_e.name
ik.foot_roll_e.tail = ik.foot_roll_e.head - ik.foot_roll_e.vector / 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
ik.foot_roll_01_e.tail = mt_chain.foot_e.tail
ik.foot_roll_01_e.parent = ik.foot_e # heel is disconnected
# same as above but reverse direction
ik.foot_roll_02_e = copy_bone_simple(arm, mt.heel, "MCH-%s_roll.02" % base_foot_name)
ik.foot_roll_02 = ik.foot_roll_02_e.name
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", get_base_name(base_names[mt_chain.toe]) + "_ik" + get_side_name(base_names[mt_chain.toe]))
ik_chain.toe_e.use_connect = False
ik_chain.toe_e.parent = ik.foot_roll_01_e
# re-parent ik_chain.foot to the
ik_chain.foot_e.use_connect = 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" + get_side_name(mt.heel))
ik.knee_target = ik.knee_target_e.name
offset = ik.knee_target_e.tail - ik.knee_target_e.head
offset.z = 0
offset.length = mt_chain.shin_e.head.z - mt.heel_e.head.z
offset.z += offset.length
ik.knee_target_e.translate(offset)
ik.knee_target_e.length *= 0.5
ik.knee_target_e.parent = ik.foot_e
ik.knee_target_e.use_local_location = False
# roll the bone to point up... could also point in the same direction as ik.foot_roll
# ik.foot_roll_02_e.matrix * Vector((0.0, 0.0, 1.0)) # ACK!, no rest matrix in editmode
ik.foot_roll_01_e.align_roll((0.0, 0.0, -1.0))
bpy.ops.object.mode_set(mode='OBJECT')
ik.update()
mt_chain.update()
ik_chain.update()
# Set IK dof
ik_chain.shin_p.lock_ik_x = False
ik_chain.shin_p.lock_ik_y = True
ik_chain.shin_p.lock_ik_z = True
# Set rotation modes and axis locks
ik.foot_roll_p.rotation_mode = 'XYZ'
ik.foot_roll_p.lock_rotation = False, True, True
ik_chain.toe_p.rotation_mode = 'YXZ'
ik_chain.toe_p.lock_rotation = False, True, True
ik_chain.toe_p.lock_location = True, True, True
ik.foot_roll_p.lock_location = True, True, True
# IK
con = ik_chain.shin_p.constraints.new('IK')
con.chain_count = 2
con.iterations = 500
con.pole_angle = -pi / 2.0
con.use_tail = True
con.use_stretch = True
con.use_target = True
con.use_rotation = False
con.weight = 1.0
con.target = obj
con.subtarget = ik_chain.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'))]
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.min_x = 0.0
con.max_x = 180.0 # XXX -deg
else:
con.min_x = -180.0 # XXX -deg
con.max_x = 0.0
# last step setup layers
if "ik_layer" in options:
layer = [n == options["ik_layer"] for n in range(0, 32)]
else:
layer = list(mt_chain.thigh_b.layers)
for attr in ik_chain.attr_names:
getattr(ik_chain, attr + "_b").layers = layer
for attr in ik.attr_names:
getattr(ik, attr + "_b").layers = layer
bpy.ops.object.mode_set(mode='EDIT')
return (None, ik_chain.thigh, ik_chain.shin, ik_chain.foot, ik_chain.toe, None, ik.foot)
def fk(obj, bone_definition, base_names, options):
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)
ebone = arm.edit_bones[bone_definition[i]]
setattr(bone_class, attr, ebone.name)
bone_class.update()
ex.thigh_socket_e = copy_bone_simple(arm, mt_chain.thigh, "MCH-%s_socket" % base_names[mt_chain.thigh], parent=True)
ex.thigh_socket = ex.thigh_socket_e.name
ex.thigh_socket_e.tail = ex.thigh_socket_e.head + Vector((0.0, 0.0, ex.thigh_socket_e.length / 4.0))
ex.thigh_hinge_e = copy_bone_simple(arm, mt.hips, "MCH-%s_hinge" % base_names[mt_chain.thigh], parent=False)
ex.thigh_hinge = ex.thigh_hinge_e.name
fk_chain = mt_chain.copy(base_names=base_names) # fk has no prefix!
fk_chain.foot_e.name = "MCH-" + fk_chain.foot
fk_chain.foot = fk_chain.foot_e.name
# Set up fk foot control
foot_e = copy_bone_simple(arm, mt.heel, base_names[mt_chain.foot])
foot = foot_e.name
foot_e.translate(mt_chain.foot_e.head - foot_e.head)
foot_e.parent = fk_chain.shin_e
foot_e.use_connect = fk_chain.foot_e.use_connect
fk_chain.foot_e.use_connect = False
fk_chain.foot_e.parent = foot_e
fk_chain.thigh_e.use_connect = False
fk_chain.thigh_e.parent = ex.thigh_hinge_e
bpy.ops.object.mode_set(mode='OBJECT')
ex.update()
mt_chain.update()
fk_chain.update()
foot_p = obj.pose.bones[foot]
# Set rotation modes and axis locks
fk_chain.shin_p.rotation_mode = 'XYZ'
fk_chain.shin_p.lock_rotation = False, True, True
foot_p.rotation_mode = 'YXZ'
fk_chain.toe_p.rotation_mode = 'YXZ'
fk_chain.toe_p.lock_rotation = False, True, True
fk_chain.thigh_p.lock_location = True, True, True
con = fk_chain.thigh_p.constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = ex.thigh_socket
# hinge
prop = rna_idprop_ui_prop_get(fk_chain.thigh_p, "hinge", create=True)
fk_chain.thigh_p["hinge"] = 0.0
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_from_id() + '["hinge"]'
fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = hinge_driver_path
mod = fcurve.modifiers[0]
mod.poly_order = 1
mod.coefficients[0] = 1.0
mod.coefficients[1] = -1.0
# last step setup layers
if "fk_layer" in options:
layer = [n == options["fk_layer"] for n in range(0, 32)]
else:
layer = list(mt_chain.thigh_b.layers)
for attr in fk_chain.attr_names:
getattr(fk_chain, attr + "_b").layers = layer
for attr in ex.attr_names:
getattr(ex, attr + "_b").layers = layer
arm.bones[foot].layers = layer
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, None)
def deform(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
# Create upper leg bones: two bones, each half of the upper leg.
uleg1 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.01" % base_names[definitions[1]], parent=True)
uleg2 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.02" % base_names[definitions[1]], parent=True)
uleg1.use_connect = False
uleg2.use_connect = False
uleg2.parent = uleg1
center = uleg1.center
uleg1.tail = center
uleg2.head = center
# Create lower leg bones: two bones, each half of the lower leg.
lleg1 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.01" % base_names[definitions[2]], parent=True)
lleg2 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.02" % base_names[definitions[2]], parent=True)
lleg1.use_connect = False
lleg2.use_connect = False
lleg2.parent = lleg1
center = lleg1.center
lleg1.tail = center
lleg2.head = center
# Create a bone for the second lower leg deform bone to twist with
twist = copy_bone_simple(obj.data, lleg2.name, "MCH-leg_twist")
twist.length /= 4
twist.use_connect = False
twist.parent = obj.data.edit_bones[definitions[3]]
# Create foot bone
foot = copy_bone_simple(obj.data, definitions[3], "DEF-%s" % base_names[definitions[3]], parent=True)
# Create toe bone
toe = copy_bone_simple(obj.data, definitions[4], "DEF-%s" % base_names[definitions[4]], parent=True)
# Store names before leaving edit mode
uleg1_name = uleg1.name
uleg2_name = uleg2.name
lleg1_name = lleg1.name
lleg2_name = lleg2.name
twist_name = twist.name
foot_name = foot.name
toe_name = toe.name
# Leave edit mode
bpy.ops.object.mode_set(mode='OBJECT')
# Get the pose bones
uleg1 = obj.pose.bones[uleg1_name]
uleg2 = obj.pose.bones[uleg2_name]
lleg1 = obj.pose.bones[lleg1_name]
lleg2 = obj.pose.bones[lleg2_name]
foot = obj.pose.bones[foot_name]
toe = obj.pose.bones[toe_name]
# Upper leg constraints
con = uleg1.constraints.new('DAMPED_TRACK')
con.name = "trackto"
con.target = obj
con.subtarget = definitions[2]
con = uleg1.constraints.new('COPY_SCALE')
con.name = "scale"
con.target = obj
con.subtarget = definitions[1]
con = uleg2.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[1]
# Lower leg constraints
con = lleg1.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[2]
con = lleg1.constraints.new('COPY_SCALE')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[2]
con = lleg2.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = twist_name
con = lleg2.constraints.new('DAMPED_TRACK')
con.name = "trackto"
con.target = obj
con.subtarget = definitions[3]
# Foot constraint
con = foot.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[3]
# Toe constraint
con = toe.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[4]
bpy.ops.object.mode_set(mode='EDIT')
return (uleg1_name, uleg2_name, lleg1_name, lleg2_name, foot_name, toe_name, None)
def main(obj, bone_definition, base_names, options):
bones_fk = fk(obj, bone_definition, base_names, options)
bones_ik = ik(obj, bone_definition, base_names, options)
deform(obj, bone_definition, base_names, options)
bpy.ops.object.mode_set(mode='OBJECT')
blend_bone_list(obj, bone_definition + [None], bones_fk, bones_ik, target_bone=bones_ik[6], target_prop="ik", blend_default=1.0)

View File

@ -1,497 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rna_prop_ui import rna_idprop_ui_prop_get
from math import pi
from rigify import RigifyError
from rigify_utils import bone_class_instance, copy_bone_simple, get_side_name, get_base_name
from mathutils import Vector
METARIG_NAMES = "hips", "thigh", "shin", "foot", "toe"
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('body')
bone.head[:] = -0.0728, -0.2427, 0.0000
bone.tail[:] = -0.0728, -0.2427, 0.2427
bone.roll = 0.0000
bone.use_connect = False
bone = arm.edit_bones.new('thigh')
bone.head[:] = 0.0000, 0.0000, -0.0000
bone.tail[:] = 0.0813, -0.2109, -0.3374
bone.roll = -0.4656
bone.use_connect = False
bone.parent = arm.edit_bones['body']
bone = arm.edit_bones.new('shin')
bone.head[:] = 0.0813, -0.2109, -0.3374
bone.tail[:] = 0.0714, -0.0043, -0.5830
bone.roll = -0.2024
bone.use_connect = True
bone.parent = arm.edit_bones['thigh']
bone = arm.edit_bones.new('foot')
bone.head[:] = 0.0714, -0.0043, -0.5830
bone.tail[:] = 0.0929, -0.0484, -0.7652
bone.roll = -0.3766
bone.use_connect = True
bone.parent = arm.edit_bones['shin']
bone = arm.edit_bones.new('toe')
bone.head[:] = 0.0929, -0.0484, -0.7652
bone.tail[:] = 0.1146, -0.1244, -0.7652
bone.roll = -0.0000
bone.use_connect = True
bone.parent = arm.edit_bones['foot']
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['thigh']
pbone['type'] = 'leg_quadruped'
def metarig_definition(obj, orig_bone_name):
'''
The bone given is the first in a chain
Expects a chain of at least 3 children.
eg.
thigh -> shin -> foot -> [toe, heel]
'''
bone_definition = []
orig_bone = obj.data.bones[orig_bone_name]
orig_bone_parent = orig_bone.parent
if orig_bone_parent is None:
raise RigifyError("expected the thigh bone to have a parent hip bone")
bone_definition.append(orig_bone_parent.name)
bone_definition.append(orig_bone.name)
bone = orig_bone
chain = 0
while chain < 3: # first 2 bones only have 1 child
children = bone.children
if len(children) != 1:
raise RigifyError("expected the thigh bone to have 3 children without a fork")
bone = children[0]
bone_definition.append(bone.name) # shin, foot
chain += 1
if len(bone_definition) != len(METARIG_NAMES):
raise RigifyError("internal problem, expected %d bones" % len(METARIG_NAMES))
return bone_definition
def ik(obj, bone_definition, base_names, options):
eb = obj.data.edit_bones
pb = obj.pose.bones
arm = obj.data
bpy.ops.object.mode_set(mode='EDIT')
# setup the existing bones, use names from METARIG_NAMES
mt = bone_class_instance(obj, ["hips"])
mt_chain = bone_class_instance(obj, ["thigh", "shin", "foot", "toe"])
mt.attr_initialize(METARIG_NAMES, bone_definition)
mt_chain.attr_initialize(METARIG_NAMES, bone_definition)
ik_chain = mt_chain.copy(to_fmt="MCH-%s.ik", base_names=base_names)
ik_chain.thigh_e.use_connect = False
ik_chain.thigh_e.parent = mt.hips_e
ik_chain.foot_e.parent = None
ik_chain.rename("foot", get_base_name(base_names[bone_definition[3]]) + "_ik" + get_side_name(base_names[bone_definition[3]]))
ik_chain.rename("toe", get_base_name(base_names[bone_definition[4]]) + "_ik" + get_side_name(base_names[bone_definition[4]]))
# keep the foot_ik as the parent
ik_chain.toe_e.use_connect = False
# Foot uses pose space, not local space, for translation
ik_chain.foot_e.use_local_location = False
# must be after disconnecting the toe
ik_chain.foot_e.align_orientation(mt_chain.toe_e)
# children of ik_foot
ik = bone_class_instance(obj, ["foot_roll", "foot_roll_01", "foot_roll_02", "foot_target"])
# knee rotator
knee_rotator = copy_bone_simple(arm, mt_chain.toe, "knee_rotator" + get_side_name(base_names[mt_chain.foot]), parent=True).name
eb[knee_rotator].use_connect = False
eb[knee_rotator].parent = eb[mt.hips]
eb[knee_rotator].head = eb[ik_chain.thigh].head
eb[knee_rotator].tail = eb[knee_rotator].head + eb[mt_chain.toe].vector
eb[knee_rotator].length = eb[ik_chain.thigh].length / 2
eb[knee_rotator].roll += pi/2
# parent ik leg to the knee rotator
eb[ik_chain.thigh].parent = eb[knee_rotator]
# foot roll is an interesting one!
# plot a vector from the toe bones head, bactwards to the length of the foot
# then align it with the foot but reverse direction.
ik.foot_roll_e = copy_bone_simple(arm, mt_chain.toe, get_base_name(base_names[mt_chain.foot]) + "_roll" + get_side_name(base_names[mt_chain.foot]))
ik.foot_roll = ik.foot_roll_e.name
ik.foot_roll_e.use_connect = False
ik.foot_roll_e.parent = ik_chain.foot_e
ik.foot_roll_e.head -= mt_chain.toe_e.vector.normalize() * mt_chain.foot_e.length
ik.foot_roll_e.tail = ik.foot_roll_e.head - (mt_chain.foot_e.vector.normalize() * mt_chain.toe_e.length)
ik.foot_roll_e.align_roll(mt_chain.foot_e.matrix.rotation_part() * Vector((0.0, 0.0, -1.0)))
# MCH-foot
ik.foot_roll_01_e = copy_bone_simple(arm, mt_chain.foot, "MCH-" + base_names[mt_chain.foot])
ik.foot_roll_01 = ik.foot_roll_01_e.name
ik.foot_roll_01_e.parent = ik_chain.foot_e
ik.foot_roll_01_e.head, ik.foot_roll_01_e.tail = mt_chain.foot_e.tail, mt_chain.foot_e.head
ik.foot_roll_01_e.roll = ik.foot_roll_e.roll
# ik_target, child of MCH-foot
ik.foot_target_e = copy_bone_simple(arm, mt_chain.foot, "MCH-" + base_names[mt_chain.foot] + "_ik_target")
ik.foot_target = ik.foot_target_e.name
ik.foot_target_e.parent = ik.foot_roll_01_e
ik.foot_target_e.align_orientation(ik_chain.foot_e)
ik.foot_target_e.length = ik_chain.foot_e.length / 2.0
ik.foot_target_e.use_connect = True
# MCH-foot.02 child of MCH-foot
ik.foot_roll_02_e = copy_bone_simple(arm, mt_chain.foot, "MCH-%s_02" % base_names[mt_chain.foot])
ik.foot_roll_02 = ik.foot_roll_02_e.name
ik.foot_roll_02_e.parent = ik.foot_roll_01_e
bpy.ops.object.mode_set(mode='OBJECT')
mt.update()
mt_chain.update()
ik.update()
ik_chain.update()
# Set rotation modes and axis locks
#pb[knee_rotator].rotation_mode = 'YXZ'
#pb[knee_rotator].lock_rotation = False, True, False
pb[knee_rotator].lock_location = True, True, True
pb[ik.foot_roll].rotation_mode = 'XYZ'
pb[ik.foot_roll].lock_rotation = False, True, True
pb[ik_chain.toe].rotation_mode = 'XYZ'
pb[ik_chain.toe].lock_rotation = False, True, True
# IK switch property
prop = rna_idprop_ui_prop_get(pb[ik_chain.foot], "ik", create=True)
pb[ik_chain.foot]["ik"] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop["min"] = 0.0
prop["max"] = 1.0
ik_driver_path = pb[ik_chain.foot].path_from_id() + '["ik"]'
# simple constraining of orig bones
con = mt_chain.thigh_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = ik_chain.thigh
fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = ik_driver_path
con = mt_chain.shin_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = ik_chain.shin
fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = ik_driver_path
con = mt_chain.foot_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = ik.foot_roll_02
fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = ik_driver_path
con = mt_chain.toe_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = ik_chain.toe
fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = ik_driver_path
# others...
con = ik.foot_roll_01_p.constraints.new('COPY_ROTATION')
con.target = obj
con.subtarget = ik.foot_roll
con.target_space = 'LOCAL'
con.owner_space = 'LOCAL'
# IK
con = ik_chain.shin_p.constraints.new('IK')
con.chain_count = 2
con.iterations = 500
con.pole_angle = -90.0 # XXX - in deg!
con.use_tail = True
con.use_stretch = True
con.use_target = True
con.use_rotation = False
con.weight = 1.0
con.target = obj
con.subtarget = ik.foot_target
con.pole_target = None
ik.update()
ik_chain.update()
# Set layers of the bones.
if "ik_layer" in options:
layer = [n==options["ik_layer"] for n in range(0,32)]
else:
layer = list(mt_chain.thigh_b.layers)
for attr in ik_chain.attr_names:
obj.data.bones[getattr(ik_chain, attr)].layers = layer
for attr in ik.attr_names:
obj.data.bones[getattr(ik, attr)].layers = layer
obj.data.bones[knee_rotator].layers = layer
return None, ik_chain.thigh, ik_chain.shin, ik_chain.foot, ik_chain.toe
def fk(obj, bone_definition, base_names, options):
eb = obj.data.edit_bones
pb = obj.pose.bones
arm = obj.data
bpy.ops.object.mode_set(mode='EDIT')
# setup the existing bones, use names from METARIG_NAMES
mt = bone_class_instance(obj, ["hips"])
mt_chain = bone_class_instance(obj, ["thigh", "shin", "foot", "toe"])
mt.attr_initialize(METARIG_NAMES, bone_definition)
mt_chain.attr_initialize(METARIG_NAMES, bone_definition)
fk_chain = mt_chain.copy(to_fmt="%s", base_names=base_names)
# Create the socket
socket = copy_bone_simple(arm, mt_chain.thigh, "MCH-leg_socket").name
eb[socket].parent = eb[mt.hips]
eb[socket].length = eb[mt_chain.thigh].length / 4
# Create the hinge
hinge = copy_bone_simple(arm, mt.hips, "MCH-leg_hinge").name
eb[hinge].length = eb[mt.hips].length / 2
# Make leg child of hinge
eb[fk_chain.thigh].use_connect = False
eb[fk_chain.thigh].parent = eb[hinge]
bpy.ops.object.mode_set(mode='OBJECT')
# Set rotation modes and axis locks
pb[fk_chain.shin].rotation_mode = 'XYZ'
pb[fk_chain.shin].lock_rotation = False, True, True
# Constrain original bones to control bones
con = mt_chain.thigh_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = fk_chain.thigh
con = mt_chain.shin_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = fk_chain.shin
con = mt_chain.foot_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = fk_chain.foot
con = mt_chain.toe_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = fk_chain.toe
# Socket constraint
con = pb[fk_chain.thigh].constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = socket
# Hinge constraint
con = pb[hinge].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = mt.hips
prop = rna_idprop_ui_prop_get(pb[fk_chain.thigh], "hinge", create=True)
pb[fk_chain.thigh]["hinge"] = 0.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop["min"] = 0.0
prop["max"] = 1.0
hinge_driver_path = pb[fk_chain.thigh].path_from_id() + '["hinge"]'
fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = hinge_driver_path
mod = fcurve.modifiers[0]
mod.poly_order = 1
mod.coefficients[0] = 1.0
mod.coefficients[1] = -1.0
return None, fk_chain.thigh, fk_chain.shin, fk_chain.foot, fk_chain.toe
def deform(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
# Create upper leg bones: two bones, each half of the upper leg.
uleg1 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.01" % base_names[definitions[1]], parent=True)
uleg2 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.02" % base_names[definitions[1]], parent=True)
uleg1.use_connect = False
uleg2.use_connect = False
uleg2.parent = uleg1
center = uleg1.center
uleg1.tail = center
uleg2.head = center
# Create lower leg bones: two bones, each half of the lower leg.
lleg1 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.01" % base_names[definitions[2]], parent=True)
lleg2 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.02" % base_names[definitions[2]], parent=True)
lleg1.use_connect = False
lleg2.use_connect = False
lleg2.parent = lleg1
center = lleg1.center
lleg1.tail = center
lleg2.head = center
# Create a bone for the second lower leg deform bone to twist with
twist = copy_bone_simple(obj.data, lleg2.name, "MCH-leg_twist")
twist.length /= 4
twist.use_connect = False
twist.parent = obj.data.edit_bones[definitions[3]]
# Create foot bone
foot = copy_bone_simple(obj.data, definitions[3], "DEF-%s" % base_names[definitions[3]], parent=True)
# Create toe bone
toe = copy_bone_simple(obj.data, definitions[4], "DEF-%s" % base_names[definitions[4]], parent=True)
# Store names before leaving edit mode
uleg1_name = uleg1.name
uleg2_name = uleg2.name
lleg1_name = lleg1.name
lleg2_name = lleg2.name
twist_name = twist.name
foot_name = foot.name
toe_name = toe.name
# Leave edit mode
bpy.ops.object.mode_set(mode='OBJECT')
# Get the pose bones
uleg1 = obj.pose.bones[uleg1_name]
uleg2 = obj.pose.bones[uleg2_name]
lleg1 = obj.pose.bones[lleg1_name]
lleg2 = obj.pose.bones[lleg2_name]
foot = obj.pose.bones[foot_name]
toe = obj.pose.bones[toe_name]
# Upper leg constraints
con = uleg1.constraints.new('DAMPED_TRACK')
con.name = "trackto"
con.target = obj
con.subtarget = definitions[2]
con = uleg2.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[1]
# Lower leg constraints
con = lleg1.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[2]
con = lleg2.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = twist_name
con = lleg2.constraints.new('DAMPED_TRACK')
con.name = "trackto"
con.target = obj
con.subtarget = definitions[3]
# Foot constraint
con = foot.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[3]
# Toe constraint
con = toe.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[4]
bpy.ops.object.mode_set(mode='EDIT')
return (uleg1_name, uleg2_name, lleg1_name, lleg2_name, foot_name, toe_name, None)
def main(obj, bone_definition, base_names, options):
bones_fk = fk(obj, bone_definition, base_names, options)
bones_ik = ik(obj, bone_definition, base_names, options)
deform(obj, bone_definition, base_names, options)
return bones_ik

View File

@ -1,756 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rna_prop_ui import rna_idprop_ui_prop_get
from math import acos, pi
from mathutils import Vector
from rigify import RigifyError
from rigify_utils import copy_bone_simple
#METARIG_NAMES = ("cpy",)
RIG_TYPE = "mouth"
def mark_actions():
for action in bpy.data.actions:
action.tag = True
def get_unmarked_action():
for action in bpy.data.actions:
if action.tag != True:
return action
return None
def add_action(name=None):
mark_actions()
bpy.ops.action.new()
action = get_unmarked_action()
if name is not None:
action.name = name
return action
def addget_shape_key(obj, name="Key"):
""" Fetches a shape key, or creates it if it doesn't exist
"""
# Create a shapekey set if it doesn't already exist
if obj.data.shape_keys is None:
shape = obj.add_shape_key(name="Basis", from_mix=False)
obj.active_shape_key_index = 0
# Get the shapekey, or create it if it doesn't already exist
if name in obj.data.shape_keys.keys:
shape_key = obj.data.shape_keys.keys[name]
else:
shape_key = obj.add_shape_key(name=name, from_mix=False)
return shape_key
def addget_shape_key_driver(obj, name="Key"):
""" Fetches the driver for the shape key, or creates it if it doesn't
already exist.
"""
driver_path = 'keys["' + name + '"].value'
fcurve = None
driver = None
new = False
if obj.data.shape_keys.animation_data is not None:
for driver_s in obj.data.shape_keys.animation_data.drivers:
if driver_s.data_path == driver_path:
fcurve = driver_s
if fcurve is None:
fcurve = obj.data.shape_keys.keys[name].driver_add("value")
fcurve.driver.type = 'AVERAGE'
new = True
return fcurve, new
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('Bone')
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 1.0000
bone.roll = 0.0000
bone.use_connect = False
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['Bone']
pbone['type'] = 'copy'
def metarig_definition(obj, orig_bone_name):
bone = obj.data.bones[orig_bone_name]
chain = []
try:
chain += [bone.parent.parent.name, bone.parent.name, bone.name]
except AttributeError:
raise RigifyError("'%s' rig type requires a chain of two parents (bone: %s)" % (RIG_TYPE, orig_bone_name))
chain += [child.name for child in bone.children_recursive_basename]
if len(chain) < 10:
raise RigifyError("'%s' rig type requires a chain of 8 bones (bone: %s)" % (RIG_TYPE, orig_bone_name))
return chain[:10]
def deform(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
eb = obj.data.edit_bones
bb = obj.data.bones
pb = obj.pose.bones
jaw = definitions[1]
# Options
req_options = ["mesh"]
for option in req_options:
if option not in options:
raise RigifyError("'%s' rig type requires a '%s' option (bone: %s)" % (RIG_TYPE, option, base_names[definitions[0]]))
meshes = options["mesh"].replace(" ", "").split(",")
# Lip DEF
lip1 = copy_bone_simple(obj.data, definitions[2], "DEF-" + base_names[definitions[2]]).name
lip2 = copy_bone_simple(obj.data, definitions[3], "DEF-" + base_names[definitions[3]]).name
lip3 = copy_bone_simple(obj.data, definitions[4], "DEF-" + base_names[definitions[4]]).name
lip4 = copy_bone_simple(obj.data, definitions[5], "DEF-" + base_names[definitions[5]]).name
lip5 = copy_bone_simple(obj.data, definitions[6], "DEF-" + base_names[definitions[6]]).name
lip6 = copy_bone_simple(obj.data, definitions[7], "DEF-" + base_names[definitions[7]]).name
lip7 = copy_bone_simple(obj.data, definitions[8], "DEF-" + base_names[definitions[8]]).name
lip8 = copy_bone_simple(obj.data, definitions[9], "DEF-" + base_names[definitions[9]]).name
# Mouth corner spread bones (for driving corrective shape keys)
spread_l_1 = copy_bone_simple(obj.data, definitions[6], "MCH-" + base_names[definitions[6]] + ".spread_1").name
spread_l_2 = copy_bone_simple(obj.data, definitions[6], "MCH-" + base_names[definitions[6]] + ".spread_2").name
eb[spread_l_1].tail = eb[definitions[5]].head
eb[spread_l_2].tail = eb[definitions[5]].head
eb[spread_l_1].roll = 0
eb[spread_l_2].roll = 0
eb[spread_l_1].use_connect = False
eb[spread_l_2].use_connect = False
eb[spread_l_1].parent = eb[definitions[6]]
eb[spread_l_2].parent = eb[definitions[6]]
spread_r_1 = copy_bone_simple(obj.data, definitions[2], "MCH-" + base_names[definitions[2]] + ".spread_1").name
spread_r_2 = copy_bone_simple(obj.data, definitions[2], "MCH-" + base_names[definitions[2]] + ".spread_2").name
eb[spread_r_1].tail = eb[definitions[3]].head
eb[spread_r_2].tail = eb[definitions[3]].head
eb[spread_r_1].roll = 0
eb[spread_r_2].roll = 0
eb[spread_r_1].use_connect = False
eb[spread_r_2].use_connect = False
eb[spread_r_1].parent = eb[definitions[2]]
eb[spread_r_2].parent = eb[definitions[2]]
# Jaw open bones (for driving corrective shape keys)
jopen1 = copy_bone_simple(obj.data, jaw, "MCH-"+base_names[jaw]+".track1", parent=True).name
eb[jopen1].use_connect = False
eb[jopen1].head = eb[jaw].tail
eb[jopen1].tail = eb[jopen1].head + Vector((0, 0, eb[jaw].length/4))
jopen2 = copy_bone_simple(obj.data, jopen1, "MCH-"+base_names[jaw]+".track2").name
eb[jopen2].parent = eb[jaw]
bpy.ops.object.mode_set(mode='OBJECT')
# Constrain DEF bones to ORG bones
con = pb[lip1].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = definitions[2]
con = pb[lip2].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = definitions[3]
con = pb[lip3].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = definitions[4]
con = pb[lip4].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = definitions[5]
con = pb[lip5].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = definitions[6]
con = pb[lip6].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = definitions[7]
con = pb[lip7].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = definitions[8]
con = pb[lip8].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = definitions[9]
# Constraint mouth corner spread bones
con = pb[spread_l_1].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = lip4
con = pb[spread_l_2].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = spread_l_1
con = pb[spread_l_2].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = lip6
con = pb[spread_r_1].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = lip2
con = pb[spread_r_2].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = spread_r_1
con = pb[spread_r_2].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = lip8
# Corrective shape keys for the corners of the mouth.
bpy.ops.object.mode_set(mode='EDIT')
# Calculate the rotation difference between the bones
rotdiff_l = acos((eb[lip5].head - eb[lip4].head).normalize().dot((eb[lip5].head - eb[lip6].head).normalize()))
rotdiff_r = acos((eb[lip1].head - eb[lip2].head).normalize().dot((eb[lip1].head - eb[lip8].head).normalize()))
bpy.ops.object.mode_set(mode='OBJECT')
# Left side shape key
for mesh_name in meshes:
mesh_obj = bpy.data.objects[mesh_name]
shape_key_name = "COR-" + base_names[definitions[6]] + ".spread"
# Add/get the shape key
shape_key = addget_shape_key(mesh_obj, name=shape_key_name)
# Add/get the shape key driver
fcurve, is_new_driver = addget_shape_key_driver(mesh_obj, name=shape_key_name)
driver = fcurve.driver
# Get the variable, or create it if it doesn't already exist
var_name = base_names[definitions[6]]
if var_name in driver.variables:
var = driver.variables[var_name]
else:
var = driver.variables.new()
var.name = var_name
# Set up the variable
var.type = "ROTATION_DIFF"
var.targets[0].id = obj
var.targets[0].bone_target = spread_l_1
var.targets[1].id = obj
var.targets[1].bone_target = spread_l_2
# Set fcurve offset
if is_new_driver:
mod = fcurve.modifiers[0]
if rotdiff_l != pi:
mod.coefficients[0] = -rotdiff_l / (pi-rotdiff_l)
mod.coefficients[1] = 1 / (pi-rotdiff_l)
# Right side shape key
for mesh_name in meshes:
mesh_obj = bpy.data.objects[mesh_name]
shape_key_name = "COR-" + base_names[definitions[2]] + ".spread"
# Add/get the shape key
shape_key = addget_shape_key(mesh_obj, name=shape_key_name)
# Add/get the shape key driver
fcurve, is_new_driver = addget_shape_key_driver(mesh_obj, name=shape_key_name)
driver = fcurve.driver
# Get the variable, or create it if it doesn't already exist
var_name = base_names[definitions[2]]
if var_name in driver.variables:
var = driver.variables[var_name]
else:
var = driver.variables.new()
var.name = var_name
# Set up the variable
var.type = "ROTATION_DIFF"
var.targets[0].id = obj
var.targets[0].bone_target = spread_r_1
var.targets[1].id = obj
var.targets[1].bone_target = spread_r_2
# Set fcurve offset
if is_new_driver:
mod = fcurve.modifiers[0]
if rotdiff_r != pi:
mod.coefficients[0] = -rotdiff_r / (pi-rotdiff_r)
mod.coefficients[1] = 1 / (pi-rotdiff_r)
# Jaw open corrective shape key
for mesh_name in meshes:
mesh_obj = bpy.data.objects[mesh_name]
shape_key_name = "COR-" + base_names[definitions[4]] + ".jaw_open"
# Add/get the shape key
shape_key = addget_shape_key(mesh_obj, name=shape_key_name)
# Add/get the shape key driver
fcurve, is_new_driver = addget_shape_key_driver(mesh_obj, name=shape_key_name)
driver = fcurve.driver
# Get the variable, or create it if it doesn't already exist
var_name = base_names[definitions[4]]
if var_name in driver.variables:
var = driver.variables[var_name]
else:
var = driver.variables.new()
var.name = var_name
# Set up the variable
var.type = "LOC_DIFF"
var.targets[0].id = obj
var.targets[0].bone_target = jopen1
var.targets[1].id = obj
var.targets[1].bone_target = jopen2
# Set fcurve offset
if is_new_driver:
mod = fcurve.modifiers[0]
mod.coefficients[0] = 0.0
mod.coefficients[1] = 1.0 / bb[jaw].length
return (None,)
def control(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
eb = obj.data.edit_bones
bb = obj.data.bones
pb = obj.pose.bones
head_e = eb[definitions[0]]
jaw_e = eb[definitions[1]]
jaw = definitions[1]
# Head lips
hlip1 = copy_bone_simple(obj.data, definitions[2], "MCH-"+base_names[definitions[2]]+".head").name
hlip2 = copy_bone_simple(obj.data, definitions[3], "MCH-"+base_names[definitions[3]]+".head").name
hlip3 = copy_bone_simple(obj.data, definitions[4], "MCH-"+base_names[definitions[4]]+".head").name
hlip4 = copy_bone_simple(obj.data, definitions[5], "MCH-"+base_names[definitions[5]]+".head").name
hlip5 = copy_bone_simple(obj.data, definitions[6], "MCH-"+base_names[definitions[6]]+".head").name
hlip6 = copy_bone_simple(obj.data, definitions[7], "MCH-"+base_names[definitions[7]]+".head").name
hlip7 = copy_bone_simple(obj.data, definitions[8], "MCH-"+base_names[definitions[8]]+".head").name
hlip8 = copy_bone_simple(obj.data, definitions[9], "MCH-"+base_names[definitions[9]]+".head").name
eb[hlip1].parent = head_e
eb[hlip2].parent = head_e
eb[hlip3].parent = head_e
eb[hlip4].parent = head_e
eb[hlip5].parent = head_e
eb[hlip6].parent = head_e
eb[hlip7].parent = head_e
eb[hlip8].parent = head_e
# Jaw lips
jlip1 = copy_bone_simple(obj.data, definitions[2], "MCH-"+base_names[definitions[2]]+".jaw").name
jlip2 = copy_bone_simple(obj.data, definitions[3], "MCH-"+base_names[definitions[3]]+".jaw").name
jlip3 = copy_bone_simple(obj.data, definitions[4], "MCH-"+base_names[definitions[4]]+".jaw").name
jlip4 = copy_bone_simple(obj.data, definitions[5], "MCH-"+base_names[definitions[5]]+".jaw").name
jlip5 = copy_bone_simple(obj.data, definitions[6], "MCH-"+base_names[definitions[6]]+".jaw").name
jlip6 = copy_bone_simple(obj.data, definitions[7], "MCH-"+base_names[definitions[7]]+".jaw").name
jlip7 = copy_bone_simple(obj.data, definitions[8], "MCH-"+base_names[definitions[8]]+".jaw").name
jlip8 = copy_bone_simple(obj.data, definitions[9], "MCH-"+base_names[definitions[9]]+".jaw").name
eb[jlip1].parent = jaw_e
eb[jlip2].parent = jaw_e
eb[jlip3].parent = jaw_e
eb[jlip4].parent = jaw_e
eb[jlip5].parent = jaw_e
eb[jlip6].parent = jaw_e
eb[jlip7].parent = jaw_e
eb[jlip8].parent = jaw_e
# Control lips
lip1 = copy_bone_simple(obj.data, definitions[2], base_names[definitions[2]]).name
lip2 = copy_bone_simple(obj.data, definitions[3], base_names[definitions[3]]).name
lip3 = copy_bone_simple(obj.data, definitions[4], base_names[definitions[4]]).name
lip4 = copy_bone_simple(obj.data, definitions[5], base_names[definitions[5]]).name
lip5 = copy_bone_simple(obj.data, definitions[6], base_names[definitions[6]]).name
lip6 = copy_bone_simple(obj.data, definitions[7], base_names[definitions[7]]).name
lip7 = copy_bone_simple(obj.data, definitions[8], base_names[definitions[8]]).name
lip8 = copy_bone_simple(obj.data, definitions[9], base_names[definitions[9]]).name
eb[lip1].parent = eb[hlip1]
eb[lip2].parent = eb[hlip2]
eb[lip3].parent = eb[hlip3]
eb[lip4].parent = eb[hlip4]
eb[lip5].parent = eb[hlip5]
eb[lip6].parent = eb[hlip6]
eb[lip7].parent = eb[hlip7]
eb[lip8].parent = eb[hlip8]
# Jaw open tracker
jopent = copy_bone_simple(obj.data, jaw_e.name, "MCH-"+base_names[jaw_e.name]+".track", parent=True).name
eb[jopent].use_connect = False
eb[jopent].tail = jaw_e.tail + Vector((0.0, 0.0, jaw_e.length))
eb[jopent].head = jaw_e.tail
bpy.ops.object.mode_set(mode='OBJECT')
# Add mouth open action if it doesn't already exist
action_name = "mouth_open"
if action_name in bpy.data.actions:
open_action = bpy.data.actions[action_name]
else:
open_action = add_action(name=action_name)
# Add close property (useful when making the animation in the action)
prop_name = "open_action"
prop = rna_idprop_ui_prop_get(pb[lip1], prop_name, create=True)
pb[lip1][prop_name] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop["min"] = 0.0
prop["max"] = 1.0
open_driver_path = pb[lip1].path_from_id() + '["open_action"]'
# Constraints
# Jaw open tracker stretches to jaw tip
con = pb[jopent].constraints.new('STRETCH_TO')
con.target = obj
con.subtarget = jaw
con.head_tail = 1.0
con.rest_length = bb[jopent].length
con.volume = 'NO_VOLUME'
# Head lips to jaw lips
influence = [0.02, 0.1, 0.35, 0.25, 0.0]
con = pb[hlip1].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = jlip1
con.influence = influence[2]
con = pb[hlip2].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = jlip2
con.influence = influence[1]
con = pb[hlip3].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = jlip3
con.influence = influence[0]
con = pb[hlip4].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = jlip4
con.influence = influence[1]
con = pb[hlip5].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = jlip5
con.influence = influence[2]
con = pb[hlip6].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = jlip6
con.influence = 1.0 - influence[3]
con = pb[hlip7].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = jlip7
con.influence = 1.0 - influence[4]
con = pb[hlip8].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = jlip8
con.influence = 1.0 - influence[3]
# ORG bones to lips
con = pb[definitions[2]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lip1
con = pb[definitions[3]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lip2
con = pb[definitions[4]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lip3
con = pb[definitions[5]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lip4
con = pb[definitions[6]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lip5
con = pb[definitions[7]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lip6
con = pb[definitions[8]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lip7
con = pb[definitions[9]].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lip8
# Action constraints for open mouth
con = pb[lip1].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.frame_start = 0
con.frame_end = 60
con.min = 0.0
con.max = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip2].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.frame_start = 0
con.frame_end = 60
con.min = 0.0
con.max = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip3].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.frame_start = 0
con.frame_end = 60
con.min = 0.0
con.max = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip4].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.frame_start = 0
con.frame_end = 60
con.min = 0.0
con.max = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip5].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.frame_start = 0
con.frame_end = 60
con.min = 0.0
con.max = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip6].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.frame_start = 0
con.frame_end = 60
con.min = 0.0
con.max = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip7].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.frame_start = 0
con.frame_end = 60
con.min = 0.0
con.max = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip8].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.frame_start = 0
con.frame_end = 60
con.min = 0.0
con.max = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
# Set layers
layer = list(bb[definitions[2]].layers)
bb[lip1].layers = layer
bb[lip2].layers = layer
bb[lip3].layers = layer
bb[lip4].layers = layer
bb[lip5].layers = layer
bb[lip6].layers = layer
bb[lip7].layers = layer
bb[lip8].layers = layer
return (None,)
def main(obj, bone_definition, base_names, options):
# Create control rig
control(obj, bone_definition, base_names, options)
# Create deform rig
deform(obj, bone_definition, base_names, options)
return (None,)
def make_lip_stretch_bone(obj, name, bone1, bone2, roll_alpha):
eb = obj.data.edit_bones
pb = obj.pose.bones
# Create the bone, pointing from bone1 to bone2
bone_e = copy_bone_simple(obj.data, bone1, name, parent=True)
bone_e.use_connect = False
bone_e.tail = eb[bone2].head
bone = bone_e.name
# Align the bone roll with the average direction of bone1 and bone2
vec = bone_e.y_axis.cross(((1.0-roll_alpha)*eb[bone1].y_axis) + (roll_alpha*eb[bone2].y_axis)).normalize()
ang = acos(vec * bone_e.x_axis)
bone_e.roll += ang
c1 = vec * bone_e.x_axis
bone_e.roll -= (ang*2)
c2 = vec * bone_e.x_axis
if c1 > c2:
bone_e.roll += (ang*2)
bpy.ops.object.mode_set(mode='OBJECT')
bone_p = pb[bone]
# Constrains
con = bone_p.constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = bone1
con = bone_p.constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = bone2
con = bone_p.constraints.new('STRETCH_TO')
con.target = obj
con.subtarget = bone2
con.volume = 'NO_VOLUME'
bpy.ops.object.mode_set(mode='EDIT')
return bone

View File

@ -1,344 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rigify import RigifyError
from rigify_utils import bone_class_instance, copy_bone_simple
from rna_prop_ui import rna_idprop_ui_prop_get
def metarig_template():
# TODO:
## generated by rigify.write_meta_rig
#bpy.ops.object.mode_set(mode='EDIT')
#obj = bpy.context.active_object
#arm = obj.data
#bone = arm.edit_bones.new('body')
#bone.head[:] = 0.0000, -0.0276, -0.1328
#bone.tail[:] = 0.0000, -0.0170, -0.0197
#bone.roll = 0.0000
#bone.use_connect = False
#bone = arm.edit_bones.new('head')
#bone.head[:] = 0.0000, -0.0170, -0.0197
#bone.tail[:] = 0.0000, 0.0726, 0.1354
#bone.roll = 0.0000
#bone.use_connect = True
#bone.parent = arm.edit_bones['body']
#bone = arm.edit_bones.new('neck.01')
#bone.head[:] = 0.0000, -0.0170, -0.0197
#bone.tail[:] = 0.0000, -0.0099, 0.0146
#bone.roll = 0.0000
#bone.use_connect = False
#bone.parent = arm.edit_bones['head']
#bone = arm.edit_bones.new('neck.02')
#bone.head[:] = 0.0000, -0.0099, 0.0146
#bone.tail[:] = 0.0000, -0.0242, 0.0514
#bone.roll = 0.0000
#bone.use_connect = True
#bone.parent = arm.edit_bones['neck.01']
#bone = arm.edit_bones.new('neck.03')
#bone.head[:] = 0.0000, -0.0242, 0.0514
#bone.tail[:] = 0.0000, -0.0417, 0.0868
#bone.roll = 0.0000
#bone.use_connect = True
#bone.parent = arm.edit_bones['neck.02']
#bone = arm.edit_bones.new('neck.04')
#bone.head[:] = 0.0000, -0.0417, 0.0868
#bone.tail[:] = 0.0000, -0.0509, 0.1190
#bone.roll = 0.0000
#bone.use_connect = True
#bone.parent = arm.edit_bones['neck.03']
#bone = arm.edit_bones.new('neck.05')
#bone.head[:] = 0.0000, -0.0509, 0.1190
#bone.tail[:] = 0.0000, -0.0537, 0.1600
#bone.roll = 0.0000
#bone.use_connect = True
#bone.parent = arm.edit_bones['neck.04']
#
#bpy.ops.object.mode_set(mode='OBJECT')
#pbone = obj.pose.bones['head']
#pbone['type'] = 'neck_flex'
pass
def metarig_definition(obj, orig_bone_name):
'''
The bone given is neck_01, its parent is the body
eg.
body -> neck_01 -> neck_02 -> neck_03.... etc
'''
arm = obj.data
neck = arm.bones[orig_bone_name]
body = neck.parent
bone_definition = [body.name, neck.name]
bone_definition.extend([child.name for child in neck.children_recursive_basename])
return bone_definition
def deform(obj, definitions, base_names, options):
for org_bone_name in definitions[1:]:
bpy.ops.object.mode_set(mode='EDIT')
# Create deform bone.
bone = copy_bone_simple(obj.data, org_bone_name, "DEF-%s" % base_names[org_bone_name], parent=True)
# Store name before leaving edit mode
bone_name = bone.name
# Leave edit mode
bpy.ops.object.mode_set(mode='OBJECT')
# Get the pose bone
bone = obj.pose.bones[bone_name]
# Constrain to the original bone
# XXX. Todo, is this needed if the bone is connected to its parent?
con = bone.constraints.new('COPY_TRANSFORMS')
con.name = "copy_loc"
con.target = obj
con.subtarget = org_bone_name
def main(obj, bone_definition, base_names, options):
from mathutils import Vector
arm = obj.data
eb = obj.data.edit_bones
bb = obj.data.bones
pb = obj.pose.bones
body = bone_definition[0]
# Create the neck and head control bones
if "head_name" in options:
head_name = options["head_name"]
else:
head_name = "head"
neck_name = base_names[bone_definition[1]].split(".")[0]
neck_ctrl = copy_bone_simple(arm, bone_definition[1], neck_name).name
head_ctrl = copy_bone_simple(arm, bone_definition[len(bone_definition)-1], head_name).name
eb[head_ctrl].tail += eb[neck_ctrl].head - eb[head_ctrl].head
eb[head_ctrl].head = eb[neck_ctrl].head
# Create hinge and socket bones
neck_hinge = copy_bone_simple(arm, bone_definition[0], "MCH-" + neck_name + "_hinge").name
head_hinge = copy_bone_simple(arm, neck_ctrl, "MCH-" + head_name + "_hinge").name
eb[neck_hinge].tail += eb[neck_ctrl].head - eb[neck_hinge].head
eb[neck_hinge].head = eb[neck_ctrl].head
eb[head_hinge].tail += eb[neck_ctrl].head - eb[head_hinge].head
eb[head_hinge].head = eb[neck_ctrl].head
neck_socket = copy_bone_simple(arm, bone_definition[1], "MCH-" + neck_name + "_socket").name
head_socket = copy_bone_simple(arm, bone_definition[1], "MCH-" + head_name + "_socket").name
# Parent-child relationships between the body, hinges, controls, and sockets
eb[neck_ctrl].parent = eb[neck_hinge]
eb[head_ctrl].parent = eb[head_hinge]
eb[neck_socket].parent = eb[body]
eb[head_socket].parent = eb[body]
# Create neck bones
neck = [] # neck bones
neck_neck = [] # bones constrained to neck control
neck_head = [] # bones constrained to head control
for i in range(1, len(bone_definition)):
# Create bones
neck_bone = copy_bone_simple(arm, bone_definition[i], base_names[bone_definition[i]]).name
neck_neck_bone = copy_bone_simple(arm, neck_ctrl, "MCH-" + base_names[bone_definition[i]] + ".neck").name
neck_head_bone = copy_bone_simple(arm, head_ctrl, "MCH-" + base_names[bone_definition[i]] + ".head").name
# Move them all to the same place
eb[neck_neck_bone].tail += eb[neck_bone].head - eb[neck_neck_bone].head
eb[neck_head_bone].tail += eb[neck_bone].head - eb[neck_neck_bone].head
eb[neck_neck_bone].head = eb[neck_bone].head
eb[neck_head_bone].head = eb[neck_bone].head
# Parent/child relationships
eb[neck_bone].parent = eb[neck_head_bone]
eb[neck_head_bone].parent = eb[neck_neck_bone]
if i > 1:
eb[neck_neck_bone].parent = eb[neck[i-2]]
else:
eb[neck_neck_bone].parent = eb[body]
# Add them to the lists
neck += [neck_bone]
neck_neck += [neck_neck_bone]
neck_head += [neck_head_bone]
# Create deformation rig
deform(obj, bone_definition, base_names, options)
bpy.ops.object.mode_set(mode='OBJECT')
# Axis locks
pb[neck_ctrl].lock_location = True, True, True
pb[head_ctrl].lock_location = True, True, True
for bone in neck:
pb[bone].lock_location = True, True, True
# Neck hinge
prop = rna_idprop_ui_prop_get(pb[neck_ctrl], "hinge", create=True)
pb[neck_ctrl]["hinge"] = 0.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop["hard_min"] = 0.0
prop["hard_max"] = 1.0
con = pb[neck_hinge].constraints.new('COPY_LOCATION')
con.name = "socket"
con.target = obj
con.subtarget = neck_socket
con = pb[neck_hinge].constraints.new('COPY_ROTATION')
con.name = "hinge"
con.target = obj
con.subtarget = body
hinge_driver_path = pb[neck_ctrl].path_from_id() + '["hinge"]'
fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = hinge_driver_path
mod = fcurve.modifiers[0]
mod.poly_order = 1
mod.coefficients[0] = 1.0
mod.coefficients[1] = -1.0
# Head hinge
prop = rna_idprop_ui_prop_get(pb[head_ctrl], "hinge", create=True)
pb[head_ctrl]["hinge"] = 0.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop["hard_min"] = 0.0
prop["hard_max"] = 1.0
con = pb[head_hinge].constraints.new('COPY_LOCATION')
con.name = "socket"
con.target = obj
con.subtarget = head_socket
con = pb[head_hinge].constraints.new('COPY_ROTATION')
con.name = "hinge"
con.target = obj
con.subtarget = neck_ctrl
hinge_driver_path = pb[head_ctrl].path_from_id() + '["hinge"]'
fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = hinge_driver_path
mod = fcurve.modifiers[0]
mod.poly_order = 1
mod.coefficients[0] = 1.0
mod.coefficients[1] = -1.0
# Neck rotation constraints
for i in range(0, len(neck_neck)):
con = pb[neck_neck[i]].constraints.new('COPY_ROTATION')
con.name = "neck rotation"
con.target = obj
con.subtarget = neck_ctrl
con.influence = (i+1) / len(neck_neck)
# Head rotation constraints/drivers
prop = rna_idprop_ui_prop_get(pb[head_ctrl], "extent", create=True)
if "extent" in options:
pb[head_ctrl]["extent"] = options["extent"]
else:
pb[head_ctrl]["extent"] = 0.5
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop["hard_min"] = 0.0
prop["hard_max"] = 1.0
extent_prop_path = pb[head_ctrl].path_from_id() + '["extent"]'
for i in range(0, len(neck_head)):
con = pb[neck_head[i]].constraints.new('COPY_ROTATION')
con.name = "head rotation"
con.target = obj
con.subtarget = head_ctrl
if i < (len(neck_head)-1):
inf = (i+1) / len(neck_head)
fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
var.name = "ext"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = extent_prop_path
driver.expression = "0 if ext == 0 else (((%s-1)/ext)+1)" % inf
else:
con.influence = 1.0
# Constrain original bones to the neck bones
for i in range(0, len(neck)):
con = pb[bone_definition[i+1]].constraints.new('COPY_TRANSFORMS')
con.name = "copy_transform"
con.target = obj
con.subtarget = neck[i]
# Set the controls' custom shapes to use other bones for transforms
pb[neck_ctrl].custom_shape_transform = pb[bone_definition[len(bone_definition)//2]]
pb[head_ctrl].custom_shape_transform = pb[bone_definition[len(bone_definition)-1]]
# last step setup layers
if "ex_layer" in options:
layer = [n==options["ex_layer"] for n in range(0,32)]
else:
layer = list(arm.bones[bone_definition[1]].layers)
for bone in neck:
bb[bone].layers = layer
layer = list(arm.bones[bone_definition[1]].layers)
bb[neck_ctrl].layers = layer
bb[head_ctrl].layers = layer
# no blending the result of this
return None

View File

@ -1,348 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rigify import RigifyError
from rigify_utils import bone_class_instance, copy_bone_simple
from rna_prop_ui import rna_idprop_ui_prop_get
# not used, defined for completeness
METARIG_NAMES = ("body", "head")
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('body')
bone.head[:] = 0.0000, -0.0276, -0.1328
bone.tail[:] = 0.0000, -0.0170, -0.0197
bone.roll = 0.0000
bone.use_connect = False
bone = arm.edit_bones.new('head')
bone.head[:] = 0.0000, -0.0170, -0.0197
bone.tail[:] = 0.0000, 0.0726, 0.1354
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones['body']
bone = arm.edit_bones.new('neck.01')
bone.head[:] = 0.0000, -0.0170, -0.0197
bone.tail[:] = 0.0000, -0.0099, 0.0146
bone.roll = 0.0000
bone.use_connect = False
bone.parent = arm.edit_bones['head']
bone = arm.edit_bones.new('neck.02')
bone.head[:] = 0.0000, -0.0099, 0.0146
bone.tail[:] = 0.0000, -0.0242, 0.0514
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones['neck.01']
bone = arm.edit_bones.new('neck.03')
bone.head[:] = 0.0000, -0.0242, 0.0514
bone.tail[:] = 0.0000, -0.0417, 0.0868
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones['neck.02']
bone = arm.edit_bones.new('neck.04')
bone.head[:] = 0.0000, -0.0417, 0.0868
bone.tail[:] = 0.0000, -0.0509, 0.1190
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones['neck.03']
bone = arm.edit_bones.new('neck.05')
bone.head[:] = 0.0000, -0.0509, 0.1190
bone.tail[:] = 0.0000, -0.0537, 0.1600
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones['neck.04']
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['head']
pbone['type'] = 'neck_flex'
def metarig_definition(obj, orig_bone_name):
'''
The bone given is the head, its parent is the body,
# its only child the first of a chain with matching basenames.
eg.
body -> head -> neck_01 -> neck_02 -> neck_03.... etc
'''
arm = obj.data
head = arm.bones[orig_bone_name]
body = head.parent
children = head.children
if len(children) != 1:
raise RigifyError("expected the head bone '%s' to have only 1 child." % orig_bone_name)
child = children[0]
bone_definition = [body.name, head.name, child.name]
bone_definition.extend([child.name for child in child.children_recursive_basename])
return bone_definition
def deform(obj, definitions, base_names, options):
for org_bone_name in definitions[2:]:
bpy.ops.object.mode_set(mode='EDIT')
# Create deform bone.
bone = copy_bone_simple(obj.data, org_bone_name, "DEF-%s" % base_names[org_bone_name], parent=True)
# Store name before leaving edit mode
bone_name = bone.name
# Leave edit mode
bpy.ops.object.mode_set(mode='OBJECT')
# Get the pose bone
bone = obj.pose.bones[bone_name]
# Constrain to the original bone
# XXX. Todo, is this needed if the bone is connected to its parent?
con = bone.constraints.new('COPY_TRANSFORMS')
con.name = "copy_loc"
con.target = obj
con.subtarget = org_bone_name
def main(obj, bone_definition, base_names, options):
from mathutils import Vector
arm = obj.data
# Initialize container classes for convenience
mt = bone_class_instance(obj, ["body", "head"]) # meta
mt.body = bone_definition[0]
mt.head = bone_definition[1]
mt.update()
neck_chain = bone_definition[2:]
mt_chain = bone_class_instance(obj, [("neck_%.2d" % (i + 1)) for i in range(len(neck_chain))]) # 99 bones enough eh?
for i, attr in enumerate(mt_chain.attr_names):
setattr(mt_chain, attr, neck_chain[i])
mt_chain.update()
neck_chain_basename = base_names[mt_chain.neck_01_e.name].split(".")[0]
neck_chain_segment_length = mt_chain.neck_01_e.length
ex = bone_class_instance(obj, ["head", "head_hinge", "neck_socket", "head_ctrl"]) # hinge & extras
# Add the head hinge at the bodys location, becomes the parent of the original head
# apply everything to this copy of the chain
ex_chain = mt_chain.copy(base_names=base_names)
ex_chain.neck_01_e.parent = mt_chain.neck_01_e.parent
# Copy the head bone and offset
ex.head_e = copy_bone_simple(arm, mt.head, "MCH-%s" % base_names[mt.head], parent=True)
ex.head_e.use_connect = False
ex.head = ex.head_e.name
# offset
head_length = ex.head_e.length
ex.head_e.head.y += head_length / 2.0
ex.head_e.tail.y += head_length / 2.0
# Yes, use the body bone but call it a head hinge
ex.head_hinge_e = copy_bone_simple(arm, mt.body, "MCH-%s_hinge" % base_names[mt.head], parent=False)
ex.head_hinge_e.use_connect = False
ex.head_hinge = ex.head_hinge_e.name
ex.head_hinge_e.head.y += head_length / 4.0
ex.head_hinge_e.tail.y += head_length / 4.0
# Insert the neck socket, the head copys this loation
ex.neck_socket_e = arm.edit_bones.new("MCH-%s_socked" % neck_chain_basename)
ex.neck_socket = ex.neck_socket_e.name
ex.neck_socket_e.use_connect = False
ex.neck_socket_e.parent = mt.body_e
ex.neck_socket_e.head = mt.head_e.head
ex.neck_socket_e.tail = mt.head_e.head - Vector((0.0, neck_chain_segment_length / 2.0, 0.0))
ex.neck_socket_e.roll = 0.0
# copy of the head for controling
ex.head_ctrl_e = copy_bone_simple(arm, mt.head, base_names[mt.head])
ex.head_ctrl = ex.head_ctrl_e.name
ex.head_ctrl_e.parent = ex.head_hinge_e
for i, attr in enumerate(ex_chain.attr_names):
neck_e = getattr(ex_chain, attr + "_e")
# dont store parent names, re-reference as each chain bones parent.
neck_e_parent = arm.edit_bones.new("MCH-rot_%s" % base_names[getattr(mt_chain, attr)])
neck_e_parent.head = neck_e.head
neck_e_parent.tail = neck_e.head + (mt.head_e.vector.normalize() * neck_chain_segment_length / 2.0)
neck_e_parent.roll = mt.head_e.roll
orig_parent = neck_e.parent
neck_e.use_connect = False
neck_e.parent = neck_e_parent
neck_e_parent.use_connect = False
if i == 0:
neck_e_parent.parent = mt.body_e
else:
neck_e_parent.parent = orig_parent
deform(obj, bone_definition, base_names, options)
bpy.ops.object.mode_set(mode='OBJECT')
mt.update()
mt_chain.update()
ex_chain.update()
ex.update()
# Axis locks
ex.head_ctrl_p.lock_location = True, True, True
# Simple one off constraints, no drivers
con = ex.head_ctrl_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 = ex.head_ctrl
# driven hinge
prop = rna_idprop_ui_prop_get(ex.head_ctrl_p, "hinge", create=True)
ex.head_ctrl_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 = ex.head_ctrl_p.path_from_id() + '["hinge"]'
fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_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 = ex.head_ctrl_p.path_from_id()
target_names = [("b%.2d" % (i + 1)) for i in range(len(neck_chain))]
ex.head_ctrl_p["bend_tot"] = 0.0
fcurve = ex.head_ctrl_p.driver_add('["bend_tot"]')
driver = fcurve.driver
driver.type = 'SUM'
fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
for i in range(len(neck_chain)):
var = driver.variables.new()
var.name = target_names[i]
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = head_driver_path + ('["bend_%.2d"]' % (i + 1))
for i, attr in enumerate(ex_chain.attr_names):
neck_p = getattr(ex_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(ex.head_ctrl_p, prop_name, create=True)
ex.head_ctrl_p[prop_name] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
# add parent constraint
neck_p_parent = neck_p.parent
# add constraint
con = neck_p_parent.constraints.new('COPY_ROTATION')
con.name = "Copy Rotation"
con.target = obj
con.subtarget = ex.head
con.owner_space = 'LOCAL'
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'SCRIPTED'
driver.expression = "bend/bend_tot"
fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
# add target
var = driver.variables.new()
var.name = "bend_tot"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = head_driver_path + ('["bend_tot"]')
var = driver.variables.new()
var.name = "bend"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = head_driver_path + ('["%s"]' % prop_name)
# finally constrain the original bone to this one
orig_neck_p = getattr(mt_chain, attr + "_p")
con = orig_neck_p.constraints.new('COPY_ROTATION')
con.target = obj
con.subtarget = neck_p.name
# Set the head control's custom shape to use the last
# org neck bone for its transform
ex.head_ctrl_p.custom_shape_transform = obj.pose.bones[bone_definition[len(bone_definition)-1]]
# last step setup layers
if "ex_layer" in options:
layer = [n == options["ex_layer"] for n in range(0, 32)]
else:
layer = list(arm.bones[bone_definition[1]].layers)
for attr in ex_chain.attr_names:
getattr(ex_chain, attr + "_b").layers = layer
for attr in ex.attr_names:
getattr(ex, attr + "_b").layers = layer
layer = list(arm.bones[bone_definition[1]].layers)
ex.head_ctrl_b.layers = layer
# no blending the result of this
return None

View File

@ -1,270 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rigify_utils import copy_bone_simple, get_side_name
from rna_prop_ui import rna_idprop_ui_prop_get
# not used, defined for completeness
METARIG_NAMES = tuple()
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('hand')
bone.head[:] = 0.0004, -0.0629, 0.0000
bone.tail[:] = 0.0021, -0.0209, 0.0000
bone.roll = 0.0000
bone.use_connect = False
bone = arm.edit_bones.new('palm.03')
bone.head[:] = -0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0025, 0.0644, -0.0065
bone.roll = -3.1396
bone.use_connect = False
bone.parent = arm.edit_bones['hand']
bone = arm.edit_bones.new('palm.02')
bone.head[:] = 0.0252, -0.0000, 0.0000
bone.tail[:] = 0.0324, 0.0627, -0.0065
bone.roll = -3.1357
bone.use_connect = False
bone.parent = arm.edit_bones['hand']
bone = arm.edit_bones.new('palm.01')
bone.head[:] = 0.0504, 0.0000, 0.0000
bone.tail[:] = 0.0703, 0.0508, -0.0065
bone.roll = -3.1190
bone.use_connect = False
bone.parent = arm.edit_bones['hand']
bone = arm.edit_bones.new('palm.04')
bone.head[:] = -0.0252, 0.0000, 0.0000
bone.tail[:] = -0.0286, 0.0606, -0.0065
bone.roll = 3.1386
bone.use_connect = False
bone.parent = arm.edit_bones['hand']
bone = arm.edit_bones.new('palm.05')
bone.head[:] = -0.0504, 0.0000, 0.0000
bone.tail[:] = -0.0669, 0.0534, -0.0065
bone.roll = 3.1239
bone.use_connect = False
bone.parent = arm.edit_bones['hand']
bone = arm.edit_bones.new('thumb')
bone.head[:] = 0.0682, -0.0148, 0.0000
bone.tail[:] = 0.1063, 0.0242, -0.0065
bone.roll = -3.0929
bone.use_connect = False
bone.parent = arm.edit_bones['hand']
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['palm.01']
pbone['type'] = 'palm_curl'
def metarig_definition(obj, orig_bone_name):
'''
The bone given is the first in an array of siblings with a matching basename
sorted with pointer first, little finger last.
eg.
[pointer, middle, ring, pinky... ] # any number of fingers
'''
arm = obj.data
palm_bone = arm.bones[orig_bone_name]
palm_parent = palm_bone.parent
palm_base = palm_bone.basename
bone_definition = [bone.name for bone in palm_parent.children if bone.basename == palm_base]
bone_definition.sort()
bone_definition.reverse()
return [palm_parent.name] + bone_definition
def deform(obj, definitions, base_names, options):
for org_bone_name in definitions[1:]:
bpy.ops.object.mode_set(mode='EDIT')
# Create deform bone.
bone = copy_bone_simple(obj.data, org_bone_name, "DEF-%s" % base_names[org_bone_name], parent=True)
# Store name before leaving edit mode
bone_name = bone.name
# Leave edit mode
bpy.ops.object.mode_set(mode='OBJECT')
# Get the pose bone
bone = obj.pose.bones[bone_name]
# Constrain to the original bone
# XXX. Todo, is this needed if the bone is connected to its parent?
con = bone.constraints.new('COPY_TRANSFORMS')
con.name = "copy_loc"
con.target = obj
con.subtarget = org_bone_name
def main(obj, bone_definition, base_names, options):
arm = obj.data
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]]
# FIXME, why split the second one?
base_name = base_names[pinky_ebone.name].rsplit('.', 2)[0]
control_ebone = copy_bone_simple(arm, pinky_ebone.name, base_name + get_side_name(base_names[pinky_ebone.name]), parent=True)
control_name = control_ebone.name
offset = (pinky_ebone.head - ring_ebone.head)
control_ebone.translate(offset)
deform(obj, bone_definition, base_names, options)
bpy.ops.object.mode_set(mode='OBJECT')
arm = obj.data
control_pbone = obj.pose.bones[control_name]
pinky_pbone = obj.pose.bones[children[0]]
control_pbone.rotation_mode = 'YZX'
control_pbone.lock_rotation = False, True, True
control_pbone.lock_location = True, True, True
driver_fcurves = pinky_pbone.driver_add("rotation_euler")
controller_path = control_pbone.path_from_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
prop["min"] = -1.0
prop["max"] = 1.0
# *****
driver = driver_fcurves[0].driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.name = "x"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = controller_path + ".rotation_euler[0]"
# *****
driver = driver_fcurves[1].driver
driver.expression = "-x/4.0"
var = driver.variables.new()
var.name = "x"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = controller_path + ".rotation_euler[0]"
# *****
driver = driver_fcurves[2].driver
driver.expression = "(1.0-cos(x))-s"
for fcurve in driver_fcurves:
fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
var = driver.variables.new()
var.name = "x"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = controller_path + ".rotation_euler[0]"
var = driver.variables.new()
var.name = "s"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = controller_path + '["spread"]'
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 = 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
con.subtarget = children[0] # also pinky_pbone
con.owner_space = con.target_space = 'LOCAL'
con.use_x, con.use_y, con.use_z = False, False, True
con.influence = inf
con = child_pbone.constraints.new('COPY_ROTATION')
con.name = "Copy XY Rot"
con.target = obj
con.subtarget = children[0] # also pinky_pbone
con.owner_space = con.target_space = 'LOCAL'
con.use_x, con.use_y, con.use_z = True, True, False
con.influence = inf_minor
child_pbone = obj.pose.bones[children[-1]]
child_pbone.rotation_mode = 'QUATERNION'
# fix at the end since there is some trouble with tx info not being updated otherwise
def x_direction():
# NOTE: the direction of the Z rotation depends on which side the palm is on.
# we could do a simple side-of-x test but better to work out the direction
# the hand is facing.
from mathutils import Vector
from math import degrees
child_pbone_01 = obj.pose.bones[children[0]].bone
child_pbone_02 = obj.pose.bones[children[1]].bone
rel_vec = child_pbone_01.head - child_pbone_02.head
x_vec = child_pbone_01.matrix.rotation_part() * Vector((1.0, 0.0, 0.0))
return degrees(rel_vec.angle(x_vec)) > 90.0
if x_direction(): # flip
driver.expression = "-(%s)" % driver.expression
# last step setup layers
arm.bones[control_name].layers = list(arm.bones[bone_definition[1]].layers)
# no blending the result of this
return None

View File

@ -1,320 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rigify import RigifyError
from rigify_utils import copy_bone_simple
from rna_prop_ui import rna_idprop_ui_prop_get
#METARIG_NAMES = ("cpy",)
RIG_TYPE = "shape_key_control"
def addget_shape_key(obj, name="Key"):
""" Fetches a shape key, or creates it if it doesn't exist
"""
# Create a shapekey set if it doesn't already exist
if obj.data.shape_keys is None:
shape = obj.add_shape_key(name="Basis", from_mix=False)
obj.active_shape_key_index = 0
# Get the shapekey, or create it if it doesn't already exist
if name in obj.data.shape_keys.keys:
shape_key = obj.data.shape_keys.keys[name]
else:
shape_key = obj.add_shape_key(name=name, from_mix=False)
return shape_key
def addget_shape_key_driver(obj, name="Key"):
""" Fetches the driver for the shape key, or creates it if it doesn't
already exist.
"""
driver_path = 'keys["' + name + '"].value'
fcurve = None
driver = None
new = False
if obj.data.shape_keys.animation_data is not None:
for driver_s in obj.data.shape_keys.animation_data.drivers:
if driver_s.data_path == driver_path:
fcurve = driver_s
if fcurve is None:
fcurve = obj.data.shape_keys.keys[name].driver_add("value")
fcurve.driver.type = 'AVERAGE'
new = True
return fcurve, new
# TODO:
def metarig_template():
# generated by rigify.write_meta_rig
#bpy.ops.object.mode_set(mode='EDIT')
#obj = bpy.context.active_object
#arm = obj.data
#bone = arm.edit_bones.new('Bone')
#bone.head[:] = 0.0000, 0.0000, 0.0000
#bone.tail[:] = 0.0000, 0.0000, 1.0000
#bone.roll = 0.0000
#bone.use_connect = False
#
#bpy.ops.object.mode_set(mode='OBJECT')
#pbone = obj.pose.bones['Bone']
#pbone['type'] = 'copy'
pass
def metarig_definition(obj, orig_bone_name):
bone = obj.data.bones[orig_bone_name]
return [bone.name]
def main(obj, definitions, base_names, options):
""" A rig that drives shape keys with the local transforms and/or custom
properties of a single bone.
A different shape can be driven by the negative value of a transform as
well by giving a comma-separated list of two shapes.
Required options:
mesh: name of mesh object(s) to add/get shapekeys to/from
(if multiple objects, make a comma-separated list)
Optional options:
loc_<x/y/z>: name of the shape key to tie to translation of the bone
loc_<x/y/z>_fac: default multiplier of the bone influence on the shape key
rot_<x/y/z>: name of the shape key to tie to rotation of the bone
rot_<x/y/z>_fac: default multiplier of the bone influence on the shape key
scale_<x/y/z>: name of the shape key to tie to scale of the bone
scale_<x/y/z>_fac: default multiplier of the bone influence on the shape key
shape_key_sliders: comma-separated list of custom properties to create sliders out of for driving shape keys
<custom_prop>: for each property listed in shape_key_sliders, specify a shape key for it to drive
"""
bpy.ops.object.mode_set(mode='EDIT')
eb = obj.data.edit_bones
pb = obj.pose.bones
org_bone = definitions[0]
# Options
req_options = ["mesh"]
for option in req_options:
if option not in options:
raise RigifyError("'%s' rig type requires a '%s' option (bone: %s)" % (RIG_TYPE, option, base_names[definitions[0]]))
meshes = options["mesh"].replace(" ", "").split(",")
bone = copy_bone_simple(obj.data, org_bone, base_names[org_bone], parent=True).name
bpy.ops.object.mode_set(mode='OBJECT')
# Set rotation mode and axis locks
pb[bone].rotation_mode = pb[org_bone].rotation_mode
pb[bone].lock_location = tuple(pb[org_bone].lock_location)
pb[bone].lock_rotation = tuple(pb[org_bone].lock_rotation)
pb[bone].lock_rotation_w = pb[org_bone].lock_rotation_w
pb[bone].lock_rotations_4d = pb[org_bone].lock_rotations_4d
pb[bone].lock_scale = tuple(pb[org_bone].lock_scale)
# List of rig options for specifying shape keys
# Append '_fac' to the end for the name of the corresponding 'factor
# default' option for that shape
shape_key_options = ["loc_x",
"loc_y",
"loc_z",
"rot_x",
"rot_y",
"rot_z",
"scale_x",
"scale_y",
"scale_z"]
driver_paths = {"loc_x":".location[0]",
"loc_y":".location[1]",
"loc_z":".location[2]",
"rot_x":".rotation_euler[0]",
"rot_y":".rotation_euler[1]",
"rot_z":".rotation_euler[2]",
"qrot_x":".rotation_quaternion[1]",
"qrot_y":".rotation_quaternion[2]",
"qrot_z":".rotation_quaternion[3]",
"scale_x":".scale[0]",
"scale_y":".scale[1]",
"scale_z":".scale[2]"}
# Create the shape keys and drivers for transforms
shape_info = []
for option in shape_key_options:
if option in options:
shape_names = options[option].replace(" ", "").split(",")
var_name = bone.replace(".","").replace("-","_") + "_" + option
# Different RNA paths for euler vs quat
if option in (shape_key_options[3:6]+shape_key_options[12:15]) \
and pb[bone].rotation_mode == 'QUATERNION':
var_path = driver_paths['q' + option]
else:
var_path = driver_paths[option]
if (option+"_fac") in options:
fac = options[option+"_fac"]
else:
fac = 1.0
# Positive
if shape_names[0] != "":
# Different expressions for loc/rot/scale and positive/negative
if option in shape_key_options[:3]:
# Location
expression = var_name + " * " + str(fac)
elif option in shape_key_options[3:6]:
# Rotation
# Different expressions for euler vs quats
if pb[bone].rotation_mode == 'QUATERNION':
expression = "2 * asin(" + var_name + ") * " + str(fac)
else:
expression = var_name + " * " + str(fac)
elif option in shape_key_options[6:9]:
# Scale
expression = "(1.0 - " + var_name + ") * " + str(fac) + " * -2"
shape_name = shape_names[0]
create_shape_and_driver(obj, bone, meshes, shape_name, var_name, var_path, expression)
# Negative
if shape_names[0] != "" and len(shape_names) > 1:
# Different expressions for loc/rot/scale and positive/negative
if option in shape_key_options[:3]:
# Location
expression = var_name + " * " + str(fac) + " * -1"
elif option in shape_key_options[3:6]:
# Rotation
# Different expressions for euler vs quats
if pb[bone].rotation_mode == 'QUATERNION':
expression = "-2 * asin(" + var_name + ") * " + str(fac)
else:
expression = var_name + " * " + str(fac) + " * -1"
elif option in shape_key_options[6:9]:
# Scale
expression = "(1.0 - " + var_name + ") * " + str(fac) + " * 2"
shape_name = shape_names[1]
create_shape_and_driver(obj, bone, meshes, shape_name, var_name, var_path, expression)
# Create the shape keys and drivers for custom-property sliders
if "shape_key_sliders" in options:
# Get the slider names
slider_names = options["shape_key_sliders"].replace(" ", "").split(",")
if slider_names[0] != "":
# Loop through the slider names and check if they have
# shape keys specified for them, and if so, set them up.
for slider_name in slider_names:
if slider_name in options:
shape_names = options[slider_name].replace(" ", "").split(",")
# Set up the custom property on the bone
prop = rna_idprop_ui_prop_get(pb[bone], slider_name, create=True)
pb[bone][slider_name] = 0.0
prop["min"] = 0.0
prop["max"] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
if len(shape_names) > 1:
prop["min"] = -1.0
prop["soft_min"] = -1.0
# Add the shape drivers
# Positive
if shape_names[0] != "":
# Set up the variables for creating the shape key driver
shape_name = shape_names[0]
var_name = slider_name.replace(".", "_").replace("-", "_")
var_path = '["' + slider_name + '"]'
if slider_name + "_fac" in options:
fac = options[slider_name + "_fac"]
else:
fac = 1.0
expression = var_name + " * " + str(fac)
# Create the shape key driver
create_shape_and_driver(obj, bone, meshes, shape_name, var_name, var_path, expression)
# Negative
if shape_names[0] != "" and len(shape_names) > 1:
# Set up the variables for creating the shape key driver
shape_name = shape_names[1]
var_name = slider_name.replace(".", "_").replace("-", "_")
var_path = '["' + slider_name + '"]'
if slider_name + "_fac" in options:
fac = options[slider_name + "_fac"]
else:
fac = 1.0
expression = var_name + " * " + str(fac) + " * -1"
# Create the shape key driver
create_shape_and_driver(obj, bone, meshes, shape_name, var_name, var_path, expression)
# Org bone copy transforms of control bone
con = pb[org_bone].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = bone
return (None,)
def create_shape_and_driver(obj, bone, meshes, shape_name, var_name, var_path, expression):
""" Creates/gets a shape key and sets up a driver for it.
obj = armature object
bone = driving bone name
meshes = list of meshes to create the shapekey/driver on
shape_name = name of the shape key
var_name = name of the driving variable
var_path = path to the property on the bone to drive with
expression = python expression for the driver
"""
pb = obj.pose.bones
bpy.ops.object.mode_set(mode='OBJECT')
for mesh_name in meshes:
mesh_obj = bpy.data.objects[mesh_name]
# Add/get the shape key
shape = addget_shape_key(mesh_obj, name=shape_name)
# Add/get the shape key driver
fcurve, a = addget_shape_key_driver(mesh_obj, name=shape_name)
# Set up the driver
driver = fcurve.driver
driver.type = 'SCRIPTED'
driver.expression = expression
# Get the variable, or create it if it doesn't already exist
if var_name in driver.variables:
var = driver.variables[var_name]
else:
var = driver.variables.new()
var.name = var_name
# Set up the variable
var.type = "SINGLE_PROP"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = 'pose.bones["' + bone + '"]' + var_path

View File

@ -1,172 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rigify import RigifyError
#METARIG_NAMES = ("cpy",)
RIG_TYPE = "shape_key_distance"
def addget_shape_key(obj, name="Key"):
""" Fetches a shape key, or creates it if it doesn't exist
"""
# Create a shapekey set if it doesn't already exist
if obj.data.shape_keys is None:
shape = obj.add_shape_key(name="Basis", from_mix=False)
obj.active_shape_key_index = 0
# Get the shapekey, or create it if it doesn't already exist
if name in obj.data.shape_keys.keys:
shape_key = obj.data.shape_keys.keys[name]
else:
shape_key = obj.add_shape_key(name=name, from_mix=False)
return shape_key
def addget_shape_key_driver(obj, name="Key"):
""" Fetches the driver for the shape key, or creates it if it doesn't
already exist.
"""
driver_path = 'keys["' + name + '"].value'
fcurve = None
driver = None
if obj.data.shape_keys.animation_data is not None:
for driver_s in obj.data.shape_keys.animation_data.drivers:
if driver_s.data_path == driver_path:
fcurve = driver_s
if fcurve is None:
fcurve = obj.data.shape_keys.keys[name].driver_add("value")
fcurve.driver.type = 'AVERAGE'
return fcurve
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('Bone')
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 1.0000
bone.roll = 0.0000
bone.use_connect = False
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['Bone']
pbone['type'] = 'copy'
def metarig_definition(obj, orig_bone_name):
bone = obj.data.bones[orig_bone_name]
return [bone.name]
def deform(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
eb = obj.data.edit_bones
bone_from = definitions[0]
# Options
req_options = ["to", "mesh", "shape_key"]
for option in req_options:
if option not in options:
raise RigifyError("'%s' rig type requires a '%s' option (bone: %s)" % (RIG_TYPE, option, base_names[definitions[0]]))
bone_to = "ORG-" + options["to"]
meshes = options["mesh"].replace(" ", "").split(",")
shape_key_name = options["shape_key"]
if "dmul" in options:
shape_blend_fac = options["dmul"]
else:
shape_blend_fac = 1.0
# Calculate the distance between the bones
distance = (eb[bone_from].head - eb[bone_to].head).length
bpy.ops.object.mode_set(mode='OBJECT')
# For every listed mesh object
for mesh_name in meshes:
mesh_obj = bpy.data.objects[mesh_name]
# Add/get the shape key
shape_key = addget_shape_key(mesh_obj, name=shape_key_name)
# Add/get the shape key driver
fcurve = addget_shape_key_driver(mesh_obj, name=shape_key_name)
driver = fcurve.driver
# Get the variable, or create it if it doesn't already exist
var_name = base_names[bone_from]
if var_name in driver.variables:
var = driver.variables[var_name]
else:
var = driver.variables.new()
var.name = var_name
# Set up the variable
var.type = "LOC_DIFF"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].bone_target = bone_from
var.targets[1].id_type = 'OBJECT'
var.targets[1].id = obj
var.targets[1].bone_target = bone_to
# Set fcurve offset, so zero is at the rest distance
mod = fcurve.modifiers[0]
if distance > 0.00001:
mod.coefficients[0] = -shape_blend_fac
mod.coefficients[1] = shape_blend_fac / distance
return (None,)
def control(obj, definitions, base_names, options):
""" options:
mesh: name of mesh object with the shape key
shape_key: name of shape key
to: name of bone to measure distance from
"""
pass
def main(obj, bone_definition, base_names, options):
# Create control rig
#control(obj, bone_definition, base_names, options)
# Create deform rig
deform(obj, bone_definition, base_names, options)
return (None,)

View File

@ -1,172 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rigify import RigifyError
#METARIG_NAMES = ("cpy",)
RIG_TYPE = "shape_key_rotdiff"
def addget_shape_key(obj, name="Key"):
""" Fetches a shape key, or creates it if it doesn't exist
"""
# Create a shapekey set if it doesn't already exist
if obj.data.shape_keys is None:
shape = obj.add_shape_key(name="Basis", from_mix=False)
obj.active_shape_key_index = 0
# Get the shapekey, or create it if it doesn't already exist
if name in obj.data.shape_keys.keys:
shape_key = obj.data.shape_keys.keys[name]
else:
shape_key = obj.add_shape_key(name=name, from_mix=False)
return shape_key
def addget_shape_key_driver(obj, name="Key"):
""" Fetches the driver for the shape key, or creates it if it doesn't
already exist.
"""
driver_path = 'keys["' + name + '"].value'
fcurve = None
driver = None
if obj.data.shape_keys.animation_data is not None:
for driver_s in obj.data.shape_keys.animation_data.drivers:
if driver_s.data_path == driver_path:
fcurve = driver_s
if fcurve is None:
fcurve = obj.data.shape_keys.keys[name].driver_add("value")
fcurve.driver.type = 'AVERAGE'
return fcurve
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('Bone')
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 1.0000
bone.roll = 0.0000
bone.use_connect = False
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['Bone']
pbone['type'] = 'copy'
def metarig_definition(obj, orig_bone_name):
bone = obj.data.bones[orig_bone_name]
return [bone.name]
def deform(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
eb = obj.data.edit_bones
bone_from = definitions[0]
# Options
req_options = ["to", "mesh", "shape_key"]
for option in req_options:
if option not in options:
raise RigifyError("'%s' rig type requires a '%s' option (bone: %s)" % (RIG_TYPE, option, base_names[definitions[0]]))
bone_to = "ORG-" + options["to"]
meshes = options["mesh"].replace(" ", "").split(",")
shape_key_name = options["shape_key"]
if "dmul" in options:
shape_blend_fac = options["dmul"]
else:
shape_blend_fac = 1.0
# Calculate the rotation difference between the bones
rotdiff = (eb[bone_from].matrix.to_quat() * eb[bone_to].matrix.to_quat()) * 2
bpy.ops.object.mode_set(mode='OBJECT')
# For every listed mesh object
for mesh_name in meshes:
mesh_obj = bpy.data.objects[mesh_name]
# Add/get the shape key
shape_key = addget_shape_key(mesh_obj, name=shape_key_name)
# Add/get the shape key driver
fcurve = addget_shape_key_driver(mesh_obj, name=shape_key_name)
driver = fcurve.driver
# Get the variable, or create it if it doesn't already exist
var_name = base_names[bone_from]
if var_name in driver.variables:
var = driver.variables[var_name]
else:
var = driver.variables.new()
var.name = var_name
# Set up the variable
var.type = "ROTATION_DIFF"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].bone_target = bone_from
var.targets[1].id_type = 'OBJECT'
var.targets[1].id = obj
var.targets[1].bone_target = bone_to
# Set fcurve offset, so zero is at the rest distance
mod = fcurve.modifiers[0]
if rotdiff > 0.00001:
mod.coefficients[0] = -shape_blend_fac
mod.coefficients[1] = shape_blend_fac / rotdiff
return (None,)
def control(obj, definitions, base_names, options):
""" options:
mesh: name of mesh object with the shape key
shape_key: name of shape key
to: name of bone to measure distance from
"""
pass
def main(obj, bone_definition, base_names, options):
# Create control rig
#control(obj, bone_definition, base_names, options)
# Create deform rig
deform(obj, bone_definition, base_names, options)
return (None,)

View File

@ -1,481 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rigify import RigifyError
from rigify_utils import bone_class_instance, copy_bone_simple
from rna_prop_ui import rna_idprop_ui_prop_get
# not used, defined for completeness
METARIG_NAMES = ("pelvis", "ribcage")
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('pelvis')
bone.head[:] = 0.0000, -0.0306, 0.1039
bone.tail[:] = 0.0000, -0.0306, -0.0159
bone.roll = 0.0000
bone.use_connect = False
bone = arm.edit_bones.new('rib_cage')
bone.head[:] = 0.0000, -0.0306, 0.1039
bone.tail[:] = 0.0000, -0.0306, 0.2236
bone.roll = -0.0000
bone.use_connect = False
bone.parent = arm.edit_bones['pelvis']
bone = arm.edit_bones.new('spine.01')
bone.head[:] = 0.0000, 0.0000, -0.0000
bone.tail[:] = 0.0000, -0.0306, 0.1039
bone.roll = -0.0000
bone.use_connect = False
bone.parent = arm.edit_bones['rib_cage']
bone = arm.edit_bones.new('spine.02')
bone.head[:] = 0.0000, -0.0306, 0.1039
bone.tail[:] = -0.0000, -0.0398, 0.2045
bone.roll = -0.0000
bone.use_connect = True
bone.parent = arm.edit_bones['spine.01']
bone = arm.edit_bones.new('spine.03')
bone.head[:] = -0.0000, -0.0398, 0.2045
bone.tail[:] = -0.0000, -0.0094, 0.2893
bone.roll = -0.0000
bone.use_connect = True
bone.parent = arm.edit_bones['spine.02']
bone = arm.edit_bones.new('spine.04')
bone.head[:] = -0.0000, -0.0094, 0.2893
bone.tail[:] = -0.0000, 0.0335, 0.3595
bone.roll = -0.0000
bone.use_connect = True
bone.parent = arm.edit_bones['spine.03']
bone = arm.edit_bones.new('spine.05')
bone.head[:] = -0.0000, 0.0335, 0.3595
bone.tail[:] = -0.0000, 0.0555, 0.4327
bone.roll = -0.0000
bone.use_connect = True
bone.parent = arm.edit_bones['spine.04']
bone = arm.edit_bones.new('spine.06')
bone.head[:] = -0.0000, 0.0555, 0.4327
bone.tail[:] = -0.0000, 0.0440, 0.5207
bone.roll = -0.0000
bone.use_connect = True
bone.parent = arm.edit_bones['spine.05']
bone = arm.edit_bones.new('spine.07')
bone.head[:] = -0.0000, 0.0440, 0.5207
bone.tail[:] = -0.0000, 0.0021, 0.5992
bone.roll = -0.0000
bone.use_connect = True
bone.parent = arm.edit_bones['spine.06']
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['rib_cage']
pbone['type'] = 'spine_pivot_flex'
def metarig_definition(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
note: same as neck.
'''
arm = obj.data
ribcage = arm.bones[orig_bone_name]
pelvis = ribcage.parent
if pelvis is None:
raise RigifyError("expected the ribcage bone:'%s' to have a parent (ribcage)." % ribcage.name)
children = ribcage.children
if len(children) != 1:
raise RigifyError("expected the ribcage to have only 1 child.")
child = children[0]
bone_definition = [pelvis.name, ribcage.name, child.name]
bone_definition.extend([child.name for child in child.children_recursive_basename])
return bone_definition
def fk(*args):
main(*args)
def deform(obj, definitions, base_names, options):
for org_bone_name in definitions[2:]:
bpy.ops.object.mode_set(mode='EDIT')
# Create deform bone.
bone = copy_bone_simple(obj.data, org_bone_name, "DEF-%s" % base_names[org_bone_name], parent=True)
# Store name before leaving edit mode
bone_name = bone.name
# Leave edit mode
bpy.ops.object.mode_set(mode='OBJECT')
# Get the pose bone
bone = obj.pose.bones[bone_name]
# Constrain to the original bone
# XXX. Todo, is this needed if the bone is connected to its parent?
con = bone.constraints.new('COPY_TRANSFORMS')
con.name = "copy_loc"
con.target = obj
con.subtarget = org_bone_name
def main(obj, bone_definition, base_names, options):
from mathutils import Vector, Matrix
from math import radians, pi
arm = obj.data
# Initialize container classes for convenience
mt = bone_class_instance(obj, ["pelvis", "ribcage"]) # meta
mt.pelvis = bone_definition[0]
mt.ribcage = bone_definition[1]
mt.update()
spine_chain_orig = tuple(bone_definition[2:])
spine_chain = [arm.edit_bones[child_name] for child_name in spine_chain_orig]
spine_chain_basename = base_names[spine_chain[0].name].rsplit(".", 1)[0] # probably 'ORG-spine.01' -> 'spine'
spine_chain_len = len(spine_chain_orig)
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_copy", "ribcage_hinge", "ribcage_copy", "spine_rotate"])
ex.pelvis_copy_e = copy_bone_simple(arm, mt.pelvis, base_names[mt.pelvis]) # no parent
ex.pelvis_copy = ex.pelvis_copy_e.name
ex.pelvis_copy_e.use_local_location = False
# 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" % base_names[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)))
ex.spine_rotate_e = copy_bone_simple(arm, mt.ribcage, "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)))
ex.spine_rotate_e.use_connect = False
ex.spine_rotate_e.parent = ex.pelvis_copy_e
# Copy the last bone now
child = spine_chain[-1]
ex.ribcage_copy_e = copy_bone_simple(arm, mt.ribcage, base_names[mt.ribcage])
ex.ribcage_copy = ex.ribcage_copy_e.name
ex.ribcage_copy_e.use_connect = False
ex.ribcage_copy_e.parent = ex.ribcage_hinge_e
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(spine_chain_len)]
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_*
del spine_chain_attrs
for i, child_name in enumerate(spine_chain):
child_name_orig = base_names[spine_chain_orig[i]]
attr = mt_chain.attr_names[i] # eg. spine_04
setattr(mt_chain, attr, spine_chain_orig[i]) # the original bone
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.use_connect = 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 = ex_chain.attr_names[i] + "_e"
ebone = getattr(ex_chain, attr)
if i == 0:
ebone.use_connect = False
ebone.parent = ex.pelvis_copy_e
else:
attr_parent = ex_chain.attr_names[i - 1] + "_e"
ebone.parent = getattr(ex_chain, attr_parent)
# intentional! get the parent from the other parallel chain member
getattr(rv_chain, attr).parent = ebone
# 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 = base_names[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 + (mt.ribcage_e.vector.normalize() * spine_chain_segment_length / 2.0)
spine_e_parent.roll = mt.ribcage_e.roll
spine_e = getattr(ex_chain, ex_chain.attr_names[i] + "_e")
orig_parent = spine_e.parent
spine_e.use_connect = False
spine_e.parent = spine_e_parent
spine_e_parent.use_connect = 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 = Matrix.Rotation(radians(180), 3, 'X')
for i, attr in enumerate(rv_chain.attr_names): # similar to neck
spine_e = getattr(rv_chain, attr + "_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
del spine_e
deform(obj, bone_definition, base_names, options)
bpy.ops.object.mode_set(mode='OBJECT')
# refresh pose bones
mt.update()
ex.update()
mt_chain.update()
ex_chain.update()
rv_chain.update()
# Axis locks
ex.ribcage_copy_p.lock_location = True, True, True
con = ex.ribcage_hinge_p.constraints.new('COPY_ROTATION')
con.name = "hinge"
con.target = obj
con.subtarget = ex.pelvis_copy
# add driver
fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = ex.ribcage_copy_p.path_from_id() + '["hinge"]'
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 = ex.ribcage_copy
# ex.pelvis_copy_p / rib_cage
con = ex.ribcage_copy_p.constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = ex.pelvis_copy
con.head_tail = 0.0
# This stores all important ID props
prop = rna_idprop_ui_prop_get(ex.ribcage_copy_p, "hinge", create=True)
ex.ribcage_copy_p["hinge"] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop = rna_idprop_ui_prop_get(ex.ribcage_copy_p, "pivot_slide", create=True)
ex.ribcage_copy_p["pivot_slide"] = 1.0 / spine_chain_len
prop["soft_min"] = 1.0 / spine_chain_len
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
target_names = [("b%.2d" % (i + 1)) for i in range(spine_chain_len - 1)]
rib_driver_path = ex.ribcage_copy_p.path_from_id()
ex.ribcage_copy_p["bend_tot"] = 0.0
fcurve = ex.ribcage_copy_p.driver_add('["bend_tot"]')
driver = fcurve.driver
driver.type = 'SUM'
fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
for i in range(spine_chain_len - 1):
var = driver.variables.new()
var.name = target_names[i]
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = rib_driver_path + ('["bend_%.2d"]' % (i + 1))
for i in range(1, spine_chain_len):
# Add bend prop
prop_name = "bend_%.2d" % i
prop = rna_idprop_ui_prop_get(ex.ribcage_copy_p, prop_name, create=True)
if ("bend_%.2d" % i) in options:
ex.ribcage_copy_p[prop_name] = options["bend_%.2d" % i]
else:
ex.ribcage_copy_p[prop_name] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
spine_p = getattr(ex_chain, ex_chain.attr_names[i] + "_p")
spine_p_parent = spine_p.parent # interlaced bone
con = spine_p_parent.constraints.new('COPY_ROTATION')
con.target = obj
con.subtarget = ex.spine_rotate
con.owner_space = 'LOCAL'
con.target_space = 'LOCAL'
del spine_p
# add driver
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'SCRIPTED'
driver.expression = "bend/bend_tot"
fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
# add target
var = driver.variables.new()
var.name = "bend_tot"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = rib_driver_path + ('["bend_tot"]')
var = driver.variables.new()
var.name = "bend"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = rib_driver_path + ('["%s"]' % prop_name)
# 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
fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_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
# Set pelvis and ribcage controls to use the first and last bone in the
# spine respectively for their custom shape transform
ex.ribcage_copy_p.custom_shape_transform = obj.pose.bones[bone_definition[len(bone_definition)-1]]
ex.pelvis_copy_p.custom_shape_transform = obj.pose.bones[bone_definition[2]]
# last step setup layers
if "ex_layer" in options:
layer = [n == options["ex_layer"] for n in range(0, 32)]
else:
layer = list(arm.bones[bone_definition[1]].layers)
for attr in ex.attr_names:
getattr(ex, attr + "_b").layers = layer
for attr in ex_chain.attr_names:
getattr(ex_chain, attr + "_b").layers = layer
for attr in rv_chain.attr_names:
getattr(rv_chain, attr + "_b").layers = layer
layer = list(arm.bones[bone_definition[1]].layers)
arm.bones[ex.pelvis_copy].layers = layer
arm.bones[ex.ribcage_copy].layers = layer
# no support for blending chains
return None

View File

@ -1,109 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rigify import RigifyError
from rigify_utils import copy_bone_simple
METARIG_NAMES = tuple()
RIG_TYPE = "stretch"
# TODO
#def metarig_template():
# # generated by rigify.write_meta_rig
# bpy.ops.object.mode_set(mode='EDIT')
# obj = bpy.context.active_object
# arm = obj.data
# bone = arm.edit_bones.new('Bone')
# bone.head[:] = 0.0000, 0.0000, 0.0000
# bone.tail[:] = 0.0000, 0.0000, 1.0000
# bone.roll = 0.0000
# bone.use_connect = False
#
# bpy.ops.object.mode_set(mode='OBJECT')
# pbone = obj.pose.bones['Bone']
# pbone['type'] = 'copy'
bool_map = {0: False, 1: True,
0.0: False, 1.0: True,
"false": False, "true": True,
"False": False, "True": True,
"no": False, "yes": True,
"No": False, "Yes": True}
def metarig_definition(obj, orig_bone_name):
return (orig_bone_name,)
def main(obj, bone_definition, base_names, options):
""" A stretchy bone from one bone to another.
Deformation only (no controls).
"""
# Verify required parameter
if "to" not in options:
raise RigifyError("'%s' rig type requires a 'to' parameter (bone: %s)" % (RIG_TYPE, base_names[bone_definition[0]]))
if type(options["to"]) is not str:
raise RigifyError("'%s' rig type 'to' parameter must be a string (bone: %s)" % (RIG_TYPE, base_names[bone_definition[0]]))
if ("ORG-" + options["to"]) not in obj.data.bones:
raise RigifyError("'%s' rig type 'to' parameter must name a bone in the metarig (bone: %s)" % (RIG_TYPE, base_names[bone_definition[0]]))
preserve_volume = None
# Check optional parameter
if "preserve_volume" in options:
try:
preserve_volume = bool_map[options["preserve_volume"]]
except KeyError:
preserve_volume = False
eb = obj.data.edit_bones
bb = obj.data.bones
pb = obj.pose.bones
bpy.ops.object.mode_set(mode='EDIT')
arm = obj.data
mbone1 = bone_definition[0]
mbone2 = "ORG-" + options["to"]
bone_e = copy_bone_simple(obj.data, mbone1, "DEF-%s" % base_names[bone_definition[0]])
bone_e.use_connect = False
bone_e.parent = eb[mbone1]
bone_e.tail = eb[mbone2].head
bone = bone_e.name
bpy.ops.object.mode_set(mode='OBJECT')
# Constraints
con = pb[bone].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = mbone2
con = pb[bone].constraints.new('STRETCH_TO')
con.target = obj
con.subtarget = mbone2
con.rest_length = bb[bone].length
if preserve_volume:
con.volume = 'VOLUME_XZX'
else:
con.volume = 'NO_VOLUME'
return tuple()

View File

@ -1,152 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rigify import RigifyError
from rigify_utils import copy_bone_simple
METARIG_NAMES = tuple()
RIG_TYPE = "stretch_twist"
# TODO
#def metarig_template():
# # generated by rigify.write_meta_rig
# bpy.ops.object.mode_set(mode='EDIT')
# obj = bpy.context.active_object
# arm = obj.data
# bone = arm.edit_bones.new('Bone')
# bone.head[:] = 0.0000, 0.0000, 0.0000
# bone.tail[:] = 0.0000, 0.0000, 1.0000
# bone.roll = 0.0000
# bone.use_connect = False
#
# bpy.ops.object.mode_set(mode='OBJECT')
# pbone = obj.pose.bones['Bone']
# pbone['type'] = 'copy'
bool_map = {0:False, 1:True,
0.0:False, 1.0:True,
"false":False, "true":True,
"False":False, "True":True,
"no":False, "yes":True,
"No":False, "Yes":True}
def metarig_definition(obj, orig_bone_name):
return (orig_bone_name,)
def main(obj, bone_definition, base_names, options):
""" A dual-bone stretchy bone setup. Each half follows the twist of the
bone on its side.
Deformation only (no controls).
"""
# Verify required parameter
if "to" not in options:
raise RigifyError("'%s' rig type requires a 'to' parameter (bone: %s)" % (RIG_TYPE, base_names[0]))
if type(options["to"]) is not str:
raise RigifyError("'%s' rig type 'to' parameter must be a string (bone: %s)" % (RIG_TYPE, base_names[0]))
if ("ORG-" + options["to"]) not in obj.data.bones:
raise RigifyError("'%s' rig type 'to' parameter must name a bone in the metarig (bone: %s)" % (RIG_TYPE, base_names[0]))
preserve_volume = None
# Check optional parameter
if "preserve_volume" in options:
try:
preserve_volume = bool_map[options["preserve_volume"]]
except KeyError:
preserve_volume = False
eb = obj.data.edit_bones
bb = obj.data.bones
pb = obj.pose.bones
bpy.ops.object.mode_set(mode='EDIT')
arm = obj.data
mbone1 = bone_definition[0]
mbone2 = "ORG-" + options["to"]
bone_e = copy_bone_simple(obj.data, mbone1, "MCH-%s" % base_names[bone_definition[0]])
bone_e.use_connect = False
bone_e.parent = None
bone_e.head = (eb[mbone1].head + eb[mbone2].head) / 2
bone_e.tail = (bone_e.head[0], bone_e.head[1], bone_e.head[2]+0.1)
mid_bone = bone_e.name
bone_e = copy_bone_simple(obj.data, mbone1, "DEF-%s.01" % base_names[bone_definition[0]])
bone_e.use_connect = False
bone_e.parent = eb[mbone1]
bone_e.tail = eb[mid_bone].head
bone1 = bone_e.name
bone_e = copy_bone_simple(obj.data, mbone2, "DEF-%s.02" % base_names[bone_definition[0]])
bone_e.use_connect = False
bone_e.parent = eb[mbone2]
bone_e.tail = eb[mid_bone].head
bone2 = bone_e.name
bpy.ops.object.mode_set(mode='OBJECT')
# Constraints
# Mid bone
con = pb[mid_bone].constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = mbone1
con = pb[mid_bone].constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = mbone2
con.influence = 0.5
# Bone 1
con = pb[bone1].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = mid_bone
con = pb[bone1].constraints.new('STRETCH_TO')
con.target = obj
con.subtarget = mid_bone
con.rest_length = bb[bone1].length
if preserve_volume:
con.volume = 'VOLUME_XZX'
else:
con.volume = 'NO_VOLUME'
# Bone 2
con = pb[bone2].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = mid_bone
con = pb[bone2].constraints.new('STRETCH_TO')
con.target = obj
con.subtarget = mid_bone
con.rest_length = bb[bone2].length
if preserve_volume:
con.volume = 'VOLUME_XZX'
else:
con.volume = 'NO_VOLUME'
return tuple()

View File

@ -1,165 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rigify import RigifyError
from rigify_utils import bone_class_instance, copy_bone_simple
from rna_prop_ui import rna_idprop_ui_prop_get
from mathutils import Vector, Matrix
from math import radians, pi
# not used, defined for completeness
METARIG_NAMES = ("pelvis", "ribcage")
def metarig_template():
# TODO
pass
# generated by rigify.write_meta_rig
#bpy.ops.object.mode_set(mode='EDIT')
#obj = bpy.context.active_object
#arm = obj.data
#bone = arm.edit_bones.new('tail.01')
#bone.head[:] = 0.0000, -0.0306, 0.1039
#bone.tail[:] = 0.0000, -0.0306, -0.0159
#bone.roll = 0.0000
#bone.use_connect = False
#bpy.ops.object.mode_set(mode='OBJECT')
#pbone = obj.pose.bones['tail.01']
#pbone['type'] = 'tail_spline_ik'
def metarig_definition(obj, orig_bone_name):
""" Collects and returns the relevent bones for the rig.
The bone given is the first in the chain of tail bones.
It includes bones in the chain up until it hits a bone that doesn't
have the same name base.
tail.01 -> tail.02 -> tail.03 -> ... -> tail.n
"""
arm = obj.data
tail_base = arm.bones[orig_bone_name]
if tail_base.parent is None:
raise RigifyError("'tail_control' rig type on bone '%s' requires a parent." % orig_bone_name)
bone_definitions = [tail_base.name]
bone_definitions.extend([child.name for child in tail_base.children_recursive_basename])
return bone_definitions
def main(obj, bone_definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
arm = obj.data
bb = obj.data.bones
eb = obj.data.edit_bones
pb = obj.pose.bones
# Create bones for hinge/free
# hinge 1 sticks with the parent
# hinge 2 is the parent of the tail controls
hinge1 = copy_bone_simple(arm, bone_definitions[0], "MCH-%s.hinge1" % base_names[bone_definitions[0]], parent=True).name
hinge2 = copy_bone_simple(arm, bone_definitions[0], "MCH-%s.hinge2" % base_names[bone_definitions[0]], parent=False).name
# Create tail control bones
bones = []
i = 0
for bone_def in bone_definitions:
bone = copy_bone_simple(arm, bone_def, base_names[bone_def], parent=True).name
if i == 1: # Don't change parent of first tail bone
eb[bone].use_connect = False
eb[bone].parent = eb[hinge2]
eb[bone].use_local_location = False
i = 1
bones += [bone]
bpy.ops.object.mode_set(mode='OBJECT')
# Rotation mode and axis locks
for bone, org_bone in zip(bones, bone_definitions):
pb[bone].rotation_mode = pb[org_bone].rotation_mode
pb[bone].lock_location = tuple(pb[org_bone].lock_location)
pb[bone].lock_rotations_4d = pb[org_bone].lock_rotations_4d
pb[bone].lock_rotation = tuple(pb[org_bone].lock_rotation)
pb[bone].lock_rotation_w = pb[org_bone].lock_rotation_w
pb[bone].lock_scale = tuple(pb[org_bone].lock_scale)
# Add custom properties
pb[bones[0]]["hinge"] = 0.0
prop = rna_idprop_ui_prop_get(pb[bones[0]], "hinge", create=True)
prop["min"] = 0.0
prop["max"] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
pb[bones[0]]["free"] = 0.0
prop = rna_idprop_ui_prop_get(pb[bones[0]], "free", create=True)
prop["min"] = 0.0
prop["max"] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
# Add constraints
for bone, org_bone in zip(bones, bone_definitions):
con = pb[org_bone].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = bone
con_f = pb[hinge2].constraints.new('COPY_LOCATION')
con_f.target = obj
con_f.subtarget = hinge1
con_h = pb[hinge2].constraints.new('COPY_TRANSFORMS')
con_h.target = obj
con_h.subtarget = hinge1
# Add drivers
bone_path = pb[bones[0]].path_from_id()
driver_fcurve = con_f.driver_add("influence")
driver = driver_fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.name = "free"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = bone_path + '["free"]'
mod = driver_fcurve.modifiers[0]
mod.poly_order = 1
mod.coefficients[0] = 1.0
mod.coefficients[1] = -1.0
driver_fcurve = con_h.driver_add("influence")
driver = driver_fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.name = "hinge"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = bone_path + '["hinge"]'
mod = driver_fcurve.modifiers[0]
mod.poly_order = 1
mod.coefficients[0] = 1.0
mod.coefficients[1] = -1.0
return None

View File

@ -1,361 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rigify import RigifyError
from rigify_utils import bone_class_instance, copy_bone_simple
from rna_prop_ui import rna_idprop_ui_prop_get
# not used, defined for completeness
METARIG_NAMES = ("body", "head")
def metarig_template():
# TODO:
## generated by rigify.write_meta_rig
#bpy.ops.object.mode_set(mode='EDIT')
#obj = bpy.context.active_object
#arm = obj.data
#bone = arm.edit_bones.new('body')
#bone.head[:] = 0.0000, -0.0276, -0.1328
#bone.tail[:] = 0.0000, -0.0170, -0.0197
#bone.roll = 0.0000
#bone.use_connect = False
#bone = arm.edit_bones.new('head')
#bone.head[:] = 0.0000, -0.0170, -0.0197
#bone.tail[:] = 0.0000, 0.0726, 0.1354
#bone.roll = 0.0000
#bone.use_connect = True
#bone.parent = arm.edit_bones['body']
#bone = arm.edit_bones.new('neck.01')
#bone.head[:] = 0.0000, -0.0170, -0.0197
#bone.tail[:] = 0.0000, -0.0099, 0.0146
#bone.roll = 0.0000
#bone.use_connect = False
#bone.parent = arm.edit_bones['head']
#bone = arm.edit_bones.new('neck.02')
#bone.head[:] = 0.0000, -0.0099, 0.0146
#bone.tail[:] = 0.0000, -0.0242, 0.0514
#bone.roll = 0.0000
#bone.use_connect = True
#bone.parent = arm.edit_bones['neck.01']
#bone = arm.edit_bones.new('neck.03')
#bone.head[:] = 0.0000, -0.0242, 0.0514
#bone.tail[:] = 0.0000, -0.0417, 0.0868
#bone.roll = 0.0000
#bone.use_connect = True
#bone.parent = arm.edit_bones['neck.02']
#bone = arm.edit_bones.new('neck.04')
#bone.head[:] = 0.0000, -0.0417, 0.0868
#bone.tail[:] = 0.0000, -0.0509, 0.1190
#bone.roll = 0.0000
#bone.use_connect = True
#bone.parent = arm.edit_bones['neck.03']
#bone = arm.edit_bones.new('neck.05')
#bone.head[:] = 0.0000, -0.0509, 0.1190
#bone.tail[:] = 0.0000, -0.0537, 0.1600
#bone.roll = 0.0000
#bone.use_connect = True
#bone.parent = arm.edit_bones['neck.04']
#
#bpy.ops.object.mode_set(mode='OBJECT')
#pbone = obj.pose.bones['head']
#pbone['type'] = 'neck_flex'
pass
def metarig_definition(obj, orig_bone_name):
'''
The bone given is the tongue control, its parent is the body,
# its only child the first of a chain with matching basenames.
eg.
body -> tongue_control -> tongue_01 -> tongue_02 -> tongue_03.... etc
'''
arm = obj.data
tongue = arm.bones[orig_bone_name]
body = tongue.parent
children = tongue.children
if len(children) != 1:
raise RigifyError("expected the tongue bone '%s' to have only 1 child." % orig_bone_name)
child = children[0]
bone_definition = [body.name, tongue.name, child.name]
bone_definition.extend([child.name for child in child.children_recursive_basename])
return bone_definition
def deform(obj, definitions, base_names, options):
for org_bone_name in definitions[2:]:
bpy.ops.object.mode_set(mode='EDIT')
# Create deform bone.
bone = copy_bone_simple(obj.data, org_bone_name, "DEF-%s" % base_names[org_bone_name], parent=True)
# Store name before leaving edit mode
bone_name = bone.name
# Leave edit mode
bpy.ops.object.mode_set(mode='OBJECT')
# Get the pose bone
bone = obj.pose.bones[bone_name]
# Constrain to the original bone
# XXX. Todo, is this needed if the bone is connected to its parent?
con = bone.constraints.new('COPY_TRANSFORMS')
con.name = "copy_loc"
con.target = obj
con.subtarget = org_bone_name
# TODO: rename all of the head/neck references to tongue
def main(obj, bone_definition, base_names, options):
from mathutils import Vector
arm = obj.data
# Initialize container classes for convenience
mt = bone_class_instance(obj, ["body", "head"]) # meta
mt.body = bone_definition[0]
mt.head = bone_definition[1]
mt.update()
neck_chain = bone_definition[2:]
mt_chain = bone_class_instance(obj, [("neck_%.2d" % (i + 1)) for i in range(len(neck_chain))]) # 99 bones enough eh?
for i, attr in enumerate(mt_chain.attr_names):
setattr(mt_chain, attr, neck_chain[i])
mt_chain.update()
neck_chain_basename = base_names[mt_chain.neck_01_e.name].split(".")[0]
neck_chain_segment_length = mt_chain.neck_01_e.length
ex = bone_class_instance(obj, ["head", "head_hinge", "neck_socket", "head_ctrl"]) # hinge & extras
# Add the head hinge at the bodys location, becomes the parent of the original head
# apply everything to this copy of the chain
ex_chain = mt_chain.copy(base_names=base_names)
ex_chain.neck_01_e.parent = mt_chain.neck_01_e.parent
# Copy the head bone and offset
ex.head_e = copy_bone_simple(arm, mt.head, "MCH-%s" % base_names[mt.head], parent=True)
ex.head_e.use_connect = False
ex.head = ex.head_e.name
# offset
head_length = ex.head_e.length
ex.head_e.head.y += head_length / 2.0
ex.head_e.tail.y += head_length / 2.0
# Yes, use the body bone but call it a head hinge
ex.head_hinge_e = copy_bone_simple(arm, mt.body, "MCH-%s_hinge" % base_names[mt.head], parent=False)
ex.head_hinge_e.use_connect = False
ex.head_hinge = ex.head_hinge_e.name
ex.head_hinge_e.head.y += head_length / 4.0
ex.head_hinge_e.tail.y += head_length / 4.0
# Insert the neck socket, the head copys this loation
ex.neck_socket_e = arm.edit_bones.new("MCH-%s_socked" % neck_chain_basename)
ex.neck_socket = ex.neck_socket_e.name
ex.neck_socket_e.use_connect = False
ex.neck_socket_e.parent = mt.body_e
ex.neck_socket_e.head = mt.head_e.head
ex.neck_socket_e.tail = mt.head_e.head - Vector((0.0, neck_chain_segment_length / 2.0, 0.0))
ex.neck_socket_e.roll = 0.0
# copy of the head for controling
ex.head_ctrl_e = copy_bone_simple(arm, mt.head, base_names[mt.head])
ex.head_ctrl = ex.head_ctrl_e.name
ex.head_ctrl_e.parent = ex.head_hinge_e
for i, attr in enumerate(ex_chain.attr_names):
neck_e = getattr(ex_chain, attr + "_e")
# dont store parent names, re-reference as each chain bones parent.
neck_e_parent = arm.edit_bones.new("MCH-rot_%s" % base_names[getattr(mt_chain, attr)])
neck_e_parent.head = neck_e.head
neck_e_parent.tail = neck_e.head + (mt.head_e.vector.normalize() * neck_chain_segment_length / 2.0)
neck_e_parent.roll = mt.head_e.roll
orig_parent = neck_e.parent
neck_e.use_connect = False
neck_e.parent = neck_e_parent
neck_e_parent.use_connect = False
if i == 0:
neck_e_parent.parent = mt.body_e
else:
neck_e_parent.parent = orig_parent
deform(obj, bone_definition, base_names, options)
bpy.ops.object.mode_set(mode='OBJECT')
mt.update()
mt_chain.update()
ex_chain.update()
ex.update()
# Axis locks
ex.head_ctrl_p.lock_location = True, True, True
ex.head_ctrl_p.lock_scale = True, False, True
# Simple one off constraints, no drivers
con = ex.head_ctrl_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 = ex.head_ctrl
# driven hinge
prop = rna_idprop_ui_prop_get(ex.head_ctrl_p, "hinge", create=True)
ex.head_ctrl_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 = ex.head_ctrl_p.path_to_id() + '["hinge"]'
fcurve = con.driver_add("influence")
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_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 = ex.head_ctrl_p.path_to_id()
target_names = [("b%.2d" % (i + 1)) for i in range(len(neck_chain))]
ex.head_ctrl_p["bend_tot"] = 0.0
fcurve = ex.head_ctrl_p.driver_add('["bend_tot"]')
driver = fcurve.driver
driver.type = 'SUM'
fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
for i in range(len(neck_chain)):
var = driver.variables.new()
var.name = target_names[i]
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = head_driver_path + ('["bend_%.2d"]' % (i + 1))
for i, attr in enumerate(ex_chain.attr_names):
neck_p = getattr(ex_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(ex.head_ctrl_p, prop_name, create=True)
ex.head_ctrl_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 constraints
if i == 0:
con = neck_p.constraints.new('COPY_SCALE')
con.name = "Copy Scale"
con.target = obj
con.subtarget = ex.head_ctrl
con.owner_space = 'LOCAL'
con.target_space = 'LOCAL'
con = neck_p_parent.constraints.new('COPY_ROTATION')
con.name = "Copy Rotation"
con.target = obj
con.subtarget = ex.head
con.owner_space = 'LOCAL'
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'SCRIPTED'
driver.expression = "bend/bend_tot"
fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
# add target
var = driver.variables.new()
var.name = "bend_tot"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = head_driver_path + ('["bend_tot"]')
var = driver.variables.new()
var.name = "bend"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = head_driver_path + ('["%s"]' % prop_name)
# finally constrain the original bone to this one
orig_neck_p = getattr(mt_chain, attr + "_p")
con = orig_neck_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = neck_p.name
# Set the head control's custom shape to use the last
# org neck bone for its transform
ex.head_ctrl_p.custom_shape_transform = obj.pose.bones[bone_definition[len(bone_definition)-1]]
# last step setup layers
if "ex_layer" in options:
layer = [n==options["ex_layer"] for n in range(0,32)]
else:
layer = list(arm.bones[bone_definition[1]].layers)
for attr in ex_chain.attr_names:
getattr(ex_chain, attr + "_b").layers = layer
for attr in ex.attr_names:
getattr(ex, attr + "_b").layers = layer
layer = list(arm.bones[bone_definition[1]].layers)
ex.head_ctrl_b.layers = layer
# no blending the result of this
return None

View File

@ -1,110 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rigify import RigifyError
from rigify_utils import copy_bone_simple
METARIG_NAMES = tuple()
RIG_TYPE = "track_dual"
# TODO
#def metarig_template():
# # generated by rigify.write_meta_rig
# bpy.ops.object.mode_set(mode='EDIT')
# obj = bpy.context.active_object
# arm = obj.data
# bone = arm.edit_bones.new('Bone')
# bone.head[:] = 0.0000, 0.0000, 0.0000
# bone.tail[:] = 0.0000, 0.0000, 1.0000
# bone.roll = 0.0000
# bone.use_connect = False
#
# bpy.ops.object.mode_set(mode='OBJECT')
# pbone = obj.pose.bones['Bone']
# pbone['type'] = 'copy'
bool_map = {0: False, 1: True,
0.0: False, 1.0: True,
"false": False, "true": True,
"False": False, "True": True,
"no": False, "yes": True,
"No": False, "Yes": True}
def metarig_definition(obj, orig_bone_name):
return (orig_bone_name,)
def main(obj, bone_definition, base_names, options):
""" A dual-bone track setup.
Deformation only (no controls).
"""
# Verify required parameter
if "to" not in options:
raise RigifyError("'%s' rig type requires a 'to' parameter (bone: %s)" % (RIG_TYPE, base_names[0]))
if type(options["to"]) is not str:
raise RigifyError("'%s' rig type 'to' parameter must be a string (bone: %s)" % (RIG_TYPE, base_names[0]))
if ("ORG-" + options["to"]) not in obj.data.bones:
raise RigifyError("'%s' rig type 'to' parameter must name a bone in the metarig (bone: %s)" % (RIG_TYPE, base_names[0]))
eb = obj.data.edit_bones
bb = obj.data.bones
pb = obj.pose.bones
bpy.ops.object.mode_set(mode='EDIT')
arm = obj.data
mbone1 = bone_definition[0]
mbone2 = "ORG-" + options["to"]
bone_e = copy_bone_simple(obj.data, mbone1, "DEF-%s.01" % base_names[bone_definition[0]])
bone_e.use_connect = False
bone_e.parent = eb[mbone1]
bone_e.tail = (eb[mbone1].head + eb[mbone2].head) / 2
bone1 = bone_e.name
bone_e = copy_bone_simple(obj.data, mbone2, "DEF-%s.02" % base_names[bone_definition[0]])
bone_e.use_connect = False
bone_e.parent = eb[mbone1]
bone_e.tail = (eb[mbone1].head + eb[mbone2].head) / 2
bone2 = bone_e.name
bpy.ops.object.mode_set(mode='OBJECT')
# Constraints
# Bone 1
con = pb[bone1].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = mbone2
# Bone 2
con = pb[bone2].constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = mbone2
con = pb[bone2].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = mbone1
return tuple()

View File

@ -1,100 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rigify import RigifyError
from rigify_utils import copy_bone_simple
METARIG_NAMES = tuple()
RIG_TYPE = "track_reverse"
# TODO
#def metarig_template():
# # generated by rigify.write_meta_rig
# bpy.ops.object.mode_set(mode='EDIT')
# obj = bpy.context.active_object
# arm = obj.data
# bone = arm.edit_bones.new('Bone')
# bone.head[:] = 0.0000, 0.0000, 0.0000
# bone.tail[:] = 0.0000, 0.0000, 1.0000
# bone.roll = 0.0000
# bone.use_connect = False
#
# bpy.ops.object.mode_set(mode='OBJECT')
# pbone = obj.pose.bones['Bone']
# pbone['type'] = 'copy'
bool_map = {0:False, 1:True,
0.0:False, 1.0:True,
"false":False, "true":True,
"False":False, "True":True,
"no":False, "yes":True,
"No":False, "Yes":True}
def metarig_definition(obj, orig_bone_name):
return (orig_bone_name,)
def main(obj, bone_definition, base_names, options):
""" A bone that tracks bakwards towards its parent, while copying the
location of it's target.
Deformation only (no controls).
"""
# Verify required parameter
if "to" not in options:
raise RigifyError("'%s' rig type requires a 'to' parameter (bone: %s)" % (RIG_TYPE, base_names[0]))
if type(options["to"]) is not str:
raise RigifyError("'%s' rig type 'to' parameter must be a string (bone: %s)" % (RIG_TYPE, base_names[0]))
if ("ORG-" + options["to"]) not in obj.data.bones:
raise RigifyError("'%s' rig type 'to' parameter must name a bone in the metarig (bone: %s)" % (RIG_TYPE, base_names[0]))
eb = obj.data.edit_bones
bb = obj.data.bones
pb = obj.pose.bones
bpy.ops.object.mode_set(mode='EDIT')
arm = obj.data
mbone1 = bone_definition[0]
mbone2 = "ORG-" + options["to"]
bone_e = copy_bone_simple(obj.data, mbone2, "DEF-%s.02" % base_names[bone_definition[0]])
bone_e.use_connect = False
bone_e.parent = eb[mbone1]
bone_e.tail = eb[mbone1].head
bone = bone_e.name
bpy.ops.object.mode_set(mode='OBJECT')
# Constraints
con = pb[bone].constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = mbone2
con = pb[bone].constraints.new('DAMPED_TRACK')
con.target = obj
con.subtarget = mbone1
return tuple()

View File

@ -1,467 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# rigify its self does not depend on this module, however some of the
# rigify templates use these utility functions.
#
# So even though this can be for general purpose use, this module was created
# for rigify so in some cases seemingly generic functions make assumptions
# that a generic function would need to check for.
import bpy
from mathutils import Vector
from rna_prop_ui import rna_idprop_ui_prop_get
DELIMITER = '-._'
EMPTY_LAYER = [False] * 32
def add_stretch_to(obj, from_name, to_name, name):
'''
Adds a bone that stretches from one to another
'''
mode_orig = obj.mode
bpy.ops.object.mode_set(mode='EDIT')
arm = obj.data
stretch_ebone = arm.edit_bones.new(name)
stretch_name = stretch_ebone.name
del name
head = stretch_ebone.head = arm.edit_bones[from_name].head.copy()
#tail = stretch_ebone.tail = arm.edit_bones[to_name].head.copy()
# annoying exception for zero length bones, since its using stretch_to the rest pose doesnt really matter
#if (head - tail).length < 0.1:
if 1:
tail = stretch_ebone.tail = arm.edit_bones[from_name].tail.copy()
# Now for the constraint
bpy.ops.object.mode_set(mode='OBJECT')
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.rest_length = (head - tail).length
con.keep_axis = 'PLANE_X'
con.volume = 'NO_VOLUME'
bpy.ops.object.mode_set(mode=mode_orig)
return stretch_name
def copy_bone_simple(arm, from_bone, name, parent=False):
ebone = arm.edit_bones[from_bone]
ebone_new = arm.edit_bones.new(name)
if parent:
ebone_new.use_connect = ebone.use_connect
ebone_new.parent = ebone.parent
ebone_new.head = ebone.head
ebone_new.tail = ebone.tail
ebone_new.roll = ebone.roll
ebone_new.layers = list(ebone.layers)
return ebone_new
def copy_bone_simple_list(arm, from_bones, to_bones, parent=False):
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
for ebone in copy_bones:
parent = ebone.parent
if parent:
try:
i = from_bones.index(parent.name)
except:
i = -1
if i == -1:
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", blend_default=0.5):
if obj.mode == 'EDIT':
raise Exception("blending cant be called in editmode")
if len(apply_bones) != len(from_bones):
raise Exception("lists differ in length (from -> apply): \n\t%s\n\t%s" % (from_bones, apply_bones))
if len(apply_bones) != len(to_bones):
raise Exception("lists differ in length (to -> apply): \n\t%s\n\t%s" % (to_bones, apply_bones))
# setup the blend property
if target_bone is None:
target_bone = apply_bones[-1] # default to the last bone
prop_pbone = obj.pose.bones[target_bone]
if prop_pbone.get(target_bone) is None:
prop = rna_idprop_ui_prop_get(prop_pbone, target_prop, create=True)
prop_pbone[target_prop] = blend_default
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
driver_path = prop_pbone.path_from_id() + ('["%s"]' % target_prop)
def blend_target(driver):
var = driver.variables.new()
var.name = target_bone
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = driver_path
def blend_transforms(new_pbone, from_bone_name, to_bone_name):
con = new_pbone.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = from_bone_name
con = new_pbone.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = to_bone_name
fcurve = con.driver_add("influence")
driver = fcurve.driver
driver.type = 'AVERAGE'
fcurve.modifiers.remove(fcurve.modifiers[0]) # grr dont need a modifier
blend_target(driver)
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
new_pbone = obj.pose.bones[new_bone_name]
blend_transforms(new_pbone, from_bone_name, to_bone_name)
def add_pole_target_bone(obj, base_bone_name, name, mode='CROSS'):
'''
Does not actually create a poll target, just the bone to use as a poll target
'''
mode_orig = obj.mode
bpy.ops.object.mode_set(mode='EDIT')
arm = obj.data
poll_ebone = arm.edit_bones.new(name)
base_ebone = arm.edit_bones[base_bone_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':
# direction from the angle of the joint
offset = base_dir.copy().normalize() - parent_dir.copy().normalize()
offset.length = distance
elif mode == 'ZAVERAGE':
# between both bones Z axis
z_axis_a = base_ebone.matrix.copy().rotation_part() * Vector((0.0, 0.0, -1.0))
z_axis_b = parent_ebone.matrix.copy().rotation_part() * Vector((0.0, 0.0, -1.0))
offset = (z_axis_a + z_axis_b).normalize() * distance
else:
# preset axis
offset = Vector((0.0, 0.0, 0.0))
if mode[0] == "+":
val = distance
else:
val = - distance
setattr(offset, mode[1].lower(), val)
poll_ebone.head = base_head + offset
poll_ebone.tail = base_head + (offset * (1.0 - (1.0 / 4.0)))
bpy.ops.object.mode_set(mode=mode_orig)
return poll_name
def get_side_name(name):
'''
Returns the last part of a string (typically a bone's name) indicating
whether it is a a left or right (or center, or whatever) bone.
Returns an empty string if nothing is found.
'''
if name[-2] in DELIMITER:
return name[-2:]
else:
return ""
def get_base_name(name):
'''
Returns the part of a string (typically a bone's name) corresponding to it's
base name (no sidedness, no ORG prefix).
'''
if name[-2] in DELIMITER:
return name[:-2]
else:
return name
def write_meta_rig(obj, func_name="metarig_template"):
'''
Write a metarig as a python script, this rig is to have all info needed for
generating the real rig with rigify.
'''
code = []
code.append("def %s():" % func_name)
code.append(" # generated by rigify.write_meta_rig")
bpy.ops.object.mode_set(mode='EDIT')
code.append(" bpy.ops.object.mode_set(mode='EDIT')")
code.append(" obj = bpy.context.active_object")
code.append(" arm = obj.data")
arm = obj.data
# write parents first
bones = [(len(bone.parent_recursive), bone.name) for bone in arm.edit_bones]
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)
code.append(" bone.head[:] = %.4f, %.4f, %.4f" % bone.head.to_tuple(4))
code.append(" bone.tail[:] = %.4f, %.4f, %.4f" % bone.tail.to_tuple(4))
code.append(" bone.roll = %.4f" % bone.roll)
code.append(" bone.use_connect = %s" % str(bone.use_connect))
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("_"):
continue
if type(value) not in (float, str, int):
print("Unsupported ID Prop:", str((key, value)))
continue
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)
# *** bone class collection ***
def bone_class_instance(obj, slots, name="BoneContainer"):
'''
bone collection utility class to help manage cases with
edit/pose/bone bones where switching modes can invalidate some of the members.
there are also utility functions for manipulating all members.
'''
attr_names = tuple(slots) # dont modify the original
if len(slots) != len(set(slots)):
raise Exception("duplicate entries found %s" % attr_names)
slots = list(slots) # dont modify the original
for i in range(len(slots)):
member = slots[i]
slots.append(member + "_b") # bone bone
slots.append(member + "_p") # pose bone
slots.append(member + "_e") # edit bone
class_dict = { \
"obj": obj, \
"attr_names": attr_names, \
"attr_initialize": _bone_class_instance_attr_initialize, \
"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 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)()
def _bone_class_instance_attr_initialize(self, attr_names, bone_names):
''' Initializes attributes, both lists must be aligned
'''
for attr in self.attr_names:
i = attr_names.index(attr)
setattr(self, attr, bone_names[i])
self.update()
def _bone_class_instance_update(self):
''' Re-Assigns bones from the blender data
'''
arm = self.obj.data
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:
setattr(self, member + "_b", bbones.get(name))
setattr(self, member + "_p", pbones.get(name))
setattr(self, member + "_e", ebones.get(name))
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_fmt="%s", to_fmt="%s", exclude_attrs=(), base_names=None):
from_name_ls = []
new_name_ls = []
new_slot_ls = []
for attr in self.attr_names:
if attr in exclude_attrs:
continue
bone_name_orig = getattr(self, attr)
ebone = getattr(self, attr + "_e")
# orig_names[attr] = bone_name_orig
# insert formatting
if from_fmt != "%s":
bone_name = from_fmt % bone_name_orig
ebone.name = bone_name
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)
if base_names:
bone_name_orig = base_names[bone_name_orig]
new_name_ls.append(to_fmt % 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)
for i, attr in enumerate(new_slot_ls):
ebone = new_bones[i]
setattr(new_bc, attr + "_e", ebone)
setattr(new_bc, attr, ebone.name)
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)

View File

@ -1,616 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8-80 compliant>
import bpy
import mathutils
from math import cos, sin, pi
# could this be stored elsewhere?
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('pelvis')
bone.head[:] = -0.0000, -0.0145, 1.1263
bone.tail[:] = -0.0000, -0.0145, 0.9563
bone.roll = 3.1416
bone.use_connect = False
bone = arm.edit_bones.new('torso')
bone.head[:] = -0.0000, -0.0145, 1.1263
bone.tail[:] = -0.0000, -0.0145, 1.2863
bone.roll = 3.1416
bone.use_connect = False
bone.parent = arm.edit_bones['pelvis']
bone = arm.edit_bones.new('spine.01')
bone.head[:] = 0.0000, 0.0394, 0.9688
bone.tail[:] = -0.0000, -0.0145, 1.1263
bone.roll = 0.0000
bone.use_connect = False
bone.parent = arm.edit_bones['torso']
bone = arm.edit_bones.new('spine.02')
bone.head[:] = -0.0000, -0.0145, 1.1263
bone.tail[:] = -0.0000, -0.0213, 1.2884
bone.roll = -0.0000
bone.use_connect = True
bone.parent = arm.edit_bones['spine.01']
bone = arm.edit_bones.new('thigh.L')
bone.head[:] = 0.0933, -0.0421, 1.0434
bone.tail[:] = 0.0933, -0.0516, 0.5848
bone.roll = 0.0000
bone.use_connect = False
bone.parent = arm.edit_bones['spine.01']
bone = arm.edit_bones.new('thigh.R')
bone.head[:] = -0.0933, -0.0421, 1.0434
bone.tail[:] = -0.0933, -0.0516, 0.5848
bone.roll = -0.0000
bone.use_connect = False
bone.parent = arm.edit_bones['spine.01']
bone = arm.edit_bones.new('spine.03')
bone.head[:] = -0.0000, -0.0213, 1.2884
bone.tail[:] = -0.0000, 0.0160, 1.3705
bone.roll = -0.0000
bone.use_connect = True
bone.parent = arm.edit_bones['spine.02']
bone = arm.edit_bones.new('shin.L')
bone.head[:] = 0.0933, -0.0516, 0.5848
bone.tail[:] = 0.0915, 0.0100, 0.1374
bone.roll = 0.0034
bone.use_connect = True
bone.parent = arm.edit_bones['thigh.L']
bone = arm.edit_bones.new('shin.R')
bone.head[:] = -0.0933, -0.0516, 0.5848
bone.tail[:] = -0.0915, 0.0100, 0.1374
bone.roll = -0.0034
bone.use_connect = True
bone.parent = arm.edit_bones['thigh.R']
bone = arm.edit_bones.new('spine.04')
bone.head[:] = -0.0000, 0.0160, 1.3705
bone.tail[:] = -0.0000, 0.0590, 1.4497
bone.roll = -0.0000
bone.use_connect = True
bone.parent = arm.edit_bones['spine.03']
bone = arm.edit_bones.new('foot.L')
bone.head[:] = 0.0915, 0.0100, 0.1374
bone.tail[:] = 0.1033, -0.0968, 0.0510
bone.roll = 2.8964
bone.use_connect = True
bone.parent = arm.edit_bones['shin.L']
bone = arm.edit_bones.new('foot.R')
bone.head[:] = -0.0915, 0.0100, 0.1374
bone.tail[:] = -0.1033, -0.0968, 0.0510
bone.roll = -2.8793
bone.use_connect = True
bone.parent = arm.edit_bones['shin.R']
bone = arm.edit_bones.new('neck_base')
bone.head[:] = -0.0000, 0.0590, 1.4497
bone.tail[:] = -0.0000, 0.0401, 1.5389
bone.roll = -0.0000
bone.use_connect = True
bone.parent = arm.edit_bones['spine.04']
bone = arm.edit_bones.new('toe.L')
bone.head[:] = 0.1033, -0.0968, 0.0510
bone.tail[:] = 0.1136, -0.1848, 0.0510
bone.roll = 0.0001
bone.use_connect = True
bone.parent = arm.edit_bones['foot.L']
bone = arm.edit_bones.new('heel.L')
bone.head[:] = 0.0809, 0.0969, -0.0000
bone.tail[:] = 0.1020, -0.0846, -0.0000
bone.roll = -0.0001
bone.use_connect = False
bone.parent = arm.edit_bones['foot.L']
bone = arm.edit_bones.new('toe.R')
bone.head[:] = -0.1033, -0.0968, 0.0510
bone.tail[:] = -0.1136, -0.1848, 0.0510
bone.roll = -0.0002
bone.use_connect = True
bone.parent = arm.edit_bones['foot.R']
bone = arm.edit_bones.new('heel.R')
bone.head[:] = -0.0809, 0.0969, -0.0000
bone.tail[:] = -0.1020, -0.0846, -0.0000
bone.roll = -0.0000
bone.use_connect = False
bone.parent = arm.edit_bones['foot.R']
bone = arm.edit_bones.new('head')
bone.head[:] = -0.0000, 0.0401, 1.5389
bone.tail[:] = -0.0000, 0.0401, 1.5979
bone.roll = 3.1416
bone.use_connect = True
bone.parent = arm.edit_bones['neck_base']
bone = arm.edit_bones.new('DLT-shoulder.L')
bone.head[:] = 0.0141, -0.0346, 1.4991
bone.tail[:] = 0.1226, 0.0054, 1.4991
bone.roll = 0.0005
bone.use_connect = False
bone.parent = arm.edit_bones['neck_base']
bone = arm.edit_bones.new('DLT-shoulder.R')
bone.head[:] = -0.0141, -0.0346, 1.4991
bone.tail[:] = -0.1226, 0.0054, 1.4991
bone.roll = -0.0005
bone.use_connect = False
bone.parent = arm.edit_bones['neck_base']
bone = arm.edit_bones.new('neck.01')
bone.head[:] = -0.0000, 0.0401, 1.5389
bone.tail[:] = -0.0000, 0.0176, 1.5916
bone.roll = 0.0000
bone.use_connect = False
bone.parent = arm.edit_bones['head']
bone = arm.edit_bones.new('shoulder.L')
bone.head[:] = 0.0141, -0.0346, 1.4991
bone.tail[:] = 0.1226, 0.0216, 1.5270
bone.roll = -0.1225
bone.use_connect = False
bone.parent = arm.edit_bones['DLT-shoulder.L']
bone = arm.edit_bones.new('shoulder.R')
bone.head[:] = -0.0141, -0.0346, 1.4991
bone.tail[:] = -0.1226, 0.0216, 1.5270
bone.roll = 0.0849
bone.use_connect = False
bone.parent = arm.edit_bones['DLT-shoulder.R']
bone = arm.edit_bones.new('neck.02')
bone.head[:] = -0.0000, 0.0176, 1.5916
bone.tail[:] = -0.0000, 0.0001, 1.6499
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones['neck.01']
bone = arm.edit_bones.new('DLT-upper_arm.L')
bone.head[:] = 0.1482, 0.0483, 1.4943
bone.tail[:] = 0.2586, 0.1057, 1.5124
bone.roll = 1.4969
bone.use_connect = False
bone.parent = arm.edit_bones['shoulder.L']
bone = arm.edit_bones.new('DLT-upper_arm.R')
bone.head[:] = -0.1482, 0.0483, 1.4943
bone.tail[:] = -0.2586, 0.1057, 1.5124
bone.roll = -1.4482
bone.use_connect = False
bone.parent = arm.edit_bones['shoulder.R']
bone = arm.edit_bones.new('neck.03')
bone.head[:] = -0.0000, 0.0001, 1.6499
bone.tail[:] = -0.0000, 0.0001, 1.8522
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones['neck.02']
bone = arm.edit_bones.new('upper_arm.L')
bone.head[:] = 0.1482, 0.0483, 1.4943
bone.tail[:] = 0.3929, 0.0522, 1.4801
bone.roll = 1.6281
bone.use_connect = False
bone.parent = arm.edit_bones['DLT-upper_arm.L']
bone = arm.edit_bones.new('upper_arm.R')
bone.head[:] = -0.1482, 0.0483, 1.4943
bone.tail[:] = -0.3929, 0.0522, 1.4801
bone.roll = -1.6281
bone.use_connect = False
bone.parent = arm.edit_bones['DLT-upper_arm.R']
bone = arm.edit_bones.new('forearm.L')
bone.head[:] = 0.3929, 0.0522, 1.4801
bone.tail[:] = 0.6198, 0.0364, 1.4906
bone.roll = 1.5240
bone.use_connect = True
bone.parent = arm.edit_bones['upper_arm.L']
bone = arm.edit_bones.new('forearm.R')
bone.head[:] = -0.3929, 0.0522, 1.4801
bone.tail[:] = -0.6198, 0.0364, 1.4906
bone.roll = -1.5219
bone.use_connect = True
bone.parent = arm.edit_bones['upper_arm.R']
bone = arm.edit_bones.new('hand.L')
bone.head[:] = 0.6198, 0.0364, 1.4906
bone.tail[:] = 0.6592, 0.0364, 1.4853
bone.roll = -3.0065
bone.use_connect = True
bone.parent = arm.edit_bones['forearm.L']
bone = arm.edit_bones.new('hand.R')
bone.head[:] = -0.6198, 0.0364, 1.4906
bone.tail[:] = -0.6592, 0.0364, 1.4853
bone.roll = 3.0065
bone.use_connect = True
bone.parent = arm.edit_bones['forearm.R']
bone = arm.edit_bones.new('palm.04.L')
bone.head[:] = 0.6514, 0.0658, 1.4906
bone.tail[:] = 0.7287, 0.0810, 1.4747
bone.roll = -3.0715
bone.use_connect = False
bone.parent = arm.edit_bones['hand.L']
bone = arm.edit_bones.new('palm.03.L')
bone.head[:] = 0.6533, 0.0481, 1.4943
bone.tail[:] = 0.7386, 0.0553, 1.4781
bone.roll = -3.0290
bone.use_connect = False
bone.parent = arm.edit_bones['hand.L']
bone = arm.edit_bones.new('palm.02.L')
bone.head[:] = 0.6539, 0.0305, 1.4967
bone.tail[:] = 0.7420, 0.0250, 1.4835
bone.roll = -3.0669
bone.use_connect = False
bone.parent = arm.edit_bones['hand.L']
bone = arm.edit_bones.new('palm.01.L')
bone.head[:] = 0.6514, 0.0116, 1.4961
bone.tail[:] = 0.7361, -0.0074, 1.4823
bone.roll = -2.9422
bone.use_connect = False
bone.parent = arm.edit_bones['hand.L']
bone = arm.edit_bones.new('thumb.01.L')
bone.head[:] = 0.6380, -0.0005, 1.4848
bone.tail[:] = 0.6757, -0.0408, 1.4538
bone.roll = -0.7041
bone.use_connect = False
bone.parent = arm.edit_bones['hand.L']
bone = arm.edit_bones.new('palm.04.R')
bone.head[:] = -0.6514, 0.0658, 1.4906
bone.tail[:] = -0.7287, 0.0810, 1.4747
bone.roll = 3.0715
bone.use_connect = False
bone.parent = arm.edit_bones['hand.R']
bone = arm.edit_bones.new('palm.03.R')
bone.head[:] = -0.6533, 0.0481, 1.4943
bone.tail[:] = -0.7386, 0.0553, 1.4781
bone.roll = 3.0290
bone.use_connect = False
bone.parent = arm.edit_bones['hand.R']
bone = arm.edit_bones.new('palm.02.R')
bone.head[:] = -0.6539, 0.0305, 1.4967
bone.tail[:] = -0.7420, 0.0250, 1.4835
bone.roll = 3.0669
bone.use_connect = False
bone.parent = arm.edit_bones['hand.R']
bone = arm.edit_bones.new('thumb.01.R')
bone.head[:] = -0.6380, -0.0005, 1.4848
bone.tail[:] = -0.6757, -0.0408, 1.4538
bone.roll = 0.7041
bone.use_connect = False
bone.parent = arm.edit_bones['hand.R']
bone = arm.edit_bones.new('palm.01.R')
bone.head[:] = -0.6514, 0.0116, 1.4961
bone.tail[:] = -0.7361, -0.0074, 1.4823
bone.roll = 2.9332
bone.use_connect = False
bone.parent = arm.edit_bones['hand.R']
bone = arm.edit_bones.new('finger_pinky.01.L')
bone.head[:] = 0.7287, 0.0810, 1.4747
bone.tail[:] = 0.7698, 0.0947, 1.4635
bone.roll = -3.0949
bone.use_connect = True
bone.parent = arm.edit_bones['palm.04.L']
bone = arm.edit_bones.new('finger_ring.01.L')
bone.head[:] = 0.7386, 0.0553, 1.4781
bone.tail[:] = 0.7890, 0.0615, 1.4667
bone.roll = -3.0081
bone.use_connect = True
bone.parent = arm.edit_bones['palm.03.L']
bone = arm.edit_bones.new('finger_middle.01.L')
bone.head[:] = 0.7420, 0.0250, 1.4835
bone.tail[:] = 0.7975, 0.0221, 1.4712
bone.roll = -2.9982
bone.use_connect = True
bone.parent = arm.edit_bones['palm.02.L']
bone = arm.edit_bones.new('finger_index.01.L')
bone.head[:] = 0.7361, -0.0074, 1.4823
bone.tail[:] = 0.7843, -0.0204, 1.4718
bone.roll = -3.0021
bone.use_connect = True
bone.parent = arm.edit_bones['palm.01.L']
bone = arm.edit_bones.new('thumb.02.L')
bone.head[:] = 0.6757, -0.0408, 1.4538
bone.tail[:] = 0.6958, -0.0568, 1.4376
bone.roll = -0.6963
bone.use_connect = True
bone.parent = arm.edit_bones['thumb.01.L']
bone = arm.edit_bones.new('finger_pinky.01.R')
bone.head[:] = -0.7287, 0.0810, 1.4747
bone.tail[:] = -0.7698, 0.0947, 1.4635
bone.roll = 3.0949
bone.use_connect = True
bone.parent = arm.edit_bones['palm.04.R']
bone = arm.edit_bones.new('finger_ring.01.R')
bone.head[:] = -0.7386, 0.0553, 1.4781
bone.tail[:] = -0.7890, 0.0615, 1.4667
bone.roll = 2.9892
bone.use_connect = True
bone.parent = arm.edit_bones['palm.03.R']
bone = arm.edit_bones.new('finger_middle.01.R')
bone.head[:] = -0.7420, 0.0250, 1.4835
bone.tail[:] = -0.7975, 0.0221, 1.4712
bone.roll = 2.9816
bone.use_connect = True
bone.parent = arm.edit_bones['palm.02.R']
bone = arm.edit_bones.new('thumb.02.R')
bone.head[:] = -0.6757, -0.0408, 1.4538
bone.tail[:] = -0.6958, -0.0568, 1.4376
bone.roll = 0.6963
bone.use_connect = True
bone.parent = arm.edit_bones['thumb.01.R']
bone = arm.edit_bones.new('finger_index.01.R')
bone.head[:] = -0.7361, -0.0074, 1.4823
bone.tail[:] = -0.7843, -0.0204, 1.4718
bone.roll = 2.9498
bone.use_connect = True
bone.parent = arm.edit_bones['palm.01.R']
bone = arm.edit_bones.new('finger_pinky.02.L')
bone.head[:] = 0.7698, 0.0947, 1.4635
bone.tail[:] = 0.7910, 0.1018, 1.4577
bone.roll = -3.0949
bone.use_connect = True
bone.parent = arm.edit_bones['finger_pinky.01.L']
bone = arm.edit_bones.new('finger_ring.02.L')
bone.head[:] = 0.7890, 0.0615, 1.4667
bone.tail[:] = 0.8177, 0.0650, 1.4600
bone.roll = -3.0006
bone.use_connect = True
bone.parent = arm.edit_bones['finger_ring.01.L']
bone = arm.edit_bones.new('finger_middle.02.L')
bone.head[:] = 0.7975, 0.0221, 1.4712
bone.tail[:] = 0.8289, 0.0206, 1.4643
bone.roll = -2.9995
bone.use_connect = True
bone.parent = arm.edit_bones['finger_middle.01.L']
bone = arm.edit_bones.new('finger_index.02.L')
bone.head[:] = 0.7843, -0.0204, 1.4718
bone.tail[:] = 0.8117, -0.0275, 1.4660
bone.roll = -3.0064
bone.use_connect = True
bone.parent = arm.edit_bones['finger_index.01.L']
bone = arm.edit_bones.new('thumb.03.L')
bone.head[:] = 0.6958, -0.0568, 1.4376
bone.tail[:] = 0.7196, -0.0671, 1.4210
bone.roll = -0.8072
bone.use_connect = True
bone.parent = arm.edit_bones['thumb.02.L']
bone = arm.edit_bones.new('finger_pinky.02.R')
bone.head[:] = -0.7698, 0.0947, 1.4635
bone.tail[:] = -0.7910, 0.1018, 1.4577
bone.roll = 3.0949
bone.use_connect = True
bone.parent = arm.edit_bones['finger_pinky.01.R']
bone = arm.edit_bones.new('finger_ring.02.R')
bone.head[:] = -0.7890, 0.0615, 1.4667
bone.tail[:] = -0.8177, 0.0650, 1.4600
bone.roll = 3.0341
bone.use_connect = True
bone.parent = arm.edit_bones['finger_ring.01.R']
bone = arm.edit_bones.new('finger_middle.02.R')
bone.head[:] = -0.7975, 0.0221, 1.4712
bone.tail[:] = -0.8289, 0.0206, 1.4643
bone.roll = 3.0291
bone.use_connect = True
bone.parent = arm.edit_bones['finger_middle.01.R']
bone = arm.edit_bones.new('thumb.03.R')
bone.head[:] = -0.6958, -0.0568, 1.4376
bone.tail[:] = -0.7196, -0.0671, 1.4210
bone.roll = 0.8072
bone.use_connect = True
bone.parent = arm.edit_bones['thumb.02.R']
bone = arm.edit_bones.new('finger_index.02.R')
bone.head[:] = -0.7843, -0.0204, 1.4718
bone.tail[:] = -0.8117, -0.0275, 1.4660
bone.roll = 3.0705
bone.use_connect = True
bone.parent = arm.edit_bones['finger_index.01.R']
bone = arm.edit_bones.new('finger_pinky.03.L')
bone.head[:] = 0.7910, 0.1018, 1.4577
bone.tail[:] = 0.8109, 0.1085, 1.4523
bone.roll = -3.0949
bone.use_connect = True
bone.parent = arm.edit_bones['finger_pinky.02.L']
bone = arm.edit_bones.new('finger_ring.03.L')
bone.head[:] = 0.8177, 0.0650, 1.4600
bone.tail[:] = 0.8396, 0.0677, 1.4544
bone.roll = -2.9819
bone.use_connect = True
bone.parent = arm.edit_bones['finger_ring.02.L']
bone = arm.edit_bones.new('finger_middle.03.L')
bone.head[:] = 0.8289, 0.0206, 1.4643
bone.tail[:] = 0.8534, 0.0193, 1.4589
bone.roll = -3.0004
bone.use_connect = True
bone.parent = arm.edit_bones['finger_middle.02.L']
bone = arm.edit_bones.new('finger_index.03.L')
bone.head[:] = 0.8117, -0.0275, 1.4660
bone.tail[:] = 0.8331, -0.0333, 1.4615
bone.roll = -3.0103
bone.use_connect = True
bone.parent = arm.edit_bones['finger_index.02.L']
bone = arm.edit_bones.new('finger_pinky.03.R')
bone.head[:] = -0.7910, 0.1018, 1.4577
bone.tail[:] = -0.8109, 0.1085, 1.4523
bone.roll = 3.0949
bone.use_connect = True
bone.parent = arm.edit_bones['finger_pinky.02.R']
bone = arm.edit_bones.new('finger_ring.03.R')
bone.head[:] = -0.8177, 0.0650, 1.4600
bone.tail[:] = -0.8396, 0.0677, 1.4544
bone.roll = 2.9819
bone.use_connect = True
bone.parent = arm.edit_bones['finger_ring.02.R']
bone = arm.edit_bones.new('finger_middle.03.R')
bone.head[:] = -0.8289, 0.0206, 1.4643
bone.tail[:] = -0.8534, 0.0193, 1.4589
bone.roll = 3.0004
bone.use_connect = True
bone.parent = arm.edit_bones['finger_middle.02.R']
bone = arm.edit_bones.new('finger_index.03.R')
bone.head[:] = -0.8117, -0.0275, 1.4660
bone.tail[:] = -0.8331, -0.0333, 1.4615
bone.roll = 2.9917
bone.use_connect = True
bone.parent = arm.edit_bones['finger_index.02.R']
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['torso']
pbone['type'] = 'spine_pivot_flex'
pbone = obj.pose.bones['torso']
pbone['spine_pivot_flex.later_main'] = 1
pbone = obj.pose.bones['torso']
pbone['spine_pivot_flex.layer_extra'] = 2
pbone = obj.pose.bones['thigh.L']
pbone['type'] = 'leg_biped'
pbone = obj.pose.bones['thigh.L']
pbone['leg_biped_generic.layer_ik'] = 12
pbone = obj.pose.bones['thigh.L']
pbone['leg_biped_generic.layer_fk'] = 11
pbone = obj.pose.bones['thigh.R']
pbone['type'] = 'leg_biped'
pbone = obj.pose.bones['thigh.R']
pbone['leg_biped_generic.layer_ik'] = 14
pbone = obj.pose.bones['thigh.R']
pbone['leg_biped_generic.layer_fk'] = 13
pbone = obj.pose.bones['head']
pbone['type'] = 'neck_flex'
pbone = obj.pose.bones['head']
pbone['neck_flex.layer_extra'] = 4
pbone = obj.pose.bones['head']
pbone['neck_flex.layer_main'] = 3
pbone = obj.pose.bones['DLT-shoulder.L']
pbone['type'] = 'delta'
pbone = obj.pose.bones['DLT-shoulder.R']
pbone['type'] = 'delta'
pbone = obj.pose.bones['shoulder.L']
pbone['type'] = 'copy'
pbone = obj.pose.bones['shoulder.L']
pbone['copy.layers'] = 1
pbone = obj.pose.bones['shoulder.R']
pbone['type'] = 'copy'
pbone = obj.pose.bones['shoulder.R']
pbone['copy.layers'] = 1
pbone = obj.pose.bones['DLT-upper_arm.L']
pbone['type'] = 'delta'
pbone = obj.pose.bones['DLT-upper_arm.R']
pbone['type'] = 'delta'
pbone = obj.pose.bones['upper_arm.L']
pbone['type'] = 'arm_biped'
pbone = obj.pose.bones['upper_arm.L']
pbone['arm_biped_generic.elbow_parent'] = 'spine.04'
pbone = obj.pose.bones['upper_arm.L']
pbone['arm_biped_generic.layer_fk'] = 7
pbone = obj.pose.bones['upper_arm.L']
pbone['arm_biped_generic.layer_ik'] = 8
pbone = obj.pose.bones['upper_arm.R']
pbone['type'] = 'arm_biped'
pbone = obj.pose.bones['upper_arm.R']
pbone['arm_biped_generic.layer_fk'] = 9
pbone = obj.pose.bones['upper_arm.R']
pbone['arm_biped_generic.layer_ik'] = 10
pbone = obj.pose.bones['upper_arm.R']
pbone['arm_biped_generic.elbow_parent'] = 'spine.04'
pbone = obj.pose.bones['palm.01.L']
pbone['type'] = 'palm_curl'
pbone = obj.pose.bones['palm.01.L']
pbone['palm_curl.layers'] = 5
pbone = obj.pose.bones['thumb.01.L']
pbone['type'] = 'finger_curl'
pbone = obj.pose.bones['thumb.01.L']
pbone['finger_curl.layer_main'] = 5
pbone = obj.pose.bones['thumb.01.L']
pbone['finger_curl.layer_extra'] = 6
pbone = obj.pose.bones['thumb.01.R']
pbone['type'] = 'finger_curl'
pbone = obj.pose.bones['thumb.01.R']
pbone['finger_curl.layer_main'] = 5
pbone = obj.pose.bones['thumb.01.R']
pbone['finger_curl.layer_extra'] = 6
pbone = obj.pose.bones['palm.01.R']
pbone['type'] = 'palm_curl'
pbone = obj.pose.bones['palm.01.R']
pbone['palm_curl.layers'] = 5
pbone = obj.pose.bones['finger_pinky.01.L']
pbone['type'] = 'finger_curl'
pbone = obj.pose.bones['finger_pinky.01.L']
pbone['finger_curl.layer_main'] = 5
pbone = obj.pose.bones['finger_pinky.01.L']
pbone['finger_curl.layer_extra'] = 6
pbone = obj.pose.bones['finger_ring.01.L']
pbone['type'] = 'finger_curl'
pbone = obj.pose.bones['finger_ring.01.L']
pbone['finger_curl.layer_main'] = 5
pbone = obj.pose.bones['finger_ring.01.L']
pbone['finger_curl.layer_extra'] = 6
pbone = obj.pose.bones['finger_middle.01.L']
pbone['type'] = 'finger_curl'
pbone = obj.pose.bones['finger_middle.01.L']
pbone['finger_curl.layer_main'] = 5
pbone = obj.pose.bones['finger_middle.01.L']
pbone['finger_curl.layer_extra'] = 6
pbone = obj.pose.bones['finger_index.01.L']
pbone['type'] = 'finger_curl'
pbone = obj.pose.bones['finger_index.01.L']
pbone['finger_curl.layer_main'] = 5
pbone = obj.pose.bones['finger_index.01.L']
pbone['finger_curl.layer_extra'] = 6
pbone = obj.pose.bones['finger_pinky.01.R']
pbone['type'] = 'finger_curl'
pbone = obj.pose.bones['finger_pinky.01.R']
pbone['finger_curl.layer_main'] = 5
pbone = obj.pose.bones['finger_pinky.01.R']
pbone['finger_curl.layer_extra'] = 6
pbone = obj.pose.bones['finger_ring.01.R']
pbone['type'] = 'finger_curl'
pbone = obj.pose.bones['finger_ring.01.R']
pbone['finger_curl.layer_main'] = 5
pbone = obj.pose.bones['finger_ring.01.R']
pbone['finger_curl.layer_extra'] = 6
pbone = obj.pose.bones['finger_middle.01.R']
pbone['type'] = 'finger_curl'
pbone = obj.pose.bones['finger_middle.01.R']
pbone['finger_curl.layer_main'] = 5
pbone = obj.pose.bones['finger_middle.01.R']
pbone['finger_curl.layer_extra'] = 6
pbone = obj.pose.bones['finger_index.01.R']
pbone['type'] = 'finger_curl'
pbone = obj.pose.bones['finger_index.01.R']
pbone['finger_curl.layer_main'] = 5
pbone = obj.pose.bones['finger_index.01.R']
pbone['finger_curl.layer_extra'] = 6
class AddHuman(bpy.types.Operator):
'''Add an advanced human metarig base'''
bl_idname = "object.armature_human_advanced_add"
bl_label = "Add Humanoid (advanced metarig)"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
bpy.ops.object.armature_add()
obj = context.active_object
mode_orig = obj.mode
bpy.ops.object.mode_set(mode='EDIT') # grr, remove bone
bones = context.active_object.data.edit_bones
bones.remove(bones[0])
metarig_template()
bpy.ops.object.mode_set(mode=mode_orig)
return {'FINISHED'}
# Add to a menu
menu_func = (lambda self, context: self.layout.operator(AddHuman.bl_idname,
icon='OUTLINER_OB_ARMATURE', text="Human (Meta-Rig)"))
def register():
bpy.types.INFO_MT_armature_add.append(menu_func)
def unregister():
bpy.types.INFO_MT_armature_add.remove(menu_func)
if __name__ == "__main__":
register()

View File

@ -1,334 +0,0 @@
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from bpy.props import *
class PoseTemplate(bpy.types.IDPropertyGroup):
name = StringProperty(name="Name of the slave", description="", maxlen=64, default="")
class PoseTemplateSettings(bpy.types.IDPropertyGroup):
templates = CollectionProperty(type=PoseTemplate, name="Templates", description="")
active_template_index = IntProperty(name="Index of the active slave", description="", default=-1, min=-1, max=65535)
use_generate_deform_rig = BoolProperty(name="Create Deform Rig", description="Create a copy of the metarig, constrainted by the generated rig", default=False)
def metarig_templates():
import rigify
return rigify.get_submodule_types()
class DATA_PT_template(bpy.types.Panel):
bl_label = "Meta-Rig Templates"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "data"
bl_options = {'DEFAULT_CLOSED'}
templates = []
@classmethod
def poll(cls, context):
if not context.armature:
return False
obj = context.object
if obj:
return (obj.mode in ('POSE', 'OBJECT'))
return False
def draw(self, context):
layout = self.layout
try:
active_type = context.active_pose_bone["type"]
except:
active_type = None
scene = context.scene
pose_templates = scene.pose_templates
if pose_templates.active_template_index == -1:
pose_templates.active_template_index = 0
if not self.templates:
self.templates[:] = metarig_templates()
while(len(pose_templates.templates) < len(self.templates)):
pose_templates.templates.add()
while(len(pose_templates.templates) > len(self.templates)):
pose_templates.templates.remove(0)
for i, template_name in enumerate(self.templates):
template = pose_templates.templates[i]
if active_type == template_name:
template.name = "<%s>" % template_name.replace("_", " ")
else:
template.name = " %s " % template_name.replace("_", " ")
row = layout.row()
row.operator("pose.metarig_generate", text="Generate")
row.operator("pose.metarig_validate", text="Check")
row.operator("pose.metarig_graph", text="Graph")
row = layout.row()
row.prop(pose_templates, "use_generate_deform_rig")
row = layout.row()
col = row.column()
col.template_list(pose_templates, "templates", pose_templates, "active_template_index", rows=1)
subrow = col.split(percentage=0.5, align=True)
subsubrow = subrow.row(align=True)
subsubrow.operator("pose.metarig_assign", text="Assign")
subsubrow.operator("pose.metarig_clear", text="Clear")
if self.templates:
subsubrow = subrow.split(percentage=0.8)
subsubrow.operator("pose.metarig_sample_add", text="Sample").metarig_type = self.templates[pose_templates.active_template_index]
subsubrow.operator("pose.metarig_sample_add", text="All").metarig_type = "" # self.templates[pose_templates.active_template_index]
sub = row.column(align=True)
sub.operator("pose.metarig_reload", icon="FILE_REFRESH", text="")
class Reload(bpy.types.Operator):
'''Re-Scan the metarig package directory for scripts'''
bl_idname = "pose.metarig_reload"
bl_label = "Re-Scan the list of metarig types"
def execute(self, context):
DATA_PT_template.templates[:] = metarig_templates()
return {'FINISHED'}
def rigify_report_exception(operator, exception):
import traceback
import sys
import os
# find the module name where the error happened
# hint, this is the metarig type!
exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
fn = traceback.extract_tb(exceptionTraceback)[-1][0]
fn = os.path.basename(fn)
fn = os.path.splitext(fn)[0]
message = []
if fn.startswith("__"):
message.append("Incorrect armature...")
else:
message.append("Incorrect armature for type '%s'" % fn)
message.append(exception.message)
message.reverse() # XXX - stupid! menu's are upside down!
operator.report(set(['INFO']), '\n'.join(message))
class Generate(bpy.types.Operator):
'''Generates a metarig from the active armature'''
bl_idname = "pose.metarig_generate"
bl_label = "Generate Metarig"
def execute(self, context):
import rigify
reload(rigify)
meta_def = context.scene.pose_templates.use_generate_deform_rig
try:
rigify.generate_rig(context, context.object, META_DEF=meta_def)
except rigify.RigifyError as rig_exception:
rigify_report_exception(self, rig_exception)
return {'FINISHED'}
class Validate(bpy.types.Operator):
'''Validate a metarig from the active armature'''
bl_idname = "pose.metarig_validate"
bl_label = "Validate Metarig"
def execute(self, context):
import rigify
reload(rigify)
try:
rigify.validate_rig(context, context.object)
except rigify.RigifyError as rig_exception:
rigify_report_exception(self, rig_exception)
return {'FINISHED'}
class Sample(bpy.types.Operator):
'''Create a sample metarig to be modified before generating the final rig.'''
bl_idname = "pose.metarig_sample_add"
bl_label = "Re-Scan Metarig Scripts"
metarig_type = StringProperty(name="Type", description="Name of the rig type to generate a sample of, a blank string for all", maxlen=128, default="")
def execute(self, context):
import rigify
reload(rigify)
final = (self.metarig_type == "")
objects = rigify.generate_test(context, metarig_type=self.metarig_type, GENERATE_FINAL=final)
if len(objects) > 1:
for i, (obj_meta, obj_gen) in enumerate(objects):
obj_meta.location.x = i * 1.0
if obj_gen:
obj_gen.location.x = i * 1.0
return {'FINISHED'}
class Graph(bpy.types.Operator):
'''Create a graph from the active armature through graphviz'''
bl_idname = "pose.metarig_graph"
bl_label = "Pose Graph"
def execute(self, context):
import os
import graphviz_export
import bpy
reload(graphviz_export)
obj = bpy.context.object
if(bpy.data.filepath):
path = os.path.splitext(bpy.data.filepath)[0] + "-" + bpy.path.clean_name(obj.name)
else:
import tempfile
path = tempfile.mktemp(prefix=bpy.app.tempdir) + "-" + bpy.path.clean_name(obj.name)
path_dot = path + ".dot"
path_png = path + ".png"
saved = graphviz_export.graph_armature(bpy.context.object, path_dot, CONSTRAINTS=False, DRIVERS=False)
if saved:
# if we seriously want this working everywhere we'll need some new approach
os.system("dot -Tpng %r > %r" % (path_dot, path_png))
if not os.path.exists(path_png) or os.stat(path_png)[6] == 0:
self.report('ERROR', "Graphvis could not create %r check graphviz is installed" % path_png)
return {'CANCELLED'}
bpy.ops.image.external_edit(filepath=path_png)
#os.system("python /b/xdot.py '%s' &" % path_dot)
return {'FINISHED'}
class AsScript(bpy.types.Operator):
'''Write the edit armature out as a python script'''
bl_idname = "pose.metarig_to_script"
bl_label = "Write Metarig to Script"
bl_options = {'REGISTER', 'UNDO'}
filepath = StringProperty(name="File Path", description="File path used for exporting the Armature file", maxlen=1024, default="")
def execute(self, context):
import rigify_utils
reload(rigify_utils)
obj = context.object
code = rigify_utils.write_meta_rig(obj)
path = self.filepath
file = open(path, "w")
file.write(code)
file.close()
return {'FINISHED'}
def invoke(self, context, event):
import os
obj = context.object
self.filepath = os.path.splitext(bpy.data.filepath)[0] + "-" + bpy.path.clean_name(obj.name) + ".py"
wm = context.window_manager
wm.add_fileselect(self)
return {'RUNNING_MODAL'}
# operators that use the GUI
class ActiveAssign(bpy.types.Operator):
'''Assign to the active posebone'''
bl_idname = "pose.metarig_assign"
bl_label = "Assign to the active posebone"
@classmethod
def poll(cls, context):
bone = context.active_pose_bone
return bool(bone and bone.id_data.mode == 'POSE')
def execute(self, context):
scene = context.scene
pose_templates = scene.pose_templates
template_name = DATA_PT_template.templates[pose_templates.active_template_index]
context.active_pose_bone["type"] = template_name
return {'FINISHED'}
class ActiveClear(bpy.types.Operator):
'''Clear type from the active posebone'''
bl_idname = "pose.metarig_clear"
bl_label = "Metarig Clear Type"
@classmethod
def poll(cls, context):
bone = context.active_pose_bone
return bool(bone and bone.id_data.mode == 'POSE')
def execute(self, context):
scene = context.scene
try:
del context.active_pose_bone["type"]
except:
return {'CANCELLED'}
return {'FINISHED'}
class INFO_MT_armature_metarig_add(bpy.types.Menu):
bl_idname = "INFO_MT_armature_metarig_add"
bl_label = "Meta-Rig"
def draw(self, context):
import rigify
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
for submodule_type in rigify.get_submodule_types():
text = bpy.path.display_name(submodule_type)
layout.operator("pose.metarig_sample_add", text=text, icon='OUTLINER_OB_ARMATURE').metarig_type = submodule_type
menu_func = (lambda self, context: self.layout.menu("INFO_MT_armature_metarig_add", icon='OUTLINER_OB_ARMATURE'))
import space_info # ensure the menu is loaded first
def register():
bpy.types.Scene.pose_templates = PointerProperty(type=PoseTemplateSettings, name="Pose Templates", description="Pose Template Settings")
space_info.INFO_MT_armature_add.append(menu_func)
def unregister():
del bpy.types.Scene.pose_templates
space_info.INFO_MT_armature_add.remove(menu_func)
if __name__ == "__main__":
register()