Update for changes in Blender's API
[blender-addons.git] / rigify / utils.py
blob876ee0d33d8f028de472fd12585363b4d187f061
1 #====================== BEGIN GPL LICENSE BLOCK ======================
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.
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.
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.
17 #======================= END GPL LICENSE BLOCK ========================
19 # <pep8 compliant>
21 import bpy
22 import imp
23 import importlib
24 import math
25 import random
26 import time
27 import re
28 import os
29 from mathutils import Vector, Matrix, Color
30 from rna_prop_ui import rna_idprop_ui_prop_get
32 RIG_DIR = "rigs" # Name of the directory where rig types are kept
33 METARIG_DIR = "metarigs" # Name of the directory where metarigs are kept
35 ORG_PREFIX = "ORG-" # Prefix of original bones.
36 MCH_PREFIX = "MCH-" # Prefix of mechanism bones.
37 DEF_PREFIX = "DEF-" # Prefix of deformation bones.
38 WGT_PREFIX = "WGT-" # Prefix for widget objects
39 ROOT_NAME = "root" # Name of the root bone.
41 WGT_LAYERS = [x == 19 for x in range(0, 20)] # Widgets go on the last scene layer.
43 MODULE_NAME = "rigify" # Windows/Mac blender is weird, so __package__ doesn't work
45 outdated_types = {"pitchipoy.limbs.super_limb": "limbs.super_limb",
46 "pitchipoy.limbs.super_arm": "limbs.super_limb",
47 "pitchipoy.limbs.super_leg": "limbs.super_limb",
48 "pitchipoy.limbs.super_front_paw": "limbs.super_limb",
49 "pitchipoy.limbs.super_rear_paw": "limbs.super_limb",
50 "pitchipoy.limbs.super_finger": "limbs.super_finger",
51 "pitchipoy.super_torso_turbo": "spines.super_spine",
52 "pitchipoy.simple_tentacle": "limbs.simple_tentacle",
53 "pitchipoy.super_face": "faces.super_face",
54 "pitchipoy.super_palm": "limbs.super_palm",
55 "pitchipoy.super_copy": "basic.super_copy",
56 "pitchipoy.tentacle": "",
57 "palm": "limbs.super_palm",
58 "basic.copy": "basic.super_copy",
59 "biped.arm": "",
60 "biped.leg": "",
61 "finger": "",
62 "neck_short": "",
63 "misc.delta": "",
64 "spine": ""
67 #=======================================================================
68 # Error handling
69 #=======================================================================
70 class MetarigError(Exception):
71 """ Exception raised for errors.
72 """
73 def __init__(self, message):
74 self.message = message
76 def __str__(self):
77 return repr(self.message)
80 #=======================================================================
81 # Name manipulation
82 #=======================================================================
84 def strip_trailing_number(s):
85 m = re.search(r'\.(\d{3})$', s)
86 return s[0:-4] if m else s
89 def unique_name(collection, base_name):
90 base_name = strip_trailing_number(base_name)
91 count = 1
92 name = base_name
94 while collection.get(name):
95 name = "%s.%03d" % (base_name, count)
96 count += 1
97 return name
100 def org_name(name):
101 """ Returns the name with ORG_PREFIX stripped from it.
103 if name.startswith(ORG_PREFIX):
104 return name[len(ORG_PREFIX):]
105 else:
106 return name
109 def strip_org(name):
110 """ Returns the name with ORG_PREFIX stripped from it.
112 if name.startswith(ORG_PREFIX):
113 return name[len(ORG_PREFIX):]
114 else:
115 return name
116 org_name = strip_org
119 def strip_mch(name):
120 """ Returns the name with ORG_PREFIX stripped from it.
122 if name.startswith(MCH_PREFIX):
123 return name[len(MCH_PREFIX):]
124 else:
125 return name
127 def org(name):
128 """ Prepends the ORG_PREFIX to a name if it doesn't already have
129 it, and returns it.
131 if name.startswith(ORG_PREFIX):
132 return name
133 else:
134 return ORG_PREFIX + name
135 make_original_name = org
138 def mch(name):
139 """ Prepends the MCH_PREFIX to a name if it doesn't already have
140 it, and returns it.
142 if name.startswith(MCH_PREFIX):
143 return name
144 else:
145 return MCH_PREFIX + name
146 make_mechanism_name = mch
149 def deformer(name):
150 """ Prepends the DEF_PREFIX to a name if it doesn't already have
151 it, and returns it.
153 if name.startswith(DEF_PREFIX):
154 return name
155 else:
156 return DEF_PREFIX + name
157 make_deformer_name = deformer
160 def insert_before_lr(name, text):
161 if name[-1] in ['l', 'L', 'r', 'R'] and name[-2] in ['.', '-', '_']:
162 return name[:-2] + text + name[-2:]
163 else:
164 return name + text
167 def upgradeMetarigTypes(metarig, revert=False):
168 """Replaces rigify_type properties from old versions with their current names
170 :param revert: revert types to previous version (if old type available)
173 if revert:
174 vals = list(outdated_types.values())
175 rig_defs = {v: k for k, v in outdated_types.items() if vals.count(v) == 1}
176 else:
177 rig_defs = outdated_types
179 for bone in metarig.pose.bones:
180 rig_type = bone.rigify_type
181 if rig_type in rig_defs:
182 bone.rigify_type = rig_defs[rig_type]
183 if 'leg' in rig_type:
184 bone.rigfy_parameters.limb_type = 'leg'
185 if 'arm' in rig_type:
186 bone.rigfy_parameters.limb_type = 'arm'
187 if 'paw' in rig_type:
188 bone.rigfy_parameters.limb_type = 'paw'
189 if rig_type == "basic.copy":
190 bone.rigify_parameters.make_widget = False
194 #=======================
195 # Bone manipulation
196 #=======================
198 def new_bone(obj, bone_name):
199 """ Adds a new bone to the given armature object.
200 Returns the resulting bone's name.
202 if obj == bpy.context.active_object and bpy.context.mode == 'EDIT_ARMATURE':
203 edit_bone = obj.data.edit_bones.new(bone_name)
204 name = edit_bone.name
205 edit_bone.head = (0, 0, 0)
206 edit_bone.tail = (0, 1, 0)
207 edit_bone.roll = 0
208 bpy.ops.object.mode_set(mode='OBJECT')
209 bpy.ops.object.mode_set(mode='EDIT')
210 return name
211 else:
212 raise MetarigError("Can't add new bone '%s' outside of edit mode" % bone_name)
215 def copy_bone_simple(obj, bone_name, assign_name=''):
216 """ Makes a copy of the given bone in the given armature object.
217 but only copies head, tail positions and roll. Does not
218 address parenting either.
220 #if bone_name not in obj.data.bones:
221 if bone_name not in obj.data.edit_bones:
222 raise MetarigError("copy_bone(): bone '%s' not found, cannot copy it" % bone_name)
224 if obj == bpy.context.active_object and bpy.context.mode == 'EDIT_ARMATURE':
225 if assign_name == '':
226 assign_name = bone_name
227 # Copy the edit bone
228 edit_bone_1 = obj.data.edit_bones[bone_name]
229 edit_bone_2 = obj.data.edit_bones.new(assign_name)
230 bone_name_1 = bone_name
231 bone_name_2 = edit_bone_2.name
233 # Copy edit bone attributes
234 edit_bone_2.layers = list(edit_bone_1.layers)
236 edit_bone_2.head = Vector(edit_bone_1.head)
237 edit_bone_2.tail = Vector(edit_bone_1.tail)
238 edit_bone_2.roll = edit_bone_1.roll
240 return bone_name_2
241 else:
242 raise MetarigError("Cannot copy bones outside of edit mode")
245 def copy_bone(obj, bone_name, assign_name=''):
246 """ Makes a copy of the given bone in the given armature object.
247 Returns the resulting bone's name.
249 #if bone_name not in obj.data.bones:
250 if bone_name not in obj.data.edit_bones:
251 raise MetarigError("copy_bone(): bone '%s' not found, cannot copy it" % bone_name)
253 if obj == bpy.context.active_object and bpy.context.mode == 'EDIT_ARMATURE':
254 if assign_name == '':
255 assign_name = bone_name
256 # Copy the edit bone
257 edit_bone_1 = obj.data.edit_bones[bone_name]
258 edit_bone_2 = obj.data.edit_bones.new(assign_name)
259 bone_name_1 = bone_name
260 bone_name_2 = edit_bone_2.name
262 edit_bone_2.parent = edit_bone_1.parent
263 edit_bone_2.use_connect = edit_bone_1.use_connect
265 # Copy edit bone attributes
266 edit_bone_2.layers = list(edit_bone_1.layers)
268 edit_bone_2.head = Vector(edit_bone_1.head)
269 edit_bone_2.tail = Vector(edit_bone_1.tail)
270 edit_bone_2.roll = edit_bone_1.roll
272 edit_bone_2.use_inherit_rotation = edit_bone_1.use_inherit_rotation
273 edit_bone_2.use_inherit_scale = edit_bone_1.use_inherit_scale
274 edit_bone_2.use_local_location = edit_bone_1.use_local_location
276 edit_bone_2.use_deform = edit_bone_1.use_deform
277 edit_bone_2.bbone_segments = edit_bone_1.bbone_segments
278 edit_bone_2.bbone_easein = edit_bone_1.bbone_easein
279 edit_bone_2.bbone_easeout = edit_bone_1.bbone_easeout
281 bpy.ops.object.mode_set(mode='OBJECT')
283 # Get the pose bones
284 pose_bone_1 = obj.pose.bones[bone_name_1]
285 pose_bone_2 = obj.pose.bones[bone_name_2]
287 # Copy pose bone attributes
288 pose_bone_2.rotation_mode = pose_bone_1.rotation_mode
289 pose_bone_2.rotation_axis_angle = tuple(pose_bone_1.rotation_axis_angle)
290 pose_bone_2.rotation_euler = tuple(pose_bone_1.rotation_euler)
291 pose_bone_2.rotation_quaternion = tuple(pose_bone_1.rotation_quaternion)
293 pose_bone_2.lock_location = tuple(pose_bone_1.lock_location)
294 pose_bone_2.lock_scale = tuple(pose_bone_1.lock_scale)
295 pose_bone_2.lock_rotation = tuple(pose_bone_1.lock_rotation)
296 pose_bone_2.lock_rotation_w = pose_bone_1.lock_rotation_w
297 pose_bone_2.lock_rotations_4d = pose_bone_1.lock_rotations_4d
299 # Copy custom properties
300 for key in pose_bone_1.keys():
301 if key != "_RNA_UI" \
302 and key != "rigify_parameters" \
303 and key != "rigify_type":
304 prop1 = rna_idprop_ui_prop_get(pose_bone_1, key, create=False)
305 prop2 = rna_idprop_ui_prop_get(pose_bone_2, key, create=True)
306 pose_bone_2[key] = pose_bone_1[key]
307 for key in prop1.keys():
308 prop2[key] = prop1[key]
310 bpy.ops.object.mode_set(mode='EDIT')
312 return bone_name_2
313 else:
314 raise MetarigError("Cannot copy bones outside of edit mode")
317 def flip_bone(obj, bone_name):
318 """ Flips an edit bone.
320 if bone_name not in obj.data.bones:
321 raise MetarigError("flip_bone(): bone '%s' not found, cannot copy it" % bone_name)
323 if obj == bpy.context.active_object and bpy.context.mode == 'EDIT_ARMATURE':
324 bone = obj.data.edit_bones[bone_name]
325 head = Vector(bone.head)
326 tail = Vector(bone.tail)
327 bone.tail = head + tail
328 bone.head = tail
329 bone.tail = head
330 else:
331 raise MetarigError("Cannot flip bones outside of edit mode")
334 def put_bone(obj, bone_name, pos):
335 """ Places a bone at the given position.
337 if bone_name not in obj.data.bones:
338 raise MetarigError("put_bone(): bone '%s' not found, cannot move it" % bone_name)
340 if obj == bpy.context.active_object and bpy.context.mode == 'EDIT_ARMATURE':
341 bone = obj.data.edit_bones[bone_name]
343 delta = pos - bone.head
344 bone.translate(delta)
345 else:
346 raise MetarigError("Cannot 'put' bones outside of edit mode")
349 def make_nonscaling_child(obj, bone_name, location, child_name_postfix=""):
350 """ Takes the named bone and creates a non-scaling child of it at
351 the given location. The returned bone (returned by name) is not
352 a true child, but behaves like one sans inheriting scaling.
354 It is intended as an intermediate construction to prevent rig types
355 from scaling with their parents. The named bone is assumed to be
356 an ORG bone.
358 if bone_name not in obj.data.bones:
359 raise MetarigError("make_nonscaling_child(): bone '%s' not found, cannot copy it" % bone_name)
361 if obj == bpy.context.active_object and bpy.context.mode == 'EDIT_ARMATURE':
362 # Create desired names for bones
363 name1 = make_mechanism_name(strip_org(insert_before_lr(bone_name, child_name_postfix + "_ns_ch")))
364 name2 = make_mechanism_name(strip_org(insert_before_lr(bone_name, child_name_postfix + "_ns_intr")))
366 # Create bones
367 child = copy_bone(obj, bone_name, name1)
368 intermediate_parent = copy_bone(obj, bone_name, name2)
370 # Get edit bones
371 eb = obj.data.edit_bones
372 child_e = eb[child]
373 intrpar_e = eb[intermediate_parent]
375 # Parenting
376 child_e.use_connect = False
377 child_e.parent = None
379 intrpar_e.use_connect = False
380 intrpar_e.parent = eb[bone_name]
382 # Positioning
383 child_e.length *= 0.5
384 intrpar_e.length *= 0.25
386 put_bone(obj, child, location)
387 put_bone(obj, intermediate_parent, location)
389 # Object mode
390 bpy.ops.object.mode_set(mode='OBJECT')
391 pb = obj.pose.bones
393 # Add constraints
394 con = pb[child].constraints.new('COPY_LOCATION')
395 con.name = "parent_loc"
396 con.target = obj
397 con.subtarget = intermediate_parent
399 con = pb[child].constraints.new('COPY_ROTATION')
400 con.name = "parent_loc"
401 con.target = obj
402 con.subtarget = intermediate_parent
404 bpy.ops.object.mode_set(mode='EDIT')
406 return child
407 else:
408 raise MetarigError("Cannot make nonscaling child outside of edit mode")
411 #=============================================
412 # Widget creation
413 #=============================================
415 def obj_to_bone(obj, rig, bone_name):
416 """ Places an object at the location/rotation/scale of the given bone.
418 if bpy.context.mode == 'EDIT_ARMATURE':
419 raise MetarigError("obj_to_bone(): does not work while in edit mode")
421 bone = rig.data.bones[bone_name]
423 mat = rig.matrix_world * bone.matrix_local
425 obj.location = mat.to_translation()
427 obj.rotation_mode = 'XYZ'
428 obj.rotation_euler = mat.to_euler()
430 scl = mat.to_scale()
431 scl_avg = (scl[0] + scl[1] + scl[2]) / 3
432 obj.scale = (bone.length * scl_avg), (bone.length * scl_avg), (bone.length * scl_avg)
435 def create_widget(rig, bone_name, bone_transform_name=None):
436 """ Creates an empty widget object for a bone, and returns the object.
438 if bone_transform_name is None:
439 bone_transform_name = bone_name
441 obj_name = WGT_PREFIX + rig.name + '_' + bone_name
442 scene = bpy.context.scene
443 id_store = bpy.context.window_manager
445 # Check if it already exists in the scene
446 if obj_name in scene.objects:
447 # Move object to bone position, in case it changed
448 obj = scene.objects[obj_name]
449 obj_to_bone(obj, rig, bone_transform_name)
451 return None
452 else:
453 # Delete object if it exists in blend data but not scene data.
454 # This is necessary so we can then create the object without
455 # name conflicts.
456 if obj_name in bpy.data.objects:
457 bpy.data.objects[obj_name].user_clear()
458 bpy.data.objects.remove(bpy.data.objects[obj_name])
460 # Create mesh object
461 mesh = bpy.data.meshes.new(obj_name)
462 obj = bpy.data.objects.new(obj_name, mesh)
463 scene.objects.link(obj)
465 # Move object to bone position and set layers
466 obj_to_bone(obj, rig, bone_transform_name)
467 wgts_group_name = 'WGTS_' + rig.name
468 if wgts_group_name in bpy.data.objects.keys():
469 obj.parent = bpy.data.objects[wgts_group_name]
470 obj.layers = WGT_LAYERS
472 return obj
475 # Common Widgets
477 def create_line_widget(rig, bone_name, bone_transform_name=None):
478 """ Creates a basic line widget, a line that spans the length of the bone.
480 obj = create_widget(rig, bone_name, bone_transform_name)
481 if obj is not None:
482 mesh = obj.data
483 mesh.from_pydata([(0, 0, 0), (0, 1, 0)], [(0, 1)], [])
484 mesh.update()
487 def create_circle_widget(rig, bone_name, radius=1.0, head_tail=0.0, with_line=False, bone_transform_name=None):
488 """ Creates a basic circle widget, a circle around the y-axis.
489 radius: the radius of the circle
490 head_tail: where along the length of the bone the circle is (0.0=head, 1.0=tail)
492 obj = create_widget(rig, bone_name, bone_transform_name)
493 if obj != None:
494 v = [(0.7071068286895752, 2.980232238769531e-07, -0.7071065306663513), (0.8314696550369263, 2.980232238769531e-07, -0.5555699467658997), (0.9238795042037964, 2.682209014892578e-07, -0.3826831877231598), (0.9807852506637573, 2.5331974029541016e-07, -0.19509011507034302), (1.0, 2.365559055306221e-07, 1.6105803979371558e-07), (0.9807853698730469, 2.2351741790771484e-07, 0.19509044289588928), (0.9238796234130859, 2.086162567138672e-07, 0.38268351554870605), (0.8314696550369263, 1.7881393432617188e-07, 0.5555704236030579), (0.7071068286895752, 1.7881393432617188e-07, 0.7071070075035095), (0.5555702447891235, 1.7881393432617188e-07, 0.8314698934555054), (0.38268327713012695, 1.7881393432617188e-07, 0.923879861831665), (0.19509008526802063, 1.7881393432617188e-07, 0.9807855486869812), (-3.2584136988589307e-07, 1.1920928955078125e-07, 1.000000238418579), (-0.19509072601795197, 1.7881393432617188e-07, 0.9807854294776917), (-0.3826838731765747, 1.7881393432617188e-07, 0.9238795638084412), (-0.5555707216262817, 1.7881393432617188e-07, 0.8314695358276367), (-0.7071071863174438, 1.7881393432617188e-07, 0.7071065902709961), (-0.8314700126647949, 1.7881393432617188e-07, 0.5555698871612549), (-0.923879861831665, 2.086162567138672e-07, 0.3826829195022583), (-0.9807853698730469, 2.2351741790771484e-07, 0.1950896978378296), (-1.0, 2.365559907957504e-07, -7.290432222362142e-07), (-0.9807850122451782, 2.5331974029541016e-07, -0.195091113448143), (-0.9238790273666382, 2.682209014892578e-07, -0.38268423080444336), (-0.831468939781189, 2.980232238769531e-07, -0.5555710196495056), (-0.7071058750152588, 2.980232238769531e-07, -0.707107424736023), (-0.555569052696228, 2.980232238769531e-07, -0.8314701318740845), (-0.38268208503723145, 2.980232238769531e-07, -0.923879861831665), (-0.19508881866931915, 2.980232238769531e-07, -0.9807853102684021), (1.6053570561780361e-06, 2.980232238769531e-07, -0.9999997615814209), (0.19509197771549225, 2.980232238769531e-07, -0.9807847142219543), (0.3826850652694702, 2.980232238769531e-07, -0.9238786101341248), (0.5555717945098877, 2.980232238769531e-07, -0.8314683437347412)]
495 verts = [(a[0] * radius, head_tail, a[2] * radius) for a in v]
496 if with_line:
497 edges = [(28, 12), (0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10), (10, 11), (11, 12), (12, 13), (13, 14), (14, 15), (15, 16), (16, 17), (17, 18), (18, 19), (19, 20), (20, 21), (21, 22), (22, 23), (23, 24), (24, 25), (25, 26), (26, 27), (27, 28), (28, 29), (29, 30), (30, 31), (0, 31)]
498 else:
499 edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10), (10, 11), (11, 12), (12, 13), (13, 14), (14, 15), (15, 16), (16, 17), (17, 18), (18, 19), (19, 20), (20, 21), (21, 22), (22, 23), (23, 24), (24, 25), (25, 26), (26, 27), (27, 28), (28, 29), (29, 30), (30, 31), (0, 31)]
500 mesh = obj.data
501 mesh.from_pydata(verts, edges, [])
502 mesh.update()
503 return obj
504 else:
505 return None
508 def create_cube_widget(rig, bone_name, radius=0.5, bone_transform_name=None):
509 """ Creates a basic cube widget.
511 obj = create_widget(rig, bone_name, bone_transform_name)
512 if obj is not None:
513 r = radius
514 verts = [(r, r, r), (r, -r, r), (-r, -r, r), (-r, r, r), (r, r, -r), (r, -r, -r), (-r, -r, -r), (-r, r, -r)]
515 edges = [(0, 1), (1, 2), (2, 3), (3, 0), (4, 5), (5, 6), (6, 7), (7, 4), (0, 4), (1, 5), (2, 6), (3, 7)]
516 mesh = obj.data
517 mesh.from_pydata(verts, edges, [])
518 mesh.update()
521 def create_chain_widget(rig, bone_name, radius=0.5, invert=False, bone_transform_name=None):
522 """Creates a basic chain widget
524 obj = create_widget(rig, bone_name, bone_transform_name)
525 if obj != None:
526 r = radius
527 rh = radius/2
528 if invert:
529 verts = [(rh, rh, rh), (r, -r, r), (-r, -r, r), (-rh, rh, rh), (rh, rh, -rh), (r, -r, -r), (-r, -r, -r), (-rh, rh, -rh)]
530 else:
531 verts = [(r, r, r), (rh, -rh, rh), (-rh, -rh, rh), (-r, r, r), (r, r, -r), (rh, -rh, -rh), (-rh, -rh, -rh), (-r, r, -r)]
532 edges = [(0, 1), (1, 2), (2, 3), (3, 0), (4, 5), (5, 6), (6, 7), (7, 4), (0, 4), (1, 5), (2, 6), (3, 7)]
533 mesh = obj.data
534 mesh.from_pydata(verts, edges, [])
535 mesh.update()
538 def create_sphere_widget(rig, bone_name, bone_transform_name=None):
539 """ Creates a basic sphere widget, three pependicular overlapping circles.
541 obj = create_widget(rig, bone_name, bone_transform_name)
542 if obj != None:
543 verts = [(0.3535533845424652, 0.3535533845424652, 0.0), (0.4619397521018982, 0.19134171307086945, 0.0), (0.5, -2.1855694143368964e-08, 0.0), (0.4619397521018982, -0.19134175777435303, 0.0), (0.3535533845424652, -0.3535533845424652, 0.0), (0.19134174287319183, -0.4619397521018982, 0.0), (7.549790126404332e-08, -0.5, 0.0), (-0.1913416087627411, -0.46193981170654297, 0.0), (-0.35355329513549805, -0.35355350375175476, 0.0), (-0.4619397521018982, -0.19134178757667542, 0.0), (-0.5, 5.962440319251527e-09, 0.0), (-0.4619397222995758, 0.1913418024778366, 0.0), (-0.35355326533317566, 0.35355350375175476, 0.0), (-0.19134148955345154, 0.46193987131118774, 0.0), (3.2584136988589307e-07, 0.5, 0.0), (0.1913420855998993, 0.46193960309028625, 0.0), (7.450580596923828e-08, 0.46193960309028625, 0.19134199619293213), (5.9254205098113744e-08, 0.5, 2.323586443253589e-07), (4.470348358154297e-08, 0.46193987131118774, -0.1913415789604187), (2.9802322387695312e-08, 0.35355350375175476, -0.3535533547401428), (2.9802322387695312e-08, 0.19134178757667542, -0.46193981170654297), (5.960464477539063e-08, -1.1151834122813398e-08, -0.5000000596046448), (5.960464477539063e-08, -0.1913418024778366, -0.46193984150886536), (5.960464477539063e-08, -0.35355350375175476, -0.3535533845424652), (7.450580596923828e-08, -0.46193981170654297, -0.19134166836738586), (9.348272556053416e-08, -0.5, 1.624372103492533e-08), (1.043081283569336e-07, -0.4619397521018982, 0.19134168326854706), (1.1920928955078125e-07, -0.3535533845424652, 0.35355329513549805), (1.1920928955078125e-07, -0.19134174287319183, 0.46193966269493103), (1.1920928955078125e-07, -4.7414250303745575e-09, 0.49999991059303284), (1.1920928955078125e-07, 0.19134172797203064, 0.46193966269493103), (8.940696716308594e-08, 0.3535533845424652, 0.35355329513549805), (0.3535534739494324, 0.0, 0.35355329513549805), (0.1913418173789978, -2.9802322387695312e-08, 0.46193966269493103), (8.303572940349113e-08, -5.005858838558197e-08, 0.49999991059303284), (-0.19134165346622467, -5.960464477539063e-08, 0.46193966269493103), (-0.35355329513549805, -8.940696716308594e-08, 0.35355329513549805), (-0.46193963289260864, -5.960464477539063e-08, 0.19134168326854706), (-0.49999991059303284, -5.960464477539063e-08, 1.624372103492533e-08), (-0.4619397521018982, -2.9802322387695312e-08, -0.19134166836738586), (-0.3535534143447876, -2.9802322387695312e-08, -0.3535533845424652), (-0.19134171307086945, 0.0, -0.46193984150886536), (7.662531942287387e-08, 9.546055501630235e-09, -0.5000000596046448), (0.19134187698364258, 5.960464477539063e-08, -0.46193981170654297), (0.3535535931587219, 5.960464477539063e-08, -0.3535533547401428), (0.4619399905204773, 5.960464477539063e-08, -0.1913415789604187), (0.5000000596046448, 5.960464477539063e-08, 2.323586443253589e-07), (0.4619396924972534, 2.9802322387695312e-08, 0.19134199619293213)]
544 edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10), (10, 11), (11, 12), (12, 13), (13, 14), (14, 15), (0, 15), (16, 31), (16, 17), (17, 18), (18, 19), (19, 20), (20, 21), (21, 22), (22, 23), (23, 24), (24, 25), (25, 26), (26, 27), (27, 28), (28, 29), (29, 30), (30, 31), (32, 33), (33, 34), (34, 35), (35, 36), (36, 37), (37, 38), (38, 39), (39, 40), (40, 41), (41, 42), (42, 43), (43, 44), (44, 45), (45, 46), (46, 47), (32, 47)]
545 mesh = obj.data
546 mesh.from_pydata(verts, edges, [])
547 mesh.update()
550 def create_limb_widget(rig, bone_name, bone_transform_name=None):
551 """ Creates a basic limb widget, a line that spans the length of the
552 bone, with a circle around the center.
554 obj = create_widget(rig, bone_name, bone_transform_name)
555 if obj != None:
556 verts = [(-1.1920928955078125e-07, 1.7881393432617188e-07, 0.0), (3.5762786865234375e-07, 1.0000004768371582, 0.0), (0.1767769455909729, 0.5000001192092896, 0.17677664756774902), (0.20786768198013306, 0.5000001192092896, 0.1388925313949585), (0.23097014427185059, 0.5000001192092896, 0.09567084908485413), (0.24519658088684082, 0.5000001192092896, 0.048772573471069336), (0.2500002384185791, 0.5000001192092896, -2.545945676502015e-09), (0.24519658088684082, 0.5000001192092896, -0.048772573471069336), (0.23097014427185059, 0.5000001192092896, -0.09567084908485413), (0.20786768198013306, 0.5000001192092896, -0.13889259099960327), (0.1767769455909729, 0.5000001192092896, -0.1767767071723938), (0.13889282941818237, 0.5000001192092896, -0.20786744356155396), (0.09567105770111084, 0.5000001192092896, -0.23096990585327148), (0.04877278208732605, 0.5000001192092896, -0.24519634246826172), (1.7279069197684294e-07, 0.5000000596046448, -0.25), (-0.0487724244594574, 0.5000001192092896, -0.24519634246826172), (-0.09567070007324219, 0.5000001192092896, -0.2309698462486267), (-0.13889241218566895, 0.5000001192092896, -0.20786738395690918), (-0.17677652835845947, 0.5000001192092896, -0.17677664756774902), (-0.20786726474761963, 0.5000001192092896, -0.13889244198799133), (-0.23096972703933716, 0.5000001192092896, -0.09567070007324219), (-0.24519610404968262, 0.5000001192092896, -0.04877239465713501), (-0.2499997615814209, 0.5000001192092896, 2.1997936983098043e-07), (-0.24519598484039307, 0.5000001192092896, 0.04877282679080963), (-0.23096948862075806, 0.5000001192092896, 0.09567108750343323), (-0.20786696672439575, 0.5000001192092896, 0.1388927698135376), (-0.1767762303352356, 0.5000001192092896, 0.17677688598632812), (-0.13889199495315552, 0.5000001192092896, 0.2078675627708435), (-0.09567028284072876, 0.5000001192092896, 0.23097002506256104), (-0.048771947622299194, 0.5000001192092896, 0.24519634246826172), (6.555903269145347e-07, 0.5000001192092896, 0.25), (0.04877324402332306, 0.5000001192092896, 0.24519622325897217), (0.09567153453826904, 0.5000001192092896, 0.23096966743469238), (0.13889318704605103, 0.5000001192092896, 0.20786714553833008)]
557 edges = [(0, 1), (2, 3), (4, 3), (5, 4), (5, 6), (6, 7), (8, 7), (8, 9), (10, 9), (10, 11), (11, 12), (13, 12), (14, 13), (14, 15), (16, 15), (16, 17), (17, 18), (19, 18), (19, 20), (21, 20), (21, 22), (22, 23), (24, 23), (25, 24), (25, 26), (27, 26), (27, 28), (29, 28), (29, 30), (30, 31), (32, 31), (32, 33), (2, 33)]
558 mesh = obj.data
559 mesh.from_pydata(verts, edges, [])
560 mesh.update()
563 def create_bone_widget(rig, bone_name, bone_transform_name=None):
564 """ Creates a basic bone widget, a simple obolisk-esk shape.
566 obj = create_widget(rig, bone_name, bone_transform_name)
567 if obj != None:
568 verts = [(0.04, 1.0, -0.04), (0.1, 0.0, -0.1), (-0.1, 0.0, -0.1), (-0.04, 1.0, -0.04), (0.04, 1.0, 0.04), (0.1, 0.0, 0.1), (-0.1, 0.0, 0.1), (-0.04, 1.0, 0.04)]
569 edges = [(1, 2), (0, 1), (0, 3), (2, 3), (4, 5), (5, 6), (6, 7), (4, 7), (1, 5), (0, 4), (2, 6), (3, 7)]
570 mesh = obj.data
571 mesh.from_pydata(verts, edges, [])
572 mesh.update()
575 def create_compass_widget(rig, bone_name, bone_transform_name=None):
576 """ Creates a compass-shaped widget.
578 obj = create_widget(rig, bone_name, bone_transform_name)
579 if obj != None:
580 verts = [(0.0, 1.2000000476837158, 0.0), (0.19509032368659973, 0.9807852506637573, 0.0), (0.3826834559440613, 0.9238795042037964, 0.0), (0.5555702447891235, 0.8314695954322815, 0.0), (0.7071067690849304, 0.7071067690849304, 0.0), (0.8314696550369263, 0.5555701851844788, 0.0), (0.9238795042037964, 0.3826834261417389, 0.0), (0.9807852506637573, 0.19509035348892212, 0.0), (1.2000000476837158, 7.549790126404332e-08, 0.0), (0.9807853102684021, -0.19509020447731018, 0.0), (0.9238795638084412, -0.38268327713012695, 0.0), (0.8314696550369263, -0.5555701851844788, 0.0), (0.7071067690849304, -0.7071067690849304, 0.0), (0.5555701851844788, -0.8314696550369263, 0.0), (0.38268327713012695, -0.9238796234130859, 0.0), (0.19509008526802063, -0.9807853102684021, 0.0), (-3.2584136988589307e-07, -1.2999999523162842, 0.0), (-0.19509072601795197, -0.9807851910591125, 0.0), (-0.3826838731765747, -0.9238793253898621, 0.0), (-0.5555707216262817, -0.8314692974090576, 0.0), (-0.7071072459220886, -0.707106351852417, 0.0), (-0.8314700126647949, -0.5555696487426758, 0.0), (-0.923879861831665, -0.3826826810836792, 0.0), (-0.9807854294776917, -0.1950894594192505, 0.0), (-1.2000000476837158, 9.655991561885457e-07, 0.0), (-0.980785071849823, 0.1950913518667221, 0.0), (-0.923879086971283, 0.38268446922302246, 0.0), (-0.831468939781189, 0.5555712580680847, 0.0), (-0.7071058750152588, 0.707107663154602, 0.0), (-0.5555691123008728, 0.8314703702926636, 0.0), (-0.38268208503723145, 0.9238801002502441, 0.0), (-0.19508881866931915, 0.9807855486869812, 0.0)]
581 edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10), (10, 11), (11, 12), (12, 13), (13, 14), (14, 15), (15, 16), (16, 17), (17, 18), (18, 19), (19, 20), (20, 21), (21, 22), (22, 23), (23, 24), (24, 25), (25, 26), (26, 27), (27, 28), (28, 29), (29, 30), (30, 31), (0, 31)]
582 mesh = obj.data
583 mesh.from_pydata(verts, edges, [])
584 mesh.update()
587 def create_root_widget(rig, bone_name, bone_transform_name=None):
588 """ Creates a widget for the root bone.
590 obj = create_widget(rig, bone_name, bone_transform_name)
591 if obj != None:
592 verts = [(0.7071067690849304, 0.7071067690849304, 0.0), (0.7071067690849304, -0.7071067690849304, 0.0), (-0.7071067690849304, 0.7071067690849304, 0.0), (-0.7071067690849304, -0.7071067690849304, 0.0), (0.8314696550369263, 0.5555701851844788, 0.0), (0.8314696550369263, -0.5555701851844788, 0.0), (-0.8314696550369263, 0.5555701851844788, 0.0), (-0.8314696550369263, -0.5555701851844788, 0.0), (0.9238795042037964, 0.3826834261417389, 0.0), (0.9238795042037964, -0.3826834261417389, 0.0), (-0.9238795042037964, 0.3826834261417389, 0.0), (-0.9238795042037964, -0.3826834261417389, 0.0), (0.9807852506637573, 0.19509035348892212, 0.0), (0.9807852506637573, -0.19509035348892212, 0.0), (-0.9807852506637573, 0.19509035348892212, 0.0), (-0.9807852506637573, -0.19509035348892212, 0.0), (0.19509197771549225, 0.9807849526405334, 0.0), (0.19509197771549225, -0.9807849526405334, 0.0), (-0.19509197771549225, 0.9807849526405334, 0.0), (-0.19509197771549225, -0.9807849526405334, 0.0), (0.3826850652694702, 0.9238788485527039, 0.0), (0.3826850652694702, -0.9238788485527039, 0.0), (-0.3826850652694702, 0.9238788485527039, 0.0), (-0.3826850652694702, -0.9238788485527039, 0.0), (0.5555717945098877, 0.8314685821533203, 0.0), (0.5555717945098877, -0.8314685821533203, 0.0), (-0.5555717945098877, 0.8314685821533203, 0.0), (-0.5555717945098877, -0.8314685821533203, 0.0), (0.19509197771549225, 1.2807848453521729, 0.0), (0.19509197771549225, -1.2807848453521729, 0.0), (-0.19509197771549225, 1.2807848453521729, 0.0), (-0.19509197771549225, -1.2807848453521729, 0.0), (1.280785322189331, 0.19509035348892212, 0.0), (1.280785322189331, -0.19509035348892212, 0.0), (-1.280785322189331, 0.19509035348892212, 0.0), (-1.280785322189331, -0.19509035348892212, 0.0), (0.3950919806957245, 1.2807848453521729, 0.0), (0.3950919806957245, -1.2807848453521729, 0.0), (-0.3950919806957245, 1.2807848453521729, 0.0), (-0.3950919806957245, -1.2807848453521729, 0.0), (1.280785322189331, 0.39509034156799316, 0.0), (1.280785322189331, -0.39509034156799316, 0.0), (-1.280785322189331, 0.39509034156799316, 0.0), (-1.280785322189331, -0.39509034156799316, 0.0), (0.0, 1.5807849168777466, 0.0), (0.0, -1.5807849168777466, 0.0), (1.5807852745056152, 0.0, 0.0), (-1.5807852745056152, 0.0, 0.0)]
593 edges = [(0, 4), (1, 5), (2, 6), (3, 7), (4, 8), (5, 9), (6, 10), (7, 11), (8, 12), (9, 13), (10, 14), (11, 15), (16, 20), (17, 21), (18, 22), (19, 23), (20, 24), (21, 25), (22, 26), (23, 27), (0, 24), (1, 25), (2, 26), (3, 27), (16, 28), (17, 29), (18, 30), (19, 31), (12, 32), (13, 33), (14, 34), (15, 35), (28, 36), (29, 37), (30, 38), (31, 39), (32, 40), (33, 41), (34, 42), (35, 43), (36, 44), (37, 45), (38, 44), (39, 45), (40, 46), (41, 46), (42, 47), (43, 47)]
594 mesh = obj.data
595 mesh.from_pydata(verts, edges, [])
596 mesh.update()
599 def create_neck_bend_widget(rig, bone_name, radius=1.0, head_tail=0.0, bone_transform_name=None):
600 obj = create_widget(rig, bone_name, bone_transform_name)
601 size = 2.0
602 if obj != None:
603 v = [(-0.08855080604553223 * size, 0.7388765811920166 * size, -0.3940150737762451 * size),
604 (0.08855044841766357 * size, 0.7388765811920166 * size, -0.3940150737762451 * size),
605 (0.17710095643997192 * size, 0.5611097812652588 * size, -0.6478927135467529 * size),
606 (-4.0892032870942785e-07 * size, 0.4087378978729248 * size, -0.865501880645752 * size),
607 (-0.17710143327713013 * size, 0.5611097812652588 * size, -0.6478922367095947 * size),
608 (0.08855026960372925 * size, 0.5611097812652588 * size, -0.6478924751281738 * size),
609 (-0.08855092525482178 * size, 0.5611097812652588 * size, -0.6478927135467529 * size),
610 (-0.6478927135467529 * size, 0.5611097812652588 * size, 0.08855098485946655 * size),
611 (-0.6478927135467529 * size, 0.5611097812652588 * size, -0.08855020999908447 * size),
612 (-0.6478924751281738 * size, 0.5611097812652588 * size, 0.17710155248641968 * size),
613 (-0.865501880645752 * size, 0.4087378978729248 * size, 4.6876743908796925e-07 * size),
614 (-0.647892951965332 * size, 0.5611097812652588 * size, -0.17710083723068237 * size),
615 (-0.39401543140411377 * size, 0.7388765811920166 * size, -0.08855029940605164 * size),
616 (-0.39401543140411377 * size, 0.7388765811920166 * size, 0.08855095505714417 * size),
617 (0.6478927135467529 * size, 0.5611097812652588 * size, -0.08855059742927551 * size),
618 (0.6478927135467529 * size, 0.5611097812652588 * size, 0.08855065703392029 * size),
619 (0.6478924751281738 * size, 0.5611097812652588 * size, -0.17710113525390625 * size),
620 (0.865501880645752 * size, 0.4087378978729248 * size, -3.264514703005261e-08 * size),
621 (0.647892951965332 * size, 0.5611097812652588 * size, 0.1771012544631958 * size),
622 (0.08855065703392029 * size, 0.7388765811920166 * size, 0.3940155506134033 * size),
623 (-0.08855056762695312 * size, 0.7388765811920166 * size, 0.3940155506134033 * size),
624 (-0.17710107564926147 * size, 0.5611097812652588 * size, 0.647892951965332 * size),
625 (2.244429140318971e-07 * size, 0.4087378978729248 * size, 0.865502119064331 * size),
626 (0.17710131406784058 * size, 0.5611097812652588 * size, 0.6478927135467529 * size),
627 (-0.08855044841766357 * size, 0.5611097812652588 * size, 0.647892951965332 * size),
628 (0.08855074644088745 * size, 0.5611097812652588 * size, 0.647892951965332 * size),
629 (0.3940153121948242 * size, 0.7388765811920166 * size, 0.08855071663856506 * size),
630 (0.39401519298553467 * size, 0.7388765811920166 * size, -0.08855047821998596 * size),
631 (-8.416645869147032e-08 * size, 0.8255770206451416 * size, -0.2656517028808594 * size),
632 (-0.06875583529472351 * size, 0.8255770206451416 * size, -0.2565997838973999 * size),
633 (-0.13282597064971924 * size, 0.8255770206451416 * size, -0.2300611138343811 * size),
634 (-0.18784427642822266 * size, 0.8255770206451416 * size, -0.18784409761428833 * size),
635 (-0.2300613522529602 * size, 0.8255770206451416 * size, -0.1328257918357849 * size),
636 (-0.256600022315979 * size, 0.8255770206451416 * size, -0.06875564157962799 * size),
637 (-0.2656519412994385 * size, 0.8255770206451416 * size, 9.328307726264029e-08 * size),
638 (-0.25660014152526855 * size, 0.8255770206451416 * size, 0.06875583529472351 * size),
639 (-0.2300613522529602 * size, 0.8255770206451416 * size, 0.13282597064971924 * size),
640 (-0.18784433603286743 * size, 0.8255770206451416 * size, 0.18784421682357788 * size),
641 (-0.1328260898590088 * size, 0.8255770206451416 * size, 0.23006129264831543 * size),
642 (-0.06875592470169067 * size, 0.8255770206451416 * size, 0.256600022315979 * size),
643 (-1.8761508613351907e-07 * size, 0.8255770206451416 * size, 0.2656519412994385 * size),
644 (0.06875556707382202 * size, 0.8255770206451416 * size, 0.2566000819206238 * size),
645 (0.13282573223114014 * size, 0.8255770206451416 * size, 0.23006141185760498 * size),
646 (0.18784403800964355 * size, 0.8255770206451416 * size, 0.1878443956375122 * size),
647 (0.23006105422973633 * size, 0.8255770206451416 * size, 0.1328260898590088 * size),
648 (0.25659990310668945 * size, 0.8255770206451416 * size, 0.06875596940517426 * size),
649 (0.2656517028808594 * size, 0.8255770206451416 * size, 2.3684407324253698e-07 * size),
650 (0.25659990310668945 * size, 0.8255770206451416 * size, -0.06875550746917725 * size),
651 (0.23006117343902588 * size, 0.8255770206451416 * size, -0.13282567262649536 * size),
652 (0.18784427642822266 * size, 0.8255770206451416 * size, -0.18784397840499878 * size),
653 (0.13282597064971924 * size, 0.8255770206451416 * size, -0.23006099462509155 * size),
654 (0.0687558501958847 * size, 0.8255770206451416 * size, -0.2565997838973999 * size), ]
655 edges = [(1, 0), (3, 2), (5, 2), (4, 3), (6, 4), (1, 5), (0, 6), (13, 7), (12, 8), (7, 9), (9, 10), (8, 11),
656 (27, 14), (26, 15), (14, 16), (16, 17), (15, 18), (17, 18), (10, 11), (12, 13), (20, 19), (22, 21),
657 (24, 21), (23, 22), (29, 28), (30, 29), (31, 30), (32, 31), (33, 32), (34, 33), (35, 34), (36, 35),
658 (37, 36), (38, 37), (39, 38), (40, 39), (41, 40), (42, 41), (43, 42), (44, 43), (45, 44), (46, 45),
659 (47, 46), (48, 47), (49, 48), (50, 49), (51, 50), (28, 51), (26, 27), (25, 23), (20, 24),
660 (19, 25), ]
662 verts = [(a[0] * radius, head_tail, a[2] * radius) for a in v]
663 mesh = obj.data
664 mesh.from_pydata(verts, edges, [])
665 mesh.update()
668 def create_neck_tweak_widget(rig, bone_name, size=1.0, bone_transform_name=None):
669 obj = create_widget(rig, bone_name, bone_transform_name)
671 if obj != None:
672 verts = [(0.3535533845424652 * size, 0.3535533845424652 * size, 0.0 * size),
673 (0.4619397521018982 * size, 0.19134171307086945 * size, 0.0 * size),
674 (0.5 * size, -2.1855694143368964e-08 * size, 0.0 * size),
675 (0.4619397521018982 * size, -0.19134175777435303 * size, 0.0 * size),
676 (0.3535533845424652 * size, -0.3535533845424652 * size, 0.0 * size),
677 (0.19134174287319183 * size, -0.4619397521018982 * size, 0.0 * size),
678 (7.549790126404332e-08 * size, -0.5 * size, 0.0 * size),
679 (-0.1913416087627411 * size, -0.46193981170654297 * size, 0.0 * size),
680 (-0.35355329513549805 * size, -0.35355350375175476 * size, 0.0 * size),
681 (-0.4619397521018982 * size, -0.19134178757667542 * size, 0.0 * size),
682 (-0.5 * size, 5.962440319251527e-09 * size, 0.0 * size),
683 (-0.4619397222995758 * size, 0.1913418024778366 * size, 0.0 * size),
684 (-0.35355326533317566 * size, 0.35355350375175476 * size, 0.0 * size),
685 (-0.19134148955345154 * size, 0.46193987131118774 * size, 0.0 * size),
686 (3.2584136988589307e-07 * size, 0.5 * size, 0.0 * size),
687 (0.1913420855998993 * size, 0.46193960309028625 * size, 0.0 * size),
688 (7.450580596923828e-08 * size, 0.46193960309028625 * size, 0.19134199619293213 * size),
689 (5.9254205098113744e-08 * size, 0.5 * size, 2.323586443253589e-07 * size),
690 (4.470348358154297e-08 * size, 0.46193987131118774 * size, -0.1913415789604187 * size),
691 (2.9802322387695312e-08 * size, 0.35355350375175476 * size, -0.3535533547401428 * size),
692 (2.9802322387695312e-08 * size, 0.19134178757667542 * size, -0.46193981170654297 * size),
693 (5.960464477539063e-08 * size, -1.1151834122813398e-08 * size, -0.5000000596046448 * size),
694 (5.960464477539063e-08 * size, -0.1913418024778366 * size, -0.46193984150886536 * size),
695 (5.960464477539063e-08 * size, -0.35355350375175476 * size, -0.3535533845424652 * size),
696 (7.450580596923828e-08 * size, -0.46193981170654297 * size, -0.19134166836738586 * size),
697 (9.348272556053416e-08 * size, -0.5 * size, 1.624372103492533e-08 * size),
698 (1.043081283569336e-07 * size, -0.4619397521018982 * size, 0.19134168326854706 * size),
699 (1.1920928955078125e-07 * size, -0.3535533845424652 * size, 0.35355329513549805 * size),
700 (1.1920928955078125e-07 * size, -0.19134174287319183 * size, 0.46193966269493103 * size),
701 (1.1920928955078125e-07 * size, -4.7414250303745575e-09 * size, 0.49999991059303284 * size),
702 (1.1920928955078125e-07 * size, 0.19134172797203064 * size, 0.46193966269493103 * size),
703 (8.940696716308594e-08 * size, 0.3535533845424652 * size, 0.35355329513549805 * size),
704 (0.3535534739494324 * size, 0.0 * size, 0.35355329513549805 * size),
705 (0.1913418173789978 * size, -2.9802322387695312e-08 * size, 0.46193966269493103 * size),
706 (8.303572940349113e-08 * size, -5.005858838558197e-08 * size, 0.49999991059303284 * size),
707 (-0.19134165346622467 * size, -5.960464477539063e-08 * size, 0.46193966269493103 * size),
708 (-0.35355329513549805 * size, -8.940696716308594e-08 * size, 0.35355329513549805 * size),
709 (-0.46193963289260864 * size, -5.960464477539063e-08 * size, 0.19134168326854706 * size),
710 (-0.49999991059303284 * size, -5.960464477539063e-08 * size, 1.624372103492533e-08 * size),
711 (-0.4619397521018982 * size, -2.9802322387695312e-08 * size, -0.19134166836738586 * size),
712 (-0.3535534143447876 * size, -2.9802322387695312e-08 * size, -0.3535533845424652 * size),
713 (-0.19134171307086945 * size, 0.0 * size, -0.46193984150886536 * size),
714 (7.662531942287387e-08 * size, 9.546055501630235e-09 * size, -0.5000000596046448 * size),
715 (0.19134187698364258 * size, 5.960464477539063e-08 * size, -0.46193981170654297 * size),
716 (0.3535535931587219 * size, 5.960464477539063e-08 * size, -0.3535533547401428 * size),
717 (0.4619399905204773 * size, 5.960464477539063e-08 * size, -0.1913415789604187 * size),
718 (0.5000000596046448 * size, 5.960464477539063e-08 * size, 2.323586443253589e-07 * size),
719 (0.4619396924972534 * size, 2.9802322387695312e-08 * size, 0.19134199619293213 * size),
720 (1.563460111618042 * size, 2.778762819843905e-08 * size, 1.5634593963623047 * size),
721 (0.8461387157440186 * size, -1.0400220418205208e-07 * size, 2.0427582263946533 * size),
722 (7.321979467178608e-08 * size, -1.9357810288056498e-07 * size, 2.2110657691955566 * size),
723 (-0.8461385369300842 * size, -2.3579201524626114e-07 * size, 2.0427582263946533 * size),
724 (-1.5634597539901733 * size, -3.67581861837607e-07 * size, 1.5634593963623047 * size),
725 (-2.0427584648132324 * size, -2.3579204366797057e-07 * size, 0.8461383581161499 * size),
726 (-2.211066246032715 * size, -2.3579204366797057e-07 * size, 9.972505665700737e-08 * size),
727 (-2.0427589416503906 * size, -1.0400223260376151e-07 * size, -0.8461381196975708 * size),
728 (-1.5634604692459106 * size, -1.040022183929068e-07 * size, -1.563459873199463 * size),
729 (-0.8461387753486633 * size, 2.77876033294433e-08 * size, -2.042759418487549 * size),
730 (4.4872678017782164e-08 * size, 7.00015263532805e-08 * size, -2.211066484451294 * size),
731 (0.8461388349533081 * size, 2.913672290105751e-07 * size, -2.0427591800689697 * size),
732 (1.5634608268737793 * size, 2.9136725743228453e-07 * size, -1.563459873199463 * size),
733 (2.042759895324707 * size, 2.9136725743228453e-07 * size, -0.8461377024650574 * size),
734 (2.211066722869873 * size, 2.9136725743228453e-07 * size, 1.0554133496043505e-06 * size),
735 (2.0427587032318115 * size, 1.5957746768435754e-07 * size, 0.8461397886276245 * size), ]
736 edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10), (10, 11),
737 (11, 12), (12, 13), (13, 14), (14, 15), (0, 15), (16, 31), (16, 17), (17, 18), (18, 19), (19, 20),
738 (20, 21), (21, 22), (22, 23), (23, 24), (24, 25), (25, 26), (26, 27), (27, 28), (28, 29), (29, 30),
739 (30, 31), (32, 33), (33, 34), (34, 35), (35, 36), (36, 37), (37, 38), (38, 39), (39, 40), (40, 41),
740 (41, 42), (42, 43), (43, 44), (44, 45), (45, 46), (46, 47), (32, 47), (48, 49), (49, 50), (50, 51),
741 (51, 52), (52, 53), (53, 54), (54, 55), (55, 56), (56, 57), (57, 58), (58, 59), (59, 60), (60, 61),
742 (61, 62), (62, 63), (48, 63), (21, 58), (10, 54), (29, 50), (2, 62), ]
744 mesh = obj.data
745 mesh.from_pydata(verts, edges, [])
746 mesh.update()
749 #=============================================
750 # Math
751 #=============================================
753 def angle_on_plane(plane, vec1, vec2):
754 """ Return the angle between two vectors projected onto a plane.
756 plane.normalize()
757 vec1 = vec1 - (plane * (vec1.dot(plane)))
758 vec2 = vec2 - (plane * (vec2.dot(plane)))
759 vec1.normalize()
760 vec2.normalize()
762 # Determine the angle
763 angle = math.acos(max(-1.0, min(1.0, vec1.dot(vec2))))
765 if angle < 0.00001: # close enough to zero that sign doesn't matter
766 return angle
768 # Determine the sign of the angle
769 vec3 = vec2.cross(vec1)
770 vec3.normalize()
771 sign = vec3.dot(plane)
772 if sign >= 0:
773 sign = 1
774 else:
775 sign = -1
777 return angle * sign
780 def align_bone_roll(obj, bone1, bone2):
781 """ Aligns the roll of two bones.
783 bone1_e = obj.data.edit_bones[bone1]
784 bone2_e = obj.data.edit_bones[bone2]
786 bone1_e.roll = 0.0
788 # Get the directions the bones are pointing in, as vectors
789 y1 = bone1_e.y_axis
790 x1 = bone1_e.x_axis
791 y2 = bone2_e.y_axis
792 x2 = bone2_e.x_axis
794 # Get the shortest axis to rotate bone1 on to point in the same direction as bone2
795 axis = y1.cross(y2)
796 axis.normalize()
798 # Angle to rotate on that shortest axis
799 angle = y1.angle(y2)
801 # Create rotation matrix to make bone1 point in the same direction as bone2
802 rot_mat = Matrix.Rotation(angle, 3, axis)
804 # Roll factor
805 x3 = rot_mat * x1
806 dot = x2 * x3
807 if dot > 1.0:
808 dot = 1.0
809 elif dot < -1.0:
810 dot = -1.0
811 roll = math.acos(dot)
813 # Set the roll
814 bone1_e.roll = roll
816 # Check if we rolled in the right direction
817 x3 = rot_mat * bone1_e.x_axis
818 check = x2 * x3
820 # If not, reverse
821 if check < 0.9999:
822 bone1_e.roll = -roll
825 def align_bone_x_axis(obj, bone, vec):
826 """ Rolls the bone to align its x-axis as closely as possible to
827 the given vector.
828 Must be in edit mode.
830 bone_e = obj.data.edit_bones[bone]
832 vec = vec.cross(bone_e.y_axis)
833 vec.normalize()
835 dot = max(-1.0, min(1.0, bone_e.z_axis.dot(vec)))
836 angle = math.acos(dot)
838 bone_e.roll += angle
840 dot1 = bone_e.z_axis.dot(vec)
842 bone_e.roll -= angle * 2
844 dot2 = bone_e.z_axis.dot(vec)
846 if dot1 > dot2:
847 bone_e.roll += angle * 2
850 def align_bone_z_axis(obj, bone, vec):
851 """ Rolls the bone to align its z-axis as closely as possible to
852 the given vector.
853 Must be in edit mode.
855 bone_e = obj.data.edit_bones[bone]
857 vec = bone_e.y_axis.cross(vec)
858 vec.normalize()
860 dot = max(-1.0, min(1.0, bone_e.x_axis.dot(vec)))
861 angle = math.acos(dot)
863 bone_e.roll += angle
865 dot1 = bone_e.x_axis.dot(vec)
867 bone_e.roll -= angle * 2
869 dot2 = bone_e.x_axis.dot(vec)
871 if dot1 > dot2:
872 bone_e.roll += angle * 2
875 def align_bone_y_axis(obj, bone, vec):
876 """ Matches the bone y-axis to
877 the given vector.
878 Must be in edit mode.
881 bone_e = obj.data.edit_bones[bone]
882 vec.normalize()
883 vec = vec * bone_e.length
885 bone_e.tail = bone_e.head + vec
888 #=============================================
889 # Misc
890 #=============================================
892 def copy_attributes(a, b):
893 keys = dir(a)
894 for key in keys:
895 if not key.startswith("_") \
896 and not key.startswith("error_") \
897 and key != "group" \
898 and key != "is_valid" \
899 and key != "rna_type" \
900 and key != "bl_rna":
901 try:
902 setattr(b, key, getattr(a, key))
903 except AttributeError:
904 pass
907 def get_rig_type(rig_type):
908 """ Fetches a rig module by name, and returns it.
910 name = ".%s.%s" % (RIG_DIR, rig_type)
911 submod = importlib.import_module(name, package=MODULE_NAME)
912 importlib.reload(submod)
913 return submod
916 def get_metarig_module(metarig_name, path=METARIG_DIR):
917 """ Fetches a rig module by name, and returns it.
920 name = ".%s.%s" % (path, metarig_name)
921 submod = importlib.import_module(name, package=MODULE_NAME)
922 importlib.reload(submod)
923 return submod
926 def connected_children_names(obj, bone_name):
927 """ Returns a list of bone names (in order) of the bones that form a single
928 connected chain starting with the given bone as a parent.
929 If there is a connected branch, the list stops there.
931 bone = obj.data.bones[bone_name]
932 names = []
934 while True:
935 connects = 0
936 con_name = ""
938 for child in bone.children:
939 if child.use_connect:
940 connects += 1
941 con_name = child.name
943 if connects == 1:
944 names += [con_name]
945 bone = obj.data.bones[con_name]
946 else:
947 break
949 return names
952 def has_connected_children(bone):
953 """ Returns true/false whether a bone has connected children or not.
955 t = False
956 for b in bone.children:
957 t = t or b.use_connect
958 return t
961 def get_layers(layers):
962 """ Does it's best to exctract a set of layers from any data thrown at it.
964 if type(layers) == int:
965 return [x == layers for x in range(0, 32)]
966 elif type(layers) == str:
967 s = layers.split(",")
968 l = []
969 for i in s:
970 try:
971 l += [int(float(i))]
972 except ValueError:
973 pass
974 return [x in l for x in range(0, 32)]
975 elif type(layers) == tuple or type(layers) == list:
976 return [x in layers for x in range(0, 32)]
977 else:
978 try:
979 list(layers)
980 except TypeError:
981 pass
982 else:
983 return [x in layers for x in range(0, 32)]
986 def write_metarig(obj, layers=False, func_name="create", groups=False):
988 Write a metarig as a python script, this rig is to have all info needed for
989 generating the real rig with rigify.
991 code = []
993 code.append("import bpy\n\n")
994 code.append("from mathutils import Color\n\n")
996 code.append("def %s(obj):" % func_name)
997 code.append(" # generated by rigify.utils.write_metarig")
998 bpy.ops.object.mode_set(mode='EDIT')
999 code.append(" bpy.ops.object.mode_set(mode='EDIT')")
1000 code.append(" arm = obj.data")
1002 arm = obj.data
1004 # Rigify bone group colors info
1005 if groups and len(arm.rigify_colors) > 0:
1006 code.append("\n for i in range(" + str(len(arm.rigify_colors)) + "):")
1007 code.append(" arm.rigify_colors.add()\n")
1009 for i in range(len(arm.rigify_colors)):
1010 name = arm.rigify_colors[i].name
1011 active = arm.rigify_colors[i].active
1012 normal = arm.rigify_colors[i].normal
1013 select = arm.rigify_colors[i].select
1014 standard_colors_lock = arm.rigify_colors[i].standard_colors_lock
1015 code.append(' arm.rigify_colors[' + str(i) + '].name = "' + name + '"')
1016 code.append(' arm.rigify_colors[' + str(i) + '].active = Color(' + str(active[:]) + ')')
1017 code.append(' arm.rigify_colors[' + str(i) + '].normal = Color(' + str(normal[:]) + ')')
1018 code.append(' arm.rigify_colors[' + str(i) + '].select = Color(' + str(select[:]) + ')')
1019 code.append(' arm.rigify_colors[' + str(i) + '].standard_colors_lock = ' + str(standard_colors_lock))
1021 # Rigify layer layout info
1022 if layers and len(arm.rigify_layers) > 0:
1023 code.append("\n for i in range(" + str(len(arm.rigify_layers)) + "):")
1024 code.append(" arm.rigify_layers.add()\n")
1026 for i in range(len(arm.rigify_layers)):
1027 name = arm.rigify_layers[i].name
1028 row = arm.rigify_layers[i].row
1029 set = arm.rigify_layers[i].set
1030 group = arm.rigify_layers[i].group
1031 code.append(' arm.rigify_layers[' + str(i) + '].name = "' + name + '"')
1032 code.append(' arm.rigify_layers[' + str(i) + '].row = ' + str(row))
1033 code.append(' arm.rigify_layers[' + str(i) + '].set = ' + str(set))
1034 code.append(' arm.rigify_layers[' + str(i) + '].group = ' + str(group))
1036 # write parents first
1037 bones = [(len(bone.parent_recursive), bone.name) for bone in arm.edit_bones]
1038 bones.sort(key=lambda item: item[0])
1039 bones = [item[1] for item in bones]
1041 code.append("\n bones = {}\n")
1043 for bone_name in bones:
1044 bone = arm.edit_bones[bone_name]
1045 code.append(" bone = arm.edit_bones.new(%r)" % bone.name)
1046 code.append(" bone.head[:] = %.4f, %.4f, %.4f" % bone.head.to_tuple(4))
1047 code.append(" bone.tail[:] = %.4f, %.4f, %.4f" % bone.tail.to_tuple(4))
1048 code.append(" bone.roll = %.4f" % bone.roll)
1049 code.append(" bone.use_connect = %s" % str(bone.use_connect))
1050 if bone.parent:
1051 code.append(" bone.parent = arm.edit_bones[bones[%r]]" % bone.parent.name)
1052 code.append(" bones[%r] = bone.name" % bone.name)
1054 bpy.ops.object.mode_set(mode='OBJECT')
1055 code.append("")
1056 code.append(" bpy.ops.object.mode_set(mode='OBJECT')")
1058 # Rig type and other pose properties
1059 for bone_name in bones:
1060 pbone = obj.pose.bones[bone_name]
1062 code.append(" pbone = obj.pose.bones[bones[%r]]" % bone_name)
1063 code.append(" pbone.rigify_type = %r" % pbone.rigify_type)
1064 code.append(" pbone.lock_location = %s" % str(tuple(pbone.lock_location)))
1065 code.append(" pbone.lock_rotation = %s" % str(tuple(pbone.lock_rotation)))
1066 code.append(" pbone.lock_rotation_w = %s" % str(pbone.lock_rotation_w))
1067 code.append(" pbone.lock_scale = %s" % str(tuple(pbone.lock_scale)))
1068 code.append(" pbone.rotation_mode = %r" % pbone.rotation_mode)
1069 if layers:
1070 code.append(" pbone.bone.layers = %s" % str(list(pbone.bone.layers)))
1071 # Rig type parameters
1072 for param_name in pbone.rigify_parameters.keys():
1073 param = getattr(pbone.rigify_parameters, param_name, '')
1074 if str(type(param)) == "<class 'bpy_prop_array'>":
1075 param = list(param)
1076 if type(param) == str:
1077 param = '"' + param + '"'
1078 code.append(" try:")
1079 code.append(" pbone.rigify_parameters.%s = %s" % (param_name, str(param)))
1080 code.append(" except AttributeError:")
1081 code.append(" pass")
1083 code.append("\n bpy.ops.object.mode_set(mode='EDIT')")
1084 code.append(" for bone in arm.edit_bones:")
1085 code.append(" bone.select = False")
1086 code.append(" bone.select_head = False")
1087 code.append(" bone.select_tail = False")
1089 code.append(" for b in bones:")
1090 code.append(" bone = arm.edit_bones[bones[b]]")
1091 code.append(" bone.select = True")
1092 code.append(" bone.select_head = True")
1093 code.append(" bone.select_tail = True")
1094 code.append(" arm.edit_bones.active = bone")
1096 # Set appropriate layers visible
1097 if layers:
1098 # Find what layers have bones on them
1099 active_layers = []
1100 for bone_name in bones:
1101 bone = obj.data.bones[bone_name]
1102 for i in range(len(bone.layers)):
1103 if bone.layers[i]:
1104 if i not in active_layers:
1105 active_layers.append(i)
1106 active_layers.sort()
1108 code.append("\n arm.layers = [(x in " + str(active_layers) + ") for x in range(" + str(len(arm.layers)) + ")]")
1110 code.append('\nif __name__ == "__main__":')
1111 code.append(" " + func_name + "(bpy.context.active_object)")
1113 return "\n".join(code)
1116 def write_widget(obj):
1117 """ Write a mesh object as a python script for widget use.
1119 script = ""
1120 script += "def create_thing_widget(rig, bone_name, size=1.0, bone_transform_name=None):\n"
1121 script += " obj = create_widget(rig, bone_name, bone_transform_name)\n"
1122 script += " if obj != None:\n"
1124 # Vertices
1125 if len(obj.data.vertices) > 0:
1126 script += " verts = ["
1127 for v in obj.data.vertices:
1128 script += "(" + str(v.co[0]) + "*size, " + str(v.co[1]) + "*size, " + str(v.co[2]) + "*size), "
1129 script += "]\n"
1131 # Edges
1132 if len(obj.data.edges) > 0:
1133 script += " edges = ["
1134 for e in obj.data.edges:
1135 script += "(" + str(e.vertices[0]) + ", " + str(e.vertices[1]) + "), "
1136 script += "]\n"
1138 # Faces
1139 if len(obj.data.polygons) > 0:
1140 script += " faces = ["
1141 for f in obj.data.polygons:
1142 script += "("
1143 for v in f.vertices:
1144 script += str(v) + ", "
1145 script += "), "
1146 script += "]\n"
1148 # Build mesh
1149 script += "\n mesh = obj.data\n"
1150 script += " mesh.from_pydata(verts, edges, faces)\n"
1151 script += " mesh.update()\n"
1152 script += " mesh.update()\n"
1153 script += " return obj\n"
1154 script += " else:\n"
1155 script += " return None\n"
1157 return script
1160 def random_id(length=8):
1161 """ Generates a random alphanumeric id string.
1163 tlength = int(length / 2)
1164 rlength = int(length / 2) + int(length % 2)
1166 chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
1167 text = ""
1168 for i in range(0, rlength):
1169 text += random.choice(chars)
1170 text += str(hex(int(time.time())))[2:][-tlength:].rjust(tlength, '0')[::-1]
1171 return text
1174 #=============================================
1175 # Color correction functions
1176 #=============================================
1178 def linsrgb_to_srgb (linsrgb):
1179 """Convert physically linear RGB values into sRGB ones. The transform is
1180 uniform in the components, so *linsrgb* can be of any shape.
1182 *linsrgb* values should range between 0 and 1, inclusively.
1185 # From Wikipedia, but easy analogue to the above.
1186 gamma = 1.055 * linsrgb**(1./2.4) - 0.055
1187 scale = linsrgb * 12.92
1188 # return np.where (linsrgb > 0.0031308, gamma, scale)
1189 if linsrgb > 0.0031308:
1190 return gamma
1191 return scale
1194 def gamma_correct(color):
1196 corrected_color = Color()
1197 for i, component in enumerate(color):
1198 corrected_color[i] = linsrgb_to_srgb(color[i])
1199 return corrected_color
1202 #=============================================
1203 # Keyframing functions
1204 #=============================================
1207 def get_keyed_frames(rig):
1208 frames = []
1209 if rig.animation_data:
1210 if rig.animation_data.action:
1211 fcus = rig.animation_data.action.fcurves
1212 for fc in fcus:
1213 for kp in fc.keyframe_points:
1214 if kp.co[0] not in frames:
1215 frames.append(kp.co[0])
1217 frames.sort()
1219 return frames
1222 def bones_in_frame(f, rig, *args):
1224 True if one of the bones listed in args is animated at frame f
1225 :param f: the frame
1226 :param rig: the rig
1227 :param args: bone names
1228 :return:
1231 if rig.animation_data and rig.animation_data.action:
1232 fcus = rig.animation_data.action.fcurves
1233 else:
1234 return False
1236 for fc in fcus:
1237 animated_frames = [kp.co[0] for kp in fc.keyframe_points]
1238 for bone in args:
1239 if bone in fc.data_path.split('"') and f in animated_frames:
1240 return True
1242 return False
1245 def overwrite_prop_animation(rig, bone, prop_name, value, frames):
1246 act = rig.animation_data.action
1247 if not act:
1248 return
1250 bone_name = bone.name
1251 curve = None
1253 for fcu in act.fcurves:
1254 words = fcu.data_path.split('"')
1255 if words[0] == "pose.bones[" and words[1] == bone_name and words[-2] == prop_name:
1256 curve = fcu
1257 break
1259 if not curve:
1260 return
1262 for kp in curve.keyframe_points:
1263 if kp.co[0] in frames:
1264 kp.co[1] = value