pyjallib 0.1.8__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 +100 -92
- pyjallib/max/autoClavicleChain.py +173 -0
- pyjallib/max/bip.py +211 -14
- pyjallib/max/bone.py +348 -16
- pyjallib/max/constraint.py +29 -38
- pyjallib/max/groinBone.py +109 -39
- pyjallib/max/groinBoneChain.py +173 -0
- pyjallib/max/header.py +40 -6
- pyjallib/max/helper.py +3 -21
- pyjallib/max/hip.py +239 -0
- 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 +259 -476
- 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/perforce.py +446 -653
- {pyjallib-0.1.8.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 -171
- pyjallib-0.1.8.dist-info/RECORD +0 -39
- {pyjallib-0.1.8.dist-info → pyjallib-0.1.10.dist-info}/WHEEL +0 -0
@@ -0,0 +1,173 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
"""
|
5
|
+
자동 쇄골 체인(AutoClavicle Chain) 관련 기능을 제공하는 클래스.
|
6
|
+
AutoClavicle 클래스가 생성한 자동 쇄골 뼈대들을 관리하고 접근하는 인터페이스를 제공합니다.
|
7
|
+
|
8
|
+
Examples:
|
9
|
+
# 자동 쇄골 체인 생성 예시
|
10
|
+
from pyjallib.max import AutoClavicle, AutoClavicleChain
|
11
|
+
from pymxs import runtime as rt
|
12
|
+
|
13
|
+
# 선택된 쇄골과 상완 객체
|
14
|
+
clavicle = rt.selection[0]
|
15
|
+
upperArm = rt.selection[1]
|
16
|
+
|
17
|
+
# AutoClavicle 클래스 인스턴스 생성
|
18
|
+
auto_clavicle = AutoClavicle()
|
19
|
+
|
20
|
+
# 자동 쇄골 뼈대 생성
|
21
|
+
clavicle_bones = auto_clavicle.create_bones(clavicle, upperArm, liftScale=0.8)
|
22
|
+
|
23
|
+
# 생성된 뼈대로 AutoClavicleChain 인스턴스 생성
|
24
|
+
chain = AutoClavicleChain.from_auto_clavicle_result(
|
25
|
+
{
|
26
|
+
"Bones": clavicle_bones,
|
27
|
+
"Helpers": auto_clavicle.helpers,
|
28
|
+
"Clavicle": clavicle,
|
29
|
+
"UpperArm": upperArm,
|
30
|
+
"LiftScale": 0.8
|
31
|
+
}
|
32
|
+
)
|
33
|
+
|
34
|
+
# 체인 관리 기능 사용
|
35
|
+
bone = chain.get_bone()
|
36
|
+
|
37
|
+
# 체인의 모든 뼈대 이름 변경
|
38
|
+
chain.rename_bones(prefix="character_", suffix="_autoClavicle")
|
39
|
+
|
40
|
+
# 체인의 LiftScale 수정
|
41
|
+
chain.update_lift_scale(0.9)
|
42
|
+
|
43
|
+
# 필요 없어지면 체인의 모든 뼈대와 헬퍼 삭제
|
44
|
+
# chain.delete_all()
|
45
|
+
"""
|
46
|
+
|
47
|
+
from pymxs import runtime as rt
|
48
|
+
from pyjallib.max.header import get_pyjallibmaxheader
|
49
|
+
jal = get_pyjallibmaxheader()
|
50
|
+
|
51
|
+
|
52
|
+
class AutoClavicleChain:
|
53
|
+
def __init__(self, inResult):
|
54
|
+
"""
|
55
|
+
클래스 초기화.
|
56
|
+
|
57
|
+
Args:
|
58
|
+
inResult: AutoClavicle 클래스의 생성 결과 (딕셔너리)
|
59
|
+
"""
|
60
|
+
self.bones = inResult.get("Bones", [])
|
61
|
+
self.helpers = inResult.get("Helpers", [])
|
62
|
+
self.clavicle = inResult.get("Clavicle", None)
|
63
|
+
self.upperArm = inResult.get("UpperArm", None)
|
64
|
+
self.liftScale = inResult.get("LiftScale", 0.8)
|
65
|
+
|
66
|
+
def get_bones(self):
|
67
|
+
"""
|
68
|
+
체인의 모든 뼈대 가져오기
|
69
|
+
|
70
|
+
Returns:
|
71
|
+
모든 뼈대 객체의 배열
|
72
|
+
"""
|
73
|
+
if self.is_empty():
|
74
|
+
return []
|
75
|
+
|
76
|
+
return self.bones
|
77
|
+
|
78
|
+
def get_helpers(self):
|
79
|
+
"""
|
80
|
+
체인의 모든 헬퍼 가져오기
|
81
|
+
|
82
|
+
Returns:
|
83
|
+
모든 헬퍼 객체의 배열
|
84
|
+
"""
|
85
|
+
if self.is_empty():
|
86
|
+
return []
|
87
|
+
|
88
|
+
return self.helpers
|
89
|
+
|
90
|
+
def is_empty(self):
|
91
|
+
"""
|
92
|
+
체인이 비어있는지 확인
|
93
|
+
|
94
|
+
Returns:
|
95
|
+
체인이 비어있으면 True, 아니면 False
|
96
|
+
"""
|
97
|
+
return len(self.bones) == 0
|
98
|
+
|
99
|
+
def clear(self):
|
100
|
+
"""체인의 모든 뼈대와 헬퍼 참조 제거"""
|
101
|
+
self.bones = []
|
102
|
+
self.helpers = []
|
103
|
+
self.clavicle = None
|
104
|
+
self.upperArm = None
|
105
|
+
|
106
|
+
def delete_all(self):
|
107
|
+
"""
|
108
|
+
체인의 모든 뼈대와 헬퍼를 3ds Max 씬에서 삭제
|
109
|
+
|
110
|
+
Returns:
|
111
|
+
삭제 성공 여부 (boolean)
|
112
|
+
"""
|
113
|
+
if self.is_empty():
|
114
|
+
return False
|
115
|
+
|
116
|
+
try:
|
117
|
+
for bone in self.bones:
|
118
|
+
if rt.isValidNode(bone):
|
119
|
+
rt.delete(bone)
|
120
|
+
|
121
|
+
for helper in self.helpers:
|
122
|
+
if rt.isValidNode(helper):
|
123
|
+
rt.delete(helper)
|
124
|
+
|
125
|
+
self.clear()
|
126
|
+
return True
|
127
|
+
except:
|
128
|
+
return False
|
129
|
+
|
130
|
+
def update_lift_scale(self, newLiftScale=0.8):
|
131
|
+
"""
|
132
|
+
자동 쇄골의 들어올림 스케일 업데이트
|
133
|
+
|
134
|
+
Args:
|
135
|
+
newLiftScale: 새로운 들어올림 스케일 (기본값: 0.8)
|
136
|
+
|
137
|
+
Returns:
|
138
|
+
업데이트 성공 여부 (boolean)
|
139
|
+
"""
|
140
|
+
if self.is_empty() or not rt.isValidNode(self.clavicle) or not rt.isValidNode(self.upperArm):
|
141
|
+
return False
|
142
|
+
|
143
|
+
clavicle = self.clavicle
|
144
|
+
upperArm = self.upperArm
|
145
|
+
|
146
|
+
# 기존 본과 헬퍼 삭제
|
147
|
+
self.delete_all()
|
148
|
+
|
149
|
+
# 새로운 LiftScale 값 설정
|
150
|
+
self.liftScale = newLiftScale
|
151
|
+
self.clavicle = clavicle
|
152
|
+
self.upperArm = upperArm
|
153
|
+
|
154
|
+
# 재생성
|
155
|
+
result = jal.autoClavicle.create_bones(self.clavicle, self.upperArm, self.liftScale)
|
156
|
+
if result:
|
157
|
+
return True
|
158
|
+
|
159
|
+
return False
|
160
|
+
|
161
|
+
@classmethod
|
162
|
+
def from_auto_clavicle_result(cls, inResult):
|
163
|
+
"""
|
164
|
+
AutoClavicle 클래스의 결과로부터 AutoClavicleChain 인스턴스 생성
|
165
|
+
|
166
|
+
Args:
|
167
|
+
inResult: AutoClavicle 클래스의 메서드가 반환한 결과값 딕셔너리
|
168
|
+
|
169
|
+
Returns:
|
170
|
+
AutoClavicleChain 인스턴스
|
171
|
+
"""
|
172
|
+
chain = cls(inResult)
|
173
|
+
return chain
|
pyjallib/max/bip.py
CHANGED
@@ -6,6 +6,9 @@ Biped 모듈 - 3ds Max의 Biped 객체 관련 기능 제공
|
|
6
6
|
원본 MAXScript의 bip.ms를 Python으로 변환하였으며, pymxs 모듈 기반으로 구현됨
|
7
7
|
"""
|
8
8
|
|
9
|
+
|
10
|
+
import os
|
11
|
+
|
9
12
|
from pymxs import runtime as rt
|
10
13
|
|
11
14
|
# Import necessary service classes for default initialization
|
@@ -452,11 +455,11 @@ class Bip:
|
|
452
455
|
if rt.isValidObj(baseSkelObj):
|
453
456
|
baseSkel[i] = baseSkelObj
|
454
457
|
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
458
|
+
self.anim.save_xform(bipSkel[i])
|
459
|
+
self.anim.set_xform(bipSkel[i])
|
460
|
+
|
461
|
+
self.anim.save_xform(baseSkel[i])
|
462
|
+
self.anim.set_xform(baseSkel[i])
|
460
463
|
|
461
464
|
for i in range(len(baseSkel)):
|
462
465
|
if baseSkel[i] is not None:
|
@@ -478,21 +481,25 @@ class Bip:
|
|
478
481
|
"""
|
479
482
|
rt.setWaitCursor()
|
480
483
|
|
481
|
-
|
484
|
+
bipComs = self.get_coms()
|
485
|
+
allBips = self.get_nodes(bipComs[0])
|
486
|
+
bipSkel = [item for item in allBips if item != bipComs[0]]
|
482
487
|
baseSkel = [None] * len(bipSkel)
|
483
488
|
|
484
489
|
for i in range(len(bipSkel)):
|
485
|
-
baseSkeletonName = self.name.
|
486
|
-
baseSkeletonName = self.name.
|
490
|
+
baseSkeletonName = self.name.replace_name_part("Base", bipSkel[i].name, skinBoneBaseName)
|
491
|
+
baseSkeletonName = self.name.replace_filtering_char(baseSkeletonName, "_")
|
492
|
+
print("baseSkeletonName", baseSkeletonName)
|
487
493
|
baseSkelObj = rt.getNodeByName(baseSkeletonName)
|
494
|
+
print("baseSkelObj", baseSkelObj)
|
488
495
|
if rt.isValidObj(baseSkelObj):
|
489
496
|
baseSkel[i] = baseSkelObj
|
490
497
|
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
498
|
+
self.anim.save_xform(bipSkel[i])
|
499
|
+
self.anim.set_xform(bipSkel[i])
|
500
|
+
|
501
|
+
self.anim.save_xform(baseSkel[i])
|
502
|
+
self.anim.set_xform(baseSkel[i])
|
496
503
|
|
497
504
|
for i in range(len(baseSkel)):
|
498
505
|
if baseSkel[i] is not None:
|
@@ -503,4 +510,194 @@ class Bip:
|
|
503
510
|
if baseSkel[i] is not None:
|
504
511
|
baseSkel[i].boneEnable = True
|
505
512
|
|
506
|
-
rt.setArrowCursor()
|
513
|
+
rt.setArrowCursor()
|
514
|
+
|
515
|
+
def convert_name_for_ue5(self, inBipRoot, inBipNameConfigFile):
|
516
|
+
"""
|
517
|
+
Biped 이름을 UE5에 맞게 변환
|
518
|
+
|
519
|
+
Args:
|
520
|
+
inBipRoot: 변환할 Biped 객체
|
521
|
+
|
522
|
+
Returns:
|
523
|
+
변환된 Biped 객체
|
524
|
+
"""
|
525
|
+
bipComs = self.get_coms()
|
526
|
+
|
527
|
+
if len(bipComs) > 1:
|
528
|
+
rt.messageBox("Please select only one Biped object.")
|
529
|
+
return False
|
530
|
+
|
531
|
+
from pyjallib.max.name import Name
|
532
|
+
|
533
|
+
bipNameTool = Name(configPath=inBipNameConfigFile)
|
534
|
+
|
535
|
+
bipObj = bipComs[0]
|
536
|
+
bipNodes = self.get_all(bipObj)
|
537
|
+
for bipNode in bipNodes:
|
538
|
+
if bipNode.name == bipObj.controller.rootName:
|
539
|
+
bipNode.name = bipNode.name.lower()
|
540
|
+
continue
|
541
|
+
|
542
|
+
bipNodeNameDict = bipNameTool.convert_to_dictionary(bipNode.name)
|
543
|
+
|
544
|
+
newNameDict = {}
|
545
|
+
for namePartName, value in bipNodeNameDict.items():
|
546
|
+
namePart = bipNameTool.get_name_part(namePartName)
|
547
|
+
desc = namePart.get_description_by_value(value)
|
548
|
+
|
549
|
+
if namePartName == "RealName" or namePartName == "Index" or namePartName == "Nub":
|
550
|
+
newNameDict[namePartName] = value
|
551
|
+
else:
|
552
|
+
newNameDict[namePartName] = self.name.get_name_part(namePartName).get_value_by_description(desc)
|
553
|
+
|
554
|
+
if newNameDict["Index"] == "" and self.name._has_digit(newNameDict["RealName"]):
|
555
|
+
if "Finger" not in newNameDict["RealName"]:
|
556
|
+
splitedRealName = self.name._split_into_string_and_digit(newNameDict["RealName"])
|
557
|
+
newNameDict["RealName"] = splitedRealName[0]
|
558
|
+
newNameDict["Index"] = splitedRealName[1]
|
559
|
+
if newNameDict["Nub"] == "" and bipNameTool.get_name_part_value_by_description("Nub", "Nub") in (newNameDict["RealName"]):
|
560
|
+
newNameDict["RealName"] = newNameDict["RealName"].replace(bipNameTool.get_name_part_value_by_description("Nub", "Nub"), "")
|
561
|
+
newNameDict["Nub"] = self.name.get_name_part_value_by_description("Nub", "Nub")
|
562
|
+
|
563
|
+
if newNameDict["RealName"] == "Forearm":
|
564
|
+
newNameDict["RealName"] = "Lowerarm"
|
565
|
+
|
566
|
+
if newNameDict["RealName"] == "Spine" or newNameDict["RealName"] == "Neck":
|
567
|
+
if newNameDict["Index"] == "":
|
568
|
+
newNameDict["Index"] = str(int(1)).zfill(self.name.get_padding_num())
|
569
|
+
else:
|
570
|
+
newNameDict["Index"] = str(int(newNameDict["Index"]) + 1).zfill(self.name.get_padding_num())
|
571
|
+
|
572
|
+
newBipName = self.name.combine(newNameDict)
|
573
|
+
|
574
|
+
bipNode.name = newBipName.lower()
|
575
|
+
|
576
|
+
# 손가락 바꾸는 부분
|
577
|
+
# 5개가 아닌 손가락은 지원하지 않음
|
578
|
+
# 손가락 하나의 최대 링크는 3개
|
579
|
+
indices = []
|
580
|
+
if bipObj.controller.knuckles:
|
581
|
+
pass
|
582
|
+
else:
|
583
|
+
indices = list(range(0, 15, 3))
|
584
|
+
|
585
|
+
fingerNum = bipObj.controller.fingers
|
586
|
+
fingerLinkNum = bipObj.controller.fingerLinks
|
587
|
+
|
588
|
+
lFingersList = []
|
589
|
+
rFingersList = []
|
590
|
+
|
591
|
+
for i in range(1, fingerNum+1):
|
592
|
+
fingers = []
|
593
|
+
for j in range(1, fingerLinkNum+1):
|
594
|
+
linkIndex = (i-1)*fingerLinkNum + j
|
595
|
+
fingerNode = rt.biped.getNode(bipObj.controller, rt.name("lFingers"), link=linkIndex)
|
596
|
+
fingers.append(fingerNode)
|
597
|
+
lFingersList.append(fingers)
|
598
|
+
for i in range(1, fingerNum+1):
|
599
|
+
fingers = []
|
600
|
+
for j in range(1, fingerLinkNum+1):
|
601
|
+
linkIndex = (i-1)*fingerLinkNum + j
|
602
|
+
fingerNode = rt.biped.getNode(bipObj.controller, rt.name("rFingers"), link=linkIndex)
|
603
|
+
fingers.append(fingerNode)
|
604
|
+
rFingersList.append(fingers)
|
605
|
+
|
606
|
+
fingerName = ["thumb", "index", "middle", "ring", "pinky"]
|
607
|
+
|
608
|
+
for i, fingers in enumerate(lFingersList):
|
609
|
+
for j, item in enumerate(fingers):
|
610
|
+
item.name = self.name.replace_name_part("RealName", item.name, fingerName[i])
|
611
|
+
item.name = self.name.replace_name_part("Index", item.name, str(j+1))
|
612
|
+
|
613
|
+
fingerNub = self.bone.get_every_children(fingers[-1])[0]
|
614
|
+
fingerNub.name = self.name.replace_name_part("RealName", fingerNub.name, fingerName[i])
|
615
|
+
fingerNub.name = self.name.remove_name_part("Index", fingerNub.name)
|
616
|
+
fingerNub.name = self.name.replace_name_part("Nub", fingerNub.name, self.name.get_name_part_value_by_description("Nub", "Nub"))
|
617
|
+
|
618
|
+
for i, fingers in enumerate(rFingersList):
|
619
|
+
for j, item in enumerate(fingers):
|
620
|
+
item.name = self.name.replace_name_part("RealName", item.name, fingerName[i])
|
621
|
+
item.name = self.name.replace_name_part("Index", item.name, str(j+1))
|
622
|
+
|
623
|
+
fingerNub = self.bone.get_every_children(fingers[-1])[0]
|
624
|
+
fingerNub.name = self.name.replace_name_part("RealName", fingerNub.name, fingerName[i])
|
625
|
+
fingerNub.name = self.name.remove_name_part("Index", fingerNub.name)
|
626
|
+
fingerNub.name = self.name.replace_name_part("Nub", fingerNub.name, self.name.get_name_part_value_by_description("Nub", "Nub"))
|
627
|
+
|
628
|
+
# Toe 이름 바꾸는 부분
|
629
|
+
lToesList = []
|
630
|
+
rToesList = []
|
631
|
+
|
632
|
+
toeNum = bipObj.controller.toes
|
633
|
+
toeLinkNum = bipObj.controller.toeLinks
|
634
|
+
|
635
|
+
# Use the same sequential indexing pattern as fingers
|
636
|
+
for i in range(1, toeNum+1):
|
637
|
+
toes = []
|
638
|
+
for j in range(1, toeLinkNum+1):
|
639
|
+
linkIndex = (i-1)*toeLinkNum + j
|
640
|
+
toeNode = rt.biped.getNode(bipObj.controller, rt.name("lToes"), link=linkIndex)
|
641
|
+
if toeNode:
|
642
|
+
toes.append(toeNode)
|
643
|
+
if toes:
|
644
|
+
lToesList.append(toes)
|
645
|
+
|
646
|
+
for i in range(1, toeNum+1):
|
647
|
+
toes = []
|
648
|
+
for j in range(1, toeLinkNum+1):
|
649
|
+
linkIndex = (i-1)*toeLinkNum + j
|
650
|
+
toeNode = rt.biped.getNode(bipObj.controller, rt.name("rToes"), link=linkIndex)
|
651
|
+
if toeNode:
|
652
|
+
toes.append(toeNode)
|
653
|
+
if toes:
|
654
|
+
rToesList.append(toes)
|
655
|
+
|
656
|
+
for i, toes in enumerate(lToesList):
|
657
|
+
for j, item in enumerate(toes):
|
658
|
+
item.name = self.name.replace_name_part("RealName", item.name, "ball"+str(i+1))
|
659
|
+
item.name = self.name.replace_name_part("Index", item.name, str(j+1))
|
660
|
+
|
661
|
+
toeNub = self.bone.get_every_children(toes[-1])[0]
|
662
|
+
toeNub.name = self.name.replace_name_part("RealName", toeNub.name, "ball"+str(i+1))
|
663
|
+
toeNub.name = self.name.remove_name_part("Index", toeNub.name)
|
664
|
+
toeNub.name = self.name.replace_name_part("Nub", toeNub.name, self.name.get_name_part_value_by_description("Nub", "Nub"))
|
665
|
+
|
666
|
+
for i, toes in enumerate(rToesList):
|
667
|
+
for j, item in enumerate(toes):
|
668
|
+
item.name = self.name.replace_name_part("RealName", item.name, "ball"+str(i+1))
|
669
|
+
item.name = self.name.replace_name_part("Index", item.name, str(j+1))
|
670
|
+
|
671
|
+
toeNub = self.bone.get_every_children(toes[-1])[0]
|
672
|
+
toeNub.name = self.name.replace_name_part("RealName", toeNub.name, "ball"+str(i+1))
|
673
|
+
toeNub.name = self.name.remove_name_part("Index", toeNub.name)
|
674
|
+
toeNub.name = self.name.replace_name_part("Nub", toeNub.name, self.name.get_name_part_value_by_description("Nub", "Nub"))
|
675
|
+
|
676
|
+
if toeNum == 1:
|
677
|
+
if toeLinkNum == 1:
|
678
|
+
lToesList[0][0].name = self.name.replace_name_part("RealName", lToesList[0][0].name, "ball")
|
679
|
+
lToesList[0][0].name = self.name.remove_name_part("Index", lToesList[0][0].name)
|
680
|
+
else:
|
681
|
+
for i, item in enumerate(lToesList[0]):
|
682
|
+
item.name = self.name.replace_name_part("RealName", item.name, "ball")
|
683
|
+
item.name = self.name.replace_name_part("Index", item.name, str(i+1))
|
684
|
+
|
685
|
+
toeNub = self.bone.get_every_children(lToesList[0][-1])[0]
|
686
|
+
toeNub.name = self.name.replace_name_part("RealName", toeNub.name, "ball")
|
687
|
+
toeNub.name = self.name.remove_name_part("Index", toeNub.name)
|
688
|
+
toeNub.name = self.name.replace_name_part("Nub", toeNub.name, self.name.get_name_part_value_by_description("Nub", "Nub"))
|
689
|
+
|
690
|
+
if toeLinkNum == 1:
|
691
|
+
rToesList[0][0].name = self.name.replace_name_part("RealName", lToesList[0][0].name, "ball")
|
692
|
+
rToesList[0][0].name = self.name.remove_name_part("Index", lToesList[0][0].name)
|
693
|
+
else:
|
694
|
+
for i, item in enumerate(rToesList[0]):
|
695
|
+
item.name = self.name.replace_name_part("RealName", item.name, "ball")
|
696
|
+
item.name = self.name.replace_name_part("Index", item.name, str(i+1))
|
697
|
+
|
698
|
+
toeNub = self.bone.get_every_children(rToesList[0][-1])[0]
|
699
|
+
toeNub.name = self.name.replace_name_part("RealName", toeNub.name, "ball")
|
700
|
+
toeNub.name = self.name.remove_name_part("Index", toeNub.name)
|
701
|
+
toeNub.name = self.name.replace_name_part("Nub", toeNub.name, self.name.get_name_part_value_by_description("Nub", "Nub"))
|
702
|
+
|
703
|
+
return True
|