rna data path names which are more likely to break animations.
[blender-staging.git] / release / scripts / modules / rigify / leg_biped.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20
21 import bpy
22 from math import pi
23 from rigify import RigifyError
24 from rigify_utils import bone_class_instance, copy_bone_simple, blend_bone_list, get_side_name, get_base_name
25 from rna_prop_ui import rna_idprop_ui_prop_get
26
27 METARIG_NAMES = "hips", "thigh", "shin", "foot", "toe", "heel"
28
29
30 def metarig_template():
31     # generated by rigify.write_meta_rig
32     bpy.ops.object.mode_set(mode='EDIT')
33     obj = bpy.context.active_object
34     arm = obj.data
35     bone = arm.edit_bones.new('hips')
36     bone.head[:] = 0.0000, 0.0000, 0.0000
37     bone.tail[:] = 0.0000, 0.0000, 0.2506
38     bone.roll = 0.0000
39     bone.use_connect = False
40     bone = arm.edit_bones.new('thigh')
41     bone.head[:] = 0.1253, 0.0000, -0.0000
42     bone.tail[:] = 0.0752, -0.0251, -0.4260
43     bone.roll = 0.1171
44     bone.use_connect = False
45     bone.parent = arm.edit_bones['hips']
46     bone = arm.edit_bones.new('shin')
47     bone.head[:] = 0.0752, -0.0251, -0.4260
48     bone.tail[:] = 0.0752, 0.0000, -0.8771
49     bone.roll = 0.0000
50     bone.use_connect = True
51     bone.parent = arm.edit_bones['thigh']
52     bone = arm.edit_bones.new('foot')
53     bone.head[:] = 0.0752, 0.0000, -0.8771
54     bone.tail[:] = 0.1013, -0.1481, -0.9773
55     bone.roll = -0.4662
56     bone.use_connect = True
57     bone.parent = arm.edit_bones['shin']
58     bone = arm.edit_bones.new('toe')
59     bone.head[:] = 0.1013, -0.1481, -0.9773
60     bone.tail[:] = 0.1100, -0.2479, -0.9773
61     bone.roll = 3.1416
62     bone.use_connect = True
63     bone.parent = arm.edit_bones['foot']
64     bone = arm.edit_bones.new('heel')
65     bone.head[:] = 0.0652, 0.0501, -1.0024
66     bone.tail[:] = 0.0927, -0.1002, -1.0024
67     bone.roll = 0.0000
68     bone.use_connect = False
69     bone.parent = arm.edit_bones['foot']
70
71     bpy.ops.object.mode_set(mode='OBJECT')
72     pbone = obj.pose.bones['thigh']
73     pbone['type'] = 'leg_biped'
74
75
76 def metarig_definition(obj, orig_bone_name):
77     '''
78     The bone given is the first in a chain
79     Expects a chain of at least 3 children.
80     eg.
81         thigh -> shin -> foot -> [toe, heel]
82     '''
83
84     bone_definition = []
85
86     orig_bone = obj.data.bones[orig_bone_name]
87     orig_bone_parent = orig_bone.parent
88
89     if orig_bone_parent is None:
90         raise RigifyError("expected the thigh bone to have a parent hip bone")
91
92     bone_definition.append(orig_bone_parent.name)
93     bone_definition.append(orig_bone.name)
94
95
96     bone = orig_bone
97     chain = 0
98     while chain < 2: # first 2 bones only have 1 child
99         children = bone.children
100
101         if len(children) != 1:
102             raise RigifyError("expected the thigh bone to have 3 children without a fork")
103         bone = children[0]
104         bone_definition.append(bone.name) # shin, foot
105         chain += 1
106
107     children = bone.children
108     # Now there must be 2 children, only one connected
109     if len(children) != 2:
110         raise RigifyError("expected the foot bone:'%s' to have 2 children" % bone.name)
111
112     if children[0].use_connect == children[1].use_connect:
113         raise RigifyError("expected one bone to be connected")
114
115     toe, heel = children
116     if heel.use_connect:
117         toe, heel = heel, toe
118
119
120     bone_definition.append(toe.name)
121     bone_definition.append(heel.name)
122
123     if len(bone_definition) != len(METARIG_NAMES):
124         raise RigifyError("internal problem, expected %d bones" % len(METARIG_NAMES))
125
126     return bone_definition
127
128
129 def ik(obj, bone_definition, base_names, options):
130     arm = obj.data
131
132     # setup the existing bones, use names from METARIG_NAMES
133     mt_chain = bone_class_instance(obj, ["thigh", "shin", "foot", "toe"])
134     mt = bone_class_instance(obj, ["hips", "heel"])
135
136     mt.attr_initialize(METARIG_NAMES, bone_definition)
137     mt_chain.attr_initialize(METARIG_NAMES, bone_definition)
138
139     # children of ik_foot
140     ik = bone_class_instance(obj, ["foot", "foot_roll", "foot_roll_01", "foot_roll_02", "knee_target"])
141
142     # Make a new chain
143     ik_chain = mt_chain.copy(to_fmt="MCH-%s", base_names=base_names)
144
145     # simple rename
146     ik_chain.rename("thigh", ik_chain.thigh + "_ik")
147     ik_chain.rename("shin", ik_chain.shin + "_ik")
148
149     # make sure leg is child of hips
150     ik_chain.thigh_e.parent = mt.hips_e
151
152     # ik foot: no parents
153     base_foot_name = get_base_name(base_names[mt_chain.foot])
154     ik.foot_e = copy_bone_simple(arm, mt.heel, base_foot_name + "_ik" + get_side_name(base_names[mt_chain.foot]))
155     ik.foot = ik.foot_e.name
156     ik.foot_e.translate(mt_chain.foot_e.head - ik.foot_e.head)
157     ik.foot_e.use_local_location = False
158
159     # foot roll: heel pointing backwards, half length
160     ik.foot_roll_e = copy_bone_simple(arm, mt.heel, base_foot_name + "_roll" + get_side_name(base_names[mt_chain.foot]))
161     ik.foot_roll = ik.foot_roll_e.name
162     ik.foot_roll_e.tail = ik.foot_roll_e.head - ik.foot_roll_e.vector / 2.0
163     ik.foot_roll_e.parent = ik.foot_e # heel is disconnected
164
165     # heel pointing forwards to the toe base, parent of the following 2 bones
166     ik.foot_roll_01_e = copy_bone_simple(arm, mt.heel, "MCH-%s_roll.01" % base_foot_name)
167     ik.foot_roll_01 = ik.foot_roll_01_e.name
168     ik.foot_roll_01_e.tail = mt_chain.foot_e.tail
169     ik.foot_roll_01_e.parent = ik.foot_e # heel is disconnected
170
171     # same as above but reverse direction
172     ik.foot_roll_02_e = copy_bone_simple(arm, mt.heel, "MCH-%s_roll.02" % base_foot_name)
173     ik.foot_roll_02 = ik.foot_roll_02_e.name
174     ik.foot_roll_02_e.parent = ik.foot_roll_01_e # heel is disconnected
175     ik.foot_roll_02_e.head = mt_chain.foot_e.tail
176     ik.foot_roll_02_e.tail = mt.heel_e.head
177
178     del base_foot_name
179
180     # rename 'MCH-toe' --> to 'toe_ik' and make the child of ik.foot_roll_01
181     # ------------------ FK or IK?
182     ik_chain.rename("toe", get_base_name(base_names[mt_chain.toe]) + "_ik" + get_side_name(base_names[mt_chain.toe]))
183     ik_chain.toe_e.use_connect = False
184     ik_chain.toe_e.parent = ik.foot_roll_01_e
185
186     # re-parent ik_chain.foot to the
187     ik_chain.foot_e.use_connect = False
188     ik_chain.foot_e.parent = ik.foot_roll_02_e
189
190
191     # knee target is the heel moved up and forward on its local axis
192     ik.knee_target_e = copy_bone_simple(arm, mt.heel, "knee_target" + get_side_name(mt.heel))
193     ik.knee_target = ik.knee_target_e.name
194     offset = ik.knee_target_e.tail - ik.knee_target_e.head
195     offset.z = 0
196     offset.length = mt_chain.shin_e.head.z - mt.heel_e.head.z
197     offset.z += offset.length
198     ik.knee_target_e.translate(offset)
199     ik.knee_target_e.length *= 0.5
200     ik.knee_target_e.parent = ik.foot_e
201     ik.knee_target_e.use_local_location = False
202
203     # roll the bone to point up... could also point in the same direction as ik.foot_roll
204     # ik.foot_roll_02_e.matrix * Vector((0.0, 0.0, 1.0)) # ACK!, no rest matrix in editmode
205     ik.foot_roll_01_e.align_roll((0.0, 0.0, -1.0))
206
207     bpy.ops.object.mode_set(mode='OBJECT')
208
209     ik.update()
210     mt_chain.update()
211     ik_chain.update()
212
213     # Set IK dof
214     ik_chain.shin_p.lock_ik_x = False
215     ik_chain.shin_p.lock_ik_y = True
216     ik_chain.shin_p.lock_ik_z = True
217
218     # Set rotation modes and axis locks
219     ik.foot_roll_p.rotation_mode = 'XYZ'
220     ik.foot_roll_p.lock_rotation = False, True, True
221     ik_chain.toe_p.rotation_mode = 'YXZ'
222     ik_chain.toe_p.lock_rotation = False, True, True
223     ik_chain.toe_p.lock_location = True, True, True
224     ik.foot_roll_p.lock_location = True, True, True
225
226     # IK
227     con = ik_chain.shin_p.constraints.new('IK')
228     con.chain_count = 2
229     con.iterations = 500
230     con.pole_angle = -pi / 2.0
231     con.use_tail = True
232     con.use_stretch = True
233     con.use_target = True
234     con.use_rotation = False
235     con.weight = 1.0
236
237     con.target = obj
238     con.subtarget = ik_chain.foot
239
240     con.pole_target = obj
241     con.pole_subtarget = ik.knee_target
242
243     # foot roll
244     cons = [ \
245         (ik.foot_roll_01_p.constraints.new('COPY_ROTATION'), ik.foot_roll_01_p.constraints.new('LIMIT_ROTATION')), \
246         (ik.foot_roll_02_p.constraints.new('COPY_ROTATION'), ik.foot_roll_02_p.constraints.new('LIMIT_ROTATION'))]
247
248     for con, con_l in cons:
249         con.target = obj
250         con.subtarget = ik.foot_roll
251         con.use_x, con.use_y, con.use_z = True, False, False
252         con.target_space = con.owner_space = 'LOCAL'
253
254         con = con_l
255         con.use_limit_x, con.use_limit_y, con.use_limit_z = True, False, False
256         con.owner_space = 'LOCAL'
257
258         if con_l is cons[-1][-1]:
259             con.min_x = 0.0
260             con.max_x = 180.0 # XXX -deg
261         else:
262             con.min_x = -180.0 # XXX -deg
263             con.max_x = 0.0
264
265
266     # last step setup layers
267     if "ik_layer" in options:
268         layer = [n == options["ik_layer"] for n in range(0, 32)]
269     else:
270         layer = list(mt_chain.thigh_b.layers)
271     for attr in ik_chain.attr_names:
272         getattr(ik_chain, attr + "_b").layers = layer
273     for attr in ik.attr_names:
274         getattr(ik, attr + "_b").layers = layer
275
276     bpy.ops.object.mode_set(mode='EDIT')
277
278     return (None, ik_chain.thigh, ik_chain.shin, ik_chain.foot, ik_chain.toe, None, ik.foot)
279
280
281 def fk(obj, bone_definition, base_names, options):
282     from mathutils import Vector
283     arm = obj.data
284
285     # these account for all bones in METARIG_NAMES
286     mt_chain = bone_class_instance(obj, ["thigh", "shin", "foot", "toe"])
287     mt = bone_class_instance(obj, ["hips", "heel"])
288
289     # new bones
290     ex = bone_class_instance(obj, ["thigh_socket", "thigh_hinge"])
291
292     for bone_class in (mt, mt_chain):
293         for attr in bone_class.attr_names:
294             i = METARIG_NAMES.index(attr)
295             ebone = arm.edit_bones[bone_definition[i]]
296             setattr(bone_class, attr, ebone.name)
297         bone_class.update()
298
299     ex.thigh_socket_e = copy_bone_simple(arm, mt_chain.thigh, "MCH-%s_socket" % base_names[mt_chain.thigh], parent=True)
300     ex.thigh_socket = ex.thigh_socket_e.name
301     ex.thigh_socket_e.tail = ex.thigh_socket_e.head + Vector((0.0, 0.0, ex.thigh_socket_e.length / 4.0))
302
303     ex.thigh_hinge_e = copy_bone_simple(arm, mt.hips, "MCH-%s_hinge" % base_names[mt_chain.thigh], parent=False)
304     ex.thigh_hinge = ex.thigh_hinge_e.name
305
306     fk_chain = mt_chain.copy(base_names=base_names) # fk has no prefix!
307     fk_chain.foot_e.name = "MCH-" + fk_chain.foot
308     fk_chain.foot = fk_chain.foot_e.name
309
310     # Set up fk foot control
311     foot_e = copy_bone_simple(arm, mt.heel, base_names[mt_chain.foot])
312     foot = foot_e.name
313     foot_e.translate(mt_chain.foot_e.head - foot_e.head)
314     foot_e.parent = fk_chain.shin_e
315     foot_e.use_connect = fk_chain.foot_e.use_connect
316     fk_chain.foot_e.use_connect = False
317     fk_chain.foot_e.parent = foot_e
318
319     fk_chain.thigh_e.use_connect = False
320     fk_chain.thigh_e.parent = ex.thigh_hinge_e
321
322     bpy.ops.object.mode_set(mode='OBJECT')
323
324     ex.update()
325     mt_chain.update()
326     fk_chain.update()
327     foot_p = obj.pose.bones[foot]
328
329     # Set rotation modes and axis locks
330     fk_chain.shin_p.rotation_mode = 'XYZ'
331     fk_chain.shin_p.lock_rotation = False, True, True
332     foot_p.rotation_mode = 'YXZ'
333     fk_chain.toe_p.rotation_mode = 'YXZ'
334     fk_chain.toe_p.lock_rotation = False, True, True
335     fk_chain.thigh_p.lock_location = True, True, True
336
337     con = fk_chain.thigh_p.constraints.new('COPY_LOCATION')
338     con.target = obj
339     con.subtarget = ex.thigh_socket
340
341     # hinge
342     prop = rna_idprop_ui_prop_get(fk_chain.thigh_p, "hinge", create=True)
343     fk_chain.thigh_p["hinge"] = 0.0
344     prop["soft_min"] = 0.0
345     prop["soft_max"] = 1.0
346
347     con = ex.thigh_hinge_p.constraints.new('COPY_ROTATION')
348     con.target = obj
349     con.subtarget = mt.hips
350
351     # add driver
352     hinge_driver_path = fk_chain.thigh_p.path_from_id() + '["hinge"]'
353
354     fcurve = con.driver_add("influence")
355     driver = fcurve.driver
356     var = driver.variables.new()
357     driver.type = 'AVERAGE'
358     var.name = "var"
359     var.targets[0].id_type = 'OBJECT'
360     var.targets[0].id = obj
361     var.targets[0].data_path = hinge_driver_path
362
363     mod = fcurve.modifiers[0]
364     mod.poly_order = 1
365     mod.coefficients[0] = 1.0
366     mod.coefficients[1] = -1.0
367
368
369     # last step setup layers
370     if "fk_layer" in options:
371         layer = [n == options["fk_layer"] for n in range(0, 32)]
372     else:
373         layer = list(mt_chain.thigh_b.layers)
374     for attr in fk_chain.attr_names:
375         getattr(fk_chain, attr + "_b").layers = layer
376     for attr in ex.attr_names:
377         getattr(ex, attr + "_b").layers = layer
378     arm.bones[foot].layers = layer
379
380
381     bpy.ops.object.mode_set(mode='EDIT')
382
383     # dont blend the hips or heel
384     return (None, fk_chain.thigh, fk_chain.shin, fk_chain.foot, fk_chain.toe, None, None)
385
386
387 def deform(obj, definitions, base_names, options):
388     bpy.ops.object.mode_set(mode='EDIT')
389
390     # Create upper leg bones: two bones, each half of the upper leg.
391     uleg1 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.01" % base_names[definitions[1]], parent=True)
392     uleg2 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.02" % base_names[definitions[1]], parent=True)
393     uleg1.use_connect = False
394     uleg2.use_connect = False
395     uleg2.parent = uleg1
396     center = uleg1.center
397     uleg1.tail = center
398     uleg2.head = center
399
400     # Create lower leg bones: two bones, each half of the lower leg.
401     lleg1 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.01" % base_names[definitions[2]], parent=True)
402     lleg2 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.02" % base_names[definitions[2]], parent=True)
403     lleg1.use_connect = False
404     lleg2.use_connect = False
405     lleg2.parent = lleg1
406     center = lleg1.center
407     lleg1.tail = center
408     lleg2.head = center
409
410     # Create a bone for the second lower leg deform bone to twist with
411     twist = copy_bone_simple(obj.data, lleg2.name, "MCH-leg_twist")
412     twist.length /= 4
413     twist.use_connect = False
414     twist.parent = obj.data.edit_bones[definitions[3]]
415
416     # Create foot bone
417     foot = copy_bone_simple(obj.data, definitions[3], "DEF-%s" % base_names[definitions[3]], parent=True)
418
419     # Create toe bone
420     toe = copy_bone_simple(obj.data, definitions[4], "DEF-%s" % base_names[definitions[4]], parent=True)
421
422     # Store names before leaving edit mode
423     uleg1_name = uleg1.name
424     uleg2_name = uleg2.name
425     lleg1_name = lleg1.name
426     lleg2_name = lleg2.name
427     twist_name = twist.name
428     foot_name = foot.name
429     toe_name = toe.name
430
431     # Leave edit mode
432     bpy.ops.object.mode_set(mode='OBJECT')
433
434     # Get the pose bones
435     uleg1 = obj.pose.bones[uleg1_name]
436     uleg2 = obj.pose.bones[uleg2_name]
437     lleg1 = obj.pose.bones[lleg1_name]
438     lleg2 = obj.pose.bones[lleg2_name]
439     foot = obj.pose.bones[foot_name]
440     toe = obj.pose.bones[toe_name]
441
442     # Upper leg constraints
443     con = uleg1.constraints.new('DAMPED_TRACK')
444     con.name = "trackto"
445     con.target = obj
446     con.subtarget = definitions[2]
447
448     con = uleg1.constraints.new('COPY_SCALE')
449     con.name = "scale"
450     con.target = obj
451     con.subtarget = definitions[1]
452
453     con = uleg2.constraints.new('COPY_ROTATION')
454     con.name = "copy_rot"
455     con.target = obj
456     con.subtarget = definitions[1]
457
458     # Lower leg constraints
459     con = lleg1.constraints.new('COPY_ROTATION')
460     con.name = "copy_rot"
461     con.target = obj
462     con.subtarget = definitions[2]
463
464     con = lleg1.constraints.new('COPY_SCALE')
465     con.name = "copy_rot"
466     con.target = obj
467     con.subtarget = definitions[2]
468
469     con = lleg2.constraints.new('COPY_ROTATION')
470     con.name = "copy_rot"
471     con.target = obj
472     con.subtarget = twist_name
473
474     con = lleg2.constraints.new('DAMPED_TRACK')
475     con.name = "trackto"
476     con.target = obj
477     con.subtarget = definitions[3]
478
479     # Foot constraint
480     con = foot.constraints.new('COPY_ROTATION')
481     con.name = "copy_rot"
482     con.target = obj
483     con.subtarget = definitions[3]
484
485     # Toe constraint
486     con = toe.constraints.new('COPY_ROTATION')
487     con.name = "copy_rot"
488     con.target = obj
489     con.subtarget = definitions[4]
490
491     bpy.ops.object.mode_set(mode='EDIT')
492     return (uleg1_name, uleg2_name, lleg1_name, lleg2_name, foot_name, toe_name, None)
493
494
495 def main(obj, bone_definition, base_names, options):
496     bones_fk = fk(obj, bone_definition, base_names, options)
497     bones_ik = ik(obj, bone_definition, base_names, options)
498     deform(obj, bone_definition, base_names, options)
499
500     bpy.ops.object.mode_set(mode='OBJECT')
501     blend_bone_list(obj, bone_definition + [None], bones_fk, bones_ik, target_bone=bones_ik[6], target_prop="ik", blend_default=1.0)