Files
FunnyGirl/Plugins/VRM4U/Content/Python/VRM4U_OverrideMannequinRigUE5.py
T
2026-05-19 13:42:41 +07:00

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)