11import bpy
22from ...utils import copy_bone
33from ...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
66from ...utils import MetarigError
7- from rna_prop_ui import rna_idprop_ui_prop_get
87
98
109class Rig :
@@ -26,25 +25,46 @@ def __init__(self, obj, bone_name, params):
2625 "RIGIFY ERROR: invalid rig structure on bone: %s" % (strip_org (bone_name ))
2726 )
2827
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+
2949 def make_controls (self ):
3050
31- bpy .ops .object .mode_set (mode = 'EDIT' )
51+ bpy .ops .object .mode_set (mode = 'EDIT' )
3252 org_bones = self .org_bones
3353
3454 ctrl_chain = []
35- for i in range ( len ( org_bones ) ):
55+ for i in range (len (org_bones ) ):
3656 name = org_bones [i ]
3757
38- ctrl_bone = copy_bone (
58+ ctrl_bone = copy_bone (
3959 self .obj ,
4060 name ,
4161 strip_org (name )
4262 )
4363
44- ctrl_chain .append ( ctrl_bone )
64+ ctrl_chain .append (ctrl_bone )
4565
4666 # Make widgets
47- bpy .ops .object .mode_set (mode = 'OBJECT' )
67+ bpy .ops .object .mode_set (mode = 'OBJECT' )
4868
4969 for ctrl in ctrl_chain :
5070 create_circle_widget (self .obj , ctrl , radius = 0.3 , head_tail = 0.5 )
@@ -58,8 +78,8 @@ def make_tweaks(self):
5878 org_bones = self .org_bones
5979
6080 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 ):
6383 # Make final tweak at the tip of the tentacle
6484 name = org_bones [i - 1 ]
6585 else :
@@ -71,32 +91,32 @@ def make_tweaks(self):
7191 "tweak_" + strip_org (name )
7292 )
7393
74- tweak_e = eb [ tweak_bone ]
94+ tweak_e = eb [tweak_bone ]
7595
76- tweak_e .length /= 2 # Set size to half
96+ tweak_e .length /= 2 # Set size to half
7797
7898 if i == len ( org_bones ):
7999 # 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 )
81101
82- tweak_chain .append ( tweak_bone )
102+ tweak_chain .append (tweak_bone )
83103
84104 # Make widgets
85- bpy .ops .object .mode_set (mode = 'OBJECT' )
105+ bpy .ops .object .mode_set (mode = 'OBJECT' )
86106
87107 for tweak in tweak_chain :
88- create_sphere_widget ( self .obj , tweak )
108+ create_sphere_widget (self .obj , tweak )
89109
90- tweak_pb = self .obj .pose .bones [ tweak ]
110+ tweak_pb = self .obj .pose .bones [tweak ]
91111
92112 # Set locks
93- if tweak_chain .index ( tweak ) != len ( tweak_chain ) - 1 :
113+ if tweak_chain .index (tweak ) != len (tweak_chain ) - 1 :
94114 tweak_pb .lock_rotation = (True , False , True )
95- tweak_pb .lock_scale = (False , True , False )
115+ tweak_pb .lock_scale = (False , True , False )
96116 else :
97117 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 )
100120
101121 # Set up tweak bone layers
102122 if self .tweak_layers :
@@ -106,79 +126,78 @@ def make_tweaks(self):
106126
107127 def make_deform (self ):
108128
109- bpy .ops .object .mode_set (mode = 'EDIT' )
129+ bpy .ops .object .mode_set (mode = 'EDIT' )
110130 org_bones = self .org_bones
111131
112132 def_chain = []
113- for i in range ( len ( org_bones ) ):
133+ for i in range (len (org_bones ) ):
114134 name = org_bones [i ]
115135
116- def_bone = copy_bone (
136+ def_bone = copy_bone (
117137 self .obj ,
118138 name ,
119139 make_deformer_name (strip_org (name ))
120140 )
121141
122- def_chain .append ( def_bone )
142+ def_chain .append (def_bone )
123143
124144 return def_chain
125145
126146 def parent_bones (self , all_bones ):
127147
128- bpy .ops .object .mode_set (mode = 'EDIT' )
148+ bpy .ops .object .mode_set (mode = 'EDIT' )
129149 org_bones = self .org_bones
130- eb = self .obj .data .edit_bones
150+ eb = self .obj .data .edit_bones
131151
132152 # Parent control bones
133153 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 ]]
136156
137157 # Parent tweak bones
138158 tweaks = all_bones ['tweak' ]
139159 for tweak in all_bones ['tweak' ]:
140160 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 ]
143163 else :
144- parent = all_bones ['control' ][ tweaks .index ( tweak ) ]
164+ parent = all_bones ['control' ][tweaks .index (tweak ) ]
145165
146- eb [ tweak ].parent = eb [ parent ]
166+ eb [tweak ].parent = eb [parent ]
147167
148168 # Parent deform bones
149169 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
151171
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
154174
155175 # 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 ]
158178
159179 def make_constraints (self , all_bones ):
160180
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
164183
165184 # 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' ]
169188
170189 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
173192 con .subtarget = tweak
174193
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 ]
178197
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 ]
182201
183202 # Control bones' constraints
184203 if ctrl != ctrls [0 ]:
@@ -195,23 +214,25 @@ def make_constraints(self, all_bones):
195214 con .owner_space = 'LOCAL'
196215
197216 def generate (self ):
198- bpy .ops .object .mode_set (mode = 'EDIT' )
217+ bpy .ops .object .mode_set (mode = 'EDIT' )
199218 eb = self .obj .data .edit_bones
200219
220+ self .orient_org_bones ()
221+
201222 # Clear all initial parenting
202223 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
205226
206227 # Creating all bones
207- ctrl_chain = self .make_controls ()
228+ ctrl_chain = self .make_controls ()
208229 tweak_chain = self .make_tweaks ()
209- def_chain = self .make_deform ()
230+ def_chain = self .make_deform ()
210231
211232 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
215236 }
216237
217238 self .make_constraints (all_bones )
@@ -230,25 +251,29 @@ def add_parameters(params):
230251
231252 # Setting up extra tweak layers
232253 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 = ""
236257 )
237258
238259 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 )] )
242263 )
243264
265+ items = [('automatic' , 'Automatic' , '' ), ('manual' , 'Manual' , '' )]
266+ params .roll_alignment = bpy .props .EnumProperty (items = items , name = "Bone roll alignment" , default = 'automatic' )
267+
244268
245269def parameters_ui (layout , params ):
246270 """ Create the ui for the rig parameters.
247271 """
248272
249273 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 )
252277 for i , axis in enumerate (['x' , 'y' , 'z' ]):
253278 row .prop (params , "copy_rotation_axes" , index = i , toggle = True , text = axis )
254279
@@ -286,7 +311,7 @@ def parameters_ui(layout, params):
286311
287312 row = col .row (align = True )
288313
289- for i in range ( 24 , 32 ): # Layers 24-31
314+ for i in range (24 , 32 ): # Layers 24-31
290315 icon = "NONE"
291316 if bone_layers [i ]:
292317 icon = "LAYER_ACTIVE"
0 commit comments