split up metarig hierarchy evaluation and modifying the metarig into 2 steps,
[blender.git] / release / scripts / modules / rigify / arm.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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 import bpy
20 from rigify import bone_class_instance, copy_bone_simple, add_pole_target_bone, add_stretch_to
21 from rna_prop_ui import rna_idprop_ui_get, rna_idprop_ui_prop_get
22
23 METARIG_NAMES = "shoulder", "arm", "forearm", "hand"
24
25 def metarig_template():
26     bpy.ops.object.mode_set(mode='EDIT')
27     obj = bpy.context.object
28     arm = obj.data
29     bone = arm.edit_bones.new('shoulder')
30     bone.head[:] = 0.0000, -0.4515, 0.0000
31     bone.tail[:] = 1.0000, -0.0794, 0.3540
32     bone.roll = -0.2227
33     bone.connected = False
34     bone = arm.edit_bones.new('upper_arm')
35     bone.head[:] = 1.1319, -0.0808, -0.0101
36     bone.tail[:] = 3.0319, 0.2191, -0.1101
37     bone.roll = 1.6152
38     bone.connected = False
39     bone.parent = arm.edit_bones['shoulder']
40     bone = arm.edit_bones.new('forearm')
41     bone.head[:] = 3.0319, 0.2191, -0.1101
42     bone.tail[:] = 4.8319, -0.0809, -0.0242
43     bone.roll = 1.5153
44     bone.connected = True
45     bone.parent = arm.edit_bones['upper_arm']
46     bone = arm.edit_bones.new('hand')
47     bone.head[:] = 4.8319, -0.0809, -0.0242
48     bone.tail[:] = 5.7590, -0.1553, -0.1392
49     bone.roll = -3.0083
50     bone.connected = True
51     bone.parent = arm.edit_bones['forearm']
52
53     bpy.ops.object.mode_set(mode='OBJECT')
54     pbone = obj.pose.bones['upper_arm']
55     pbone['type'] = 'arm'
56
57
58 def metarig_definition(obj, orig_bone_name):
59     mt = bone_class_instance(obj, METARIG_NAMES) # meta
60     mt.arm = orig_bone_name
61     mt.update()
62     
63     mt.shoulder_p = mt.arm_p.parent
64     mt.shoulder = mt.shoulder_p.name
65     
66     if not mt.shoulder_p:
67         raise Exception("could not find 'arm' parent, skipping:", orig_bone_name)
68
69     # We could have some bones attached, find the bone that has this as its 2nd parent
70     hands = []
71     for pbone in obj.pose.bones:
72         index = pbone.parent_index(mt.arm_p)
73         if index == 2:
74             hands.append(pbone)
75
76     if len(hands) > 1:
77         raise Exception("more then 1 hand found on:", orig_bone_name)
78
79     # first add the 2 new bones
80     mt.hand_p = hands[0]
81     mt.hand = mt.hand_p.name
82
83     mt.forearm_p = mt.hand_p.parent
84     mt.forearm = mt.forearm_p.name
85     
86     return mt.names()
87
88
89 def main(obj, definitions, base_names):
90     """
91     the bone with the 'arm' property is the upper arm, this assumes a chain as follows.
92     [shoulder, upper_arm, forearm, hand]
93     ...where this bone is 'upper_arm'
94     
95     there are 3 chains
96     - Original
97     - IK, MCH-%s_ik
98     - IKSwitch, MCH-%s ()
99     
100     
101     """
102     
103     # Since there are 3 chains, this gets confusing so divide into 3 chains
104     # Initialize container classes for convenience
105     mt = bone_class_instance(obj, METARIG_NAMES) # meta
106     mt.shoulder, mt.arm, mt.forearm, mt.hand = definitions
107     
108     ik = bone_class_instance(obj, ["arm", "forearm", "pole", "hand"]) # ik
109     sw = bone_class_instance(obj, ["socket", "shoulder", "arm", "forearm", "hand"]) # hinge
110     ex = bone_class_instance(obj, ["arm_hinge"]) # hinge & extras
111     
112     arm = obj.data
113     
114     
115     def chain_ik(prefix="MCH-%s_ik"):
116         
117         mt.update()
118         
119         # Add the edit bones
120         ik.hand_e = copy_bone_simple(arm, mt.hand, prefix % mt.hand)
121         ik.hand = ik.hand_e.name
122         
123         ik.arm_e = copy_bone_simple(arm, mt.arm, prefix % mt.arm)
124         ik.arm = ik.arm_e.name
125
126         ik.forearm_e = copy_bone_simple(arm, mt.forearm, prefix % mt.forearm)
127         ik.forearm = ik.forearm_e.name
128
129         ik.arm_e.parent = mt.arm_e.parent
130         ik.forearm_e.connected = mt.arm_e.connected
131         
132         ik.forearm_e.parent = ik.arm_e
133         ik.forearm_e.connected = True
134         
135         
136         # Add the bone used for the arms poll target
137         ik.pole = add_pole_target_bone(obj, mt.forearm, "elbow_poll", mode='+Z')
138         
139         bpy.ops.object.mode_set(mode='OBJECT')
140         
141         ik.update()
142         
143         con = ik.forearm_p.constraints.new('IK')
144         con.target = obj
145         con.subtarget = ik.hand
146         con.pole_target = obj
147         con.pole_subtarget = ik.pole
148         
149         con.use_tail = True
150         con.use_stretch = True
151         con.use_target = True
152         con.use_rotation =  False
153         con.chain_length = 2
154         con.pole_angle = -90.0 # XXX, RAD2DEG
155         
156         # ID Propery on the hand for IK/FK switch
157         
158         prop = rna_idprop_ui_prop_get(ik.hand_p, "ik", create=True)
159         ik.hand_p["ik"] = 0.5
160         prop["soft_min"] = 0.0
161         prop["soft_max"] = 1.0
162         
163         bpy.ops.object.mode_set(mode='EDIT')
164         
165         ik.arm = ik.arm
166         ik.forearm = ik.forearm
167         ik.hand = ik.hand
168         ik.pole = ik.pole
169     
170     def chain_switch(prefix="MCH-%s"):
171         
172         sw.update()
173         mt.update()
174         
175         sw.shoulder_e = copy_bone_simple(arm, mt.shoulder, prefix % mt.shoulder)
176         sw.shoulder = sw.shoulder_e.name
177         sw.shoulder_e.parent = mt.shoulder_e.parent
178         sw.shoulder_e.connected = mt.shoulder_e.connected
179
180         sw.arm_e = copy_bone_simple(arm, mt.arm, prefix % mt.arm)
181         sw.arm = sw.arm_e.name
182         sw.arm_e.parent = sw.shoulder_e
183         sw.arm_e.connected = arm.edit_bones[mt.shoulder].connected
184         
185         sw.forearm_e = copy_bone_simple(arm, mt.forearm, prefix % mt.forearm)
186         sw.forearm = sw.forearm_e.name
187         sw.forearm_e.parent = sw.arm_e
188         sw.forearm_e.connected = arm.edit_bones[mt.forearm].connected
189
190         sw.hand_e = copy_bone_simple(arm, mt.hand, prefix % mt.hand)
191         sw.hand = sw.hand_e.name
192         sw.hand_e.parent = sw.forearm_e
193         sw.hand_e.connected = arm.edit_bones[mt.hand].connected
194         
195         # The sw.hand_e needs to own all the children on the metarig's hand
196         for child in mt.hand_e.children:
197             child.parent = sw.hand_e
198         
199         
200         # These are made the children of sw.shoulder_e
201         
202         
203         bpy.ops.object.mode_set(mode='OBJECT')
204         
205         # Add constraints
206         sw.update()
207         
208         #dummy, ik.arm, ik.forearm, ik.hand, ik.pole = ik_chain_tuple
209         
210         ik_driver_path = obj.pose.bones[ik.hand].path_to_id() + '["ik"]'
211         
212         
213         def ik_fk_driver(con):
214             '''
215             3 bones use this for ik/fk switching
216             '''
217             fcurve = con.driver_add("influence", 0)
218             driver = fcurve.driver
219             tar = driver.targets.new()
220             driver.type = 'AVERAGE'
221             tar.name = "ik"
222             tar.id_type = 'OBJECT'
223             tar.id = obj
224             tar.rna_path = ik_driver_path
225
226         # ***********
227         con = sw.arm_p.constraints.new('COPY_ROTATION')
228         con.name = "FK"
229         con.target = obj
230         con.subtarget = mt.arm
231
232         con = sw.arm_p.constraints.new('COPY_ROTATION')
233
234         con.target = obj
235         con.subtarget = ik.arm
236         con.influence = 0.5
237         ik_fk_driver(con)
238         
239         # ***********
240         con = sw.forearm_p.constraints.new('COPY_ROTATION')
241         con.name = "FK"
242         con.target = obj
243         con.subtarget = mt.forearm
244
245         con = sw.forearm_p.constraints.new('COPY_ROTATION')
246         con.name = "IK"
247         con.target = obj
248         con.subtarget = ik.forearm
249         con.influence = 0.5
250         ik_fk_driver(con)
251         
252         # ***********
253         con = sw.hand_p.constraints.new('COPY_ROTATION')
254         con.name = "FK"
255         con.target = obj
256         con.subtarget = mt.hand
257
258         con = sw.hand_p.constraints.new('COPY_ROTATION')
259         con.name = "IK"
260         con.target = obj
261         con.subtarget = ik.hand
262         con.influence = 0.5
263         ik_fk_driver(con)
264         
265         
266         add_stretch_to(obj, sw.forearm, ik.pole, "VIS-elbow_ik_poll")
267         add_stretch_to(obj, sw.hand, ik.hand, "VIS-hand_ik")
268         
269         bpy.ops.object.mode_set(mode='EDIT')
270
271
272     def chain_shoulder(prefix="MCH-%s"):
273
274         sw.socket_e = copy_bone_simple(arm, mt.arm, (prefix % mt.arm) + "_socket")
275         sw.socket = sw.socket_e.name
276         sw.socket_e.tail = arm.edit_bones[mt.shoulder].tail
277         
278         
279         # Set the shoulder as parent
280         ik.update()
281         sw.update()
282         mt.update()
283         
284         sw.socket_e.parent = sw.shoulder_e
285         ik.arm_e.parent = sw.shoulder_e
286         
287         
288         # ***** add the shoulder hinge
289         # yes this is correct, the shoulder copy gets the arm's name
290         ex.arm_hinge_e = copy_bone_simple(arm, mt.shoulder, (prefix % mt.arm) + "_hinge")
291         ex.arm_hinge = ex.arm_hinge_e.name
292         offset = ex.arm_hinge_e.length / 2.0
293         
294         ex.arm_hinge_e.head.y += offset
295         ex.arm_hinge_e.tail.y += offset
296         
297         # Note: meta arm becomes child of hinge
298         mt.arm_e.parent = ex.arm_hinge_e
299         
300         
301         bpy.ops.object.mode_set(mode='OBJECT')
302         
303         ex.update()
304         
305         con = mt.arm_p.constraints.new('COPY_LOCATION')
306         con.target = obj
307         con.subtarget = sw.socket
308         
309         
310         # Hinge constraint & driver
311         con = ex.arm_hinge_p.constraints.new('COPY_ROTATION')
312         con.name = "hinge"
313         con.target = obj
314         con.subtarget = sw.shoulder
315         driver_fcurve = con.driver_add("influence", 0)
316         driver = driver_fcurve.driver
317
318         
319         controller_path = mt.arm_p.path_to_id()
320         # add custom prop
321         mt.arm_p["hinge"] = 0.0
322         prop = rna_idprop_ui_prop_get(mt.arm_p, "hinge", create=True)
323         prop["soft_min"] = 0.0
324         prop["soft_max"] = 1.0
325         
326         
327         # *****
328         driver = driver_fcurve.driver
329         driver.type = 'AVERAGE'
330         
331         tar = driver.targets.new()
332         tar.name = "hinge"
333         tar.id_type = 'OBJECT'
334         tar.id = obj
335         tar.rna_path = controller_path + '["hinge"]'
336         
337         
338         bpy.ops.object.mode_set(mode='EDIT')
339         
340         # remove the shoulder and re-parent 
341         
342         
343     
344     chain_init()
345     chain_ik()
346     chain_switch()
347     chain_shoulder()
348     
349     # Shoulder with its delta and hinge.
350     
351     # TODO - return a list for fk and IK
352     return None