Rigify 0.5 general maintenance and bug fixing

This commit is contained in:
Lucio Rossi 2017-06-01 15:24:01 +02:00
parent 21158cf155
commit 5b1b7b9489
13 changed files with 590 additions and 239 deletions

View File

@ -39,6 +39,7 @@ ORG_LAYER = [n == 31 for n in range(0, 32)] # Armature layer that original bone
MCH_LAYER = [n == 30 for n in range(0, 32)] # Armature layer that mechanism bones should be moved to.
DEF_LAYER = [n == 29 for n in range(0, 32)] # Armature layer that deformation bones should be moved to.
ROOT_LAYER = [n == 28 for n in range(0, 32)] # Armature layer that root bone should be moved to.
WGT_LAYERS = [x == 19 for x in range(0, 20)] # Widgets go on the last scene layer.
class Timer:
@ -252,8 +253,11 @@ def generate_rig(context, metarig):
# Create the root bone.
bpy.ops.object.mode_set(mode='EDIT')
root_bone = new_bone(obj, ROOT_NAME)
spread = get_xy_spread(metarig.data.bones) or metarig.data.bones[0].length
spread = float('%.3g' % spread)
scale = spread/0.589
obj.data.edit_bones[root_bone].head = (0, 0, 0)
obj.data.edit_bones[root_bone].tail = (0, 1, 0)
obj.data.edit_bones[root_bone].tail = (0, scale, 0)
obj.data.edit_bones[root_bone].roll = 0
bpy.ops.object.mode_set(mode='OBJECT')
obj.data.bones[root_bone].layers = ROOT_LAYER
@ -273,6 +277,7 @@ def generate_rig(context, metarig):
mesh = bpy.data.meshes.new(wgts_group_name)
wgts_obj = bpy.data.objects.new(wgts_group_name, mesh)
scene.objects.link(wgts_obj)
wgts_obj.layers = WGT_LAYERS
t.tick("Create main WGTS: ")
#----------------------------------
@ -443,6 +448,19 @@ def generate_rig(context, metarig):
# Create Bone Groups
create_bone_groups(obj, metarig)
# Add rig_ui to logic
skip = False
ctrls = obj.game.controllers
for c in ctrls:
if 'Python' in c.name and c.text.name == 'rig_ui.py':
skip = True
break
if not skip:
bpy.ops.logic.controller_add(type='PYTHON', object=obj.name)
ctrl = obj.game.controllers[-1]
ctrl.text = bpy.data.texts['rig_ui.py']
t.tick("The rest: ")
#----------------------------------
# Deconfigure
@ -549,6 +567,16 @@ def get_bone_rigs(obj, bone_name, halt_on_missing=False):
return rigs
def get_xy_spread(bones):
x_max = 0
y_max = 0
for b in bones:
x_max = max((x_max, abs(b.head[0]), abs(b.tail[0])))
y_max = max((y_max, abs(b.head[1]), abs(b.tail[1])))
return max((x_max, y_max))
def param_matches_type(param_name, rig_type):
""" Returns True if the parameter name is consistent with the rig type.
"""

View File

@ -151,7 +151,7 @@ def copy_bone_simple(obj, bone_name, assign_name=''):
edit_bone_1 = obj.data.edit_bones[bone_name]
edit_bone_2 = obj.data.edit_bones.new(assign_name)
bone_name_1 = bone_name
bone_name_2 = edit_bone_2.name
bone_name_2 = edit_bone_2.name
# Copy edit bone attributes
edit_bone_2.layers = list(edit_bone_1.layers)

View File

@ -1191,10 +1191,7 @@ def create(obj):
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
try:
pbone.rigify_parameters.chain_bone_controls = "1, 2, 3"
except AttributeError:
pass
try:
pbone.rigify_parameters.neck_pos = 5
except AttributeError:

View File

