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

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'rigify/rigs/limbs/leg.py')
-rw-r--r--rigify/rigs/limbs/leg.py1248
1 files changed, 196 insertions, 1052 deletions
diff --git a/rigify/rigs/limbs/leg.py b/rigify/rigs/limbs/leg.py
index 59e6f799..098d303a 100644
--- a/rigify/rigs/limbs/leg.py
+++ b/rigify/rigs/limbs/leg.py
@@ -1,1134 +1,280 @@
-
-import bpy, math
-from ..widgets import create_foot_widget, create_ballsocket_widget, create_gear_widget
-from .ui import create_script
-from .limb_utils import *
+#====================== 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
+import math
+
+from itertools import count
from mathutils import Vector
-from ...utils import copy_bone, flip_bone, put_bone
-from ...utils import strip_org, strip_mch
-from ...utils import create_circle_widget, create_sphere_widget, create_line_widget
-from ...utils import MetarigError, make_mechanism_name
-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 ...rig_ui_template import UTILITIES_RIG_LEG, REGISTER_RIG_LEG
-from ...utils import ControlLayersOption
-from rna_prop_ui import rna_idprop_ui_prop_get
-from ...utils.mechanism import make_property, make_driver
-from ..widgets import create_ikarrow_widget
-from math import trunc, pi
-from ...utils.switch_parent import SwitchParentBuilder
+from ...utils.rig import is_rig_base_bone
+from ...utils.bones import align_chain_x_axis, align_bone_x_axis, align_bone_y_axis, align_bone_z_axis
+from ...utils.bones import align_bone_to_axis, flip_bone, put_bone, align_bone_orientation
+from ...utils.naming import make_derived_name
+from ...utils.misc import map_list
+from ..widgets import create_foot_widget, create_ballsocket_widget
-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
+from ...base_rig import stage
+from .limb_rigs import BaseLimbRig
-class Rig:
- def __init__(self, obj, bone_name, params):
- """ Initialize leg rig and key rig properties """
- self.obj = obj
- self.params = params
+DEG_360 = math.pi * 2
+ALL_TRUE = (True, True, True)
- self.org_bones = list(
- [bone_name] + connected_children_names(obj, bone_name)
- )[:3] # The basic limb is the first 3 bones
- self.segments = params.segments
- self.bbones = params.bbones
- self.limb_type = params.limb_type
- self.rot_axis = params.rotation_axis
- self.auto_align_extremity = params.auto_align_extremity
+class Rig(BaseLimbRig):
+ """Human leg rig."""
+ def find_org_bones(self, bone):
+ bones = super().find_org_bones(bone)
- def orient_org_bones(self):
+ for b in self.get_bone(bones.main[2]).bone.children:
+ if not b.use_connect and not b.children and not is_rig_base_bone(self.obj, b.name):
+ bones.heel = b.name
+ break
+ else:
+ self.raise_error("Heel bone not found.")
- bpy.ops.object.mode_set(mode='EDIT')
- eb = self.obj.data.edit_bones
+ return bones
- thigh = self.org_bones[0]
- org_bones = list(
- [thigh] + connected_children_names(self.obj, thigh)
- ) # All the provided orgs
+ def initialize(self):
+ if len(self.bones.org.main) != 4:
+ self.raise_error("Input to rig type must be a chain of 4 bones.")
- # 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)
+ super().initialize()
- 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]]
+ def prepare_bones(self):
+ orgs = self.bones.org.main
- 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()
+ foot_x = self.vector_without_z(self.get_bone(orgs[2]).y_axis).cross((0, 0, -1))
- if self.rot_axis != 'automatic':
+ if self.params.rotation_axis == 'automatic':
+ align_chain_x_axis(self.obj, orgs[0:2])
# 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
-
- bpy.ops.object.mode_set(mode='EDIT')
- eb = self.obj.data.edit_bones
+ align_bone_x_axis(self.obj, orgs[2], foot_x)
+ align_bone_x_axis(self.obj, orgs[3], -foot_x)
- name = get_bone_name( strip_org( org_bones[0] ), 'mch', 'parent' )
+ align_bone_x_axis(self.obj, self.bones.org.heel, Vector((0, 0, 1)))
- mch = copy_bone( self.obj, org_bones[0], name )
- orient_bone( self, eb[mch], 'y' )
- eb[ mch ].length = eb[ org_bones[0] ].length / 4
-
- eb[ mch ].parent = eb[ org_bones[0] ].parent
-
- eb[ mch ].roll = 0.0
-
- # Add non-MCH main limb control
- name = get_bone_name(strip_org(org_bones[0]), 'ctrl', 'parent')
- main_parent = copy_bone(self.obj, org_bones[0], name)
- eb[main_parent].length = eb[org_bones[0]].length / 4
- eb[main_parent].parent = eb[org_bones[0]]
- eb[main_parent].roll = 0.0
-
- # Constraints
- make_constraint( self, mch, {
- 'constraint' : 'COPY_ROTATION',
- 'subtarget' : 'root'
- })
-
- make_constraint( self, mch, {
- 'constraint' : 'COPY_SCALE',
- 'subtarget' : 'root'
- })
-
- # Limb Follow Driver
- pb = self.obj.pose.bones
-
- name = 'FK_limb_follow'
-
- # pb[ mch ][ name ] = 0.0
- # prop = rna_idprop_ui_prop_get( pb[ mch ], name, create = True )
- make_property(pb[main_parent], name, 0.0)
-
- make_driver(pb[mch].constraints[0], "influence", variables=[(self.obj, main_parent, name)])
-
- size = pb[main_parent].bone.y_axis.length * 10
- create_gear_widget(self.obj, main_parent, size=size, bone_transform_name=None)
-
- return [mch, main_parent]
-
- def create_tweak(self):
- org_bones = self.org_bones
-
- bpy.ops.object.mode_set(mode ='EDIT')
- eb = self.obj.data.edit_bones
-
- tweaks = {}
- tweaks['ctrl'] = []
- tweaks['mch' ] = []
-
- # Create and parent mch and ctrl tweaks
- for i,org in enumerate(org_bones):
- if i < len(org_bones) - 1:
- # Create segments if specified
- for j in range( self.segments ):
- # MCH
- name = get_bone_name( strip_org(org), 'mch', 'tweak' )
- mch = copy_bone( self.obj, org, name )
-
- # CTRL
- name = get_bone_name( strip_org(org), 'ctrl', 'tweak' )
- ctrl = copy_bone( self.obj, org, name )
-
- eb[ mch ].length /= self.segments
- eb[ ctrl ].length /= self.segments
-
- # If we have more than one segments, place the head of the
- # 2nd and onwards at the correct position
- if j > 0:
- put_bone(self.obj, mch, eb[ tweaks['mch' ][-1] ].tail)
- put_bone(self.obj, ctrl, eb[ tweaks['ctrl'][-1] ].tail)
-
- tweaks['ctrl'] += [ ctrl ]
- tweaks['mch' ] += [ mch ]
-
- # Parenting the tweak ctrls to mchs
- eb[ mch ].parent = eb[ org ]
- eb[ ctrl ].parent = eb[ mch ]
-
- else: # Last limb bone - is not subdivided
- name = get_bone_name( strip_org(org), 'mch', 'tweak' )
- mch = copy_bone( self.obj, org_bones[i-1], name )
- eb[ mch ].length = eb[org].length / 4
- put_bone(
- self.obj,
- mch,
- eb[org_bones[i-1]].tail
- )
-
- ctrl = get_bone_name( strip_org(org), 'ctrl', 'tweak' )
- ctrl = copy_bone( self.obj, org, ctrl )
- eb[ ctrl ].length = eb[org].length / 2
-
- tweaks['mch'] += [ mch ]
- tweaks['ctrl'] += [ ctrl ]
-
- # Parenting the tweak ctrls to mchs
- eb[ mch ].parent = eb[ org ]
- eb[ ctrl ].parent = eb[ mch ]
-
- # Scale to reduce widget size and maintain conventions!
- for mch, ctrl in zip( tweaks['mch'], tweaks['ctrl'] ):
- eb[ mch ].length /= 4
- eb[ ctrl ].length /= 2
-
- # Constraints
-
- for i,b in enumerate( tweaks['mch'] ):
- first = 0
- middle = trunc( len( tweaks['mch'] ) / 2 )
- last = len( tweaks['mch'] ) - 1
-
- if i == first or i == middle:
- make_constraint( self, b, {
- 'constraint' : 'COPY_SCALE',
- 'subtarget' : 'root'
- })
- elif i != last:
- targets = []
- dt_target_idx = middle
- factor = 0
- if i < middle:
- targets = [first,middle]
- else:
- targets = [middle,last]
- factor = self.segments
- dt_target_idx = last
-
- # Use copy transforms constraints to position each bone
- # exactly in the location respective to its index (between
- # the two edges)
- make_constraint( self, b, {
- 'constraint' : 'COPY_TRANSFORMS',
- 'subtarget' : tweaks['ctrl'][targets[0]]
- })
- make_constraint( self, b, {
- 'constraint' : 'COPY_TRANSFORMS',
- 'subtarget' : tweaks['ctrl'][targets[1]],
- 'influence' : (i - factor) / self.segments
- })
- make_constraint( self, b, {
- 'constraint' : 'DAMPED_TRACK',
- 'subtarget' : tweaks['ctrl'][ dt_target_idx ],
- })
-
- # Ctrl bones Locks and Widgets
- pb = self.obj.pose.bones
- for t in tweaks['ctrl']:
- pb[t].lock_rotation = True, False, True
- pb[t].lock_scale = False, True, False
-
- create_sphere_widget(self.obj, t, bone_transform_name=None)
-
- ControlLayersOption.TWEAK.assign(self.params, pb, tweaks['ctrl'])
-
- return tweaks
-
- def create_def(self, tweaks):
- org_bones = self.org_bones
-
- bpy.ops.object.mode_set(mode ='EDIT')
- eb = self.obj.data.edit_bones
-
- def_bones = []
- for i, org in enumerate(org_bones):
- if i < len(org_bones) - 1:
- # Create segments if specified
- for j in range(self.segments):
- name = get_bone_name(strip_org(org), 'def')
- def_name = copy_bone(self.obj, org, name)
-
- eb[def_name].length /= self.segments
-
- # If we have more than one segments, place the 2nd and
- # onwards on the tail of the previous bone
- if j > 0:
- put_bone(self.obj, def_name, eb[ def_bones[-1] ].tail)
-
- def_bones += [def_name]
- else:
- name = get_bone_name(strip_org(org), 'def')
- def_name = copy_bone(self.obj, org, name)
- def_bones.append(def_name)
-
- # Parent deform bones
- for i,b in enumerate( def_bones ):
- if i > 0: # For all bones but the first (which has no parent)
- eb[b].parent = eb[ def_bones[i-1] ] # to previous
- eb[b].use_connect = True
-
- # Constraint def to tweaks
- for d,t in zip(def_bones, tweaks):
- tidx = tweaks.index(t)
-
- make_constraint( self, d, {
- 'constraint' : 'COPY_TRANSFORMS',
- 'subtarget' : t
- })
-
- if tidx != len(tweaks) - 1:
- make_constraint( self, d, {
- 'constraint' : 'DAMPED_TRACK',
- 'subtarget' : tweaks[ tidx + 1 ],
- })
-
- make_constraint( self, d, {
- 'constraint' : 'STRETCH_TO',
- 'subtarget' : tweaks[ tidx + 1 ],
- })
-
- # Create bbone segments
- for bone in def_bones[:-1]:
- self.obj.data.bones[bone].bbone_segments = self.bbones
-
- self.obj.data.bones[ def_bones[0] ].bbone_easein = 0.0
- self.obj.data.bones[ def_bones[-2] ].bbone_easeout = 0.0
- self.obj.data.bones[ def_bones[-1] ].bbone_easein = 0.0
- self.obj.data.bones[ def_bones[-1] ].bbone_easeout = 0.0
-
-
- # Rubber hose drivers
- pb = self.obj.pose.bones
- 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 ):
- defval = 0.0
+ elif self.params.auto_align_extremity:
+ if self.main_axis == 'x':
+ align_bone_x_axis(self.obj, orgs[2], foot_x)
+ align_bone_x_axis(self.obj, orgs[3], -foot_x)
else:
- defval = 1.0
-
- make_property(pb[t], name, defval, max=2.0, soft_max=1.0)
-
- for j,d in enumerate(def_bones[:-1]):
- if j != 0:
- make_driver(self.obj.data.bones[d], "bbone_easein", variables=[(self.obj, tweaks[j], 'rubber_tweak')])
-
- if j != len( def_bones[:-1] ) - 1:
- make_driver(self.obj.data.bones[d], "bbone_easeout", variables=[(self.obj, tweaks[j+1], 'rubber_tweak')])
-
- return def_bones
-
- def create_ik(self, parent):
- org_bones = self.org_bones
+ align_bone_z_axis(self.obj, orgs[2], foot_x)
+ align_bone_z_axis(self.obj, orgs[3], -foot_x)
- 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')
+ ####################################################
+ # EXTRA BONES
+ #
+ # org:
+ # heel:
+ # Heel location marker bone
+ # ctrl:
+ # heel:
+ # Foot roll control
+ # mch:
+ # heel[]:
+ # Chain of bones implementing foot roll.
+ #
+ ####################################################
- for o, ik in zip(org_bones, [ctrl, mch_ik, mch_target]):
- bone = copy_bone(self.obj, o, ik)
+ ####################################################
+ # IK controls
- if org_bones.index(o) == len(org_bones) - 1:
- eb[bone].length /= 4
+ def get_extra_ik_controls(self):
+ return [self.bones.ctrl.heel]
- # Create MCH Stretch
- mch_str = copy_bone(
- self.obj,
- org_bones[0],
- get_bone_name( org_bones[0], 'mch', 'ik_stretch' )
- )
+ def make_ik_control_bone(self, orgs):
+ name = self.copy_bone(orgs[2], make_derived_name(orgs[2], 'ctrl', '_ik'))
- eb[ mch_str ].tail = eb[ org_bones[-1] ].head
+ if self.params.rotation_axis == 'automatic' or self.params.auto_align_extremity:
+ align_bone_to_axis(self.obj, name, 'y', flip=True)
- # Parenting
- 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')
- pole_target = copy_bone(self.obj, org_bones[0], pole_name)
-
- 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 rejection of lo on tot
- elbow_vector.normalize()
- elbow_vector *= (eb[org_bones[1]].tail - eb[org_bones[0]].head).length
-
- 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
-
- # Make visual pole
- vispole_name = 'VIS_' + get_bone_name(org_bones[0], 'ctrl', 'ik_pole')
- vispole = copy_bone(self.obj, org_bones[1], vispole_name)
- eb[vispole].tail = eb[vispole].head + Vector((0.0, 0.0, eb[org_bones[1]].length/10))
- eb[vispole].use_connect = False
- eb[vispole].hide_select = True
- eb[vispole].parent = None
-
- make_constraint(self, mch_ik, {
- 'constraint': 'IK',
- 'subtarget': mch_target,
- 'chain_count': 2,
- })
-
- make_constraint(self, mch_ik, { # 2_nd IK for pole targeted chain
- 'constraint': 'IK',
- 'subtarget': mch_target,
- 'chain_count': 2,
- })
-
- # VIS pole constraints
- make_constraint(self, vispole, {
- 'constraint': 'COPY_LOCATION',
- 'name': 'copy_loc',
- 'subtarget': org_bones[1],
- })
-
- pb = self.obj.pose.bones
-
- make_constraint(self, vispole, {
- 'constraint': 'STRETCH_TO',
- 'name': 'stretch_to',
- 'subtarget': pole_target,
- 'volume': 'NO_VOLUME',
- 'rest_length': pb[vispole].length
- })
-
- pb[mch_ik].constraints[-1].pole_target = self.obj
- pb[mch_ik].constraints[-1].pole_subtarget = pole_target
- pb[mch_ik].constraints[-1].pole_angle = pole_angle
-
- pb[ mch_ik ].ik_stretch = 0.1
- pb[ ctrl ].ik_stretch = 0.1
-
- # IK constraint Rotation locks
- 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
- 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}
- }
-
- def create_fk(self, parent):
- org_bones = self.org_bones.copy()
-
- bpy.ops.object.mode_set(mode='EDIT')
- eb = self.obj.data.edit_bones
-
- ctrls = []
-
- for o in org_bones:
- bone = copy_bone(self.obj, o, get_bone_name( o, 'ctrl', 'fk'))
- ctrls.append(bone)
-
- # MCH
- mch = copy_bone(
- self.obj, org_bones[-1], get_bone_name(o, 'mch', 'fk')
- )
-
- eb[mch].length /= 4
-
- # Parenting
- eb[ctrls[0]].parent = eb[parent]
- eb[ctrls[1]].parent = eb[ctrls[0]]
- eb[ctrls[1]].use_connect = True
- eb[ctrls[2]].parent = eb[mch]
- eb[mch].parent = eb[ctrls[1]]
- eb[mch].use_connect = True
-
- # Constrain MCH's scale to root
- make_constraint(self, mch, {
- 'constraint': 'COPY_SCALE',
- 'subtarget': 'root'
- })
-
- # Locks and widgets
- pb = self.obj.pose.bones
- pb[ctrls[2]].lock_location = True, True, True
-
- create_limb_widget(self.obj, ctrls[0])
- create_limb_widget(self.obj, ctrls[1])
-
- create_circle_widget(self.obj, ctrls[2], radius=0.4, head_tail=0.0)
-
- ControlLayersOption.FK.assign(self.params, pb, ctrls)
-
- return {'ctrl': ctrls, 'mch': mch}
-
- def org_parenting_and_switch(self, org_bones, ik, fk, parent):
- bpy.ops.object.mode_set(mode='EDIT')
- eb = self.obj.data.edit_bones
- # re-parent ORGs in a connected chain
- for i, o in enumerate(org_bones):
- if i > 0:
- eb[o].parent = eb[org_bones[i-1]]
- if i <= len(org_bones)-1:
- eb[o].use_connect = True
-
- bpy.ops.object.mode_set(mode='OBJECT')
- pb = self.obj.pose.bones
- pb_parent = pb[parent]
-
- # Create ik/fk switch property
- prop = make_property(pb_parent, 'IK_FK', 0.0, description='IK/FK Switch')
-
- # Constrain org to IK and FK bones
- iks = [ik['ctrl']['limb']]
- iks += [ik[k] for k in ['mch_ik', 'mch_target']]
-
- for o, i, f in zip(org_bones, iks, fk):
- make_constraint( self, o, {
- 'constraint': 'COPY_TRANSFORMS',
- 'subtarget': i
- })
- make_constraint(self, o, {
- 'constraint': 'COPY_TRANSFORMS',
- 'subtarget': f
- })
-
- # Add driver to relevant constraint
- make_driver(pb[o].constraints[-1], "influence", variables=[(self.obj, pb_parent, prop.name)])
-
- def create_leg(self, bones):
- org_bones = list(
- [self.org_bones[0]] + connected_children_names(self.obj, self.org_bones[0])
- )
-
- bones['ik']['ctrl']['terminal'] = []
-
- bpy.ops.object.mode_set(mode='EDIT')
- eb = self.obj.data.edit_bones
-
- # Create toes def bone
- toes_def = get_bone_name(org_bones[-1], 'def')
- toes_def = copy_bone( self.obj, org_bones[-1], toes_def )
-
- eb[ toes_def ].use_connect = False
- eb[ toes_def ].parent = eb[ bones['def'][-1] ]
- eb[ toes_def ].use_connect = True
-
- bones['def'] += [ toes_def ]
-
- 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)
-
- # clear parent (so that rigify will parent to root)
- eb[ctrl].parent = None
- eb[ctrl].use_connect = False
-
- mch_name = get_bone_name(strip_org(org_bones[0]), 'mch', 'parent_socket')
- mch_main_parent = copy_bone(self.obj, org_bones[0], mch_name)
- eb[mch_main_parent].length = eb[org_bones[0]].length / 12
- eb[mch_main_parent].parent = eb[bones['parent']]
- eb[mch_main_parent].roll = 0.0
- eb[bones['main_parent']].parent = eb[mch_main_parent]
-
- # Create heel ctrl bone
- heel = get_bone_name(org_bones[2], 'ctrl', 'heel_ik')
- 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)
- 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
- 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
-
- # Switchable parent
- pbuilder = SwitchParentBuilder(self.rigify_generator)
+ flip_bone(self.obj, name)
- if eb[org_bones[0]].parent:
- pbuilder.register_parent(self.rigify_wrapper, eb[org_bones[0]].parent.name)
-
- pbuilder.register_parent(self.rigify_wrapper, org_bones[2], exclude_self=True)
-
- pcontrols = [ bones['main_parent'], bones['ik']['ctrl']['limb'], heel, ctrl, pole_target ]
-
- pbuilder.build_child(
- self.rigify_wrapper, ctrl,
- prop_bone=bones['main_parent'], prop_id='IK_parent', prop_name='IK Parent', controls=pcontrols,
- )
-
- pbuilder.build_child(
- self.rigify_wrapper, pole_target, extra_parents=[(bones['ik']['mch_target'], ctrl)],
- prop_bone=bones['main_parent'], prop_id='pole_parent', prop_name='Pole Parent', controls=pcontrols,
- no_fix_rotation=True, no_fix_scale=True
- )
-
- # Parent
- eb[ heel ].use_connect = False
- eb[ heel ].parent = eb[ ctrl ]
-
- eb[ bones['ik']['mch_target'] ].parent = eb[ heel ]
- eb[ bones['ik']['mch_target'] ].use_connect = False
-
- # Create foot mch rock and roll bones
-
- # Get the tmp heel (floating unconnected without children)
- tmp_heel = ""
- 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)
-
- # clear parent
- eb[roll1_mch].use_connect = False
- eb[roll1_mch].parent = None
-
- 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)
-
- 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[ roll2_mch ].length /= 4
-
- # Rock MCH bones
- rock1_mch = get_bone_name( tmp_heel, 'mch', 'rock' )
- rock1_mch = copy_bone( self.obj, tmp_heel, rock1_mch )
-
- eb[ rock1_mch ].use_connect = False
- eb[ rock1_mch ].parent = None
-
- orient_bone( self, eb[ rock1_mch ], 'y', 1.0, reverse = True )
- align_bone_y_axis(self.obj, rock1_mch, ax)
- eb[ rock1_mch ].length = eb[ tmp_heel ].length / 2
-
- rock2_mch = get_bone_name( tmp_heel, 'mch', 'rock' )
- rock2_mch = copy_bone( self.obj, tmp_heel, rock2_mch )
-
- eb[ rock2_mch ].use_connect = False
- eb[ rock2_mch ].parent = None
-
- #orient_bone( self, eb[ rock2_mch ], 'y', 1.0 )
- align_bone_y_axis(self.obj, rock2_mch, ax)
- eb[ rock2_mch ].length = eb[ tmp_heel ].length / 2
-
- # Parent rock and roll MCH bones
- eb[ roll1_mch ].parent = eb[ roll2_mch ]
- eb[ roll2_mch ].parent = eb[ rock1_mch ]
- 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',
- 'subtarget' : heel,
- 'owner_space' : 'LOCAL',
- 'target_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
- 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)
- else:
- min_y = math.radians(-360)
- max_y = 0
- else:
- if not i:
- min_y = math.radians(-360)
- max_y = 0
- else:
- min_y = 0
- max_y = math.radians(360)
-
-
- make_constraint( self, b, {
- 'constraint' : 'COPY_ROTATION',
- 'subtarget' : heel,
- 'use_x' : False,
- 'use_z' : False,
- 'owner_space' : 'LOCAL',
- 'target_space' : 'LOCAL'
- })
- make_constraint( self, b, {
- 'constraint' : 'LIMIT_ROTATION',
- 'use_limit_y' : True,
- 'min_y' : min_y,
- 'max_y' : max_y,
- 'owner_space' : 'LOCAL'
- })
-
- # Cns toe_mch to MCH roll2
- make_constraint( self, toe_mch, {
- 'constraint' : 'COPY_TRANSFORMS',
- 'subtarget' : roll2_mch
- })
-
- # Set up constraints
-
- # Constrain mch target bone to the ik control and mch stretch
- make_constraint( self, bones['ik']['mch_target'], {
- 'constraint' : 'COPY_LOCATION',
- 'subtarget' : bones['ik']['mch_str'],
- 'head_tail' : 1.0
- })
-
- # Constrain mch ik stretch bone to the ik control
- make_constraint( self, bones['ik']['mch_str'], {
- 'constraint' : 'DAMPED_TRACK',
- 'subtarget' : roll1_mch,
- 'head_tail' : 1.0
- })
- make_constraint( self, bones['ik']['mch_str'], {
- 'constraint' : 'STRETCH_TO',
- 'subtarget' : roll1_mch,
- 'head_tail' : 1.0
- })
- make_constraint( self, bones['ik']['mch_str'], {
- 'constraint' : 'LIMIT_SCALE',
- 'use_min_y' : True,
- 'use_max_y' : True,
- 'max_y' : 1.05,
- 'owner_space' : 'LOCAL'
- })
- make_constraint(self, mch_main_parent, {
- 'constraint': 'COPY_ROTATION',
- 'subtarget': org_bones[0]
- })
-
- # Create ik/fk switch property
- pb_parent = pb[bones['main_parent']]
- pb_parent.lock_location = True, True, True
- pb_parent.lock_rotation = True, True, True
- pb_parent.lock_scale = True, True, True
-
- prop = make_property(pb_parent, 'IK_Stretch', 1.0, description='IK Stretch')
-
- # Add driver to limit scale constraint influence
- b = bones['ik']['mch_str']
-
- make_driver(pb[b].constraints[-1], "influence", variables=[(self.obj, pb_parent, prop.name)], polynomial=[1.0, -1.0])
-
- # Create leg widget
- create_foot_widget(self.obj, ctrl, bone_transform_name=None)
-
- # Create heel ctrl locks
- pb[heel].lock_location = True, True, 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
+ bone = self.get_bone(name)
+ bone.tail[2] = bone.head[2]
+ bone.roll = 0
- # Add ballsocket widget to heel
- create_ballsocket_widget(self.obj, heel, bone_transform_name=None)
+ return name
- bpy.ops.object.mode_set(mode='EDIT')
- eb = self.obj.data.edit_bones
+ def register_switch_parents(self, pbuilder):
+ super().register_switch_parents(pbuilder)
- if len(org_bones) >= 4:
- # Create toes control bone
- toes = get_bone_name(org_bones[3], 'ctrl')
- toes = copy_bone(self.obj, org_bones[3], toes)
+ pbuilder.register_parent(self, self.bones.org.main[2], exclude_self=True)
- eb[toes].use_connect = False
- eb[toes].parent = eb[toe_mch]
+ def make_ik_ctrl_widget(self, ctrl):
+ create_foot_widget(self.obj, ctrl, bone_transform_name=None)
- # 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], {
- 'constraint': 'DAMPED_TRACK',
- 'subtarget': toes
- })
- make_constraint(self, bones['def'][-2], {
- 'constraint': 'STRETCH_TO',
- 'subtarget': toes
- })
- make_constraint(self, bones['def'][-1], {
- 'constraint': 'COPY_TRANSFORMS',
- 'subtarget': toes
- })
+ ####################################################
+ # Heel control
- # Find IK/FK switch property
- pb = self.obj.pose.bones
- prop = rna_idprop_ui_prop_get( pb[bones['fk']['ctrl'][-1]], 'IK_FK' )
+ @stage.generate_bones
+ def make_heel_control_bone(self):
+ org = self.bones.org.main[2]
+ name = self.copy_bone(org, make_derived_name(org, 'ctrl', '_heel_ik'), scale=1/2)
+ self.bones.ctrl.heel = name
- # Modify rotation mode for ik and tweak controls
- pb[bones['ik']['ctrl']['limb']].rotation_mode = 'ZXY'
+ self.align_roll_bone(org, name, -self.vector_without_z(self.get_bone(org).vector))
- for b in bones['tweak']['ctrl']:
- pb[b].rotation_mode = 'ZXY'
+ @stage.parent_bones
+ def parent_heel_control_bone(self):
+ self.set_bone_parent(self.bones.ctrl.heel, self.bones.ctrl.ik)
- # Add driver to limit scale constraint influence
- b = toe_mch
+ @stage.configure_bones
+ def configure_heel_control_bone(self):
+ bone = self.get_bone(self.bones.ctrl.heel)
+ bone.lock_location = True, True, True
- make_driver(pb[b].constraints[-1], "influence", variables=[(self.obj, pb_parent, prop.name)], polynomial=[1.0, -1.0])
+ if self.main_axis == 'x':
+ bone.lock_rotation = False, False, True
+ else:
+ bone.lock_rotation = True, False, False
- # Create toe circle widget
- create_circle_widget(self.obj, toes, radius=0.4, head_tail=0.5)
+ bone.lock_scale = True, True, True
- bones['ik']['ctrl']['terminal'] += [toes]
+ @stage.generate_widgets
+ def generate_heel_control_widget(self):
+ create_ballsocket_widget(self.obj, self.bones.ctrl.heel, bone_transform_name=None)
- bones['ik']['ctrl']['terminal'] += [ heel, ctrl ]
- return bones
+ ####################################################
+ # Heel roll MCH
- def create_drivers(self, bones):
+ @stage.generate_bones
+ def make_roll_mch_chain(self):
+ orgs = self.bones.org.main
+ self.bones.mch.heel = self.make_roll_mch_bones(orgs[2], orgs[3], self.bones.org.heel)
- bpy.ops.object.mode_set(mode='OBJECT')
- pb = self.obj.pose.bones
+ def make_roll_mch_bones(self, foot, toe, heel):
+ foot_bone = self.get_bone(foot)
+ heel_bone = self.get_bone(heel)
+ axis = -self.vector_without_z(foot_bone.vector)
- #owner = pb[bones['ik']['ctrl']['limb']]
- owner = pb[bones['main_parent']]
+ roll1 = self.copy_bone(foot, make_derived_name(heel, 'mch', '_roll1'))
- props = ["pole_vector"]
+ flip_bone(self.obj, roll1)
+ self.align_roll_bone(foot, roll1, -foot_bone.vector)
- for prop in props:
+ roll2 = self.copy_bone(toe, make_derived_name(heel, 'mch', '_roll2'), scale=1/4)
- if prop == 'pole_vector':
- make_property(owner, prop, False)
- mch_ik = pb[bones['ik']['mch_ik']]
+ put_bone(self.obj, roll2, (heel_bone.head + heel_bone.tail) / 2)
+ self.align_roll_bone(foot, roll2, -axis)
- # ik target hide driver
- pole_target = pb[bones['ik']['ctrl']['ik_target']]
+ rock1 = self.copy_bone(heel, make_derived_name(heel, 'mch', '_rock1'))
- make_driver(pole_target.bone, "hide", variables=[(self.obj, owner, prop)], polynomial=[1.0, -1.0])
+ align_bone_to_axis(self.obj, rock1, 'y', roll=0, length=heel_bone.length/2, flip=True)
+ align_bone_y_axis(self.obj, rock1, axis)
- # vis-pole hide driver
- vispole = pb[bones['ik']['visuals']['vispole']]
+ rock2 = self.copy_bone(heel, make_derived_name(heel, 'mch', '_rock2'))
- make_driver(vispole.bone, "hide", variables=[(self.obj, owner, prop)], polynomial=[1.0, -1.0])
+ align_bone_to_axis(self.obj, rock2, 'y', roll=0, length=heel_bone.length/2)
+ align_bone_y_axis(self.obj, rock2, axis)
- # arrow hide driver
- # limb = pb[bones['ik']['ctrl']['limb']]
- #
- # make_driver(limb.bone, "hide", variables=[(self.obj, owner, prop)], polynomial=[0.0, 1.0])
+ return [ rock2, rock1, roll2, roll1 ]
- for cns in mch_ik.constraints:
- if 'IK' in cns.type:
- if not cns.pole_subtarget:
- make_driver(cns, "mute", variables=[(self.obj, owner, prop)], polynomial=[0.0, 1.0])
- else:
- make_driver(cns, "mute", variables=[(self.obj, owner, prop)], polynomial=[1.0, -1.0])
+ @stage.parent_bones
+ def parent_roll_mch_chain(self):
+ chain = self.bones.mch.heel
+ self.set_bone_parent(chain[0], self.bones.ctrl.ik)
+ self.parent_bone_chain(chain)
+ @stage.rig_bones
+ def rig_roll_mch_chain(self):
+ self.rig_roll_mch_bones(self.bones.mch.heel, self.bones.ctrl.heel, self.bones.org.heel)
- @staticmethod
- def get_future_names(bones):
+ def rig_roll_mch_bones(self, chain, heel, org_heel):
+ rock2, rock1, roll2, roll1 = chain
- if len(bones) != 4:
- return
+ self.make_constraint(roll1, 'COPY_ROTATION', heel, space='LOCAL')
+ self.make_constraint(roll2, 'COPY_ROTATION', heel, space='LOCAL')
- names = dict()
+ if self.main_axis == 'x':
+ self.make_constraint(roll1, 'LIMIT_ROTATION', use_limit_x=True, max_x=DEG_360, space='LOCAL')
+ self.make_constraint(roll2, 'LIMIT_ROTATION', use_limit_xyz=ALL_TRUE, min_x=-DEG_360, space='LOCAL')
+ else:
+ self.make_constraint(roll1, 'LIMIT_ROTATION', use_limit_z=True, max_z=DEG_360, space='LOCAL')
+ self.make_constraint(roll2, 'LIMIT_ROTATION', use_limit_xyz=ALL_TRUE, min_z=-DEG_360, space='LOCAL')
- thigh = strip_mch(strip_org(bones[0].name))
- shin = strip_mch(strip_org(bones[1].name))
- foot = strip_mch(strip_org(bones[2].name))
- toe = strip_mch(strip_org(bones[3].name))
+ direction = self.get_main_axis(self.get_bone(heel)).dot(self.get_bone(org_heel).vector)
- suffix = ''
- if thigh[-2:] == '.L' or thigh[-2:] == '.R':
- suffix = thigh[-2:]
- thigh = thigh.rstrip(suffix)
- shin = shin.rstrip(suffix)
- foot = foot.rstrip(suffix)
- toe = toe.rstrip(suffix)
-
- # the following is declared in rig_ui
- # controls = ['thigh_ik.R', 'thigh_fk.R', 'shin_fk.R', 'foot_fk.R', 'toe.R', 'foot_heel_ik.R', 'foot_ik.R',
- # 'MCH-foot_fk.R', 'thigh_parent.R']
- # tweaks = ['thigh_tweak.R.001', 'shin_tweak.R', 'shin_tweak.R.001']
- # ik_ctrl = ['foot_ik.R', 'MCH-thigh_ik.R', 'MCH-thigh_ik_target.R']
- # fk_ctrl = 'thigh_fk.R'
- # parent = 'thigh_parent.R'
- # foot_fk = 'foot_fk.R'
- # pole = 'thigh_ik_target.R'
+ if direction < 0:
+ rock2, rock1 = rock1, rock2
- names['controls'] = [thigh + '_ik', thigh + '_fk', shin + '_fk', foot + '_fk', toe, foot + '_heel_ik',
- foot + '_ik', make_mechanism_name(foot + '_fk'), thigh + '_parent']
- names['ik_ctrl'] = [foot + '_ik', make_mechanism_name(thigh) + '_ik', make_mechanism_name(thigh) + '_ik_target']
- names['fk_ctrl'] = thigh + '_fk' + suffix
- names['parent'] = thigh + '_parent' + suffix
- names['foot_fk'] = foot + '_fk' + suffix
- names['pole'] = thigh + '_ik_target' + suffix
+ self.make_constraint(rock1, 'COPY_ROTATION', heel, space='LOCAL')
+ self.make_constraint(rock2, 'COPY_ROTATION', heel, space='LOCAL')
- names['limb_type'] = 'leg'
+ self.make_constraint(rock1, 'LIMIT_ROTATION', use_limit_xyz=ALL_TRUE, max_y=DEG_360, space='LOCAL')
+ self.make_constraint(rock2, 'LIMIT_ROTATION', use_limit_xyz=ALL_TRUE, min_y=-DEG_360, space='LOCAL')
- if suffix:
- for i, name in enumerate(names['controls']):
- names['controls'][i] = name + suffix
- for i, name in enumerate(names['ik_ctrl']):
- names['ik_ctrl'][i] = name + suffix
- return names
+ ####################################################
+ # FK parents MCH chain
- def generate(self):
- bpy.ops.object.mode_set(mode='EDIT')
- eb = self.obj.data.edit_bones
+ def parent_fk_parent_bone(self, i, parent_mch, prev_ctrl, org, prev_org):
+ if i == 3:
+ align_bone_orientation(self.obj, parent_mch, self.bones.mch.heel[-2])
- # Adjust org-bones rotation
- self.orient_org_bones()
+ self.set_bone_parent(parent_mch, prev_org, use_connect=True)
- # Clear parents for org bones
- for bone in self.org_bones[1:]:
- eb[bone].use_connect = False
- eb[bone].parent = None
+ else:
+ super().parent_fk_parent_bone(i, parent_mch, prev_ctrl, org, prev_org)
- bones = {}
+ def rig_fk_parent_bone(self, i, parent_mch, org):
+ if i == 3:
+ con = self.make_constraint(parent_mch, 'COPY_TRANSFORMS', self.bones.mch.heel[-2])
- # Create mch limb parent
- mch_parent, main_parent = self.create_parent()
- bones['parent'] = mch_parent
- bones['main_parent'] = main_parent
- bones['tweak'] = self.create_tweak()
- bones['def'] = self.create_def(bones['tweak']['ctrl'])
- bones['ik'] = self.create_ik(bones['parent'])
- bones['fk'] = self.create_fk(bones['parent'])
+ self.make_driver(con, 'influence', variables=[(self.prop_bone, 'IK_FK')], polynomial=[1.0, -1.0])
- self.org_parenting_and_switch(self.org_bones, bones['ik'], bones['fk']['ctrl'], bones['main_parent'])
-
- bones = self.create_leg(bones)
- self.create_drivers(bones)
+ else:
+ super().rig_fk_parent_bone(i, parent_mch, org)
- # Create UI
- script = create_script(bones, 'leg')
- return {
- 'script': [script],
- 'utilities': UTILITIES_RIG_LEG,
- 'register': REGISTER_RIG_LEG,
- }
-
-
-def add_parameters(params):
- """ Add the parameters of this rig type to the
- RigifyParameters PropertyGroup
- """
-
- items = [
- ('x', 'X manual', ''),
- ('z', 'Z manual', ''),
- ('automatic', 'Automatic', '')
- ]
-
- params.rotation_axis = bpy.props.EnumProperty(
- items = items,
- name = "Rotation Axis",
- 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(
- name = 'limb segments',
- default = 2,
- min = 1,
- description = 'Number of segments'
- )
-
- params.bbones = bpy.props.IntProperty(
- name = 'bbone segments',
- default = 10,
- min = 1,
- description = 'Number of segments'
- )
-
- # Setting up extra layers for the FK and tweak
- ControlLayersOption.FK.add_parameters(params)
- ControlLayersOption.TWEAK.add_parameters(params)
+ ####################################################
+ # IK system MCH
+ ik_input_head_tail = 1.0
-def parameters_ui(layout, params):
- """ Create the ui for the rig parameters."""
+ def get_ik_input_bone(self):
+ return self.bones.mch.heel[-1]
- r = layout.row()
- r.prop(params, "rotation_axis")
+ @stage.parent_bones
+ def parent_ik_mch_chain(self):
+ super().parent_ik_mch_chain()
- if 'auto' not in params.rotation_axis.lower():
- r = layout.row()
- text = "Auto align Foot"
- r.prop(params, "auto_align_extremity", text=text)
+ self.set_bone_parent(self.bones.mch.ik_target, self.bones.ctrl.heel)
- r = layout.row()
- r.prop(params, "segments")
- r = layout.row()
- r.prop(params, "bbones")
+ ####################################################
+ # Settings
- ControlLayersOption.FK.parameters_ui(layout, params)
- ControlLayersOption.TWEAK.parameters_ui(layout, params)
+ @classmethod
+ def parameters_ui(self, layout, params):
+ super().parameters_ui(layout, params, 'Foot')
def create_sample(obj):
@@ -1176,7 +322,7 @@ def create_sample(obj):
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones[bones['thigh.L']]
- pbone.rigify_type = 'limbs.super_limb'
+ pbone.rigify_type = 'limbs.leg'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
@@ -1256,6 +402,4 @@ def create_sample(obj):
arm.layers = (False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)
-
-if __name__ == "__main__":
- create_sample(bpy.context.active_object)
+ return bones