ec36210e61d56f5e557ffb3906f71d3a423d995a
[blender-staging.git] / release / scripts / modules / rigify / arm_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 radians, pi
23 from rigify import RigifyError, ORG_PREFIX
24 from rigify_utils import bone_class_instance, copy_bone_simple, add_pole_target_bone, add_stretch_to, blend_bone_list, get_side_name, get_base_name
25 from rna_prop_ui import rna_idprop_ui_prop_get
26 from mathutils import Vector
27
28 METARIG_NAMES = "shoulder", "arm", "forearm", "hand"
29
30
31 def metarig_template():
32     # generated by rigify.write_meta_rig
33     bpy.ops.object.mode_set(mode='EDIT')
34     obj = bpy.context.active_object
35     arm = obj.data
36     bone = arm.edit_bones.new('shoulder')
37     bone.head[:] = 0.0000, -0.0425, 0.0000
38     bone.tail[:] = 0.0942, -0.0075, 0.0333
39     bone.roll = -0.2227
40     bone.use_connect = False
41     bone = arm.edit_bones.new('upper_arm')
42     bone.head[:] = 0.1066, -0.0076, -0.0010
43     bone.tail[:] = 0.2855, 0.0206, -0.0104
44     bone.roll = 1.6152
45     bone.use_connect = False
46     bone.parent = arm.edit_bones['shoulder']
47     bone = arm.edit_bones.new('forearm')
48     bone.head[:] = 0.2855, 0.0206, -0.0104
49     bone.tail[:] = 0.4550, -0.0076, -0.0023
50     bone.roll = 1.5153
51     bone.use_connect = True
52     bone.parent = arm.edit_bones['upper_arm']
53     bone = arm.edit_bones.new('hand')
54     bone.head[:] = 0.4550, -0.0076, -0.0023
55     bone.tail[:] = 0.5423, -0.0146, -0.0131
56     bone.roll = -3.0083
57     bone.use_connect = True
58     bone.parent = arm.edit_bones['forearm']
59
60     bpy.ops.object.mode_set(mode='OBJECT')
61     pbone = obj.pose.bones['upper_arm']
62     pbone['type'] = 'arm_biped'
63
64
65 def metarig_definition(obj, orig_bone_name):
66     mt = bone_class_instance(obj, METARIG_NAMES) # meta
67     mt.arm = orig_bone_name
68     mt.update()
69
70     mt.shoulder_p = mt.arm_p.parent
71
72     if not mt.shoulder_p:
73         raise RigifyError("could not find '%s' parent, skipping:" % orig_bone_name)
74
75     mt.shoulder = mt.shoulder_p.name
76
77     # We could have some bones attached, find the bone that has this as its 2nd parent
78     hands = []
79     for pbone in obj.pose.bones:
80         index = pbone.parent_index(mt.arm_p)
81         if index == 2 and pbone.bone.use_connect and pbone.bone.parent.use_connect:
82             hands.append(pbone)
83
84     if len(hands) != 1:
85         raise RigifyError("Found %s possible hands attached to this arm, expected 1 from bone: %s" % ([pbone.name for pbone in hands], orig_bone_name))
86
87     # first add the 2 new bones
88     mt.hand_p = hands[0]
89     mt.hand = mt.hand_p.name
90
91     mt.forearm_p = mt.hand_p.parent
92     mt.forearm = mt.forearm_p.name
93
94     return mt.names()
95
96
97 def ik(obj, definitions, base_names, options):
98
99     arm = obj.data
100
101     mt = bone_class_instance(obj, METARIG_NAMES)
102     mt.shoulder, mt.arm, mt.forearm, mt.hand = definitions
103     mt.update()
104
105     ik = bone_class_instance(obj, ["pole", "pole_vis", "hand_vis"])
106     ik_chain = mt.copy(to_fmt="MCH-%s_ik", base_names=base_names, exclude_attrs=["shoulder"])
107
108     # IK needs no parent_index
109     ik_chain.hand_e.use_connect = False
110     ik_chain.hand_e.parent = None
111     ik_chain.hand_e.use_local_location = False
112     ik_chain.rename("hand", get_base_name(base_names[mt.hand]) + "_ik" + get_side_name(mt.hand))
113
114     ik_chain.arm_e.use_connect = False
115     ik_chain.arm_e.parent = mt.shoulder_e
116
117     # Add the bone used for the arms poll target
118     #ik.pole = add_pole_target_bone(obj, mt.forearm, get_base_name(base_names[mt.forearm]) + "_target" + get_side_name(mt.forearm), mode='ZAVERAGE')
119     ik.pole = add_pole_target_bone(obj, mt.forearm, "elbow_target" + get_side_name(mt.forearm), mode='ZAVERAGE')
120
121     ik.update()
122     ik.pole_e.use_local_location = False
123
124     # option: elbow_parent
125     elbow_parent_name = options.get("elbow_parent", "")
126
127     if elbow_parent_name:
128         try:
129             elbow_parent_e = arm.edit_bones[ORG_PREFIX + elbow_parent_name]
130         except:
131             # TODO, old/new parent mapping
132             raise RigifyError("parent bone from property 'arm_biped_generic.elbow_parent' not found '%s'" % elbow_parent_name)
133         ik.pole_e.parent = elbow_parent_e
134
135     # update bones after this!
136     ik.hand_vis = add_stretch_to(obj, mt.hand, ik_chain.hand, "VIS-%s_ik" % base_names[mt.hand])
137     ik.pole_vis = add_stretch_to(obj, mt.forearm, ik.pole, "VIS-%s_ik" % base_names[mt.forearm])
138
139     ik.update()
140     ik.hand_vis_e.hide_select = True
141     ik.pole_vis_e.hide_select = True
142
143     bpy.ops.object.mode_set(mode='OBJECT')
144
145     mt.update()
146     ik.update()
147     ik_chain.update()
148
149     # Set IK dof
150     ik_chain.forearm_p.lock_ik_x = False
151     ik_chain.forearm_p.lock_ik_y = True
152     ik_chain.forearm_p.lock_ik_z = True
153
154     con = ik_chain.forearm_p.constraints.new('IK')
155     con.target = obj
156     con.subtarget = ik_chain.hand
157     con.pole_target = obj
158     con.pole_subtarget = ik.pole
159
160     con.use_tail = True
161     con.use_stretch = True
162     con.use_target = True
163     con.use_rotation = False
164     con.chain_length = 2
165     con.pole_angle = -pi/2
166
167     # last step setup layers
168     if "ik_layer" in options:
169         layer = [n==options["ik_layer"] for n in range(0,32)]
170     else:
171         layer = list(mt.arm_b.layers)
172     ik_chain.hand_b.layers = layer
173     ik.hand_vis_b.layers   = layer
174     ik.pole_b.layers       = layer
175     ik.pole_vis_b.layers   = layer
176
177     bpy.ops.object.mode_set(mode='EDIT')
178     # don't blend the shoulder
179     return [None] + ik_chain.names()
180
181
182 def fk(obj, definitions, base_names, options):
183
184     arm = obj.data
185
186     mt = bone_class_instance(obj, METARIG_NAMES)
187     mt.shoulder, mt.arm, mt.forearm, mt.hand = definitions
188     mt.update()
189
190     ex = bone_class_instance(obj, ["socket", "hand_delta"])
191     fk_chain = mt.copy(base_names=base_names)
192
193     # shoulder is used as a hinge
194     fk_chain.rename("shoulder", "MCH-%s_hinge" % base_names[mt.arm])
195     fk_chain.shoulder_e.translate(Vector((0.0, fk_chain.shoulder_e.length / 2, 0.0)))
196
197     # upper arm constrains to this.
198     ex.socket_e = copy_bone_simple(arm, mt.arm, "MCH-%s_socket" % base_names[mt.arm])
199     ex.socket = ex.socket_e.name
200     ex.socket_e.use_connect = False
201     ex.socket_e.parent = mt.shoulder_e
202     ex.socket_e.length *= 0.5
203
204     # insert the 'MCH-delta_hand', between the forearm and the hand
205     # copies forarm rotation
206     ex.hand_delta_e = copy_bone_simple(arm, fk_chain.hand, "MCH-delta_%s" % base_names[mt.hand], parent=True)
207     ex.hand_delta = ex.hand_delta_e.name
208     ex.hand_delta_e.length *= 0.5
209     ex.hand_delta_e.use_connect = False
210     if "hand_roll" in options:
211         ex.hand_delta_e.roll += radians(options["hand_roll"])
212
213     fk_chain.hand_e.use_connect = False
214     fk_chain.hand_e.parent = ex.hand_delta_e
215
216     bpy.ops.object.mode_set(mode='OBJECT')
217
218     mt.update()
219     ex.update()
220     fk_chain.update()
221
222     # Set rotation modes and axis locks
223     fk_chain.forearm_p.rotation_mode = 'XYZ'
224     fk_chain.forearm_p.lock_rotation = (False, True, True)
225     fk_chain.hand_p.rotation_mode = 'ZXY'
226     fk_chain.arm_p.lock_location = True, True, True
227
228     con = fk_chain.arm_p.constraints.new('COPY_LOCATION')
229     con.target = obj
230     con.subtarget = ex.socket
231
232     fk_chain.hand_p.lock_location = True, True, True
233     con = ex.hand_delta_p.constraints.new('COPY_ROTATION')
234     con.target = obj
235     con.subtarget = fk_chain.forearm
236
237     def hinge_setup():
238         # Hinge constraint & driver
239         con = fk_chain.shoulder_p.constraints.new('COPY_ROTATION')
240         con.name = "hinge"
241         con.target = obj
242         con.subtarget = mt.shoulder
243         driver_fcurve = con.driver_add("influence")
244         driver = driver_fcurve.driver
245
246
247         controller_path = fk_chain.arm_p.path_from_id()
248         # add custom prop
249         fk_chain.arm_p["hinge"] = 0.0
250         prop = rna_idprop_ui_prop_get(fk_chain.arm_p, "hinge", create=True)
251         prop["soft_min"] = 0.0
252         prop["soft_max"] = 1.0
253
254
255         # *****
256         driver = driver_fcurve.driver
257         driver.type = 'AVERAGE'
258
259         var = driver.variables.new()
260         var.name = "hinge"
261         var.targets[0].id_type = 'OBJECT'
262         var.targets[0].id = obj
263         var.targets[0].data_path = controller_path + '["hinge"]'
264
265         mod = driver_fcurve.modifiers[0]
266         mod.poly_order = 1
267         mod.coefficients[0] = 1.0
268         mod.coefficients[1] = -1.0
269
270     hinge_setup()
271
272     # last step setup layers
273     if "fk_layer" in options:
274         layer = [n==options["fk_layer"] for n in range(0,32)]
275     else:
276         layer = list(mt.arm_b.layers)
277     fk_chain.arm_b.layers     = layer
278     fk_chain.forearm_b.layers = layer
279     fk_chain.hand_b.layers    = layer
280
281     # Forearm was getting wrong roll somehow.  Hack to fix that.
282     bpy.ops.object.mode_set(mode='EDIT')
283     fk_chain.update()
284     mt.update()
285     fk_chain.forearm_e.roll = mt.forearm_e.roll
286     bpy.ops.object.mode_set(mode='OBJECT')
287
288     bpy.ops.object.mode_set(mode='EDIT')
289     return None, fk_chain.arm, fk_chain.forearm, fk_chain.hand
290
291
292 def deform(obj, definitions, base_names, options):
293     bpy.ops.object.mode_set(mode='EDIT')
294
295     # Create upper arm bones: two bones, each half of the upper arm.
296     uarm1 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.01" % base_names[definitions[1]], parent=True)
297     uarm2 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.02" % base_names[definitions[1]], parent=True)
298     uarm1.use_connect = False
299     uarm2.use_connect = False
300     uarm2.parent = uarm1
301     center = uarm1.center
302     uarm1.tail = center
303     uarm2.head = center
304
305     # Create forearm bones: two bones, each half of the forearm.
306     farm1 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.01" % base_names[definitions[2]], parent=True)
307     farm2 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.02" % base_names[definitions[2]], parent=True)
308     farm1.use_connect = False
309     farm2.use_connect = False
310     farm2.parent = farm1
311     center = farm1.center
312     farm1.tail = center
313     farm2.head = center
314
315     # Create twist bone
316     twist = copy_bone_simple(obj.data, definitions[2], "MCH-arm_twist")
317     twist.use_connect = False
318     twist.parent = obj.data.edit_bones[definitions[3]]
319     twist.length /= 2
320
321     # Create hand bone
322     hand = copy_bone_simple(obj.data, definitions[3], "DEF-%s" % base_names[definitions[3]], parent=True)
323
324     # Store names before leaving edit mode
325     uarm1_name = uarm1.name
326     uarm2_name = uarm2.name
327     farm1_name = farm1.name
328     farm2_name = farm2.name
329     twist_name = twist.name
330     hand_name = hand.name
331
332     # Leave edit mode
333     bpy.ops.object.mode_set(mode='OBJECT')
334
335     # Get the pose bones
336     uarm1 = obj.pose.bones[uarm1_name]
337     uarm2 = obj.pose.bones[uarm2_name]
338     farm1 = obj.pose.bones[farm1_name]
339     farm2 = obj.pose.bones[farm2_name]
340     twist = obj.pose.bones[twist_name]
341     hand = obj.pose.bones[hand_name]
342
343     # Upper arm constraints
344     con = uarm1.constraints.new('DAMPED_TRACK')
345     con.name = "trackto"
346     con.target = obj
347     con.subtarget = definitions[2]
348
349     con = uarm1.constraints.new('COPY_SCALE')
350     con.name = "trackto"
351     con.target = obj
352     con.subtarget = definitions[1]
353
354     con = uarm2.constraints.new('COPY_ROTATION')
355     con.name = "copy_rot"
356     con.target = obj
357     con.subtarget = definitions[1]
358
359     # Forearm constraints
360     con = farm1.constraints.new('COPY_ROTATION')
361     con.name = "copy_rot"
362     con.target = obj
363     con.subtarget = definitions[2]
364
365     con = farm1.constraints.new('COPY_SCALE')
366     con.name = "copy_rot"
367     con.target = obj
368     con.subtarget = definitions[2]
369
370     con = farm2.constraints.new('COPY_ROTATION')
371     con.name = "copy_rot"
372     con.target = obj
373     con.subtarget = twist.name
374
375     con = farm2.constraints.new('DAMPED_TRACK')
376     con.name = "trackto"
377     con.target = obj
378     con.subtarget = definitions[3]
379
380     # Hand constraint
381     con = hand.constraints.new('COPY_ROTATION')
382     con.name = "copy_rot"
383     con.target = obj
384     con.subtarget = definitions[3]
385
386     bpy.ops.object.mode_set(mode='EDIT')
387     return (uarm1_name, uarm2_name, farm1_name, farm2_name, hand_name)
388
389
390 def main(obj, bone_definition, base_names, options):
391     bones_fk = fk(obj, bone_definition, base_names, options)
392     bones_ik = ik(obj, bone_definition, base_names, options)
393     bones_deform = deform(obj, bone_definition, base_names, options)
394
395     bpy.ops.object.mode_set(mode='OBJECT')
396     blend_bone_list(obj, bone_definition, bones_fk, bones_ik, target_bone=bones_ik[3], target_prop="ik", blend_default=0.0)