@ -1,17 +1,17 @@
import bpy, re
from ..widgets import create_hand_widget, create_gear_widget
from .ui import create_script
from .limb_utils import *
from mathutils import Vector
from ...utils import copy_bone, flip_bone, put_bone, create_cube_widget
from ...utils import strip_org, make_deformer_name, create_widget
from ...utils import create_circle_widget, create_sphere_widget, create_line_widget
from ...utils import MetarigError, make_mechanism_name, org
from ...utils import create_limb_widget, connected_children_names
from ...utils import align_bone_y_axis
from rna_prop_ui import rna_idprop_ui_prop_get
from ..widgets import create_ikarrow_widget
from math import trunc, pi
from .ui import create_script
from .limb_utils import *
from mathutils import Vector
from ...utils import copy_bone, flip_bone, put_bone, create_cube_widget
from ...utils import strip_org, make_deformer_name, create_widget
from ...utils import create_circle_widget, create_sphere_widget, create_line_widget
from ...utils import MetarigError, make_mechanism_name, org
from ...utils import create_limb_widget, connected_children_names
from ...utils import align_bone_y_axis, align_bone_x_axis, align_bone_z_axis
from rna_prop_ui import rna_idprop_ui_prop_get
from ..widgets import create_ikarrow_widget
from math import trunc, pi
extra_script = """
controls = [%s]
@ -19,13 +19,14 @@ ctrl = '%s'
if is_selected( controls ):
layout.prop( pose_bones[ ctrl ], '["%s"]')
layout.prop( pose_bones[ ctrl ], '["%s"]')
if '%s' in pose_bones[ctrl].keys():
layout.prop( pose_bones[ ctrl ], '["%s"]', slider = True )
if '%s' in pose_bones[ctrl].keys():
layout.prop( pose_bones[ ctrl ], '["%s"]', slider = True )
"""
IMPLEMENTATION = True # Include and set True if Rig is just an implementation for a wrapper class
# add_parameters and parameters_ui are unused for implementation classes
IMPLEMENTATION = True # Include and set True if Rig is just an implementation for a wrapper class
# add_parameters and parameters_ui are unused for implementation classes
class Rig:
@ -43,6 +44,7 @@ class Rig:
self.bbones = params.bbones
self.limb_type = params.limb_type
self.rot_axis = params.rotation_axis
self.auto_align_extremity = params.auto_align_extremity
# Assign values to tweak/FK layers props if opted by user
if params.tweak_extra_layers:
@ -55,6 +57,36 @@ class Rig:
else:
self.fk_layers = None
def orient_org_bones(self):
bpy.ops.object.mode_set(mode='EDIT')
eb = self.obj.data.edit_bones
thigh = self.org_bones[0]
org_bones = list(
[thigh] + connected_children_names(self.obj, thigh)
) # All the provided orgs
org_uarm = eb[org_bones[0]]
org_farm = eb[org_bones[1]]
org_hand = eb[org_bones[2]]
if self.rot_axis != 'automatic':
if self.auto_align_extremity:
z_ground_projection = Vector((org_hand.z_axis[0], org_hand.z_axis[1], 0))
align_bone_z_axis(self.obj, org_hand.name, z_ground_projection.normalized())
return
# Orient uarm farm bones
chain_y_axis = org_uarm.y_axis + org_farm.y_axis
chain_rot_axis = org_uarm.y_axis.cross(chain_y_axis).normalized() # ik-plane normal axis (rotation)
align_bone_x_axis(self.obj, org_uarm.name, chain_rot_axis)
align_bone_x_axis(self.obj, org_farm.name, chain_rot_axis)
# Orient hand
align_bone_x_axis(self.obj, org_hand.name, chain_rot_axis)
def create_parent(self):
org_bones = self.org_bones
@ -350,9 +382,9 @@ class Rig:
bpy.ops.object.mode_set(mode ='EDIT')
eb = self.obj.data.edit_bones
ctrl = get_bone_name( org_bones[0], 'ctrl', 'ik' )
mch_ik = get_bone_name( org_bones[0], 'mch', 'ik' )
mch_target = get_bone_name( org_bones[0], 'mch', 'ik_target' )
ctrl = get_bone_name(org_bones[0], 'ctrl', 'ik')
mch_ik = get_bone_name(org_bones[0], 'mch', 'ik')
mch_target = get_bone_name(org_bones[0], 'mch', 'ik_target')
for o, ik in zip( org_bones, [ ctrl, mch_ik, mch_target ] ):
bone = copy_bone( self.obj, o, ik )
@ -370,9 +402,9 @@ class Rig:
eb[ mch_str ].tail = eb[ org_bones[-1] ].head
# Parenting
eb[ ctrl ].parent = eb[ parent ]
eb[ mch_str ].parent = eb[ parent ]
eb[ mch_ik ].parent = eb[ ctrl ]
eb[ctrl].parent = eb[parent]
eb[mch_str].parent = eb[parent]
eb[mch_ik].parent = eb[ctrl]
# Make standard pole target bone
pole_name = get_bone_name(org_bones[0], 'ctrl', 'ik_target')
@ -381,17 +413,25 @@ class Rig:
lo_vector = eb[org_bones[1]].tail - eb[org_bones[1]].head
tot_vector = eb[org_bones[0]].head - eb[org_bones[1]].tail
tot_vector.normalize()
elbow_vector = lo_vector.dot(tot_vector)*tot_vector - lo_vector # elbow_vec as regression of lo on tot
elbow_vector = lo_vector.dot(tot_vector)*tot_vector - lo_vector # elbow_vec as rejection of lo on tot
elbow_vector.normalize()
elbow_vector *= (eb[org_bones[1]].tail - eb[org_bones[0]].head).length
z_vector = eb[org_bones[0]].z_axis + eb[org_bones[1]].z_axis
alfa = elbow_vector.angle(z_vector)
if self.rot_axis == 'x' or self.rot_axis == 'automatic':
z_vector = eb[org_bones[0]].z_axis + eb[org_bones[1]].z_axis
alfa = elbow_vector.angle(z_vector)
elif self.rot_axis == 'z':
x_vector = eb[org_bones[0]].x_axis + eb[org_bones[1]].x_axis
alfa = elbow_vector.angle(x_vector)
if alfa > pi/2:
pole_angle = -pi/2
else:
pole_angle = pi/2
if self.rot_axis == 'z':
pole_angle = 0
eb[pole_target].head = eb[org_bones[0]].tail + elbow_vector
eb[pole_target].tail = eb[pole_target].head - elbow_vector/8
eb[pole_target].roll = 0.0
@ -441,21 +481,28 @@ class Rig:
pb[ ctrl ].ik_stretch = 0.1
# IK constraint Rotation locks
for axis in ['x','y','z']:
if axis != self.rot_axis:
setattr( pb[ mch_ik ], 'lock_ik_' + axis, True )
if self.rot_axis == 'z':
pb[mch_ik].lock_ik_x = True
pb[mch_ik].lock_ik_y = True
else:
pb[mch_ik].lock_ik_y = True
pb[mch_ik].lock_ik_z = True
# Locks and Widget
pb[ ctrl ].lock_rotation = True, False, True
create_ikarrow_widget( self.obj, ctrl, bone_transform_name=None )
pb[ctrl].lock_rotation = True, False, True
if self.rot_axis == 'x' or self.rot_axis == 'automatic':
roll = 0
else:
roll = pi/2
create_ikarrow_widget(self.obj, ctrl, bone_transform_name=None, roll=roll)
create_sphere_widget(self.obj, pole_target, bone_transform_name=None)
create_line_widget(self.obj, vispole)
return {'ctrl': {'limb': ctrl, 'ik_target': pole_target},
'mch_ik': mch_ik,
'mch_target': mch_target,
'mch_str': mch_str,
'visuals': {'vispole': vispole}
'mch_ik': mch_ik,
'mch_target': mch_target,
'mch_str': mch_str,
'visuals': {'vispole': vispole}
}
def create_fk(self, parent):
@ -521,8 +568,8 @@ class Rig:
pb_parent = pb[parent]
# Create ik/fk switch property
pb_parent['IK/FK'] = 0.0
prop = rna_idprop_ui_prop_get(pb_parent, 'IK/FK', create=True)
pb_parent['IK_FK'] = 0.0
prop = rna_idprop_ui_prop_get(pb_parent, 'IK_FK', create=True)
prop["min"] = 0.0
prop["max"] = 1.0
prop["soft_min"] = 0.0
@ -567,8 +614,8 @@ class Rig:
ctrl = copy_bone(self.obj, org_bones[2], ctrl)
# clear parent (so that rigify will parent to root)
eb[ ctrl ].parent = None
eb[ ctrl ].use_connect = False
eb[ctrl].parent = None
eb[ctrl].use_connect = False
# Parent
eb[ bones['ik']['mch_target'] ].parent = eb[ ctrl ]
@ -939,6 +986,9 @@ class Rig:
bpy.ops.object.mode_set(mode='EDIT')
eb = self.obj.data.edit_bones
# Adjust org-bones rotation
self.orient_org_bones()
# Clear parents for org bones
for bone in self.org_bones[1:]:
eb[bone].use_connect = False
@ -968,7 +1018,8 @@ class Rig:
controls_string = ", ".join(["'" + x + "'" for x in controls])
script = create_script(bones, 'arm')
script += extra_script % (controls_string, bones['main_parent'], 'IK_follow', 'pole_follow', 'root/parent', 'root/parent')
script += extra_script % (controls_string, bones['main_parent'], 'IK_follow',
'pole_follow', 'pole_follow', 'root/parent', 'root/parent')
return [script]
@ -979,14 +1030,21 @@ def add_parameters(params):
"""
items = [
('x', 'X', ''),
('y', 'Y', ''),
('z', 'Z', '')
('x', 'X manual', ''),
('z', 'Z manual', ''),
('automatic', 'Automatic', '')
]
params.rotation_axis = bpy.props.EnumProperty(
items = items,
name = "Rotation Axis",
default = 'x'
default = 'automatic'
)
params.auto_align_extremity = bpy.BoolProperty(
name='auto_align_extremity',
default=False,
description="Auto Align Extremity Bone"
)
params.segments = bpy.props.IntProperty(
@ -1033,12 +1091,14 @@ def add_parameters(params):
def parameters_ui(layout, params):
""" Create the ui for the rig parameters."""
# r = layout.row()
# r.prop(params, "limb_type")
r = layout.row()
r.prop(params, "rotation_axis")
if 'auto' not in params.rotation_axis.lower():
r = layout.row()
text = "Auto align Hand"
r.prop(params, "auto_align_extremity", text=text)
r = layout.row()
r.prop(params, "segments")

View File

@ -9,7 +9,7 @@ from ...utils import strip_org, make_deformer_name, create_widget
from ...utils import create_circle_widget, create_sphere_widget, create_line_widget
from ...utils import MetarigError, make_mechanism_name, org
from ...utils import create_limb_widget, connected_children_names
from ...utils import align_bone_y_axis, align_bone_x_axis, align_bone_roll
from ...utils import align_bone_y_axis, align_bone_x_axis, align_bone_z_axis
from rna_prop_ui import rna_idprop_ui_prop_get
from ..widgets import create_ikarrow_widget
from math import trunc, pi
@ -20,13 +20,14 @@ ctrl = '%s'
if is_selected( controls ):
layout.prop( pose_bones[ ctrl ], '["%s"]')
layout.prop( pose_bones[ ctrl ], '["%s"]')
if '%s' in pose_bones[ctrl].keys():
layout.prop( pose_bones[ ctrl ], '["%s"]', slider = True )
if '%s' in pose_bones[ctrl].keys():
layout.prop( pose_bones[ ctrl ], '["%s"]', slider = True )
"""
IMPLEMENTATION = True # Include and set True if Rig is just an implementation for a wrapper class
# add_parameters and parameters_ui are unused for implementation classes
IMPLEMENTATION = True # Include and set True if Rig is just an implementation for a wrapper class
# add_parameters and parameters_ui are unused for implementation classes
class Rig:
@ -44,6 +45,7 @@ class Rig:
self.bbones = params.bbones
self.limb_type = params.limb_type
self.rot_axis = params.rotation_axis
self.auto_align_extremity = params.auto_align_extremity
# Assign values to tweak/FK layers props if opted by user
if params.tweak_extra_layers:
@ -56,6 +58,62 @@ class Rig:
else:
self.fk_layers = None
def orient_org_bones(self):
bpy.ops.object.mode_set(mode='EDIT')
eb = self.obj.data.edit_bones
thigh = self.org_bones[0]
org_bones = list(
[thigh] + connected_children_names(self.obj, thigh)
) # All the provided orgs
# Get heel bone
heel = ''
for b in self.obj.data.bones[org_bones[2]].children:
if not b.use_connect and not b.children:
heel = b.name
if heel:
org_bones.append(heel)
org_thigh = eb[org_bones[0]]
org_shin = eb[org_bones[1]]
org_foot = eb[org_bones[2]]
org_toe = eb[org_bones[3]]
org_heel = eb[org_bones[4]]
foot_projection_on_xy = Vector((org_foot.y_axis[0], org_foot.y_axis[1], 0))
foot_x = foot_projection_on_xy.cross(Vector((0, 0, -1))).normalized()
if self.rot_axis != 'automatic':
# Orient foot and toe
if self.auto_align_extremity:
if self.rot_axis == 'x':
align_bone_x_axis(self.obj, org_foot.name, foot_x)
align_bone_x_axis(self.obj, org_toe.name, -foot_x)
elif self.rot_axis == 'z':
align_bone_z_axis(self.obj, org_foot.name, foot_x)
align_bone_z_axis(self.obj, org_toe.name, -foot_x)
else:
raise MetarigError(message='IK on %s has forbidden rotation axis (Y)' % self.org_bones[0])
return
# Orient thigh and shin bones
chain_y_axis = org_thigh.y_axis + org_shin.y_axis
chain_rot_axis = org_thigh.y_axis.cross(chain_y_axis).normalized() # ik-plane normal axis (rotation)
align_bone_x_axis(self.obj, org_thigh.name, chain_rot_axis)
align_bone_x_axis(self.obj, org_shin.name, chain_rot_axis)
# Orient foot and toe
align_bone_x_axis(self.obj, org_foot.name, foot_x)
align_bone_x_axis(self.obj, org_toe.name, -foot_x)
# Orient heel
align_bone_z_axis(self.obj, org_heel.name, Vector((0, 0, 1)))
def create_parent(self):
org_bones = self.org_bones
@ -351,9 +409,9 @@ class Rig:
bpy.ops.object.mode_set(mode ='EDIT')
eb = self.obj.data.edit_bones
ctrl = get_bone_name( org_bones[0], 'ctrl', 'ik' )
mch_ik = get_bone_name( org_bones[0], 'mch', 'ik' )
mch_target = get_bone_name( org_bones[0], 'mch', 'ik_target' )
ctrl = get_bone_name(org_bones[0], 'ctrl', 'ik')
mch_ik = get_bone_name(org_bones[0], 'mch', 'ik')
mch_target = get_bone_name(org_bones[0], 'mch', 'ik_target')
for o, ik in zip( org_bones, [ ctrl, mch_ik, mch_target ] ):
bone = copy_bone( self.obj, o, ik )
@ -371,9 +429,9 @@ class Rig:
eb[ mch_str ].tail = eb[ org_bones[-1] ].head
# Parenting
eb[ ctrl ].parent = eb[ parent ]
eb[ mch_str ].parent = eb[ parent ]
eb[ mch_ik ].parent = eb[ ctrl ]
eb[ctrl].parent = eb[parent]
eb[mch_str].parent = eb[parent]
eb[mch_ik].parent = eb[ctrl]
# Make standard pole target bone
pole_name = get_bone_name(org_bones[0], 'ctrl', 'ik_target')
@ -382,17 +440,25 @@ class Rig:
lo_vector = eb[org_bones[1]].tail - eb[org_bones[1]].head
tot_vector = eb[org_bones[0]].head - eb[org_bones[1]].tail
tot_vector.normalize()
elbow_vector = lo_vector.dot(tot_vector)*tot_vector - lo_vector # elbow_vec as regression of lo on tot
elbow_vector = lo_vector.dot(tot_vector)*tot_vector - lo_vector # elbow_vec as rejection of lo on tot
elbow_vector.normalize()
elbow_vector *= (eb[org_bones[1]].tail - eb[org_bones[0]].head).length
z_vector = eb[org_bones[0]].z_axis + eb[org_bones[1]].z_axis
alfa = elbow_vector.angle(z_vector)
if self.rot_axis == 'x' or self.rot_axis == 'automatic':
z_vector = eb[org_bones[0]].z_axis + eb[org_bones[1]].z_axis
alfa = elbow_vector.angle(z_vector)
elif self.rot_axis == 'z':
x_vector = eb[org_bones[0]].x_axis + eb[org_bones[1]].x_axis
alfa = elbow_vector.angle(x_vector)
if alfa > pi/2:
pole_angle = -pi/2
else:
pole_angle = pi/2
if self.rot_axis == 'z':
pole_angle = 0
eb[pole_target].head = eb[org_bones[0]].tail + elbow_vector
eb[pole_target].tail = eb[pole_target].head - elbow_vector/8
eb[pole_target].roll = 0.0
@ -442,21 +508,28 @@ class Rig:
pb[ ctrl ].ik_stretch = 0.1
# IK constraint Rotation locks
for axis in ['x','y','z']:
if axis != self.rot_axis:
setattr( pb[ mch_ik ], 'lock_ik_' + axis, True )
if self.rot_axis == 'z':
pb[mch_ik].lock_ik_x = True
pb[mch_ik].lock_ik_y = True
else:
pb[mch_ik].lock_ik_y = True
pb[mch_ik].lock_ik_z = True
# Locks and Widget
pb[ ctrl ].lock_rotation = True, False, True
create_ikarrow_widget( self.obj, ctrl, bone_transform_name=None )
pb[ctrl].lock_rotation = True, False, True
if self.rot_axis == 'x' or self.rot_axis == 'automatic':
roll = 0
else:
roll = pi/2
create_ikarrow_widget(self.obj, ctrl, bone_transform_name=None, roll=roll)
create_sphere_widget(self.obj, pole_target, bone_transform_name=None)
create_line_widget(self.obj, vispole)
return {'ctrl': {'limb': ctrl, 'ik_target': pole_target},
'mch_ik': mch_ik,
'mch_target': mch_target,
'mch_str': mch_str,
'visuals': {'vispole': vispole}
'mch_ik': mch_ik,
'mch_target': mch_target,
'mch_str': mch_str,
'visuals': {'vispole': vispole}
}
def create_fk(self, parent):
@ -522,8 +595,8 @@ class Rig:
pb_parent = pb[parent]
# Create ik/fk switch property
pb_parent['IK/FK'] = 0.0
prop = rna_idprop_ui_prop_get(pb_parent, 'IK/FK', create=True)
pb_parent['IK_FK'] = 0.0
prop = rna_idprop_ui_prop_get(pb_parent, 'IK_FK', create=True)
prop["min"] = 0.0
prop["max"] = 1.0
prop["soft_min"] = 0.0
@ -578,12 +651,12 @@ class Rig:
pole_target = get_bone_name(org_bones[0], 'ctrl', 'ik_target')
# Create IK leg control
ctrl = get_bone_name( org_bones[2], 'ctrl', 'ik' )
ctrl = copy_bone( self.obj, org_bones[2], ctrl )
ctrl = get_bone_name(org_bones[2], 'ctrl', 'ik')
ctrl = copy_bone(self.obj, org_bones[2], ctrl)
# clear parent (so that rigify will parent to root)
eb[ ctrl ].parent = None
eb[ ctrl ].use_connect = False
eb[ctrl].parent = None
eb[ctrl].use_connect = False
# MCH for ik control
ctrl_socket = copy_bone(self.obj, org_bones[2], get_bone_name( org_bones[2], 'mch', 'ik_socket'))
@ -616,18 +689,27 @@ class Rig:
# Create heel ctrl bone
heel = get_bone_name(org_bones[2], 'ctrl', 'heel_ik')
heel = copy_bone( self.obj, org_bones[2], heel )
# orient_bone( self, eb[ heel ], 'y', 0.5 )
heel = copy_bone(self.obj, org_bones[2], heel)
ax = eb[org_bones[2]].head - eb[org_bones[2]].tail
ax[2] = 0
align_bone_y_axis(self.obj, heel, ax)
align_bone_x_axis(self.obj, heel, eb[org_bones[2]].x_axis)
if self.rot_axis == 'x' or self.rot_axis == 'automatic':
align_bone_x_axis(self.obj, heel, eb[org_bones[2]].x_axis)
elif self.rot_axis == 'z':
align_bone_z_axis(self.obj, heel, eb[org_bones[2]].z_axis)
eb[heel].length = eb[org_bones[2]].length / 2
# Reset control position and orientation
l = eb[ctrl].length
orient_bone(self, eb[ctrl], 'y', reverse=True)
eb[ctrl].length = l
if self.rot_axis == 'automatic' or self.auto_align_extremity:
l = eb[ctrl].length
orient_bone(self, eb[ctrl], 'y', reverse=True)
eb[ctrl].length = l
else:
flip_bone(self.obj, ctrl)
eb[ctrl].tail[2] = eb[ctrl].head[2]
eb[ctrl].roll = 0
# Parent
eb[ heel ].use_connect = False
@ -640,32 +722,35 @@ class Rig:
# Get the tmp heel (floating unconnected without children)
tmp_heel = ""
for b in self.obj.data.bones[ org_bones[2] ].children:
for b in self.obj.data.bones[org_bones[2]].children:
if not b.use_connect and not b.children:
tmp_heel = b.name
# roll1 MCH bone
roll1_mch = get_bone_name( tmp_heel, 'mch', 'roll' )
roll1_mch = copy_bone( self.obj, org_bones[2], roll1_mch )
roll1_mch = get_bone_name(tmp_heel, 'mch', 'roll')
roll1_mch = copy_bone(self.obj, org_bones[2], roll1_mch)
# clear parent
eb[ roll1_mch ].use_connect = False
eb[ roll1_mch ].parent = None
eb[roll1_mch].use_connect = False
eb[roll1_mch].parent = None
flip_bone( self.obj, roll1_mch )
align_bone_x_axis(self.obj, roll1_mch, eb[org_bones[2]].x_axis)
flip_bone(self.obj, roll1_mch)
if self.rot_axis == 'x' or self.rot_axis == 'automatic':
align_bone_x_axis(self.obj, roll1_mch, eb[org_bones[2]].x_axis)
elif self.rot_axis == 'z':
align_bone_z_axis(self.obj, roll1_mch, eb[org_bones[2]].z_axis)
# Create 2nd roll mch, and two rock mch bones
roll2_mch = get_bone_name( tmp_heel, 'mch', 'roll' )
roll2_mch = copy_bone( self.obj, org_bones[3], roll2_mch )
roll2_mch = get_bone_name(tmp_heel, 'mch', 'roll')
roll2_mch = copy_bone(self.obj, org_bones[3], roll2_mch)
eb[ roll2_mch ].use_connect = False
eb[ roll2_mch ].parent = None
eb[roll2_mch].use_connect = False
eb[roll2_mch].parent = None
put_bone(
self.obj,
roll2_mch,
( eb[ tmp_heel ].head + eb[ tmp_heel ].tail ) / 2
(eb[tmp_heel].head + eb[tmp_heel].tail) / 2
)
eb[ roll2_mch ].length /= 4
@ -697,6 +782,22 @@ class Rig:
eb[ rock1_mch ].parent = eb[ rock2_mch ]
eb[ rock2_mch ].parent = eb[ ctrl ]
# make mch toe bone
toe = ''
foot = eb[self.org_bones[-1]]
for c in foot.children:
if 'org' in c.name.lower() and c.head == foot.tail:
toe = c.name
if not toe:
raise MetarigError.message("Wrong metarig: can't find ORG-<toe>")
toe_mch = get_bone_name(toe, 'mch')
toe_mch = copy_bone(self.obj, toe, toe_mch)
eb[toe_mch].length /= 3
eb[toe_mch].parent = eb[self.org_bones[2]]
eb[toe].use_connect = False
eb[toe].parent = eb[toe_mch]
# Constrain rock and roll MCH bones
make_constraint( self, roll1_mch, {
'constraint' : 'COPY_ROTATION',
@ -704,32 +805,61 @@ class Rig:
'owner_space' : 'LOCAL',
'target_space' : 'LOCAL'
})
make_constraint( self, roll1_mch, {
'constraint' : 'LIMIT_ROTATION',
'use_limit_x' : True,
'max_x' : math.radians(360),
'owner_space' : 'LOCAL'
})
make_constraint( self, roll2_mch, {
'constraint' : 'COPY_ROTATION',
'subtarget' : heel,
'use_y' : False,
'use_z' : False,
'invert_x' : True,
'owner_space' : 'LOCAL',
'target_space' : 'LOCAL'
})
make_constraint( self, roll2_mch, {
'constraint' : 'LIMIT_ROTATION',
'use_limit_x' : True,
'max_x' : math.radians(360),
'owner_space' : 'LOCAL'
})
if self.rot_axis == 'x'or self.rot_axis == 'automatic':
make_constraint(self, roll1_mch, {
'constraint': 'LIMIT_ROTATION',
'use_limit_x': True,
'max_x': math.radians(360),
'owner_space': 'LOCAL'
})
make_constraint(self, roll2_mch, {
'constraint': 'COPY_ROTATION',
'subtarget': heel,
'use_y': False,
'use_z': False,
'invert_x': True,
'owner_space': 'LOCAL',
'target_space': 'LOCAL'
})
make_constraint(self, roll2_mch, {
'constraint': 'LIMIT_ROTATION',
'use_limit_x': True,
'max_x': math.radians(360),
'owner_space': 'LOCAL'
})
elif self.rot_axis == 'z':
make_constraint(self, roll1_mch, {
'constraint': 'LIMIT_ROTATION',
'use_limit_z': True,
'max_z': math.radians(360),
'owner_space': 'LOCAL'
})
make_constraint(self, roll2_mch, {
'constraint': 'COPY_ROTATION',
'subtarget': heel,
'use_y': False,
'use_x': False,
'invert_z': True,
'owner_space': 'LOCAL',
'target_space': 'LOCAL'
})
make_constraint(self, roll2_mch, {
'constraint': 'LIMIT_ROTATION',
'use_limit_z': True,
'max_z': math.radians(360),
'owner_space': 'LOCAL'
})
pb = self.obj.pose.bones
for i,b in enumerate([ rock1_mch, rock2_mch ]):
head_tail = pb[b].head - pb[tmp_heel].head
if '.L' in b:
if self.rot_axis == 'x'or self.rot_axis == 'automatic':
ik_rot_axis = pb[org_bones[0]].x_axis
elif self.rot_axis == 'z':
ik_rot_axis = pb[org_bones[0]].z_axis
heel_x_orientation = pb[tmp_heel].y_axis.dot(ik_rot_axis)
for i, b in enumerate([rock1_mch, rock2_mch]):
if heel_x_orientation > 0:
if not i:
min_y = 0
max_y = math.radians(360)
@ -761,8 +891,8 @@ class Rig:
'owner_space' : 'LOCAL'
})
# Constrain 4th ORG to roll2 MCH bone
make_constraint( self, org_bones[3], {
# Cns toe_mch to MCH roll2
make_constraint( self, toe_mch, {
'constraint' : 'COPY_TRANSFORMS',
'subtarget' : roll2_mch
})
@ -857,7 +987,10 @@ class Rig:
# Create heel ctrl locks
pb[heel].lock_location = True, True, True
pb[heel].lock_rotation = False, False, True
if self.rot_axis == 'x'or self.rot_axis == 'automatic':
pb[heel].lock_rotation = False, False, True
elif self.rot_axis == 'z':
pb[heel].lock_rotation = True, False, False
pb[heel].lock_scale = True, True, True
# Add ballsocket widget to heel
@ -872,7 +1005,14 @@ class Rig:
toes = copy_bone(self.obj, org_bones[3], toes)
eb[toes].use_connect = False
eb[toes].parent = eb[org_bones[3]]
eb[toes].parent = eb[toe_mch]
# Constrain 4th ORG to toes
make_constraint(self, org_bones[3], {
'constraint': 'COPY_TRANSFORMS',
# 'subtarget' : roll2_mch
'subtarget': toes
})
# Constrain toes def bones
make_constraint(self, bones['def'][-2], {
@ -890,7 +1030,7 @@ class Rig:
# Find IK/FK switch property
pb = self.obj.pose.bones
prop = rna_idprop_ui_prop_get( pb[bones['fk']['ctrl'][-1]], 'IK/FK' )
prop = rna_idprop_ui_prop_get( pb[bones['fk']['ctrl'][-1]], 'IK_FK' )
# Modify rotation mode for ik and tweak controls
pb[bones['ik']['ctrl']['limb']].rotation_mode = 'ZXY'
@ -899,7 +1039,7 @@ class Rig:
pb[b].rotation_mode = 'ZXY'
# Add driver to limit scale constraint influence
b = org_bones[3]
b = toe_mch
drv = pb[b].constraints[-1].driver_add("influence").driver
drv.type = 'AVERAGE'
@ -923,6 +1063,7 @@ class Rig:
bones['ik']['ctrl']['terminal'] += [toes]
bones['ik']['ctrl']['terminal'] += [ heel, ctrl ]
if leg_parent:
bones['ik']['mch_foot'] = [ctrl_socket, ctrl_pole_socket, ctrl_root, ctrl_parent]
else:
@ -1036,11 +1177,11 @@ class Rig:
owner[prop] = True
rna_prop = rna_idprop_ui_prop_get(owner, prop, create=True)
rna_prop["min"] = False
rna_prop["max"] = True
rna_prop["min"] = False
rna_prop["max"] = True
rna_prop["description"] = prop
drv = ctrl.constraints[ 0 ].driver_add("mute").driver
drv = ctrl.constraints[0].driver_add("mute").driver
drv.type = 'AVERAGE'
var = drv.variables.new()
@ -1052,8 +1193,8 @@ class Rig:
drv_modifier = self.obj.animation_data.drivers[-1].modifiers[0]
drv_modifier.mode = 'POLYNOMIAL'
drv_modifier.poly_order = 1
drv_modifier.mode = 'POLYNOMIAL'
drv_modifier.poly_order = 1
drv_modifier.coefficients[0] = 1.0
drv_modifier.coefficients[1] = -1.0
@ -1070,8 +1211,8 @@ class Rig:
drv_modifier = self.obj.animation_data.drivers[-1].modifiers[0]
drv_modifier.mode = 'POLYNOMIAL'
drv_modifier.poly_order = 1
drv_modifier.mode = 'POLYNOMIAL'
drv_modifier.poly_order = 1
drv_modifier.coefficients[0] = 1.0
drv_modifier.coefficients[1] = -1.0
@ -1114,10 +1255,10 @@ class Rig:
if len(ctrl.constraints) > 1:
owner[prop] = 0.0
rna_prop = rna_idprop_ui_prop_get(owner, prop, create=True)
rna_prop["min"] = 0.0
rna_prop["max"] = 1.0
rna_prop["soft_min"] = 0.0
rna_prop["soft_max"] = 1.0
rna_prop["min"] = 0.0
rna_prop["max"] = 1.0
rna_prop["soft_min"] = 0.0
rna_prop["soft_max"] = 1.0
rna_prop["description"] = prop
drv = ctrl.constraints[1].driver_add("influence").driver
@ -1154,6 +1295,9 @@ class Rig:
bpy.ops.object.mode_set(mode='EDIT')
eb = self.obj.data.edit_bones
# Adjust org-bones rotation
self.orient_org_bones()
# Clear parents for org bones
for bone in self.org_bones[1:]:
eb[bone].use_connect = False
@ -1183,7 +1327,8 @@ class Rig:
controls_string = ", ".join(["'" + x + "'" for x in controls])
script = create_script(bones, 'leg')
script += extra_script % (controls_string, bones['main_parent'], 'IK_follow', 'pole_follow', 'root/parent', 'root/parent')
script += extra_script % (controls_string, bones['main_parent'], 'IK_follow',
'pole_follow', 'pole_follow', 'root/parent', 'root/parent')
return [script]
@ -1194,14 +1339,21 @@ def add_parameters(params):
"""
items = [
('x', 'X', ''),
('y', 'Y', ''),
('z', 'Z', '')
('x', 'X manual', ''),
('z', 'Z manual', ''),
('automatic', 'Automatic', '')
]
params.rotation_axis = bpy.props.EnumProperty(
items = items,
name = "Rotation Axis",
default = 'x'
default = 'automatic'
)
params.auto_align_extremity = bpy.props.BoolProperty(
name='auto_align_extremity',
default=False,
description="Auto Align Extremity Bone"
)
params.segments = bpy.props.IntProperty(
@ -1248,12 +1400,14 @@ def add_parameters(params):
def parameters_ui(layout, params):
""" Create the ui for the rig parameters."""
# r = layout.row()
# r.prop(params, "limb_type")
r = layout.row()
r.prop(params, "rotation_axis")
if 'auto' not in params.rotation_axis.lower():
r = layout.row()
text = "Auto align Foot"
r.prop(params, "auto_align_extremity", text=text)
r = layout.row()
r.prop(params, "segments")

View File

@ -7,6 +7,7 @@ from ...utils import strip_org, make_deformer_name, create_widget
from ...utils import create_circle_widget, create_sphere_widget, create_line_widget
from ...utils import MetarigError, make_mechanism_name, org
from ...utils import create_limb_widget, connected_children_names
from ...utils import align_bone_y_axis, align_bone_x_axis, align_bone_z_axis
from rna_prop_ui import rna_idprop_ui_prop_get
from ..widgets import create_ikarrow_widget, create_gear_widget
from ..widgets import create_foot_widget, create_ballsocket_widget
@ -18,13 +19,14 @@ ctrl = '%s'
if is_selected( controls ):
layout.prop( pose_bones[ ctrl ], '["%s"]')
layout.prop( pose_bones[ ctrl ], '["%s"]')
if '%s' in pose_bones[ctrl].keys():
layout.prop( pose_bones[ ctrl ], '["%s"]', slider = True )
if '%s' in pose_bones[ctrl].keys():
layout.prop( pose_bones[ ctrl ], '["%s"]', slider = True )
"""
IMPLEMENTATION = True # Include and set True if Rig is just an implementation for a wrapper class
# add_parameters and parameters_ui are unused for implementation classes
IMPLEMENTATION = True # Include and set True if Rig is just an implementation for a wrapper class
# add_parameters and parameters_ui are unused for implementation classes
class Rig:
@ -42,6 +44,7 @@ class Rig:
self.bbones = params.bbones
self.limb_type = params.limb_type
self.rot_axis = params.rotation_axis
self.auto_align_extremity = params.auto_align_extremity
# Assign values to tweak/FK layers props if opted by user
if params.tweak_extra_layers:
@ -54,6 +57,50 @@ class Rig:
else:
self.fk_layers = None
def orient_org_bones(self):
bpy.ops.object.mode_set(mode='EDIT')
eb = self.obj.data.edit_bones
thigh = self.org_bones[0]
org_bones = list(
[thigh] + connected_children_names(self.obj, thigh)
) # All the provided orgs
org_thigh = eb[org_bones[0]]
org_shin = eb[org_bones[1]]
org_foot = eb[org_bones[2]]
org_toe = eb[org_bones[3]]
foot_projection_on_xy = Vector((org_foot.y_axis[0], org_foot.y_axis[1], 0))
foot_x = foot_projection_on_xy.cross(Vector((0, 0, 1))).normalized()
if self.rot_axis != 'automatic':
# Orient foot and toe
if self.auto_align_extremity:
if self.rot_axis == 'x':
align_bone_x_axis(self.obj, org_foot.name, foot_x)
align_bone_x_axis(self.obj, org_toe.name, foot_x)
elif self.rot_axis == 'z':
align_bone_z_axis(self.obj, org_foot.name, -foot_x)
align_bone_z_axis(self.obj, org_toe.name, -foot_x)
else:
raise MetarigError(message='IK on %s has forbidden rotation axis (Y)' % self.org_bones[0])
return
# Orient thigh and shin bones
chain_y_axis = org_thigh.y_axis + org_shin.y_axis
chain_rot_axis = org_thigh.y_axis.cross(chain_y_axis).normalized() # ik-plane normal axis (rotation)
align_bone_x_axis(self.obj, org_thigh.name, chain_rot_axis)
align_bone_x_axis(self.obj, org_shin.name, chain_rot_axis)
# # Orient foot and toe
align_bone_x_axis(self.obj, org_foot.name, chain_rot_axis)
align_bone_x_axis(self.obj, org_toe.name, chain_rot_axis)
def create_parent(self):
org_bones = self.org_bones
@ -308,11 +355,11 @@ class Rig:
# Rubber hose drivers
pb = self.obj.pose.bones
for i,t in enumerate( tweaks[1:-1] ):
for i, t in enumerate(tweaks[1:-1]):
# Create custom property on tweak bone to control rubber hose
name = 'rubber_tweak'
if i == trunc( len( tweaks[1:-1] ) / 2 ):
if not (i+1) % self.segments:
pb[t][name] = 0.0
else:
pb[t][name] = 1.0
@ -385,17 +432,25 @@ class Rig:
lo_vector = eb[org_bones[1]].tail - eb[org_bones[1]].head
tot_vector = eb[org_bones[0]].head - eb[org_bones[1]].tail
tot_vector.normalize()
elbow_vector = lo_vector.dot(tot_vector)*tot_vector - lo_vector # elbow_vec as regression of lo on tot
elbow_vector = lo_vector.dot(tot_vector)*tot_vector - lo_vector # elbow_vec as rejection of lo on tot
elbow_vector.normalize()
elbow_vector *= (eb[org_bones[1]].tail - eb[org_bones[0]].head).length
z_vector = eb[org_bones[0]].z_axis + eb[org_bones[1]].z_axis
alfa = elbow_vector.angle(z_vector)
if self.rot_axis == 'x' or self.rot_axis == 'automatic':
z_vector = eb[org_bones[0]].z_axis + eb[org_bones[1]].z_axis
alfa = elbow_vector.angle(z_vector)
elif self.rot_axis == 'z':
x_vector = eb[org_bones[0]].x_axis + eb[org_bones[1]].x_axis
alfa = elbow_vector.angle(x_vector)
if alfa > pi/2:
pole_angle = -pi/2
else:
pole_angle = pi/2
if self.rot_axis == 'z':
pole_angle = 0
eb[pole_target].head = eb[org_bones[0]].tail + elbow_vector
eb[pole_target].tail = eb[pole_target].head - elbow_vector/8
eb[pole_target].roll = 0.0
@ -445,21 +500,28 @@ class Rig:
pb[ ctrl ].ik_stretch = 0.1
# IK constraint Rotation locks
for axis in ['x','y','z']:
if axis != self.rot_axis:
setattr( pb[ mch_ik ], 'lock_ik_' + axis, True )
if self.rot_axis == 'z':
pb[mch_ik].lock_ik_x = True
pb[mch_ik].lock_ik_y = True
else:
pb[mch_ik].lock_ik_y = True
pb[mch_ik].lock_ik_z = True
# Locks and Widget
pb[ ctrl ].lock_rotation = True, False, True
create_ikarrow_widget( self.obj, ctrl, bone_transform_name=None )
pb[ctrl].lock_rotation = True, False, True
if self.rot_axis == 'x' or self.rot_axis == 'automatic':
roll = 0
else:
roll = pi/2
create_ikarrow_widget(self.obj, ctrl, bone_transform_name=None, roll=roll)
create_sphere_widget(self.obj, pole_target, bone_transform_name=None)
create_line_widget(self.obj, vispole)
return {'ctrl': {'limb': ctrl, 'ik_target': pole_target},
'mch_ik': mch_ik,
'mch_target': mch_target,
'mch_str': mch_str,
'visuals': {'vispole': vispole}
'mch_ik': mch_ik,
'mch_target': mch_target,
'mch_str': mch_str,
'visuals': {'vispole': vispole}
}
def create_fk(self, parent):
@ -528,8 +590,8 @@ class Rig:
pb_parent = pb[parent]
# Create ik/fk switch property
pb_parent['IK/FK'] = 0.0
prop = rna_idprop_ui_prop_get(pb_parent, 'IK/FK', create=True)
pb_parent['IK_FK'] = 0.0
prop = rna_idprop_ui_prop_get(pb_parent, 'IK_FK', create=True)
prop["min"] = 0.0
prop["max"] = 1.0
prop["soft_min"] = 0.0
@ -575,7 +637,7 @@ class Rig:
# Create IK paw control
ctrl = get_bone_name(org_bones[2], 'ctrl', 'ik')
ctrl = copy_bone(self.obj, org_bones[2], ctrl)
ctrl = copy_bone(self.obj, org_bones[3], ctrl)
# clear parent (so that rigify will parent to root)
eb[ctrl].parent = None
@ -612,7 +674,12 @@ class Rig:
# Create heel ctrl bone
heel = get_bone_name(org_bones[2], 'ctrl', 'heel_ik')
heel = copy_bone( self.obj, org_bones[2], heel )
heel = copy_bone(self.obj, org_bones[2], heel)
if self.rot_axis == 'x' or self.rot_axis == 'automatic':
align_bone_x_axis(self.obj, heel, eb[org_bones[2]].x_axis)
elif self.rot_axis == 'z':
align_bone_z_axis(self.obj, heel, eb[org_bones[2]].z_axis)
# clear parent
eb[ heel ].parent = None
@ -628,9 +695,35 @@ class Rig:
eb[ bones['ik']['mch_target'] ].use_connect = False
# Reset control position and orientation
l = eb[ctrl].length
orient_bone(self, eb[ctrl], 'y', reverse=True)
eb[ctrl].length = eb[org_bones[-1]].length
if self.rot_axis == 'automatic' or self.auto_align_extremity:
orient_bone(self, eb[ctrl], 'y', reverse=True)
else:
flip_bone(self.obj, ctrl)
eb[ctrl].tail[2] = eb[ctrl].head[2]
eb[ctrl].roll = 0
v = eb[org_bones[-1]].tail - eb[org_bones[-2]].head
eb[ctrl].length = Vector((v[0], v[1], 0)).length
# make mch toe bone
toes_mch = get_bone_name(org_bones[3], 'mch')
toes_mch = copy_bone(self.obj, org_bones[3], toes_mch)
eb[toes_mch].use_connect = False
eb[toes_mch].parent = eb[ctrl]
eb[toes_mch].length /= 4
# make mch toe parent bone
toes_mch_parent = get_bone_name(org_bones[3], 'mch', 'parent')
toes_mch_parent = copy_bone(self.obj, org_bones[3], toes_mch_parent)
eb[toes_mch_parent].use_connect = False
eb[toes_mch_parent].parent = eb[org_bones[2]]
eb[toes_mch_parent].length /= 2
eb[org_bones[3]].use_connect = False
eb[org_bones[3]].parent = eb[toes_mch_parent]
# Set up constraints
@ -714,8 +807,8 @@ class Rig:
drv_modifier = self.obj.animation_data.drivers[-1].modifiers[0]
drv_modifier.mode = 'POLYNOMIAL'
drv_modifier.poly_order = 1
drv_modifier.mode = 'POLYNOMIAL'
drv_modifier.poly_order = 1
drv_modifier.coefficients[0] = 1.0
drv_modifier.coefficients[1] = -1.0
@ -723,7 +816,8 @@ class Rig:
create_foot_widget(self.obj, ctrl, bone_transform_name=None)
# Create heel ctrl locks
pb[ heel ].lock_location = True, True, True
pb[heel].lock_location = True, True, True
pb[heel].lock_scale = True, True, True
# Add ballsocket widget to heel
create_ballsocket_widget(self.obj, heel, bone_transform_name=None)
@ -736,24 +830,21 @@ class Rig:
toes = get_bone_name( org_bones[3], 'ctrl' )
toes = copy_bone( self.obj, org_bones[3], toes )
eb[ toes ].use_connect = False
eb[ toes ].parent = eb[ org_bones[3] ]
# Create toes mch bone
toes_mch = get_bone_name( org_bones[3], 'mch' )
toes_mch = copy_bone( self.obj, org_bones[3], toes_mch )
eb[ toes_mch ].use_connect = False
eb[ toes_mch ].parent = eb[ ctrl ]
eb[ toes_mch ].length /= 4
eb[toes].use_connect = False
eb[toes].parent = eb[toes_mch_parent]
# Constrain 4th ORG to toes MCH bone
make_constraint( self, org_bones[3], {
make_constraint( self, toes_mch_parent, {
'constraint' : 'COPY_TRANSFORMS',
'subtarget' : toes_mch
})
# Constrain 4th ORG to toes MCH bone
make_constraint(self, org_bones[3], {
'constraint': 'COPY_TRANSFORMS',
'subtarget': toes
})
make_constraint( self, bones['def'][-1], {
'constraint' : 'DAMPED_TRACK',
'subtarget' : toes,
@ -766,9 +857,8 @@ class Rig:
})
# Find IK/FK switch property
pb = self.obj.pose.bones
#prop = rna_idprop_ui_prop_get( pb[ bones['parent'] ], 'IK/FK' )
prop = rna_idprop_ui_prop_get(pb[bones['fk']['ctrl'][-1]], 'IK/FK')
pb = self.obj.pose.bones
prop = rna_idprop_ui_prop_get( pb[bones['fk']['ctrl'][-1]], 'IK_FK' )
# Modify rotation mode for ik and tweak controls
pb[bones['ik']['ctrl']['limb']].rotation_mode = 'ZXY'
@ -777,8 +867,8 @@ class Rig:
pb[b].rotation_mode = 'ZXY'
# Add driver to limit scale constraint influence
b = org_bones[3]
drv = pb[b].constraints[-1].driver_add("influence").driver
b = toes_mch_parent
drv = pb[b].constraints[-1].driver_add("influence").driver
drv.type = 'AVERAGE'
var = drv.variables.new()
@ -790,15 +880,15 @@ class Rig:
drv_modifier = self.obj.animation_data.drivers[-1].modifiers[0]
drv_modifier.mode = 'POLYNOMIAL'
drv_modifier.poly_order = 1
drv_modifier.mode = 'POLYNOMIAL'
drv_modifier.poly_order = 1
drv_modifier.coefficients[0] = 1.0
drv_modifier.coefficients[1] = -1.0
# Create toe circle widget
create_circle_widget(self.obj, toes, radius=0.4, head_tail=0.5)
bones['ik']['ctrl']['terminal'] += [ toes ]
bones['ik']['ctrl']['terminal'] += [toes]
bones['ik']['ctrl']['terminal'] += [ heel, ctrl ]
@ -915,11 +1005,11 @@ class Rig:
owner[prop] = True
rna_prop = rna_idprop_ui_prop_get(owner, prop, create=True)
rna_prop["min"] = False
rna_prop["max"] = True
rna_prop["min"] = False
rna_prop["max"] = True
rna_prop["description"] = prop
drv = ctrl.constraints[ 0 ].driver_add("mute").driver
drv = ctrl.constraints[0].driver_add("mute").driver
drv.type = 'AVERAGE'
var = drv.variables.new()
@ -931,8 +1021,8 @@ class Rig:
drv_modifier = self.obj.animation_data.drivers[-1].modifiers[0]
drv_modifier.mode = 'POLYNOMIAL'
drv_modifier.poly_order = 1
drv_modifier.mode = 'POLYNOMIAL'
drv_modifier.poly_order = 1
drv_modifier.coefficients[0] = 1.0
drv_modifier.coefficients[1] = -1.0
@ -949,8 +1039,8 @@ class Rig:
drv_modifier = self.obj.animation_data.drivers[-1].modifiers[0]
drv_modifier.mode = 'POLYNOMIAL'
drv_modifier.poly_order = 1
drv_modifier.mode = 'POLYNOMIAL'
drv_modifier.poly_order = 1
drv_modifier.coefficients[0] = 1.0
drv_modifier.coefficients[1] = -1.0
@ -993,10 +1083,10 @@ class Rig:
if len(ctrl.constraints) > 1:
owner[prop] = 0.0
rna_prop = rna_idprop_ui_prop_get(owner, prop, create=True)
rna_prop["min"] = 0.0
rna_prop["max"] = 1.0
rna_prop["soft_min"] = 0.0
rna_prop["soft_max"] = 1.0
rna_prop["min"] = 0.0
rna_prop["max"] = 1.0
rna_prop["soft_min"] = 0.0
rna_prop["soft_max"] = 1.0
rna_prop["description"] = prop
drv = ctrl.constraints[1].driver_add("influence").driver
@ -1033,6 +1123,9 @@ class Rig:
bpy.ops.object.mode_set(mode='EDIT')
eb = self.obj.data.edit_bones
# Adjust org-bones rotation
self.orient_org_bones()
# Clear parents for org bones
for bone in self.org_bones[1:]:
eb[bone].use_connect = False
@ -1062,7 +1155,8 @@ class Rig:
controls_string = ", ".join(["'" + x + "'" for x in controls])
script = create_script(bones, 'paw')
script += extra_script % (controls_string, bones['main_parent'], 'IK_follow', 'pole_follow', 'root/parent','root/parent')
script += extra_script % (controls_string, bones['main_parent'], 'IK_follow',
'pole_follow', 'pole_follow', 'root/parent', 'root/parent')
return [script]
@ -1072,26 +1166,22 @@ def add_parameters(params):
RigifyParameters PropertyGroup
"""
# items = [
# ('arm', 'Arm', ''),
# ('leg', 'Leg', ''),
# ('paw', 'Paw', '')
# ]
# params.limb_type = bpy.props.EnumProperty(
# items = items,
# name = "Limb Type",
# default = 'paw'
# )
items = [
('x', 'X', ''),
('y', 'Y', ''),
('z', 'Z', '')
('x', 'X manual', ''),
('z', 'Z manual', ''),
('automatic', 'Automatic', '')
]
params.rotation_axis = bpy.props.EnumProperty(
items = items,
name = "Rotation Axis",
default = 'x'
default = 'automatic'
)
params.auto_align_extremity = bpy.props.BoolProperty(
name='auto_align_extremity',
default=False,
description="Auto Align Extremity Bone"
)
params.segments = bpy.props.IntProperty(
@ -1138,12 +1228,14 @@ def add_parameters(params):
def parameters_ui(layout, params):
""" Create the ui for the rig parameters."""
# r = layout.row()
# r.prop(params, "limb_type")
r = layout.row()
r.prop(params, "rotation_axis")
if 'auto' not in params.rotation_axis.lower():
r = layout.row()
text = "Auto align Claw"
r.prop(params, "auto_align_extremity", text=text)
r = layout.row()
r.prop(params, "segments")

View File

@ -4,8 +4,8 @@ from .paw import Rig as pawRig
from .paw import parameters_ui
from .paw import add_parameters
IMPLEMENTATION = True # Include and set True if Rig is just an implementation for a wrapper class
# add_parameters and parameters_ui are unused for implementation classes
IMPLEMENTATION = True # Include and set True if Rig is just an implementation for a wrapper class
# add_parameters and parameters_ui are unused for implementation classes
class Rig(pawRig):

View File

@ -34,6 +34,7 @@ def add_parameters(params):
('leg', 'Leg', ''),
('paw', 'Paw', '')
]
params.limb_type = bpy.props.EnumProperty(
items = items,
name = "Limb Type",
@ -41,14 +42,21 @@ def add_parameters(params):
)
items = [
('x', 'X', ''),
('y', 'Y', ''),
('z', 'Z', '')
('x', 'X manual', ''),
('z', 'Z manual', ''),
('automatic', 'Automatic', '')
]
params.rotation_axis = bpy.props.EnumProperty(
items = items,
name = "Rotation Axis",
default = 'x'
default = 'automatic'
)
params.auto_align_extremity = bpy.props.BoolProperty(
name='auto_align_extremity',
default=False,
description="Auto Align Extremity Bone"
)
params.segments = bpy.props.IntProperty(
@ -97,10 +105,16 @@ def parameters_ui(layout, params):
r = layout.row()
r.prop(params, "limb_type")
r = layout.row()
r.prop(params, "rotation_axis")
if 'auto' not in params.rotation_axis.lower():
r = layout.row()
etremities = {'arm': 'Hand', 'leg': 'Foot', 'paw': 'Claw'}
text = "Auto align " + etremities[params.limb_type]
r.prop(params, "auto_align_extremity", text=text)
r = layout.row()
r.prop(params, "segments")

View File

@ -126,7 +126,7 @@ def create_script( bones, limb_type=None):
bones['main_parent'],
bones['fk']['ctrl'][-1],
pole,
'IK/FK',
'IK_FK',
'rubber_tweak',
'IK_Stretch',
'pole_vector',
@ -142,7 +142,7 @@ def create_script( bones, limb_type=None):
bones['main_parent'],
bones['fk']['ctrl'][-1],
pole,
'IK/FK',
'IK_FK',
'rubber_tweak',
'IK_Stretch',
'pole_vector',
@ -158,7 +158,7 @@ def create_script( bones, limb_type=None):
bones['main_parent'],
bones['fk']['ctrl'][-1],
pole,
'IK/FK',
'IK_FK',
'rubber_tweak',
'IK_Stretch',
'pole_vector',

View File

@ -1181,10 +1181,7 @@ def create_sample(obj):
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
try:
pbone.rigify_parameters.chain_bone_controls = "1, 2, 3"
except AttributeError:
pass
try:
pbone.rigify_parameters.neck_pos = 5
except AttributeError:

View File

@ -1,6 +1,7 @@
import bpy
import importlib
import importlib
from mathutils import Matrix
from ..utils import create_widget
WGT_LAYERS = [x == 19 for x in range(0, 20)] # Widgets go on the last scene layer.
@ -97,7 +98,7 @@ def create_face_widget(rig, bone_name, size=1.0, bone_transform_name=None):
return None
def create_ikarrow_widget(rig, bone_name, size=1.0, bone_transform_name=None):
def create_ikarrow_widget(rig, bone_name, size=1.0, bone_transform_name=None, roll=0):
obj = create_widget(rig, bone_name, bone_transform_name)
if obj is not None:
verts = [(0.10000000149011612*size, 0.0*size, -0.30000001192092896*size), (0.10000000149011612*size, 0.699999988079071*size, -0.30000001192092896*size), (-0.10000000149011612*size, 0.0*size, -0.30000001192092896*size), (-0.10000000149011612*size, 0.699999988079071*size, -0.30000001192092896*size), (0.20000000298023224*size, 0.699999988079071*size, -0.30000001192092896*size), (0.0*size, 1.0*size, -0.30000001192092896*size), (-0.20000000298023224*size, 0.699999988079071*size, -0.30000001192092896*size), (0.10000000149011612*size, 0.0*size, 0.30000001192092896*size), (0.10000000149011612*size, 0.699999988079071*size, 0.30000001192092896*size), (-0.10000000149011612*size, 0.0*size, 0.30000001192092896*size), (-0.10000000149011612*size, 0.699999988079071*size, 0.30000001192092896*size), (0.20000000298023224*size, 0.699999988079071*size, 0.30000001192092896*size), (0.0*size, 1.0*size, 0.30000001192092896*size), (-0.20000000298023224*size, 0.699999988079071*size, 0.30000001192092896*size), ]
@ -107,6 +108,10 @@ def create_ikarrow_widget(rig, bone_name, size=1.0, bone_transform_name=None):
mesh = obj.data
mesh.from_pydata(verts, edges, faces)
mesh.update()
if roll != 0:
rot_mat = Matrix.Rotation(roll, 4, 'Y')
mesh.transform(rot_mat)
return obj
else:
return None

View File

@ -597,6 +597,7 @@ class Generate(bpy.types.Operator):
bl_idname = "pose.rigify_generate"
bl_label = "Rigify Generate Rig"
bl_options = {'UNDO'}
bl_description = 'Generates a rig from the active metarig armature'
def execute(self, context):
import importlib

View File

@ -137,6 +137,7 @@ def insert_before_lr(name, text):
#=======================
# Bone manipulation
#=======================
def new_bone(obj, bone_name):
""" Adds a new bone to the given armature object.
Returns the resulting bone's name.
@ -457,6 +458,7 @@ def create_cube_widget(rig, bone_name, radius=0.5, bone_transform_name=None):
mesh.from_pydata(verts, edges, [])
mesh.update()
def create_chain_widget(rig, bone_name, radius=0.5, invert=False, bone_transform_name=None):
"""Creates a basic chain widget
"""
@ -473,6 +475,7 @@ def create_chain_widget(rig, bone_name, radius=0.5, invert=False, bone_transform
mesh.from_pydata(verts, edges, [])
mesh.update()
def create_sphere_widget(rig, bone_name, bone_transform_name=None):
""" Creates a basic sphere widget, three pependicular overlapping circles.
"""
@ -835,7 +838,7 @@ def write_metarig(obj, layers=False, func_name="create"):
code.append(" pbone.bone.layers = %s" % str(list(pbone.bone.layers)))
# Rig type parameters
for param_name in pbone.rigify_parameters.keys():
param = getattr(pbone.rigify_parameters, param_name)
param = getattr(pbone.rigify_parameters, param_name, '')
if str(type(param)) == "<class 'bpy_prop_array'>":
param = list(param)
if type(param) == str: