1
1
import bpy
2
2
from ...utils import copy_bone
3
3
from ...utils import strip_org , make_deformer_name , connected_children_names
4
- from ...utils import make_mechanism_name , put_bone , create_sphere_widget
5
- from ...utils import create_widget , create_circle_widget
4
+ from ...utils import put_bone , create_sphere_widget
5
+ from ...utils import create_circle_widget , align_bone_x_axis
6
6
from ...utils import MetarigError
7
- from rna_prop_ui import rna_idprop_ui_prop_get
8
7
9
8
10
9
class Rig :
@@ -26,25 +25,46 @@ def __init__(self, obj, bone_name, params):
26
25
"RIGIFY ERROR: invalid rig structure on bone: %s" % (strip_org (bone_name ))
27
26
)
28
27
28
+ def orient_org_bones (self ):
29
+
30
+ bpy .ops .object .mode_set (mode = 'EDIT' )
31
+ eb = self .obj .data .edit_bones
32
+
33
+ if self .params .roll_alignment == "automatic" :
34
+
35
+ first_bone = eb [self .org_bones [0 ]]
36
+ last_bone = eb [self .org_bones [- 1 ]]
37
+
38
+ # Orient uarm farm bones
39
+ chain_y_axis = last_bone .tail - first_bone .head
40
+ chain_rot_axis = first_bone .y_axis .cross (chain_y_axis ) # ik-plane normal axis (rotation)
41
+ if chain_rot_axis .length < first_bone .length / 100 :
42
+ chain_rot_axis = first_bone .x_axis .normalized ()
43
+ else :
44
+ chain_rot_axis = chain_rot_axis .normalized ()
45
+
46
+ for bone in self .org_bones :
47
+ align_bone_x_axis (self .obj , bone , chain_rot_axis )
48
+
29
49
def make_controls (self ):
30
50
31
- bpy .ops .object .mode_set (mode = 'EDIT' )
51
+ bpy .ops .object .mode_set (mode = 'EDIT' )
32
52
org_bones = self .org_bones
33
53
34
54
ctrl_chain = []
35
- for i in range ( len ( org_bones ) ):
55
+ for i in range (len (org_bones ) ):
36
56
name = org_bones [i ]
37
57
38
- ctrl_bone = copy_bone (
58
+ ctrl_bone = copy_bone (
39
59
self .obj ,
40
60
name ,
41
61
strip_org (name )
42
62
)
43
63
44
- ctrl_chain .append ( ctrl_bone )
64
+ ctrl_chain .append (ctrl_bone )
45
65
46
66
# Make widgets
47
- bpy .ops .object .mode_set (mode = 'OBJECT' )
67
+ bpy .ops .object .mode_set (mode = 'OBJECT' )
48
68
49
69
for ctrl in ctrl_chain :
50
70
create_circle_widget (self .obj , ctrl , radius = 0.3 , head_tail = 0.5 )
@@ -58,8 +78,8 @@ def make_tweaks(self):
58
78
org_bones = self .org_bones
59
79
60
80
tweak_chain = []
61
- for i in range ( len ( org_bones ) + 1 ):
62
- if i == len ( org_bones ):
81
+ for i in range (len (org_bones ) + 1 ):
82
+ if i == len (org_bones ):
63
83
# Make final tweak at the tip of the tentacle
64
84
name = org_bones [i - 1 ]
65
85
else :
@@ -71,32 +91,32 @@ def make_tweaks(self):
71
91
"tweak_" + strip_org (name )
72
92
)
73
93
74
- tweak_e = eb [ tweak_bone ]
94
+ tweak_e = eb [tweak_bone ]
75
95
76
- tweak_e .length /= 2 # Set size to half
96
+ tweak_e .length /= 2 # Set size to half
77
97
78
98
if i == len ( org_bones ):
79
99
# Position final tweak at the tip
80
- put_bone ( self .obj , tweak_bone , eb [ org_bones [- 1 ]].tail )
100
+ put_bone (self .obj , tweak_bone , eb [org_bones [- 1 ]].tail )
81
101
82
- tweak_chain .append ( tweak_bone )
102
+ tweak_chain .append (tweak_bone )
83
103
84
104
# Make widgets
85
- bpy .ops .object .mode_set (mode = 'OBJECT' )
105
+ bpy .ops .object .mode_set (mode = 'OBJECT' )
86
106
87
107
for tweak in tweak_chain :
88
- create_sphere_widget ( self .obj , tweak )
108
+ create_sphere_widget (self .obj , tweak )
89
109
90
- tweak_pb = self .obj .pose .bones [ tweak ]
110
+ tweak_pb = self .obj .pose .bones [tweak ]
91
111
92
112
# Set locks
93
- if tweak_chain .index ( tweak ) != len ( tweak_chain ) - 1 :
113
+ if tweak_chain .index (tweak ) != len (tweak_chain ) - 1 :
94
114
tweak_pb .lock_rotation = (True , False , True )
95
- tweak_pb .lock_scale = (False , True , False )
115
+ tweak_pb .lock_scale = (False , True , False )
96
116
else :
97
117
tweak_pb .lock_rotation_w = True
98
- tweak_pb .lock_rotation = (True , True , True )
99
- tweak_pb .lock_scale = (True , True , True )
118
+ tweak_pb .lock_rotation = (True , True , True )
119
+ tweak_pb .lock_scale = (True , True , True )
100
120
101
121
# Set up tweak bone layers
102
122
if self .tweak_layers :
@@ -106,79 +126,78 @@ def make_tweaks(self):
106
126
107
127
def make_deform (self ):
108
128
109
- bpy .ops .object .mode_set (mode = 'EDIT' )
129
+ bpy .ops .object .mode_set (mode = 'EDIT' )
110
130
org_bones = self .org_bones
111
131
112
132
def_chain = []
113
- for i in range ( len ( org_bones ) ):
133
+ for i in range (len (org_bones ) ):
114
134
name = org_bones [i ]
115
135
116
- def_bone = copy_bone (
136
+ def_bone = copy_bone (
117
137
self .obj ,
118
138
name ,
119
139
make_deformer_name (strip_org (name ))
120
140
)
121
141
122
- def_chain .append ( def_bone )
142
+ def_chain .append (def_bone )
123
143
124
144
return def_chain
125
145
126
146
def parent_bones (self , all_bones ):
127
147
128
- bpy .ops .object .mode_set (mode = 'EDIT' )
148
+ bpy .ops .object .mode_set (mode = 'EDIT' )
129
149
org_bones = self .org_bones
130
- eb = self .obj .data .edit_bones
150
+ eb = self .obj .data .edit_bones
131
151
132
152
# Parent control bones
133
153
for bone in all_bones ['control' ][1 :]:
134
- previous_index = all_bones ['control' ].index ( bone ) - 1
135
- eb [ bone ].parent = eb [ all_bones ['control' ][previous_index ] ]
154
+ previous_index = all_bones ['control' ].index (bone ) - 1
155
+ eb [bone ].parent = eb [all_bones ['control' ][previous_index ]]
136
156
137
157
# Parent tweak bones
138
158
tweaks = all_bones ['tweak' ]
139
159
for tweak in all_bones ['tweak' ]:
140
160
parent = ''
141
- if tweaks .index ( tweak ) == len ( tweaks ) - 1 :
142
- parent = all_bones ['control' ][ - 1 ]
161
+ if tweaks .index (tweak ) == len (tweaks ) - 1 :
162
+ parent = all_bones ['control' ][- 1 ]
143
163
else :
144
- parent = all_bones ['control' ][ tweaks .index ( tweak ) ]
164
+ parent = all_bones ['control' ][tweaks .index (tweak ) ]
145
165
146
- eb [ tweak ].parent = eb [ parent ]
166
+ eb [tweak ].parent = eb [parent ]
147
167
148
168
# Parent deform bones
149
169
for bone in all_bones ['deform' ][1 :]:
150
- previous_index = all_bones ['deform' ].index ( bone ) - 1
170
+ previous_index = all_bones ['deform' ].index (bone ) - 1
151
171
152
- eb [ bone ].parent = eb [ all_bones ['deform' ][previous_index ] ]
153
- eb [ bone ].use_connect = True
172
+ eb [bone ].parent = eb [all_bones ['deform' ][previous_index ]]
173
+ eb [bone ].use_connect = True
154
174
155
175
# Parent org bones ( to tweaks by default, or to the controls )
156
- for org , tweak in zip ( org_bones , all_bones ['tweak' ] ):
157
- eb [ org ].parent = eb [ tweak ]
176
+ for org , tweak in zip (org_bones , all_bones ['tweak' ]):
177
+ eb [org ].parent = eb [tweak ]
158
178
159
179
def make_constraints (self , all_bones ):
160
180
161
- bpy .ops .object .mode_set (mode = 'OBJECT' )
162
- org_bones = self .org_bones
163
- pb = self .obj .pose .bones
181
+ bpy .ops .object .mode_set (mode = 'OBJECT' )
182
+ pb = self .obj .pose .bones
164
183
165
184
# Deform bones' constraints
166
- ctrls = all_bones ['control' ]
167
- tweaks = all_bones ['tweak' ]
168
- deforms = all_bones ['deform' ]
185
+ ctrls = all_bones ['control' ]
186
+ tweaks = all_bones ['tweak' ]
187
+ deforms = all_bones ['deform' ]
169
188
170
189
for deform , tweak , ctrl in zip ( deforms , tweaks , ctrls ):
171
- con = pb [deform ].constraints .new ('COPY_TRANSFORMS' )
172
- con .target = self .obj
190
+ con = pb [deform ].constraints .new ('COPY_TRANSFORMS' )
191
+ con .target = self .obj
173
192
con .subtarget = tweak
174
193
175
- con = pb [deform ].constraints .new ('DAMPED_TRACK' )
176
- con .target = self .obj
177
- con .subtarget = tweaks [ tweaks .index ( tweak ) + 1 ]
194
+ con = pb [deform ].constraints .new ('DAMPED_TRACK' )
195
+ con .target = self .obj
196
+ con .subtarget = tweaks [tweaks .index (tweak ) + 1 ]
178
197
179
- con = pb [deform ].constraints .new ('STRETCH_TO' )
180
- con .target = self .obj
181
- con .subtarget = tweaks [ tweaks .index ( tweak ) + 1 ]
198
+ con = pb [deform ].constraints .new ('STRETCH_TO' )
199
+ con .target = self .obj
200
+ con .subtarget = tweaks [tweaks .index (tweak ) + 1 ]
182
201
183
202
# Control bones' constraints
184
203
if ctrl != ctrls [0 ]:
@@ -195,23 +214,25 @@ def make_constraints(self, all_bones):
195
214
con .owner_space = 'LOCAL'
196
215
197
216
def generate (self ):
198
- bpy .ops .object .mode_set (mode = 'EDIT' )
217
+ bpy .ops .object .mode_set (mode = 'EDIT' )
199
218
eb = self .obj .data .edit_bones
200
219
220
+ self .orient_org_bones ()
221
+
201
222
# Clear all initial parenting
202
223
for bone in self .org_bones :
203
- # eb[ bone ].parent = None
204
- eb [ bone ].use_connect = False
224
+ # eb[ bone ].parent = None
225
+ eb [bone ].use_connect = False
205
226
206
227
# Creating all bones
207
- ctrl_chain = self .make_controls ()
228
+ ctrl_chain = self .make_controls ()
208
229
tweak_chain = self .make_tweaks ()
209
- def_chain = self .make_deform ()
230
+ def_chain = self .make_deform ()
210
231
211
232
all_bones = {
212
- 'control' : ctrl_chain ,
213
- 'tweak' : tweak_chain ,
214
- 'deform' : def_chain
233
+ 'control' : ctrl_chain ,
234
+ 'tweak' : tweak_chain ,
235
+ 'deform' : def_chain
215
236
}
216
237
217
238
self .make_constraints (all_bones )
@@ -230,25 +251,29 @@ def add_parameters(params):
230
251
231
252
# Setting up extra tweak layers
232
253
params .tweak_extra_layers = bpy .props .BoolProperty (
233
- name = "tweak_extra_layers" ,
234
- default = True ,
235
- description = ""
254
+ name = "tweak_extra_layers" ,
255
+ default = True ,
256
+ description = ""
236
257
)
237
258
238
259
params .tweak_layers = bpy .props .BoolVectorProperty (
239
- size = 32 ,
240
- description = "Layers for the tweak controls to be on" ,
241
- default = tuple ( [ i == 1 for i in range (0 , 32 ) ] )
260
+ size = 32 ,
261
+ description = "Layers for the tweak controls to be on" ,
262
+ default = tuple ([ i == 1 for i in range (0 , 32 )] )
242
263
)
243
264
265
+ items = [('automatic' , 'Automatic' , '' ), ('manual' , 'Manual' , '' )]
266
+ params .roll_alignment = bpy .props .EnumProperty (items = items , name = "Bone roll alignment" , default = 'automatic' )
267
+
244
268
245
269
def parameters_ui (layout , params ):
246
270
""" Create the ui for the rig parameters.
247
271
"""
248
272
249
273
r = layout .row ()
250
- col = r .column (align = True )
251
- row = col .row (align = True )
274
+ r .prop (params , "roll_alignment" )
275
+
276
+ row = layout .row (align = True )
252
277
for i , axis in enumerate (['x' , 'y' , 'z' ]):
253
278
row .prop (params , "copy_rotation_axes" , index = i , toggle = True , text = axis )
254
279
@@ -286,7 +311,7 @@ def parameters_ui(layout, params):
286
311
287
312
row = col .row (align = True )
288
313
289
- for i in range ( 24 , 32 ): # Layers 24-31
314
+ for i in range (24 , 32 ): # Layers 24-31
290
315
icon = "NONE"
291
316
if bone_layers [i ]:
292
317
icon = "LAYER_ACTIVE"
0 commit comments