pyjallib 0.1.9__py3-none-any.whl → 0.1.10__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyjallib/__init__.py +1 -1
- pyjallib/max/ConfigFiles/Default_3DSMaxNamingConfig.json +161 -0
- pyjallib/max/__init__.py +14 -2
- pyjallib/max/anim.py +60 -36
- pyjallib/max/autoClavicle.py +97 -132
- pyjallib/max/autoClavicleChain.py +173 -0
- pyjallib/max/bip.py +211 -14
- pyjallib/max/bone.py +341 -16
- pyjallib/max/groinBone.py +116 -77
- pyjallib/max/groinBoneChain.py +173 -0
- pyjallib/max/header.py +42 -6
- pyjallib/max/helper.py +3 -21
- pyjallib/max/hip.py +239 -366
- pyjallib/max/kneeBone.py +517 -0
- pyjallib/max/macro/jal_macro_align.py +11 -10
- pyjallib/max/macro/jal_macro_bone.py +2 -1
- pyjallib/max/macro/jal_macro_constraint.py +2 -1
- pyjallib/max/macro/jal_macro_helper.py +2 -1
- pyjallib/max/macro/jal_macro_link.py +2 -1
- pyjallib/max/macro/jal_macro_select.py +2 -1
- pyjallib/max/mirror.py +1 -1
- pyjallib/max/twistBone.py +258 -475
- pyjallib/max/twistBoneChain.py +162 -0
- pyjallib/max/volumeBone.py +273 -0
- pyjallib/max/volumeBoneChain.py +363 -0
- pyjallib/namePart.py +16 -16
- pyjallib/nameToPath.py +1 -1
- pyjallib/naming.py +15 -16
- pyjallib/namingConfig.py +3 -3
- {pyjallib-0.1.9.dist-info → pyjallib-0.1.10.dist-info}/METADATA +1 -1
- pyjallib-0.1.10.dist-info/RECORD +46 -0
- pyjallib/max/volumePreserveBone.py +0 -209
- pyjallib/p4module.py +0 -488
- pyjallib-0.1.9.dist-info/RECORD +0 -41
- {pyjallib-0.1.9.dist-info → pyjallib-0.1.10.dist-info}/WHEEL +0 -0
pyjallib/max/bone.py
CHANGED
@@ -239,7 +239,7 @@ class Bone:
|
|
239
239
|
nubBone.backfin = False
|
240
240
|
nubBone.sidefins = False
|
241
241
|
nubBone.name = self.name.remove_name_part("Index", inName)
|
242
|
-
nubBone.name = self.name.replace_name_part("Nub", nubBone.name, "Nub")
|
242
|
+
nubBone.name = self.name.replace_name_part("Nub", nubBone.name, self.name.get_name_part_value_by_description("Nub", "Nub"))
|
243
243
|
|
244
244
|
# 화면 갱신 재개
|
245
245
|
rt.enableSceneRedraw()
|
@@ -679,18 +679,18 @@ class Bone:
|
|
679
679
|
inOriBone: 원본 뼈대
|
680
680
|
"""
|
681
681
|
self.anim.save_xform(inSkinBone)
|
682
|
-
self.anim.set_xform(inSkinBone)
|
682
|
+
self.anim.set_xform(inSkinBone, space="World")
|
683
683
|
|
684
684
|
self.anim.save_xform(inOriBone)
|
685
|
-
self.anim.set_xform(inOriBone)
|
686
685
|
|
687
686
|
rt.setPropertyController(inSkinBone.controller, "Scale", rt.scaleXYZ())
|
688
687
|
|
689
688
|
linkConst = rt.link_constraint()
|
689
|
+
linkConst.addTarget(inOriBone, 0)
|
690
|
+
|
690
691
|
inSkinBone.controller = linkConst
|
691
692
|
|
692
|
-
self.anim.set_xform(
|
693
|
-
linkConst.addTarget(inOriBone, 0)
|
693
|
+
self.anim.set_xform(inSkinBone, space="World")
|
694
694
|
|
695
695
|
def link_skin_bones(self, inSkinBoneArray, inOriBoneArray):
|
696
696
|
"""
|
@@ -705,10 +705,48 @@ class Bone:
|
|
705
705
|
False: 실패
|
706
706
|
"""
|
707
707
|
if len(inSkinBoneArray) != len(inOriBoneArray):
|
708
|
+
print("Error: Skin bone array and original bone array must have the same length.")
|
708
709
|
return False
|
709
710
|
|
710
|
-
|
711
|
-
|
711
|
+
skinBoneDict = {}
|
712
|
+
oriBoneDict = {}
|
713
|
+
|
714
|
+
# 스킨 뼈대 딕셔너리 생성 (이름과 패턴화된 이름을 함께 저장)
|
715
|
+
for item in inSkinBoneArray:
|
716
|
+
# 아이템 저장
|
717
|
+
skinBoneDict[item.name] = item
|
718
|
+
# 언더스코어를 별표로 변환한 패턴 생성
|
719
|
+
namePattern = self.name.remove_name_part("Base", item.name)
|
720
|
+
namePattern = namePattern.replace("_", "*")
|
721
|
+
skinBoneDict[item.name + "_Pattern"] = namePattern
|
722
|
+
|
723
|
+
# 원본 뼈대 딕셔너리 생성 (이름과 패턴화된 이름을 함께 저장)
|
724
|
+
for item in inOriBoneArray:
|
725
|
+
# 아이템 저장
|
726
|
+
oriBoneDict[item.name] = item
|
727
|
+
# 공백을 별표로 변환한 패턴 생성
|
728
|
+
namePattern = self.name.remove_name_part("Base", item.name)
|
729
|
+
namePattern = namePattern.replace(" ", "*")
|
730
|
+
oriBoneDict[item.name + "_Pattern"] = namePattern
|
731
|
+
|
732
|
+
# 정렬된 배열 생성
|
733
|
+
sortedSkinBoneArray = []
|
734
|
+
sortedOriBoneArray = []
|
735
|
+
|
736
|
+
# 같은 패턴을 가진 뼈대들을 찾아 매칭
|
737
|
+
for skinName, skinBone in [(k, v) for k, v in skinBoneDict.items() if not k.endswith("_Pattern")]:
|
738
|
+
skinPattern = skinBoneDict[skinName + "_Pattern"]
|
739
|
+
|
740
|
+
for oriName, oriBone in [(k, v) for k, v in oriBoneDict.items() if not k.endswith("_Pattern")]:
|
741
|
+
oriPattern = oriBoneDict[oriName + "_Pattern"]
|
742
|
+
|
743
|
+
if rt.matchPattern(skinName, pattern=oriPattern):
|
744
|
+
sortedSkinBoneArray.append(skinBone)
|
745
|
+
sortedOriBoneArray.append(oriBone)
|
746
|
+
break
|
747
|
+
# 링크 연결 수행
|
748
|
+
for i in range(len(sortedSkinBoneArray)):
|
749
|
+
self.link_skin_bone(sortedSkinBoneArray[i], sortedOriBoneArray[i])
|
712
750
|
|
713
751
|
return True
|
714
752
|
|
@@ -732,17 +770,12 @@ class Bone:
|
|
732
770
|
returnBones = []
|
733
771
|
|
734
772
|
definedSkinBoneBaseName = self.name.get_name_part_value_by_description("Base", "SkinBone")
|
735
|
-
if skinBoneBaseName == "":
|
736
|
-
if definedSkinBoneBaseName == "":
|
737
|
-
skinBoneBaseName = "b"
|
738
|
-
else:
|
739
|
-
skinBoneBaseName = definedSkinBoneBaseName
|
740
773
|
|
741
774
|
for i in range(len(inBoneArray)):
|
742
|
-
skinBoneName = self.name.replace_name_part("Base", inBoneArray[i].name,
|
775
|
+
skinBoneName = self.name.replace_name_part("Base", inBoneArray[i].name, definedSkinBoneBaseName)
|
743
776
|
skinBoneName = self.name.replace_filtering_char(skinBoneName, skinBoneFilteringChar)
|
744
777
|
|
745
|
-
skinBone = self.create_nub_bone(f"{
|
778
|
+
skinBone = self.create_nub_bone(f"{definedSkinBoneBaseName}_TempSkin", 2)
|
746
779
|
skinBone.name = skinBoneName
|
747
780
|
skinBone.wireColor = rt.Color(255, 88, 199)
|
748
781
|
skinBone.transform = inBoneArray[i].transform
|
@@ -767,12 +800,19 @@ class Bone:
|
|
767
800
|
for i in range(len(inBoneArray)):
|
768
801
|
oriParentObj = inBoneArray[i].parent
|
769
802
|
if oriParentObj is not None:
|
770
|
-
skinBoneParentObjName = self.name.
|
803
|
+
skinBoneParentObjName = self.name.replace_name_part("Base", oriParentObj.name, definedSkinBoneBaseName)
|
771
804
|
skinBoneParentObjName = self.name.replace_filtering_char(skinBoneParentObjName, skinBoneFilteringChar)
|
772
805
|
bones[i].parent = rt.getNodeByName(skinBoneParentObjName)
|
773
806
|
else:
|
774
807
|
bones[i].parent = None
|
775
808
|
|
809
|
+
for item in bones:
|
810
|
+
item.showLinks = True
|
811
|
+
item.showLinksOnly = True
|
812
|
+
|
813
|
+
for item in bones:
|
814
|
+
item.name = self.name.replace_name_part("Base", item.name, skinBoneBaseName)
|
815
|
+
|
776
816
|
if link:
|
777
817
|
self.link_skin_bones(bones, inBoneArray)
|
778
818
|
|
@@ -798,7 +838,7 @@ class Bone:
|
|
798
838
|
skipNub: Nub 뼈대 건너뛰기 (기본값: True)
|
799
839
|
mesh: 메시 스냅샷 사용 (기본값: False)
|
800
840
|
link: 원본 뼈대에 연결 (기본값: True)
|
801
|
-
skinBoneBaseName: 스킨 뼈대 기본 이름 (기본값: "
|
841
|
+
skinBoneBaseName: 스킨 뼈대 기본 이름 (기본값: "")
|
802
842
|
|
803
843
|
Returns:
|
804
844
|
생성된 스킨 뼈대 배열
|
@@ -844,6 +884,291 @@ class Bone:
|
|
844
884
|
|
845
885
|
return genBones
|
846
886
|
|
887
|
+
def gen_missing_bip_bones_for_ue5manny(self, inBoneArray):
|
888
|
+
returnBones = []
|
889
|
+
spine3 = None
|
890
|
+
neck = None
|
891
|
+
|
892
|
+
handL = None
|
893
|
+
handR = None
|
894
|
+
|
895
|
+
fingerNames = ["index", "middle", "ring", "pinky"]
|
896
|
+
knuckleName = "metacarpal"
|
897
|
+
lKnuckleDistance = []
|
898
|
+
rKnuckleDistance = []
|
899
|
+
|
900
|
+
lFingers = []
|
901
|
+
rFingers = []
|
902
|
+
|
903
|
+
for item in inBoneArray:
|
904
|
+
if rt.matchPattern(item.name, pattern="*spine 03"):
|
905
|
+
spine3 = item
|
906
|
+
if rt.matchPattern(item.name, pattern="*neck 01"):
|
907
|
+
neck = item
|
908
|
+
if rt.matchPattern(item.name, pattern="*hand*l"):
|
909
|
+
handL = item
|
910
|
+
if rt.matchPattern(item.name, pattern="*hand*r"):
|
911
|
+
handR = item
|
912
|
+
|
913
|
+
for fingerName in fingerNames:
|
914
|
+
if rt.matchPattern(item.name, pattern="*"+fingerName+"*01*l"):
|
915
|
+
lFingers.append(item)
|
916
|
+
if rt.matchPattern(item.name, pattern="*"+fingerName+"*01*r"):
|
917
|
+
rFingers.append(item)
|
918
|
+
for finger in lFingers:
|
919
|
+
fingerDistance = rt.distance(finger, handL)
|
920
|
+
lKnuckleDistance.append(fingerDistance)
|
921
|
+
for finger in rFingers:
|
922
|
+
fingerDistance = rt.distance(finger, handR)
|
923
|
+
rKnuckleDistance.append(fingerDistance)
|
924
|
+
|
925
|
+
filteringChar = self.name._get_filtering_char(inBoneArray[-1].name)
|
926
|
+
isLower = inBoneArray[-1].name[0].islower()
|
927
|
+
spineName = self.name.get_name_part_value_by_description("Base", "Biped") + filteringChar + "Spine"
|
928
|
+
|
929
|
+
spine4 = self.create_nub_bone(spineName, 2)
|
930
|
+
spine5 = self.create_nub_bone(spineName, 2)
|
931
|
+
|
932
|
+
spine4.name = self.name.replace_name_part("Index", spine4.name, "4")
|
933
|
+
spine4.name = self.name.remove_name_part("Nub", spine4.name)
|
934
|
+
spine5.name = self.name.replace_name_part("Index", spine5.name, "5")
|
935
|
+
spine5.name = self.name.remove_name_part("Nub", spine5.name)
|
936
|
+
if isLower:
|
937
|
+
spine4.name = spine4.name.lower()
|
938
|
+
spine5.name = spine5.name.lower()
|
939
|
+
|
940
|
+
spineDistance = rt.distance(spine3, neck)/3.0
|
941
|
+
rt.setProperty(spine4, "transform", spine3.transform)
|
942
|
+
rt.setProperty(spine5, "transform", spine3.transform)
|
943
|
+
self.anim.move_local(spine4, spineDistance, 0, 0)
|
944
|
+
self.anim.move_local(spine5, spineDistance * 2, 0, 0)
|
945
|
+
|
946
|
+
returnBones.append(spine4)
|
947
|
+
returnBones.append(spine5)
|
948
|
+
|
949
|
+
for i, finger in enumerate(lFingers):
|
950
|
+
knuckleBoneName = self.name.add_suffix_to_real_name(finger.name, filteringChar+knuckleName)
|
951
|
+
knuckleBoneName = self.name.remove_name_part("Index", knuckleBoneName)
|
952
|
+
|
953
|
+
knuckleBone = self.create_nub_bone(knuckleBoneName, 2)
|
954
|
+
knuckleBone.name = self.name.remove_name_part("Nub", knuckleBone.name)
|
955
|
+
if isLower:
|
956
|
+
knuckleBone.name = knuckleBone.name.lower()
|
957
|
+
|
958
|
+
knuckleBone.transform = finger.transform
|
959
|
+
lookAtConst = self.const.assign_lookat(knuckleBone, handL)
|
960
|
+
lookAtConst.upnode_world = False
|
961
|
+
lookAtConst.pickUpNode = handL
|
962
|
+
lookAtConst.lookat_vector_length = 0.0
|
963
|
+
lookAtConst.target_axisFlip = True
|
964
|
+
self.const.collapse(knuckleBone)
|
965
|
+
self.anim.move_local(knuckleBone, -lKnuckleDistance[i]*0.8, 0, 0)
|
966
|
+
|
967
|
+
returnBones.append(knuckleBone)
|
968
|
+
|
969
|
+
for i, finger in enumerate(rFingers):
|
970
|
+
knuckleBoneName = self.name.add_suffix_to_real_name(finger.name, filteringChar+knuckleName)
|
971
|
+
knuckleBoneName = self.name.remove_name_part("Index", knuckleBoneName)
|
972
|
+
|
973
|
+
knuckleBone = self.create_nub_bone(knuckleBoneName, 2)
|
974
|
+
knuckleBone.name = self.name.remove_name_part("Nub", knuckleBone.name)
|
975
|
+
if isLower:
|
976
|
+
knuckleBone.name = knuckleBone.name.lower()
|
977
|
+
|
978
|
+
knuckleBone.transform = finger.transform
|
979
|
+
lookAtConst = self.const.assign_lookat(knuckleBone, handR)
|
980
|
+
lookAtConst.upnode_world = False
|
981
|
+
lookAtConst.pickUpNode = handR
|
982
|
+
lookAtConst.lookat_vector_length = 0.0
|
983
|
+
lookAtConst.target_axisFlip = True
|
984
|
+
self.const.collapse(knuckleBone)
|
985
|
+
self.anim.move_local(knuckleBone, -rKnuckleDistance[i]*0.8, 0, 0)
|
986
|
+
|
987
|
+
returnBones.append(knuckleBone)
|
988
|
+
|
989
|
+
return returnBones
|
990
|
+
|
991
|
+
def relink_missing_bip_bones_for_ue5manny(self, inBipArray, inMissingBoneArray):
|
992
|
+
returnBones = []
|
993
|
+
|
994
|
+
spine3 = None
|
995
|
+
|
996
|
+
handL = None
|
997
|
+
handR = None
|
998
|
+
|
999
|
+
knuckleName = "metacarpal"
|
1000
|
+
|
1001
|
+
for item in inBipArray:
|
1002
|
+
if rt.matchPattern(item.name, pattern="*spine 03"):
|
1003
|
+
spine3 = item
|
1004
|
+
if rt.matchPattern(item.name, pattern="*hand*l"):
|
1005
|
+
handL = item
|
1006
|
+
if rt.matchPattern(item.name, pattern="*hand*r"):
|
1007
|
+
handR = item
|
1008
|
+
|
1009
|
+
for item in inMissingBoneArray:
|
1010
|
+
if rt.matchPattern(item.name, pattern="*spine*"):
|
1011
|
+
item.parent = spine3
|
1012
|
+
if rt.matchPattern(item.name, pattern=f"*{knuckleName}*l"):
|
1013
|
+
item.parent = handL
|
1014
|
+
if rt.matchPattern(item.name, pattern=f"*{knuckleName}*r"):
|
1015
|
+
item.parent = handR
|
1016
|
+
|
1017
|
+
returnBones.append(inBipArray)
|
1018
|
+
returnBones.append(inMissingBoneArray)
|
1019
|
+
return returnBones
|
1020
|
+
|
1021
|
+
def relink_missing_skin_bones_for_ue5manny(self, inSkinArray):
|
1022
|
+
returnBones = []
|
1023
|
+
spine3 = None
|
1024
|
+
spine4 = None
|
1025
|
+
spine5 = None
|
1026
|
+
|
1027
|
+
neck = None
|
1028
|
+
clavicleL = None
|
1029
|
+
clavicleR = None
|
1030
|
+
|
1031
|
+
handL = None
|
1032
|
+
handR = None
|
1033
|
+
|
1034
|
+
fingerNames = ["index", "middle", "ring", "pinky"]
|
1035
|
+
knuckleName = "metacarpal"
|
1036
|
+
|
1037
|
+
lFingers = []
|
1038
|
+
rFingers = []
|
1039
|
+
|
1040
|
+
for item in inSkinArray:
|
1041
|
+
if rt.matchPattern(item.name, pattern="*spine*03"):
|
1042
|
+
spine3 = item
|
1043
|
+
if rt.matchPattern(item.name, pattern="*neck*01"):
|
1044
|
+
neck = item
|
1045
|
+
if rt.matchPattern(item.name, pattern="*clavicle*l"):
|
1046
|
+
clavicleL = item
|
1047
|
+
if rt.matchPattern(item.name, pattern="*clavicle*r"):
|
1048
|
+
clavicleR = item
|
1049
|
+
|
1050
|
+
if rt.matchPattern(item.name, pattern="*hand*l"):
|
1051
|
+
handL = item
|
1052
|
+
if rt.matchPattern(item.name, pattern="*hand*r"):
|
1053
|
+
handR = item
|
1054
|
+
|
1055
|
+
for fingerName in fingerNames:
|
1056
|
+
if rt.matchPattern(item.name, pattern="*"+fingerName+"*01*l"):
|
1057
|
+
lFingers.append(item)
|
1058
|
+
if rt.matchPattern(item.name, pattern="*"+fingerName+"*01*r"):
|
1059
|
+
rFingers.append(item)
|
1060
|
+
|
1061
|
+
for item in inSkinArray:
|
1062
|
+
if rt.matchPattern(item.name, pattern="*spine*04"):
|
1063
|
+
spine4 = item
|
1064
|
+
item.parent = spine3
|
1065
|
+
|
1066
|
+
if rt.matchPattern(item.name, pattern="*spine*05"):
|
1067
|
+
spine5 = item
|
1068
|
+
item.parent = spine4
|
1069
|
+
neck.parent = spine5
|
1070
|
+
clavicleL.parent = spine5
|
1071
|
+
clavicleR.parent = spine5
|
1072
|
+
|
1073
|
+
if rt.matchPattern(item.name, pattern=f"*{knuckleName}*l"):
|
1074
|
+
item.parent = handL
|
1075
|
+
if rt.matchPattern(item.name, pattern=f"*{knuckleName}*r"):
|
1076
|
+
item.parent = handR
|
1077
|
+
|
1078
|
+
filteringChar = self.name._get_filtering_char(inSkinArray[-1].name)
|
1079
|
+
|
1080
|
+
for item in lFingers:
|
1081
|
+
fingerNamePattern = self.name.add_suffix_to_real_name(item.name, filteringChar+knuckleName)
|
1082
|
+
fingerNamePattern = self.name.remove_name_part("Index", fingerNamePattern)
|
1083
|
+
for knuckle in inSkinArray:
|
1084
|
+
if rt.matchPattern(knuckle.name, pattern=fingerNamePattern):
|
1085
|
+
item.parent = knuckle
|
1086
|
+
break
|
1087
|
+
|
1088
|
+
for item in rFingers:
|
1089
|
+
fingerNamePattern = self.name.add_suffix_to_real_name(item.name, filteringChar+knuckleName)
|
1090
|
+
fingerNamePattern = self.name.remove_name_part("Index", fingerNamePattern)
|
1091
|
+
for knuckle in inSkinArray:
|
1092
|
+
if rt.matchPattern(knuckle.name, pattern=fingerNamePattern):
|
1093
|
+
item.parent = knuckle
|
1094
|
+
break
|
1095
|
+
|
1096
|
+
return returnBones
|
1097
|
+
|
1098
|
+
def create_skin_bone_from_bip_for_ue5manny(self, inBoneArray, skipNub=True, mesh=False, link=True, isHuman=False, skinBoneBaseName=""):
|
1099
|
+
targetBones = [item for item in inBoneArray
|
1100
|
+
if (rt.classOf(item) == rt.Biped_Object)
|
1101
|
+
and (not rt.matchPattern(item.name, pattern="*Twist*"))
|
1102
|
+
and (item != item.controller.rootNode)]
|
1103
|
+
|
1104
|
+
missingBipBones = []
|
1105
|
+
|
1106
|
+
if isHuman:
|
1107
|
+
missingBipBones = self.gen_missing_bip_bones_for_ue5manny(targetBones)
|
1108
|
+
self.relink_missing_bip_bones_for_ue5manny(targetBones, missingBipBones)
|
1109
|
+
|
1110
|
+
for item in missingBipBones:
|
1111
|
+
targetBones.append(item)
|
1112
|
+
|
1113
|
+
sortedBipBones = self.sort_bones_as_hierarchy(targetBones)
|
1114
|
+
|
1115
|
+
skinBones = self.create_skin_bone(sortedBipBones, skipNub=skipNub, mesh=mesh, link=False, skinBoneBaseName=skinBoneBaseName)
|
1116
|
+
if len(skinBones) == 0:
|
1117
|
+
return False
|
1118
|
+
|
1119
|
+
for item in skinBones:
|
1120
|
+
if rt.matchPattern(item.name, pattern="*pelvis*"):
|
1121
|
+
self.anim.rotate_local(item, 180, 0, 0, dontAffectChildren=True)
|
1122
|
+
if rt.matchPattern(item.name, pattern="*spine*"):
|
1123
|
+
self.anim.rotate_local(item, 180, 0, 0, dontAffectChildren=True)
|
1124
|
+
if rt.matchPattern(item.name, pattern="*neck*"):
|
1125
|
+
self.anim.rotate_local(item, 180, 0, 0, dontAffectChildren=True)
|
1126
|
+
if rt.matchPattern(item.name, pattern="*head*"):
|
1127
|
+
self.anim.rotate_local(item, 180, 0, 0, dontAffectChildren=True)
|
1128
|
+
if rt.matchPattern(item.name, pattern="*thigh*l"):
|
1129
|
+
self.anim.rotate_local(item, 0, 0, 180, dontAffectChildren=True)
|
1130
|
+
if rt.matchPattern(item.name, pattern="*calf*l"):
|
1131
|
+
self.anim.rotate_local(item, 0, 0, 180, dontAffectChildren=True)
|
1132
|
+
if rt.matchPattern(item.name, pattern="*foot*l"):
|
1133
|
+
self.anim.rotate_local(item, 0, 0, 180, dontAffectChildren=True)
|
1134
|
+
if rt.matchPattern(item.name, pattern="*ball*r"):
|
1135
|
+
self.anim.rotate_local(item, 0, 0, 180, dontAffectChildren=True)
|
1136
|
+
|
1137
|
+
if rt.matchPattern(item.name, pattern="*clavicle*r"):
|
1138
|
+
self.anim.rotate_local(item, 0, 0, -180, dontAffectChildren=True)
|
1139
|
+
if rt.matchPattern(item.name, pattern="*upperarm*r"):
|
1140
|
+
self.anim.rotate_local(item, 0, 0, -180, dontAffectChildren=True)
|
1141
|
+
if rt.matchPattern(item.name, pattern="*lowerarm*r"):
|
1142
|
+
self.anim.rotate_local(item, 0, 0, -180, dontAffectChildren=True)
|
1143
|
+
if rt.matchPattern(item.name, pattern="*hand*r"):
|
1144
|
+
self.anim.rotate_local(item, 0, 0, -180, dontAffectChildren=True)
|
1145
|
+
|
1146
|
+
if rt.matchPattern(item.name, pattern="*thumb*r"):
|
1147
|
+
self.anim.rotate_local(item, 0, 0, 180, dontAffectChildren=True)
|
1148
|
+
if rt.matchPattern(item.name, pattern="*index*r"):
|
1149
|
+
self.anim.rotate_local(item, 0, 0, 180, dontAffectChildren=True)
|
1150
|
+
if rt.matchPattern(item.name, pattern="*middle*r"):
|
1151
|
+
self.anim.rotate_local(item, 0, 0, 180, dontAffectChildren=True)
|
1152
|
+
if rt.matchPattern(item.name, pattern="*ring*r"):
|
1153
|
+
self.anim.rotate_local(item, 0, 0, 180, dontAffectChildren=True)
|
1154
|
+
if rt.matchPattern(item.name, pattern="*pinky*r"):
|
1155
|
+
self.anim.rotate_local(item, 0, 0, 180, dontAffectChildren=True)
|
1156
|
+
|
1157
|
+
if rt.matchPattern(item.name, pattern="*metacarpal*"):
|
1158
|
+
tempArray = self.name._split_to_array(item.name)
|
1159
|
+
item.name = self.name._combine(tempArray, inFilChar="_")
|
1160
|
+
item.name = self.name.remove_name_part("Base", item.name)
|
1161
|
+
|
1162
|
+
self.anim.save_xform(item)
|
1163
|
+
|
1164
|
+
self.relink_missing_skin_bones_for_ue5manny(skinBones)
|
1165
|
+
|
1166
|
+
self.link_skin_bones(skinBones, sortedBipBones)
|
1167
|
+
for item in skinBones:
|
1168
|
+
self.anim.save_xform(item)
|
1169
|
+
|
1170
|
+
return skinBones
|
1171
|
+
|
847
1172
|
def set_bone_on(self, inBone):
|
848
1173
|
"""
|
849
1174
|
뼈대 활성화.
|
pyjallib/max/groinBone.py
CHANGED
@@ -7,7 +7,12 @@
|
|
7
7
|
|
8
8
|
from pymxs import runtime as rt
|
9
9
|
|
10
|
-
|
10
|
+
# Import necessary service classes for default initialization
|
11
|
+
from .name import Name
|
12
|
+
from .anim import Anim
|
13
|
+
from .helper import Helper
|
14
|
+
from .bone import Bone
|
15
|
+
from .constraint import Constraint
|
11
16
|
|
12
17
|
class GroinBone:
|
13
18
|
"""
|
@@ -15,107 +20,141 @@ class GroinBone:
|
|
15
20
|
3DS Max에서 고간 부 본을 생성하고 관리하는 기능을 제공합니다.
|
16
21
|
"""
|
17
22
|
|
18
|
-
def __init__(self):
|
23
|
+
def __init__(self, nameService=None, animService=None, constraintService=None, boneService=None, helperService=None):
|
19
24
|
"""
|
20
25
|
클래스 초기화.
|
21
26
|
|
22
27
|
Args:
|
23
28
|
nameService: 이름 처리 서비스 (제공되지 않으면 새로 생성)
|
24
29
|
animService: 애니메이션 서비스 (제공되지 않으면 새로 생성)
|
25
|
-
|
26
|
-
bipService:
|
30
|
+
constraintService: 제약 서비스 (제공되지 않으면 새로 생성)
|
31
|
+
bipService: Biped 서비스 (제공되지 않으면 새로 생성)
|
32
|
+
boneService: 뼈대 서비스 (제공되지 않으면 새로 생성)
|
33
|
+
twistBoneService: 트위스트 본 서비스 (제공되지 않으면 새로 생성)
|
34
|
+
helperService: 헬퍼 객체 서비스 (제공되지 않으면 새로 생성)
|
27
35
|
"""
|
28
|
-
|
29
|
-
self.
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
self.
|
34
|
-
self.
|
35
|
-
self.helper =
|
36
|
-
|
37
|
-
|
38
|
-
self.
|
39
|
-
self.
|
36
|
+
# 서비스 인스턴스 설정 또는 생성
|
37
|
+
self.name = nameService if nameService else Name()
|
38
|
+
self.anim = animService if animService else Anim()
|
39
|
+
|
40
|
+
# 종속성이 있는 서비스들은 이미 생성된 서비스들을 전달
|
41
|
+
self.const = constraintService if constraintService else Constraint(nameService=self.name)
|
42
|
+
self.bone = boneService if boneService else Bone(nameService=self.name, animService=self.anim)
|
43
|
+
self.helper = helperService if helperService else Helper(nameService=self.name)
|
44
|
+
|
45
|
+
# 초기화된 결과를 저장할 변수들
|
46
|
+
self.pelvis = None
|
47
|
+
self.lThighTwist = None
|
48
|
+
self.rThighTwist = None
|
49
|
+
self.bones = []
|
50
|
+
self.helpers = []
|
51
|
+
self.pelvisWeight = 40.0
|
52
|
+
self.thighWeight = 60.0
|
40
53
|
|
41
|
-
def
|
54
|
+
def reset(self):
|
55
|
+
"""
|
56
|
+
클래스의 주요 컴포넌트들을 초기화합니다.
|
57
|
+
서비스가 아닌 클래스 자체의 작업 데이터를 초기화하는 함수입니다.
|
58
|
+
|
59
|
+
Returns:
|
60
|
+
self: 메소드 체이닝을 위한 자기 자신 반환
|
61
|
+
"""
|
62
|
+
self.pelvis = None
|
63
|
+
self.lThighTwist = None
|
64
|
+
self.rThighTwist = None
|
65
|
+
self.bones = []
|
66
|
+
self.helpers = []
|
67
|
+
self.pelvisWeight = 40.0
|
68
|
+
self.thighWeight = 60.0
|
69
|
+
|
70
|
+
return self
|
71
|
+
|
72
|
+
def create_bone(self, inPelvis, inLThighTwist, inRThighTwist, inPelvisWeight=40.0, inThighWeight=60.0):
|
42
73
|
"""
|
43
74
|
고간 부 본을 생성하는 메소드.
|
44
75
|
|
45
76
|
Args:
|
46
|
-
|
47
|
-
|
77
|
+
inPelvis: Biped 객체
|
78
|
+
inPelvisWeight: 골반 가중치 (기본값: 40.0)
|
79
|
+
inThighWeight: 허벅지 가중치 (기본값: 60.0)
|
48
80
|
|
49
81
|
Returns:
|
50
|
-
|
82
|
+
성공 여부 (Boolean)
|
51
83
|
"""
|
52
|
-
|
53
|
-
|
84
|
+
returnVal = {
|
85
|
+
"Pelvis": None,
|
86
|
+
"LThighTwist": None,
|
87
|
+
"RThighTwist": None,
|
88
|
+
"Bones": [],
|
89
|
+
"Helpers": [],
|
90
|
+
"PelvisWeight": inPelvisWeight,
|
91
|
+
"ThighWeight": inThighWeight
|
92
|
+
}
|
93
|
+
if rt.isValidNode(inPelvis) == False or rt.isValidNode(inLThighTwist) == False or rt.isValidNode(inRThighTwist) == False:
|
94
|
+
rt.messageBox("There is no valid node.")
|
54
95
|
return False
|
55
96
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
lThigh = self.bip.get_grouped_nodes(inObj, "lLeg")[0]
|
60
|
-
rThigh = self.bip.get_grouped_nodes(inObj, "rLeg")[0]
|
61
|
-
pelvis = self.bip.get_grouped_nodes(inObj, "pelvis")[0]
|
97
|
+
groinName = "Groin"
|
98
|
+
if inPelvis.name[0].islower():
|
99
|
+
groinName = groinName.lower()
|
62
100
|
|
63
|
-
|
64
|
-
rThighTwists = self.twistBone.get_thigh_type(rThigh)
|
101
|
+
groinBaseName = self.name.replace_name_part("RealName", inPelvis.name, groinBaseName)
|
65
102
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
pelvisHelper.
|
72
|
-
self.anim.rotate_local(pelvisHelper, 90, 0, 0)
|
73
|
-
self.anim.rotate_local(pelvisHelper, 0, 0, -90)
|
74
|
-
pelvisHelper.parent = pelvis
|
103
|
+
pelvisHelperName = self.name.replace_name_part("Type", groinBaseName, self.name.get_name_part_value_by_description("Type", "Dummy"))
|
104
|
+
pelvisHelperName = self.name.replace_name_part("Index", pelvisHelperName, "00")
|
105
|
+
pelvisHelper = self.helper.create_point(pelvisHelperName)
|
106
|
+
pelvisHelper.transform = inPelvis.transform
|
107
|
+
self.anim.rotate_local(pelvisHelper, 0.0, 0.0, -180.0)
|
108
|
+
pelvisHelper.parent = inPelvis
|
75
109
|
self.helper.set_shape_to_box(pelvisHelper)
|
76
|
-
self.genHelpers.append(pelvisHelper)
|
77
110
|
|
78
|
-
|
111
|
+
lThighTwistHelperName = self.name.replace_name_part("Type", groinBaseName, self.name.get_name_part_value_by_description("Type", "Dummy"))
|
112
|
+
lThighTwistHelperName = self.name.replace_name_part("Side", lThighTwistHelperName, self.name.get_name_part_value_by_description("Side", "Left"))
|
113
|
+
lThighTwistHelperName = self.name.replace_name_part("Index", lThighTwistHelperName, "00")
|
114
|
+
lThighTwistHelper = self.helper.create_point(lThighTwistHelperName)
|
115
|
+
lThighTwistHelper.transform = pelvisHelper.transform
|
116
|
+
lThighTwistHelper.position = inLThighTwist.position
|
117
|
+
lThighTwistHelper.parent = inLThighTwist
|
118
|
+
self.helper.set_shape_to_box(lThighTwistHelper)
|
119
|
+
|
120
|
+
rThighTwistHelperName = self.name.replace_name_part("Type", groinBaseName, self.name.get_name_part_value_by_description("Type", "Dummy"))
|
121
|
+
rThighTwistHelperName = self.name.replace_name_part("Side", rThighTwistHelperName, self.name.get_name_part_value_by_description("Side", "Right"))
|
122
|
+
rThighTwistHelperName = self.name.replace_name_part("Index", rThighTwistHelperName, "00")
|
123
|
+
rThighTwistHelper = self.helper.create_point(rThighTwistHelperName)
|
124
|
+
rThighTwistHelper.transform = pelvisHelper.transform
|
125
|
+
rThighTwistHelper.position = inRThighTwist.position
|
126
|
+
rThighTwistHelper.parent = inRThighTwist
|
127
|
+
self.helper.set_shape_to_box(rThighTwistHelper)
|
128
|
+
|
129
|
+
groinBoneName = self.name.replace_name_part("Index", groinBaseName, "00")
|
130
|
+
groinBones = self.bone.create_simple_bone(3.0, groinBoneName, size=2)
|
79
131
|
groinBones[0].transform = pelvisHelper.transform
|
80
|
-
groinBones[0].parent =
|
81
|
-
for groinBone in groinBones:
|
82
|
-
self.genBones.append(groinBone)
|
132
|
+
groinBones[0].parent = inPelvis
|
83
133
|
|
84
|
-
self.const.assign_rot_const_multi(groinBones[0], [pelvisHelper,
|
134
|
+
self.const.assign_rot_const_multi(groinBones[0], [pelvisHelper, lThighTwistHelper, rThighTwistHelper])
|
85
135
|
rotConst = self.const.get_rot_list_controller(groinBones[0])[1]
|
86
136
|
rotConst.setWeight(1, inPelvisWeight)
|
87
137
|
rotConst.setWeight(2, inThighWeight/2.0)
|
88
138
|
rotConst.setWeight(3, inThighWeight/2.0)
|
89
139
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
""
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
Returns:
|
112
|
-
None
|
113
|
-
"""
|
114
|
-
if len(self.genBones) == 0:
|
115
|
-
return False
|
116
|
-
|
117
|
-
self.delete()
|
118
|
-
self.create_bone(self.bipObj, inPelvisWeight, inThighWeight)
|
119
|
-
|
120
|
-
|
121
|
-
|
140
|
+
# 결과를 멤버 변수에 저장
|
141
|
+
self.pelvis = inPelvis
|
142
|
+
self.lThighTwist = inLThighTwist
|
143
|
+
self.rThighTwist = inRThighTwist
|
144
|
+
self.bones = groinBones
|
145
|
+
self.helpers = [pelvisHelper, lThighTwistHelper, rThighTwistHelper]
|
146
|
+
self.pelvisWeight = inPelvisWeight
|
147
|
+
self.thighWeight = inThighWeight
|
148
|
+
|
149
|
+
returnVal["Pelvis"] = inPelvis
|
150
|
+
returnVal["LThighTwist"] = inLThighTwist
|
151
|
+
returnVal["RThighTwist"] = inRThighTwist
|
152
|
+
returnVal["Bones"] = groinBones
|
153
|
+
returnVal["Helpers"] = [pelvisHelper, lThighTwistHelper, rThighTwistHelper]
|
154
|
+
returnVal["PelvisWeight"] = inPelvisWeight
|
155
|
+
returnVal["ThighWeight"] = inThighWeight
|
156
|
+
|
157
|
+
# 메소드 호출 후 데이터 초기화
|
158
|
+
self.reset()
|
159
|
+
|
160
|
+
return returnVal
|