# BoneFix # Fix bones from SFM -> Unity Conversion # Adapted from https://smutba.se/project/59/ import bpy import pprint class ExitOK(Exception): pass bpy.ops.object.mode_set(mode='EDIT') edit_bones = bpy.context.object.data.edit_bones Allbones = { # Bones divided into sections # "NPC Spine [Spn0]", Causes leg movement with IK "NPC Spine1 [Spn1]", "ValveBiped.Bip01_Spine1", "bip_spine_0", "NPC Spine2 [Spn2]", "ValveBiped.Bip01_Spine2", "bip_spine_1", "ValveBiped.Bip01_Spine4", "bip_spine_2", "NPC Neck [Neck]", "ValveBiped.Bip01_Neck1", "bip_neck", "NPC Head [Head]", "ValveBiped.Bip01_Head1", "bip_head", # 1. Spine Section "NPC L Hand [LHnd]", "ValveBiped.Bip01_L_Hand", "bip_hand_L", "lHand", "NPC L Finger01 [LF01]", "ValveBiped.Bip01_L_Finger01", "bip_thumb_1_L", "lThumb2", "NPC L Finger02 [LF02]", "ValveBiped.Bip01_L_Finger02", "bip_thumb_2_L", "lThumb3", "NPC L Finger11 [LF11]", "ValveBiped.Bip01_L_Finger11", "bip_index_1_L", "lIndex2", "NPC L Finger12 [LF12]", "ValveBiped.Bip01_L_Finger12", "bip_index_2_L", "lIndex3", "NPC L Finger21 [LF21]", "ValveBiped.Bip01_L_Finger21", "bip_middle_1_L", "lMid2", "NPC L Finger22 [LF22]", "ValveBiped.Bip01_L_Finger22", "bip_middle_2_L", "lMid3", "NPC L Finger31 [LF31]", "ValveBiped.Bip01_L_Finger31", "bip_ring_1_L", "lRing2", "NPC L Finger32 [LF32]", "ValveBiped.Bip01_L_Finger32", "bip_ring_2_L", "lRing3", "NPC L Finger41 [LF41]", "ValveBiped.Bip01_L_Finger41", "bip_pinky_1_L", "lPinky2", "NPC L Finger42 [LF42]", "ValveBiped.Bip01_L_Finger42", "bip_pinky_2_L", "LPinky3", "NPC L Forearm [LLar] Chain", "NPC L Forearm [LLar]", "ValveBiped.Bip01_L_Forearm", "bip_lowerArm_L", "lForearmBend", "lShldrBend", # 2. Left Arm Section "NPC R Hand [RHnd]", "ValveBiped.Bip01_R_Hand", "bip_hand_R", "rHand", "NPC R Finger01 [RF01]", "ValveBiped.Bip01_R_Finger01", "bip_thumb_1_R", "rThumb2", "NPC R Finger02 [RF02]", "ValveBiped.Bip01_R_Finger02", "bip_thumb_2_R", "rThumb3", "NPC R Finger11 [RF11]", "ValveBiped.Bip01_R_Finger11", "bip_index_1_R", "rIndex2", "NPC R Finger12 [RF12]", "ValveBiped.Bip01_R_Finger12", "bip_index_2_R", "rIndex3", "NPC R Finger21 [RF21]", "ValveBiped.Bip01_R_Finger21", "bip_middle_1_R", "rMid2", "NPC R Finger22 [RF22]", "ValveBiped.Bip01_R_Finger22", "bip_middle_2_R", "rMid3", "NPC R Finger31 [RF31]", "ValveBiped.Bip01_R_Finger31", "bip_ring_1_R", "rRing2", "NPC R Finger32 [RF32]", "ValveBiped.Bip01_R_Finger32", "bip_ring_2_R", "rRing3", "NPC R Finger41 [RF41]", "ValveBiped.Bip01_R_Finger41", "bip_pinky_1_R", "rPinky2", "NPC R Finger42 [RF42]", "ValveBiped.Bip01_R_Finger42", "bip_pinky_2_R", "rPinky3", "NPC R Forearm [RLar] Chain", "NPC R Forearm [RLar]", "ValveBiped.Bip01_R_Forearm", "bip_lowerArm_R", "rForearmBend", "rShldrBend", # 3. Right Arm Section "NPC L Foot [LFt ]", "ValveBiped.Bip01_L_Foot", "bip_foot_L", "lFoot", "NPC L Calf [LClf] Chain", "NPC L Calf [LClf]", "ValveBiped.Bip01_L_Calf", "bip_knee_L", "lShin", "NPC L Toe0 [LToe]", "ValveBiped.Bip01_L_Toe0", "bip_toe_L", # 4. Left Foot Section "NPC R Foot [RFt ]", "ValveBiped.Bip01_R_Foot", "bip_foot_R", "rFoot", "NPC R Calf [RClf] Chain", "NPC R Calf [RClf]", "ValveBiped.Bip01_R_Calf", "bip_knee_R", "rShin", "NPC R Toe0 [RToe]", "ValveBiped.Bip01_R_Toe0", "bip_toe_R", # 5. Right Foot Section } # Update skeleton for bone in edit_bones: try: actualbone = bone.name if bone.name == "lHand": edit_bones["lHand"].parent = edit_bones["lForearmBend"] edit_bones["lHand"].tail = (edit_bones["lHand"].tail + edit_bones["lIndex1"].head + edit_bones["lMid1"].head + edit_bones["lRing1"].head + edit_bones["lPinky1"].head)/5 if bone.name == "rHand": edit_bones["rHand"].parent = edit_bones["rForearmBend"] edit_bones["rHand"].tail = (edit_bones["rHand"].tail + edit_bones["rIndex1"].head + edit_bones["rMid1"].head + edit_bones["rRing1"].head + edit_bones["rPinky1"].head)/5 if bone.name == "lForearmBend": edit_bones["lForearmBend"].parent = edit_bones["lShldrBend"] if bone.name == "rForearmBend": edit_bones["rForearmBend"].parent = edit_bones["rShldrBend"] if bone.name == "lShin": edit_bones["lShin"].parent = edit_bones["lThighBend"] if bone.name == "rShin": edit_bones["rShin"].parent = edit_bones["rThighBend"] if edit_bones[actualbone].parent: print("!!!!!!!!!!!! 2b : PARENT BONES PRESENT !!!!!!!!!") parentbone = edit_bones[actualbone].parent print("!!!!!!!!!!!! 3b : Parentbone: " + edit_bones[actualbone].parent.name) if actualbone in Allbones: print("!!!!!!!!!!!! 4b : No multiple child bones detected") EditBone = bpy.context.object.data.edit_bones[bone.name] parentbone.tail = edit_bones[actualbone].head EditBone.use_connect = True if bone.name == "NPC L Hand [LHnd]": edit_bones["NPC L Hand [LHnd]"].tail = (edit_bones["NPC L Hand [LHnd]"].tail + edit_bones["NPC L Finger40 [LF40]"].head + edit_bones["NPC L Finger30 [LF30]"].head + edit_bones["NPC L Finger20 [LF20]"].head + edit_bones["NPC L Finger10 [LF10]"].head)/5 if bone.name == "NPC R Hand [RHnd]": edit_bones["NPC R Hand [RHnd]"].tail = (edit_bones["NPC R Hand [RHnd]"].tail + edit_bones["NPC R Finger40 [RF40]"].head + edit_bones["NPC R Finger30 [RF30]"].head + edit_bones["NPC R Finger20 [RF20]"].head + edit_bones["NPC R Finger10 [RF10]"].head)/5 if bone.name == "ValveBiped.Bip01_L_Hand": edit_bones["ValveBiped.Bip01_L_Hand"].tail = (edit_bones["ValveBiped.Bip01_L_Hand"].tail + edit_bones["ValveBiped.Bip01_L_Finger4"].head + edit_bones["ValveBiped.Bip01_L_Finger3"].head + edit_bones["ValveBiped.Bip01_L_Finger2"].head + edit_bones["ValveBiped.Bip01_L_Finger1"].head)/5 if bone.name == "ValveBiped.Bip01_R_Hand": edit_bones["ValveBiped.Bip01_R_Hand"].tail = (edit_bones["ValveBiped.Bip01_R_Hand"].tail + edit_bones["ValveBiped.Bip01_R_Finger4"].head + edit_bones["ValveBiped.Bip01_R_Finger3"].head + edit_bones["ValveBiped.Bip01_R_Finger2"].head + edit_bones["ValveBiped.Bip01_R_Finger1"].head)/5 except ExitOK: print("OK") bpy.context.view_layer.update() # Update bone tail positions edit_bones = bpy.context.object.data.edit_bones for bone in edit_bones: parentbone = bone.parent if parentbone == None: continue parentbone.tail = bone.head bone.use_connect = True bpy.context.view_layer.update() # Finish off bpy.ops.object.posemode_toggle() bpy.context.object.data.show_bone_custom_shapes = False bpy.types.Pose.use_auto_ik = True