608 lines
19 KiB
Python
608 lines
19 KiB
Python
# coding: utf-8
|
|
from asyncio.windows_events import NULL
|
|
from platform import java_ver
|
|
import unreal
|
|
import time
|
|
import argparse
|
|
|
|
print("VRM4U python begin")
|
|
print (__file__)
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("-vrm")
|
|
parser.add_argument("-rig")
|
|
parser.add_argument("-meta")
|
|
args = parser.parse_args()
|
|
print(args.vrm)
|
|
|
|
with unreal.ScopedSlowTask(1, "Convert Bone") as slow_task_root:
|
|
slow_task_root.make_dialog()
|
|
|
|
reg = unreal.AssetRegistryHelpers.get_asset_registry()
|
|
|
|
rigs = unreal.ControlRigBlueprint.get_currently_open_rig_blueprints()
|
|
print(rigs)
|
|
|
|
for r in rigs:
|
|
s:str = r.get_path_name()
|
|
ss:str = args.rig
|
|
if (s.find(ss) < 0):
|
|
print("no rig")
|
|
else:
|
|
rig = r
|
|
|
|
|
|
#rig = rigs[10]
|
|
hierarchy = unreal.ControlRigBlueprintLibrary.get_hierarchy(rig)
|
|
|
|
h_con = hierarchy.get_controller()
|
|
|
|
r_con = rig.get_controller()
|
|
|
|
graph = r_con.get_graph()
|
|
node = graph.get_nodes()
|
|
|
|
def checkAndSwapPinBoneToContorl(pin):
|
|
subpins = pin.get_sub_pins()
|
|
#print(subpins)
|
|
if (len(subpins) != 2):
|
|
return;
|
|
|
|
typePin = pin.find_sub_pin('Type')
|
|
namePin = pin.find_sub_pin('Name')
|
|
|
|
#if (typePin==None or namePin==None):
|
|
if (typePin==None):
|
|
return;
|
|
|
|
#if (typePin.get_default_value() == '' or namePin.get_default_value() == ''):
|
|
if (typePin.get_default_value() == ''):
|
|
return;
|
|
|
|
if (typePin.get_default_value() != 'Bone'):
|
|
return;
|
|
|
|
#print(typePin.get_default_value() + ' : ' + namePin.get_default_value())
|
|
|
|
r_con.set_pin_default_value(typePin.get_pin_path(), 'Control', True, False)
|
|
#print('swap end')
|
|
|
|
#end check pin
|
|
|
|
bonePin = None
|
|
controlPin = None
|
|
|
|
with unreal.ScopedSlowTask(1, "Replace Bone") as slow_task:
|
|
slow_task.make_dialog()
|
|
while(len(hierarchy.get_bones()) > 0):
|
|
e = hierarchy.get_bones()[-1]
|
|
h_con.remove_all_parents(e)
|
|
h_con.import_bones(unreal.ControlRigBlueprintLibrary.get_preview_mesh(rig).skeleton)
|
|
|
|
##
|
|
with unreal.ScopedSlowTask(1, "Replace Bone to Controller") as slow_task:
|
|
slow_task.make_dialog()
|
|
for n in node:
|
|
pins = n.get_pins()
|
|
for pin in pins:
|
|
if (pin.is_array()):
|
|
if (pin.get_array_size() > 40):
|
|
# long bone list
|
|
typePin = pin.get_sub_pins()[0].find_sub_pin('Type')
|
|
if (typePin != None):
|
|
if (typePin.get_default_value() == 'Bone'):
|
|
bonePin = pin
|
|
continue
|
|
if (typePin.get_default_value() == 'Control'):
|
|
if ('Name="pelvis"' in r_con.get_pin_default_value(n.find_pin('Items').get_pin_path())):
|
|
controlPin = pin
|
|
continue
|
|
for item in pin.get_sub_pins():
|
|
checkAndSwapPinBoneToContorl(item)
|
|
else:
|
|
checkAndSwapPinBoneToContorl(pin)
|
|
|
|
|
|
for e in hierarchy.get_controls():
|
|
tmp = "{}".format(e.name)
|
|
if (tmp.endswith('_ctrl') == False):
|
|
continue
|
|
if (tmp.startswith('thumb_0') or tmp.startswith('index_0') or tmp.startswith('middle_0') or tmp.startswith('ring_0') or tmp.startswith('pinky_0')):
|
|
print('')
|
|
else:
|
|
continue
|
|
c = hierarchy.find_control(e)
|
|
|
|
#print(e.name)
|
|
|
|
|
|
#ttt = unreal.RigComputedTransform(transform=[[0.0, 0.0, 2.0], [90.0, 0.0, 0.0], [0.03, 0.03, 0.25]])
|
|
#ttt = unreal.RigComputedTransform(transform=[[0.0, 0.0, 2.0], [90.0, 0.0, 0.0], [0.03, 0.03, 0.25]])
|
|
ttt = unreal.Transform(location=[0.0, 0.0, 2.0], rotation=[0.0, 0.0, 90.0], scale=[0.03, 0.03, 0.25])
|
|
hierarchy.set_control_shape_transform(e, ttt, True)
|
|
'''
|
|
shape = c.get_editor_property('shape')
|
|
|
|
init = shape.get_editor_property('initial')
|
|
#init = shape.get_editor_property('current')
|
|
|
|
local = init.get_editor_property('local')
|
|
local = ttt
|
|
init.set_editor_property('local', local)
|
|
|
|
gl = init.get_editor_property('global_')
|
|
gl = ttt
|
|
init.set_editor_property('global_', gl)
|
|
|
|
shape.set_editor_property('initial', init)
|
|
shape.set_editor_property('current', init)
|
|
c.set_editor_property('shape', shape)
|
|
'''
|
|
|
|
|
|
###
|
|
swapBoneTable = [
|
|
["root",""],
|
|
["pelvis","hips"],
|
|
["spine_01","spine"],
|
|
["spine_02","chest"],
|
|
["spine_03","upperChest"],
|
|
["clavicle_l","leftShoulder"],
|
|
["upperArm_L","leftUpperArm"],
|
|
["lowerarm_l","leftLowerArm"],
|
|
["hand_L","leftHand"],
|
|
["index_01_l","leftIndexProximal"],
|
|
["index_02_l","leftIndexIntermediate"],
|
|
["index_03_l","leftIndexDistal"],
|
|
["middle_01_l","leftMiddleProximal"],
|
|
["middle_02_l","leftMiddleIntermediate"],
|
|
["middle_03_l","leftMiddleDistal"],
|
|
["pinky_01_l","leftLittleProximal"],
|
|
["pinky_02_l","leftLittleIntermediate"],
|
|
["pinky_03_l","leftLittleDistal"],
|
|
["ring_01_l","leftRingProximal"],
|
|
["ring_02_l","leftRingIntermediate"],
|
|
["ring_03_l","leftRingDistal"],
|
|
["thumb_01_l","leftThumbProximal"],
|
|
["thumb_02_l","leftThumbIntermediate"],
|
|
["thumb_03_l","leftThumbDistal"],
|
|
["lowerarm_twist_01_l",""],
|
|
["upperarm_twist_01_l",""],
|
|
["clavicle_r","rightShoulder"],
|
|
["upperArm_R","rightUpperArm"],
|
|
["lowerarm_r","rightLowerArm"],
|
|
["hand_R","rightHand"],
|
|
["index_01_r","rightIndexProximal"],
|
|
["index_02_r","rightIndexIntermediate"],
|
|
["index_03_r","rightIndexDistal"],
|
|
["middle_01_r","rightMiddleProximal"],
|
|
["middle_02_r","rightMiddleIntermediate"],
|
|
["middle_03_r","rightMiddleDistal"],
|
|
["pinky_01_r","rightLittleProximal"],
|
|
["pinky_02_r","rightLittleIntermediate"],
|
|
["pinky_03_r","rightLittleDistal"],
|
|
["ring_01_r","rightRingProximal"],
|
|
["ring_02_r","rightRingIntermediate"],
|
|
["ring_03_r","rightRingDistal"],
|
|
["thumb_01_r","rightThumbProximal"],
|
|
["thumb_02_r","rightThumbIntermediate"],
|
|
["thumb_03_r","rightThumbDistal"],
|
|
["lowerarm_twist_01_r",""],
|
|
["upperarm_twist_01_r",""],
|
|
["neck_01","neck"],
|
|
["head","head"],
|
|
["thigh_L","leftUpperLeg"],
|
|
["calf_l","leftLowerLeg"],
|
|
["calf_twist_01_l",""],
|
|
["foot_L","leftFoot"],
|
|
["ball_l","leftToes"],
|
|
["thigh_twist_01_l",""],
|
|
["thigh_R","rightUpperLeg"],
|
|
["calf_r","rightLowerLeg"],
|
|
["calf_twist_01_r",""],
|
|
["foot_R","rightFoot"],
|
|
["ball_r","rightToes"],
|
|
["thigh_twist_01_r",""],
|
|
|
|
["index_metacarpal_l",""],
|
|
["index_metacarpal_r",""],
|
|
["middle_metacarpal_l",""],
|
|
["middle_metacarpal_r",""],
|
|
["ring_metacarpal_l",""],
|
|
["ring_metacarpal_r",""],
|
|
["pinky_metacarpal_l",""],
|
|
["pinky_metacarpal_r",""],
|
|
|
|
#custom
|
|
["eye_l", "leftEye"],
|
|
["eye_r", "rightEye"],
|
|
|
|
]
|
|
|
|
humanoidBoneList = [
|
|
"hips",
|
|
"leftUpperLeg",
|
|
"rightUpperLeg",
|
|
"leftLowerLeg",
|
|
"rightLowerLeg",
|
|
"leftFoot",
|
|
"rightFoot",
|
|
"spine",
|
|
"chest",
|
|
"upperChest", # 9 optional
|
|
"neck",
|
|
"head",
|
|
"leftShoulder",
|
|
"rightShoulder",
|
|
"leftUpperArm",
|
|
"rightUpperArm",
|
|
"leftLowerArm",
|
|
"rightLowerArm",
|
|
"leftHand",
|
|
"rightHand",
|
|
"leftToes",
|
|
"rightToes",
|
|
"leftEye",
|
|
"rightEye",
|
|
"jaw",
|
|
"leftThumbProximal", # 24
|
|
"leftThumbIntermediate",
|
|
"leftThumbDistal",
|
|
"leftIndexProximal",
|
|
"leftIndexIntermediate",
|
|
"leftIndexDistal",
|
|
"leftMiddleProximal",
|
|
"leftMiddleIntermediate",
|
|
"leftMiddleDistal",
|
|
"leftRingProximal",
|
|
"leftRingIntermediate",
|
|
"leftRingDistal",
|
|
"leftLittleProximal",
|
|
"leftLittleIntermediate",
|
|
"leftLittleDistal",
|
|
"rightThumbProximal",
|
|
"rightThumbIntermediate",
|
|
"rightThumbDistal",
|
|
"rightIndexProximal",
|
|
"rightIndexIntermediate",
|
|
"rightIndexDistal",
|
|
"rightMiddleProximal",
|
|
"rightMiddleIntermediate",
|
|
"rightMiddleDistal",
|
|
"rightRingProximal",
|
|
"rightRingIntermediate",
|
|
"rightRingDistal",
|
|
"rightLittleProximal",
|
|
"rightLittleIntermediate",
|
|
"rightLittleDistal", #54
|
|
]
|
|
|
|
for i in range(len(humanoidBoneList)):
|
|
humanoidBoneList[i] = humanoidBoneList[i].lower()
|
|
|
|
|
|
for i in range(len(swapBoneTable)):
|
|
swapBoneTable[i][0] = swapBoneTable[i][0].lower()
|
|
swapBoneTable[i][1] = swapBoneTable[i][1].lower()
|
|
|
|
|
|
### 全ての骨
|
|
modelBoneElementList = []
|
|
modelBoneNameList = []
|
|
|
|
for e in hierarchy.get_bones():
|
|
if (e.type == unreal.RigElementType.BONE):
|
|
modelBoneElementList.append(e)
|
|
modelBoneNameList.append("{}".format(e.name))
|
|
|
|
## meta 取得
|
|
reg = unreal.AssetRegistryHelpers.get_asset_registry();
|
|
a = reg.get_all_assets();
|
|
|
|
if (args.meta):
|
|
for aa in a:
|
|
#print(aa.get_editor_property("package_name"))
|
|
#print(aa.get_editor_property("asset_name"))
|
|
if ((unreal.StringLibrary.conv_name_to_string(aa.get_editor_property("package_name"))+"."+unreal.StringLibrary.conv_name_to_string(aa.get_editor_property("asset_name"))) == unreal.StringLibrary.conv_name_to_string(args.meta)):
|
|
#if (aa.get_editor_property("object_path") == args.meta):
|
|
v:unreal.VrmMetaObject = aa
|
|
vv = aa.get_asset()
|
|
break
|
|
|
|
if (vv == None):
|
|
for aa in a:
|
|
if ((unreal.StringLibrary.conv_name_to_string(aa.get_editor_property("package_name"))+"."+unreal.StringLibrary.conv_name_to_string(aa.get_editor_property("asset_name"))) == unreal.StringLibrary.conv_name_to_string(args.meta)):
|
|
#if (aa.get_editor_property("object_path") == args.vrm):
|
|
v:unreal.VrmAssetListObject = aa
|
|
vv = v.get_asset().vrm_meta_object
|
|
break
|
|
|
|
meta = vv
|
|
|
|
# Backwards Bone Names
|
|
allBackwardsNode = []
|
|
|
|
def r_nodes(node):
|
|
b = False
|
|
try:
|
|
allBackwardsNode.index(node)
|
|
except:
|
|
b = True
|
|
if (b == True):
|
|
allBackwardsNode.append(node)
|
|
|
|
linknode = node.get_linked_source_nodes()
|
|
for n in linknode:
|
|
r_nodes(n)
|
|
|
|
linknode = node.get_linked_target_nodes()
|
|
for n in linknode:
|
|
r_nodes(n)
|
|
|
|
for n in node:
|
|
if (n.get_node_title() == 'Backwards Solve'):
|
|
r_nodes(n)
|
|
|
|
#print(len(allBackwardsNode))
|
|
#print(len(node))
|
|
|
|
def boneOverride(pin):
|
|
subpins = pin.get_sub_pins()
|
|
if (len(subpins) != 2):
|
|
return
|
|
|
|
typePin = pin.find_sub_pin('Type')
|
|
namePin = pin.find_sub_pin('Name')
|
|
|
|
if (typePin==None):
|
|
return
|
|
|
|
if (namePin==None):
|
|
return
|
|
|
|
controlName = namePin.get_default_value()
|
|
|
|
if (controlName==''):
|
|
return
|
|
|
|
if (controlName.endswith('_ctrl')):
|
|
return
|
|
if (controlName.endswith('_space')):
|
|
return
|
|
|
|
r_con.set_pin_default_value(typePin.get_pin_path(), 'Bone', True, False)
|
|
|
|
table = [i for i in swapBoneTable if i[0]==controlName]
|
|
if (len(table) == 0):
|
|
# use node or no control
|
|
return
|
|
|
|
if (table[0][0] == 'root'):
|
|
metaTable = "{}".format(hierarchy.get_bones()[0].name)
|
|
else:
|
|
metaTable = meta.humanoid_bone_table.get(table[0][1])
|
|
if (metaTable == None):
|
|
metaTable = 'None'
|
|
|
|
r_con.set_pin_default_value(namePin.get_pin_path(), metaTable, True, False)
|
|
#for e in meta.humanoid_bone_table:
|
|
|
|
for n in allBackwardsNode:
|
|
pins = n.get_pins()
|
|
for pin in pins:
|
|
if (pin.is_array()):
|
|
# finger 無変換チェック
|
|
linknode = n.get_linked_target_nodes()
|
|
if (len(linknode) == 1):
|
|
if (linknode[0].get_node_title()=='At'):
|
|
continue
|
|
|
|
for p in pin.get_sub_pins():
|
|
boneOverride(p)
|
|
else:
|
|
boneOverride(pin)
|
|
|
|
|
|
#sfsdjfkasjk
|
|
|
|
|
|
### 骨名対応表。Humanoid名 -> Model名
|
|
humanoidBoneToModel = {"" : ""}
|
|
humanoidBoneToModel.clear()
|
|
|
|
humanoidBoneToMannequin = {"" : ""}
|
|
humanoidBoneToMannequin.clear()
|
|
|
|
# humanoidBone -> modelBone のテーブル作る
|
|
for searchHumanoidBone in humanoidBoneList:
|
|
bone_h = None
|
|
for e in meta.humanoid_bone_table:
|
|
if ("{}".format(e).lower() == searchHumanoidBone):
|
|
bone_h = e;
|
|
break;
|
|
|
|
if (bone_h==None):
|
|
# not found
|
|
continue
|
|
|
|
bone_m = meta.humanoid_bone_table[bone_h]
|
|
|
|
try:
|
|
i = modelBoneNameList.index(bone_m)
|
|
except:
|
|
i = -1
|
|
if (i < 0):
|
|
# no bone
|
|
continue
|
|
|
|
humanoidBoneToModel["{}".format(bone_h).lower()] = "{}".format(bone_m)
|
|
#humanoidBoneToMannequin["{}".format(bone_h).lower()] = "{}".format(bone_m).lower(bone_h)
|
|
|
|
|
|
#print(humanoidBoneToModel)
|
|
|
|
#print(bonePin)
|
|
#print(controlPin)
|
|
|
|
if (bonePin != None and controlPin !=None):
|
|
r_con.clear_array_pin(bonePin.get_pin_path())
|
|
r_con.clear_array_pin(controlPin.get_pin_path())
|
|
|
|
#c.clear_array_pin(v.get_pin_path())
|
|
|
|
#tmp = '(Type=Control,Name='
|
|
#tmp += "{}".format('aaaaa')
|
|
#tmp += ')'
|
|
#r_con.add_array_pin(bonePin.get_pin_path(), default_value=tmp)
|
|
|
|
with unreal.ScopedSlowTask(len(swapBoneTable), "Replace Name") as slow_task:
|
|
slow_task.make_dialog()
|
|
|
|
for e in swapBoneTable:
|
|
slow_task.enter_progress_frame(1)
|
|
try:
|
|
i = 0
|
|
humanoidBoneToModel[e[1]]
|
|
except:
|
|
i = -1
|
|
if (i < 0):
|
|
# no bone
|
|
continue
|
|
#e[0] -> grayman
|
|
#e[1] -> humanoid
|
|
#humanoidBoneToModel[e[1]] -> modelBone
|
|
|
|
bone = unreal.RigElementKey(unreal.RigElementType.BONE, humanoidBoneToModel[e[1]])
|
|
space = unreal.RigElementKey(unreal.RigElementType.NULL, "{}_s".format(e[0]))
|
|
|
|
#print('aaa')
|
|
#print(bone)
|
|
#print(space)
|
|
|
|
#p = hierarchy.get_first_parent(humanoidBoneToModel[result[0][1]])
|
|
|
|
t = hierarchy.get_global_transform(bone)
|
|
#print(t)
|
|
hierarchy.set_global_transform(space, t, True)
|
|
|
|
if (bonePin != None and controlPin !=None):
|
|
|
|
tmp = '(Type=Control,Name='
|
|
tmp += "{}".format(e[0])
|
|
tmp += ')'
|
|
r_con.add_array_pin(controlPin.get_pin_path(), default_value=tmp, setup_undo_redo=False)
|
|
|
|
tmp = '(Type=Bone,Name='
|
|
tmp += "\"{}\"".format(humanoidBoneToModel[e[1]])
|
|
tmp += ')'
|
|
r_con.add_array_pin(bonePin.get_pin_path(), default_value=tmp, setup_undo_redo=False)
|
|
|
|
# for bone name space
|
|
namePin = bonePin.get_sub_pins()[-1].find_sub_pin('Name')
|
|
r_con.set_pin_default_value(namePin.get_pin_path(), "{}".format(humanoidBoneToModel[e[1]]), True, False)
|
|
|
|
|
|
# skip invalid bone, controller
|
|
|
|
# disable node
|
|
def disableNode(toNoneNode):
|
|
print(toNoneNode)
|
|
pins = toNoneNode.get_pins()
|
|
for pin in pins:
|
|
typePin = pin.find_sub_pin('Type')
|
|
namePin = pin.find_sub_pin('Name')
|
|
|
|
if (typePin==None or namePin==None):
|
|
continue
|
|
print(f'DisablePin {typePin.get_default_value()} : {namePin.get_default_value()}')
|
|
|
|
# control
|
|
key = unreal.RigElementKey(unreal.RigElementType.CONTROL, "{}".format(namePin.get_default_value()))
|
|
|
|
# disable node
|
|
r_con.set_pin_default_value(namePin.get_pin_path(), 'None', True, False)
|
|
|
|
if (typePin.get_default_value() == 'Control'):
|
|
|
|
#disable control
|
|
if (hierarchy.contains(key) == True):
|
|
settings = h_con.get_control_settings(key)
|
|
|
|
if ("5." in unreal.SystemLibrary.get_engine_version()):
|
|
if ("5.0." in unreal.SystemLibrary.get_engine_version()):
|
|
settings.set_editor_property('shape_enabled', False)
|
|
else:
|
|
settings.set_editor_property('shape_visible', False)
|
|
else:
|
|
settings.set_editor_property('shape_enabled', False)
|
|
|
|
ttt = hierarchy.get_global_control_shape_transform(key, True)
|
|
ttt.scale3d.set(0.001, 0.001, 0.001)
|
|
hierarchy.set_control_shape_transform(key, ttt, True)
|
|
|
|
h_con.set_control_settings(key, settings)
|
|
|
|
|
|
for n in node:
|
|
pins = n.get_pins()
|
|
for pin in pins:
|
|
if (pin.is_array()):
|
|
continue
|
|
else:
|
|
typePin = pin.find_sub_pin('Type')
|
|
namePin = pin.find_sub_pin('Name')
|
|
if (typePin==None or namePin==None):
|
|
continue
|
|
if (typePin.get_default_value() != 'Bone'):
|
|
continue
|
|
|
|
if (namePin.is_u_object() == True):
|
|
continue
|
|
|
|
if (len(n.get_linked_source_nodes()) > 0):
|
|
continue
|
|
|
|
key = unreal.RigElementKey(unreal.RigElementType.BONE, namePin.get_default_value())
|
|
if (hierarchy.contains(key) == True):
|
|
continue
|
|
print(f'disable linked node from {typePin.get_default_value()} : {namePin.get_default_value()}')
|
|
for toNoneNode in n.get_linked_target_nodes():
|
|
disableNode(toNoneNode)
|
|
|
|
# for n in node:
|
|
# pins = n.get_pins()
|
|
# for pin in pins:
|
|
# if (pin.is_array()):
|
|
# continue
|
|
# else:
|
|
# typePin = pin.find_sub_pin('Type')
|
|
# namePin = pin.find_sub_pin('Name')
|
|
# if (typePin == None):
|
|
# continue
|
|
# if (typePin.get_default_value() == 'Bone'):
|
|
# bonePin = pin
|
|
# continue
|
|
# if (typePin.get_default_value() == 'Control'):
|
|
# if ('Name="pelvis"' in r_con.get_pin_default_value(n.find_pin('Items').get_pin_path())):
|
|
# controlPin = pin
|
|
# continue
|
|
# for item in pin.get_sub_pins():
|
|
# checkAndSwapPinBoneToContorl(item)
|
|
# checkAndSwapPinBoneToContorl(pin)
|
|
|
|
|
|
|
|
## morph
|
|
|
|
# -vrm vrm -rig rig -debugeachsave 0
|
|
#args.vrm
|
|
#args.rig
|
|
|
|
command = 'VRM4U_CreateMorphTargetControllerUE5.py ' + '-vrm ' + args.vrm + ' -rig ' + args.rig + ' -debugeachsave 0'
|
|
|
|
print(command)
|
|
|
|
unreal.PythonScriptLibrary.execute_python_command(command)
|
|
|
|
unreal.ControlRigBlueprintLibrary.recompile_vm(rig)
|