11
11
class Rig :
12
12
13
13
CTRL_SCALE = 0.1
14
+ MCH_SCALE = 0.3
14
15
15
16
def __init__ (self , obj , bone_name , params ):
16
17
self .obj = obj
@@ -26,19 +27,45 @@ def __init__(self, obj, bone_name, params):
26
27
for child in edit_bone .children_recursive :
27
28
self .bones ['org' ].remove (child .name )
28
29
30
+ self .start_bones = self .get_start_bones ()
29
31
self .bones ['ctrl' ] = dict ()
32
+ self .bones ['mch' ] = dict ()
33
+ self .bones ['def' ] = dict ()
30
34
31
- def create_controls (self ):
35
+ def create_mch (self ):
32
36
bpy .ops .object .mode_set (mode = 'EDIT' )
33
37
edit_bones = self .obj .data .edit_bones
34
38
35
- start_bones = []
39
+ for name in self .start_bones :
40
+ subchain = [name ]
41
+ subchain .extend (connected_children_names (self .obj , name ))
42
+ self .bones ['mch' ][strip_org (name )] = []
36
43
37
- for name in self .bones ['org' ][1 :]:
38
- if not edit_bones [name ].use_connect :
39
- start_bones .append (name )
44
+ for subname in subchain :
45
+ mch = copy_bone (self .obj , subname , assign_name = make_mechanism_name (strip_org (subname )))
46
+ edit_bones [mch ].parent = None
47
+ edit_bones [mch ].length *= self .MCH_SCALE
48
+ self .bones ['mch' ][strip_org (name )].append (mch )
49
+
50
+ def create_def (self ):
51
+ bpy .ops .object .mode_set (mode = 'EDIT' )
52
+ edit_bones = self .obj .data .edit_bones
40
53
41
- for name in start_bones :
54
+ for name in self .start_bones :
55
+ subchain = [name ]
56
+ subchain .extend (connected_children_names (self .obj , name ))
57
+ self .bones ['def' ][strip_org (name )] = []
58
+
59
+ for subname in subchain :
60
+ def_bone = copy_bone (self .obj , subname , assign_name = make_deformer_name (strip_org (subname )))
61
+ edit_bones [def_bone ].parent = None
62
+ self .bones ['def' ][strip_org (name )].append (def_bone )
63
+
64
+ def create_controls (self ):
65
+ bpy .ops .object .mode_set (mode = 'EDIT' )
66
+ edit_bones = self .obj .data .edit_bones
67
+
68
+ for name in self .start_bones :
42
69
subchain = [name ]
43
70
subchain .extend (connected_children_names (self .obj , name ))
44
71
self .bones ['ctrl' ][strip_org (name )] = []
@@ -55,13 +82,110 @@ def create_controls(self):
55
82
edit_bones [last_ctrl ].length *= self .CTRL_SCALE
56
83
self .bones ['ctrl' ][strip_org (name )].append (last_ctrl )
57
84
85
+ self .aggregate_ctrls ()
86
+
58
87
bpy .ops .object .mode_set (mode = 'OBJECT' )
59
88
for subchain in self .bones ['ctrl' ]:
60
89
for ctrl in self .bones ['ctrl' ][subchain ]:
61
90
create_sphere_widget (self .obj , ctrl )
62
91
92
+ def aggregate_ctrls (self ):
93
+ bpy .ops .object .mode_set (mode = 'EDIT' )
94
+ edit_bones = self .obj .data .edit_bones
95
+
96
+ aggregates = []
97
+
98
+ all_ctrls = []
99
+
100
+ for subchain in self .start_bones :
101
+ for ctrl in self .bones ['ctrl' ][strip_org (subchain )]:
102
+ all_ctrls .append (ctrl )
103
+
104
+ while 1 :
105
+ ctrl = all_ctrls [0 ]
106
+ aggregate = [ctrl ]
107
+ for ctrl2 in all_ctrls [1 :]:
108
+ if edit_bones [ctrl ].head == edit_bones [ctrl2 ].head :
109
+ aggregate .append (ctrl2 )
110
+ for element in aggregate :
111
+ all_ctrls .remove (element )
112
+ if len (aggregate ) > 1 :
113
+ aggregates .append (aggregate )
114
+ if not all_ctrls :
115
+ break
116
+
117
+ if aggregates :
118
+ self .bones ['ctrl' ]['aggregate' ] = []
119
+
120
+ for aggregate in aggregates :
121
+ name = self .get_aggregate_name (aggregate )
122
+ aggregate_ctrl = copy_bone (self .obj , aggregate [0 ], name )
123
+ self .bones ['ctrl' ]['aggregate' ].append (aggregate_ctrl )
124
+ for ctrl in aggregate :
125
+ edit_bones .remove (edit_bones [ctrl ])
126
+ for subchain in self .start_bones :
127
+ if ctrl in self .bones ['ctrl' ][strip_org (subchain )]:
128
+ self .bones ['ctrl' ][strip_org (subchain )].remove (ctrl )
129
+ continue
130
+
131
+ return True
132
+
133
+ def get_aggregate_name (self , aggregate ):
134
+
135
+ total = '.' .join (aggregate )
136
+
137
+ root = aggregate [0 ].split ('.' )[0 ]
138
+ for name in aggregate [1 :]:
139
+ if name .split ('.' )[0 ] not in root :
140
+ root = '.' .join ([root , name .split ('.' )[0 ]])
141
+
142
+ name = root
143
+
144
+ t_b = ''
145
+ if 'T' in total and 'B' in total :
146
+ t_b = ''
147
+ elif 'T' in total :
148
+ t_b = 'T'
149
+ elif 'B' in total :
150
+ t_b = 'B'
151
+
152
+ if t_b :
153
+ name = '.' .join ([name , t_b ])
154
+
155
+ l_r = ''
156
+ if 'L' in total and 'R' in total :
157
+ l_r = ''
158
+ elif 'L' in total :
159
+ l_r = 'L'
160
+ elif 'R' in total :
161
+ l_r = 'R'
162
+
163
+ if l_r :
164
+ name = '.' .join ([name , l_r ])
165
+
166
+ return name
167
+
168
+ def get_start_bones (self ):
169
+ """
170
+ Returns all the bones starting a subchain of the face
171
+ :return:
172
+ """
173
+
174
+ bpy .ops .object .mode_set (mode = 'EDIT' )
175
+ edit_bones = self .obj .data .edit_bones
176
+
177
+ start_bones = []
178
+
179
+ for name in self .bones ['org' ][1 :]:
180
+ if not edit_bones [name ].use_connect :
181
+ start_bones .append (name )
182
+
183
+ return start_bones
184
+
63
185
def generate (self ):
64
186
187
+ self .create_mch ()
188
+ self .create_def ()
65
189
self .create_controls ()
66
190
67
191
return ["" ]
0 commit comments