content/hifi-content/caitlyn/scratch/hifi_tools (5)/armature/repose.py
2022-02-13 22:19:19 +01:00

101 lines
3.6 KiB
Python

import bpy
from mathutils import Quaternion, Matrix, Vector, Euler
from math import pi
from hifi_tools.armature.skeleton import structure as base_armature
def correct_scale_rotation(obj, rotation):
current_context = bpy.context.area.type
bpy.context.area.type = 'VIEW_3D'
# set context to 3D View and set Cursor
bpy.context.space_data.cursor_location[0] = 0.0
bpy.context.space_data.cursor_location[1] = 0.0
bpy.context.space_data.cursor_location[2] = 0.0
bpy.context.area.type = current_context
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='DESELECT')
obj.select = True
bpy.context.scene.objects.active = obj
bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
bpy.ops.object.transform_apply(location=False, rotation=True, scale=True)
obj.scale = Vector((100, 100, 100))
str_angle = -90 * pi/180
if rotation:
obj.rotation_euler = Euler((str_angle, 0, 0), 'XYZ')
bpy.ops.object.transform_apply(location=False, rotation=True, scale=True)
obj.scale = Vector((0.01, 0.01, 0.01))
if rotation:
obj.rotation_euler = Euler((-str_angle, 0, 0), 'XYZ')
def navigate_armature(data, current_rest_node, world_matrix, parent, parent_node):
name = current_rest_node["name"]
bone = data.get(name)
if(bone):
bone.rotation_mode = "QUATERNION"
destination_matrix = current_rest_node["matrix_local"].copy()
inv_destination_matrix = destination_matrix.inverted()
matrix = bone.matrix
if parent:
parent_matrix = parent.matrix.copy()
parent_inverted = parent_matrix.inverted()
parent_destination = parent_node["matrix_local"].copy()
else:
parent_matrix = Matrix()
parent_inverted = Matrix()
parent_destination = Matrix()
smat = inv_destination_matrix * \
(parent_destination * (parent_inverted * matrix))
bone.rotation_quaternion = smat.to_quaternion().inverted()
for child in current_rest_node["children"]:
navigate_armature(data, child, world_matrix,
bone, current_rest_node)
else:
bone = parent
for child in current_rest_node["children"]:
navigate_armature(data, child, world_matrix, bone, parent_node)
def retarget_armature(options):
armature = bpy.context.object
if armature != None and armature.type == "ARMATURE":
# Center Children First
bpy.ops.object.mode_set(mode='OBJECT')
# Make sure to reset the bones first.
bpy.ops.object.transform_apply(
location=False, rotation=True, scale=True)
bpy.ops.object.mode_set(mode='POSE')
bpy.ops.pose.select_all(action='SELECT')
bpy.ops.pose.transforms_clear()
bpy.ops.pose.select_all(action='DESELECT')
print("---")
# Now lets do the repose to rest
world_matrix = armature.matrix_world
bones = armature.pose.bones
for bone in base_armature:
navigate_armature(bones, bone, world_matrix, None, None)
print("Iterating Bones")
# Then apply everything
if options['apply']:
bpy.ops.object.mode_set(mode='OBJECT')
correct_scale_rotation(armature, True)
for child in armature.children:
correct_scale_rotation(child, False)
print("Set", armature, " active")
bpy.context.scene.objects.active = armature
bpy.ops.object.mode_set(mode='OBJECT')
else:
#Judas proofing:
print("No Armature, select, throw an exception")
raise Exception("You must select an armature to continue")