pyjallib 0.1.17__py3-none-any.whl → 0.1.20__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 +5 -4
- pyjallib/exceptions.py +75 -0
- pyjallib/logger.py +152 -65
- pyjallib/max/__init__.py +8 -0
- pyjallib/max/autoClavicle.py +17 -5
- pyjallib/max/bone.py +21 -1
- pyjallib/max/boneChain.py +2 -0
- pyjallib/max/constraint.py +27 -2
- pyjallib/max/elbow.py +105 -0
- pyjallib/max/groinBone.py +2 -0
- pyjallib/max/header.py +121 -113
- pyjallib/max/hip.py +2 -0
- pyjallib/max/inguinal.py +117 -0
- pyjallib/max/kneeBone.py +2 -0
- pyjallib/max/macro/jal_macro_bone.py +221 -8
- pyjallib/max/macro/jal_macro_constraint.py +30 -0
- pyjallib/max/mirror.py +20 -13
- pyjallib/max/shoulder.py +173 -0
- pyjallib/max/toolManager.py +22 -6
- pyjallib/max/twistBone.py +22 -19
- pyjallib/max/ui/__init__.py +10 -0
- pyjallib/max/volumeBone.py +12 -1
- pyjallib/max/wrist.py +113 -0
- pyjallib/nameToPath.py +78 -61
- pyjallib/perforce.py +101 -171
- pyjallib/ue5/inUnreal/animationImporter.py +111 -19
- pyjallib/ue5/inUnreal/baseImporter.py +10 -7
- pyjallib/ue5/inUnreal/skeletalMeshImporter.py +1 -1
- pyjallib/ue5/inUnreal/skeletonImporter.py +1 -1
- pyjallib/ue5/logger.py +152 -111
- pyjallib/ue5/templateProcessor.py +35 -2
- pyjallib/ue5/templates/__init__.py +6 -3
- pyjallib/ue5/templates/batchAnimImportTemplate.py +21 -0
- {pyjallib-0.1.17.dist-info → pyjallib-0.1.20.dist-info}/METADATA +1 -1
- {pyjallib-0.1.17.dist-info → pyjallib-0.1.20.dist-info}/RECORD +36 -29
- {pyjallib-0.1.17.dist-info → pyjallib-0.1.20.dist-info}/WHEEL +0 -0
pyjallib/max/twistBone.py
CHANGED
@@ -126,11 +126,6 @@ class TwistBone:
|
|
126
126
|
BoneChain: 생성된 트위스트 뼈대 BoneChain 객체
|
127
127
|
"""
|
128
128
|
limb = inObj
|
129
|
-
distance = rt.distance(limb, inChild)
|
130
|
-
facingDirVec = inChild.transform.position - inObj.transform.position
|
131
|
-
inObjXAxisVec = inObj.objectTransform.row1
|
132
|
-
distanceDir = 1.0 if rt.dot(inObjXAxisVec, facingDirVec) > 0 else -1.0
|
133
|
-
offssetAmount = (distance / twistNum) * distanceDir
|
134
129
|
|
135
130
|
boneChainArray = []
|
136
131
|
|
@@ -161,14 +156,17 @@ class TwistBone:
|
|
161
156
|
boneChainArray.append(twistBone)
|
162
157
|
|
163
158
|
if twistNum > 1:
|
159
|
+
weightVal = 100.0 / (twistNum-1)
|
160
|
+
posWeightVal = 100.0 / twistNum
|
161
|
+
|
164
162
|
lastBone = self.bone.create_nub_bone(boneName, 2)
|
165
163
|
lastBone.name = self.name.replace_name_part("Index", boneName, str(twistNum))
|
166
164
|
lastBone.name = self.name.remove_name_part("Nub", lastBone.name)
|
167
165
|
lastBone.transform = limb.transform
|
168
166
|
lastBone.parent = limb
|
169
|
-
self.
|
170
|
-
|
171
|
-
|
167
|
+
lastBonePosConst = self.const.assign_pos_const_multi(lastBone, [limb, inChild])
|
168
|
+
lastBonePosConst.setWeight(1, 100.0 - (posWeightVal*(twistNum-1)))
|
169
|
+
lastBonePosConst.setWeight(2, posWeightVal*(twistNum-1))
|
172
170
|
|
173
171
|
if twistNum > 2:
|
174
172
|
for i in range(1, twistNum-1):
|
@@ -177,7 +175,9 @@ class TwistBone:
|
|
177
175
|
twistExtraBone.name = self.name.remove_name_part("Nub", twistExtraBone.name)
|
178
176
|
twistExtraBone.transform = limb.transform
|
179
177
|
twistExtraBone.parent = limb
|
180
|
-
self.
|
178
|
+
twistExtraBonePosConst = self.const.assign_pos_const_multi(twistExtraBone, [limb, inChild])
|
179
|
+
twistExtraBonePosConst.setWeight(1, 100.0 - (posWeightVal*i))
|
180
|
+
twistExtraBonePosConst.setWeight(2, posWeightVal*i)
|
181
181
|
|
182
182
|
twistExtraBoneRotListController = self.const.assign_rot_list(twistExtraBone)
|
183
183
|
twistExtraBoneController = rt.Rotation_Script()
|
@@ -225,11 +225,8 @@ class TwistBone:
|
|
225
225
|
BoneChain: 생성된 트위스트 뼈대 BoneChain 객체
|
226
226
|
"""
|
227
227
|
limb = inChild
|
228
|
-
|
229
|
-
|
230
|
-
inObjXAxisVec = inObj.objectTransform.row1
|
231
|
-
distanceDir = 1.0 if rt.dot(inObjXAxisVec, facingDirVec) > 0 else -1.0
|
232
|
-
offssetAmount = (distance / twistNum) * distanceDir
|
228
|
+
|
229
|
+
posWeightVal = 100.0 / twistNum
|
233
230
|
|
234
231
|
boneChainArray = []
|
235
232
|
|
@@ -242,7 +239,10 @@ class TwistBone:
|
|
242
239
|
twistBone.name = self.name.remove_name_part("Nub", twistBone.name)
|
243
240
|
twistBone.transform = inObj.transform
|
244
241
|
twistBone.parent = inObj
|
245
|
-
self.
|
242
|
+
twistBonePosConst = self.const.assign_pos_const_multi(twistBone, [limb, inObj])
|
243
|
+
twistBonePosConst.setWeight(1, posWeightVal*(twistNum-1))
|
244
|
+
twistBonePosConst.setWeight(2, 100.0 - (posWeightVal*(twistNum-1)))
|
245
|
+
|
246
246
|
twistBoneLocalRefTM = limb.transform * rt.inverse(limb.parent.transform)
|
247
247
|
|
248
248
|
twistBoneRotListController = self.const.assign_rot_list(twistBone)
|
@@ -262,14 +262,13 @@ class TwistBone:
|
|
262
262
|
boneChainArray.append(twistBone)
|
263
263
|
|
264
264
|
if twistNum > 1:
|
265
|
+
weightVal = 100.0 / (twistNum-1)
|
266
|
+
|
265
267
|
lastBone = self.bone.create_nub_bone(boneName, 2)
|
266
268
|
lastBone.name = self.name.replace_name_part("Index", boneName, str(twistNum))
|
267
269
|
lastBone.name = self.name.remove_name_part("Nub", lastBone.name)
|
268
270
|
lastBone.transform = inObj.transform
|
269
271
|
lastBone.parent = inObj
|
270
|
-
self.anim.move_local(lastBone, 0, 0, 0)
|
271
|
-
|
272
|
-
weightVal = 100.0 / (twistNum-1)
|
273
272
|
|
274
273
|
if twistNum > 2:
|
275
274
|
for i in range(1, twistNum-1):
|
@@ -278,7 +277,9 @@ class TwistBone:
|
|
278
277
|
twistExtraBone.name = self.name.remove_name_part("Nub", twistExtraBone.name)
|
279
278
|
twistExtraBone.transform = inObj.transform
|
280
279
|
twistExtraBone.parent = inObj
|
281
|
-
self.
|
280
|
+
twistExtraBonePosConst = self.const.assign_pos_const_multi(twistExtraBone, [limb, inObj])
|
281
|
+
twistExtraBonePosConst.setWeight(1, 100.0 - (posWeightVal*(i+1)))
|
282
|
+
twistExtraBonePosConst.setWeight(2, posWeightVal*(i+1))
|
282
283
|
|
283
284
|
twistExtraBoneRotListController = self.const.assign_rot_list(twistExtraBone)
|
284
285
|
twistExtraBoneController = rt.Rotation_Script()
|
@@ -307,6 +308,8 @@ class TwistBone:
|
|
307
308
|
# 메소드 호출 후 데이터 초기화
|
308
309
|
self.reset()
|
309
310
|
|
311
|
+
rt.redrawViews()
|
312
|
+
|
310
313
|
return BoneChain.from_result(result)
|
311
314
|
|
312
315
|
def create_bones_from_chain(self, inBoneChain: BoneChain):
|
pyjallib/max/volumeBone.py
CHANGED
@@ -123,6 +123,7 @@ class VolumeBone: # Updated class name to match the new file name
|
|
123
123
|
rotHelper.name = self.name.replace_name_part("Type", rotHelper.name, self.name.get_name_part_value_by_description("Type", "Dummy"))
|
124
124
|
rt.setProperty(rotHelper, "transform", inObj.transform)
|
125
125
|
rotHelper.parent = inParent
|
126
|
+
self.const.assign_pos_const(rotHelper, inObj)
|
126
127
|
|
127
128
|
oriConst = self.const.assign_rot_const_multi(rootBone, [inObj, rotHelper])
|
128
129
|
oriConst.setWeight(1, inRotScale * 100.0)
|
@@ -152,9 +153,12 @@ class VolumeBone: # Updated class name to match the new file name
|
|
152
153
|
volBoneName = inObj.name
|
153
154
|
filteringChar = self.name._get_filtering_char(volBoneName)
|
154
155
|
volBoneName = self.name.add_suffix_to_real_name(volBoneName, filteringChar + "Vol" + filteringChar + inRotAxis + filteringChar+ inTransAxis)
|
156
|
+
volBoneIndex = self.name.get_name("Index", volBoneName)
|
155
157
|
|
156
158
|
volBone = self.bone.create_nub_bone(volBoneName, 2)
|
157
159
|
volBone.name = self.name.remove_name_part("Nub", volBone.name)
|
160
|
+
volBone.name = self.name.replace_name_part("Index", volBone.name, volBoneIndex)
|
161
|
+
|
158
162
|
if volBone.name[0].islower():
|
159
163
|
volBone.name = volBone.name.lower()
|
160
164
|
volBoneName = volBoneName.lower()
|
@@ -225,6 +229,10 @@ class VolumeBone: # Updated class name to match the new file name
|
|
225
229
|
|
226
230
|
rootBone = self.create_root_bone(inObj, inParent, inRotScale=inRotScale)
|
227
231
|
|
232
|
+
# rootBone이 None이면 실패
|
233
|
+
if not rootBone:
|
234
|
+
return None
|
235
|
+
|
228
236
|
# 볼륨 본들 생성
|
229
237
|
bones = []
|
230
238
|
for i in range(len(inRotAxises)):
|
@@ -240,7 +248,8 @@ class VolumeBone: # Updated class name to match the new file name
|
|
240
248
|
if volBoneName[0].islower():
|
241
249
|
volBoneName = volBoneName.lower()
|
242
250
|
|
243
|
-
|
251
|
+
final_volBoneName = self.name.remove_name_part("Nub", volBoneName)
|
252
|
+
volBone = rt.getNodeByName(final_volBoneName)
|
244
253
|
if rt.isValidNode(volBone):
|
245
254
|
bones.append(volBone)
|
246
255
|
|
@@ -259,6 +268,8 @@ class VolumeBone: # Updated class name to match the new file name
|
|
259
268
|
# 메소드 호출 후 데이터 초기화
|
260
269
|
self.reset()
|
261
270
|
|
271
|
+
rt.redrawViews()
|
272
|
+
|
262
273
|
return BoneChain.from_result(result)
|
263
274
|
|
264
275
|
def create_bones_from_chain(self, inBoneChain: BoneChain):
|
pyjallib/max/wrist.py
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
"""
|
5
|
+
손목 모듈
|
6
|
+
자동으로 손목 본을 생성.
|
7
|
+
"""
|
8
|
+
|
9
|
+
from pymxs import runtime as rt
|
10
|
+
|
11
|
+
from .volumeBone import VolumeBone
|
12
|
+
from .boneChain import BoneChain
|
13
|
+
|
14
|
+
class Wrist(VolumeBone):
|
15
|
+
def __init__(self, nameService=None, animService=None, constraintService=None, boneService=None, helperService=None):
|
16
|
+
super().__init__(nameService=nameService, animService=animService, constraintService=constraintService, boneService=boneService, helperService=helperService)
|
17
|
+
|
18
|
+
def create_bones(self, inHand, inForeArm, inRotScale=0.5, inVolumeSize=4.0, inFBRotAxis="Y", inIORotAxis="Z", inFBTransAxis="Z", inIOTransAxis="Y", inFBTransScale=1.0, inIOTransScale=1.0):
|
19
|
+
"""손목 볼륨 본들을 생성합니다."""
|
20
|
+
if not rt.isValidNode(inHand) or not rt.isValidNode(inForeArm):
|
21
|
+
return False
|
22
|
+
|
23
|
+
# 이름 생성 (로컬 변수로 처리)
|
24
|
+
filteringChar = self.name._get_filtering_char(inForeArm.name)
|
25
|
+
wristName = self.name.replace_name_part("RealName", inForeArm.name, "Wrist")
|
26
|
+
wristRootName = self.name.replace_name_part("RealName", wristName, "Wrist" + filteringChar + "Root")
|
27
|
+
wristRootDumName = self.name.replace_name_part("Type", wristRootName, self.name.get_name_part_value_by_description("Type", "Dummy"))
|
28
|
+
wristFwdName = self.name.replace_name_part("RealName", wristName, "Wrist" + filteringChar + "Fwd")
|
29
|
+
wristBckName = self.name.replace_name_part("RealName", wristName, "Wrist" + filteringChar + "Bck")
|
30
|
+
wristInName = self.name.replace_name_part("RealName", wristName, "Wrist" + filteringChar + "In")
|
31
|
+
wristOutName = self.name.replace_name_part("RealName", wristName, "Wrist" + filteringChar + "Out")
|
32
|
+
|
33
|
+
# 소문자 처리
|
34
|
+
if inForeArm.name[0].islower():
|
35
|
+
wristName = wristName.lower()
|
36
|
+
wristRootName = wristRootName.lower()
|
37
|
+
wristRootDumName = wristRootDumName.lower()
|
38
|
+
wristFwdName = wristFwdName.lower()
|
39
|
+
wristBckName = wristBckName.lower()
|
40
|
+
wristInName = wristInName.lower()
|
41
|
+
wristOutName = wristOutName.lower()
|
42
|
+
|
43
|
+
# 방향 결정
|
44
|
+
facingDirVec = inHand.transform.position - inForeArm.transform.position
|
45
|
+
inObjXAxisVec = inHand.objectTransform.row1
|
46
|
+
distanceDir = 1.0 if rt.dot(inObjXAxisVec, facingDirVec) > 0 else -1.0
|
47
|
+
|
48
|
+
# 축과 스케일 설정 - 2개의 볼륨 본: FB(앞/뒤), IO(안/바깥)
|
49
|
+
rotAxises = [inFBRotAxis, inFBRotAxis, inIORotAxis, inIORotAxis]
|
50
|
+
transScales = [inFBTransScale, inFBTransScale, inIOTransScale, inIOTransScale]
|
51
|
+
transAxises = ["Pos" + inFBTransAxis, "Neg" + inFBTransAxis, "Pos" + inIOTransAxis, "Neg" + inIOTransAxis]
|
52
|
+
transAxisNames = [transAxises[0], transAxises[1], transAxises[2], transAxises[3]]
|
53
|
+
|
54
|
+
if distanceDir < 0:
|
55
|
+
transAxisNames = [transAxises[1], transAxises[0], transAxises[3], transAxises[2]]
|
56
|
+
|
57
|
+
# 부모 클래스의 create_bones 호출
|
58
|
+
volumeBoneResult = super().create_bones(inHand, inForeArm, inRotScale, inVolumeSize, rotAxises, transAxises, transScales)
|
59
|
+
|
60
|
+
# volumeBoneResult가 None이면 실패 반환
|
61
|
+
if not volumeBoneResult:
|
62
|
+
return None
|
63
|
+
|
64
|
+
# 생성된 본들의 이름 변경
|
65
|
+
if hasattr(volumeBoneResult, 'bones') and volumeBoneResult.bones:
|
66
|
+
for item in volumeBoneResult.bones:
|
67
|
+
if rt.matchPattern(item.name.lower(), pattern="*root*"):
|
68
|
+
item.name = wristRootName
|
69
|
+
elif rt.matchPattern(item.name.lower(), pattern="*" + transAxisNames[0].lower() + "*"):
|
70
|
+
item.name = wristBckName
|
71
|
+
elif rt.matchPattern(item.name.lower(), pattern="*" + transAxisNames[1].lower() + "*"):
|
72
|
+
item.name = wristFwdName
|
73
|
+
elif rt.matchPattern(item.name.lower(), pattern="*" + transAxisNames[2].lower() + "*"):
|
74
|
+
item.name = wristInName
|
75
|
+
elif rt.matchPattern(item.name.lower(), pattern="*" + transAxisNames[3].lower() + "*"):
|
76
|
+
item.name = wristOutName
|
77
|
+
|
78
|
+
# 생성된 헬퍼들의 이름 변경
|
79
|
+
if hasattr(volumeBoneResult, 'helpers') and volumeBoneResult.helpers:
|
80
|
+
for item in volumeBoneResult.helpers:
|
81
|
+
if rt.matchPattern(item.name.lower(), pattern="*root*"):
|
82
|
+
item.name = wristRootDumName
|
83
|
+
|
84
|
+
rt.redrawViews()
|
85
|
+
|
86
|
+
return volumeBoneResult
|
87
|
+
|
88
|
+
def create_bones_from_chain(self, inBoneChain: BoneChain):
|
89
|
+
"""기존 BoneChain에서 손목 본들을 재생성합니다."""
|
90
|
+
if not inBoneChain or inBoneChain.is_empty():
|
91
|
+
return None
|
92
|
+
|
93
|
+
inBoneChain.delete()
|
94
|
+
|
95
|
+
sourceBones = inBoneChain.sourceBones
|
96
|
+
parameters = inBoneChain.parameters
|
97
|
+
|
98
|
+
if len(sourceBones) < 2 or not rt.isValidNode(sourceBones[0]) or not rt.isValidNode(sourceBones[1]):
|
99
|
+
return None
|
100
|
+
|
101
|
+
# 매개변수 추출
|
102
|
+
inHand = sourceBones[0]
|
103
|
+
inForeArm = sourceBones[1]
|
104
|
+
inRotScale = parameters[0] if len(parameters) > 0 else 0.5
|
105
|
+
inVolumeSize = parameters[1] if len(parameters) > 1 else 4.0
|
106
|
+
inFBRotAxis = parameters[2] if len(parameters) > 2 else "Y"
|
107
|
+
inIORotAxis = parameters[3] if len(parameters) > 3 else "Z"
|
108
|
+
inFBTransAxis = parameters[4] if len(parameters) > 4 else "Z"
|
109
|
+
inIOTransAxis = parameters[5] if len(parameters) > 5 else "Y"
|
110
|
+
inFBTransScale = parameters[6] if len(parameters) > 6 else 1.0
|
111
|
+
inIOTransScale = parameters[7] if len(parameters) > 7 else 1.0
|
112
|
+
|
113
|
+
return self.create_bones(inHand, inForeArm, inRotScale, inVolumeSize, inFBRotAxis, inIORotAxis, inFBTransAxis, inIOTransAxis, inFBTransScale, inIOTransScale)
|
pyjallib/nameToPath.py
CHANGED
@@ -2,37 +2,93 @@
|
|
2
2
|
# -*- coding: utf-8 -*-
|
3
3
|
|
4
4
|
"""
|
5
|
-
|
6
|
-
이름 규칙에 따라 경로를 생성하거나 경로에서 이름을 추출하는 기능 제공
|
5
|
+
입력된 네이밍 규칙에 따라 경로를 생성하고, 윈도우즈용 폴더명을 안전하게 변환하는 기능을 제공하는 클래스.
|
7
6
|
"""
|
8
7
|
|
8
|
+
from pathlib import PureWindowsPath
|
9
9
|
import os
|
10
|
-
import
|
10
|
+
import re
|
11
11
|
from typing import Optional, Dict, Any, List
|
12
12
|
|
13
13
|
from pyjallib.naming import Naming
|
14
|
-
from pyjallib.
|
14
|
+
from pyjallib.namingConfig import NamingConfig
|
15
|
+
|
15
16
|
|
16
17
|
class NameToPath(Naming):
|
17
18
|
"""
|
18
|
-
|
19
|
+
네이밍 규칙에 따라 경로를 생성하고, 폴더명을 안전하게 변환하는 기능을 제공하는 클래스.
|
19
20
|
"""
|
20
|
-
def __init__(self,
|
21
|
+
def __init__(self, inputConfigPath: str, pathConfigPath: str, rootPath: str = None):
|
22
|
+
"""
|
23
|
+
NameToPath 초기화
|
24
|
+
|
25
|
+
:param inputConfigPath: 입력 이름 파싱용 설정 파일 경로
|
26
|
+
:param pathConfigPath: 경로 생성용 설정 파일 경로
|
27
|
+
:param rootPath: 루트 경로 (옵션)
|
28
|
+
"""
|
29
|
+
super().__init__()
|
30
|
+
self.pathConfig = NamingConfig()
|
31
|
+
self.pathConfig.load(pathConfigPath)
|
32
|
+
|
33
|
+
# 루트 경로 설정 (pathAndFiles 의존성 제거)
|
34
|
+
if rootPath is not None:
|
35
|
+
self.rootPath = self._normalize_path(rootPath)
|
36
|
+
else:
|
37
|
+
self.rootPath = None
|
38
|
+
|
39
|
+
self.load_from_config_file(inputConfigPath)
|
40
|
+
|
41
|
+
@staticmethod
|
42
|
+
def _normalize_path(path: str) -> str:
|
43
|
+
"""경로를 윈도우즈 형식으로 정규화"""
|
44
|
+
if not path:
|
45
|
+
return path
|
46
|
+
return str(PureWindowsPath(path))
|
47
|
+
|
48
|
+
@staticmethod
|
49
|
+
def _sanitize_folder_name(name: str) -> str:
|
50
|
+
"""폴더명에서 유효하지 않은 문자를 제거"""
|
51
|
+
invalidChars = r'[<>:"/\\|?*]'
|
52
|
+
return re.sub(invalidChars, '_', name).strip()
|
53
|
+
|
54
|
+
@property
|
55
|
+
def rootPathProp(self) -> str:
|
56
|
+
"""루트 경로 속성 getter"""
|
57
|
+
return self.rootPath
|
58
|
+
|
59
|
+
@rootPathProp.setter
|
60
|
+
def rootPathProp(self, path: str) -> None:
|
61
|
+
"""루트 경로 속성 setter"""
|
62
|
+
self.rootPath = self._normalize_path(path)
|
63
|
+
|
64
|
+
def generate_path(self, inputName: str, inIncludeRealName: bool = False) -> str:
|
21
65
|
"""
|
22
|
-
|
23
|
-
|
24
|
-
:param
|
25
|
-
:param
|
66
|
+
입력된 이름을 기반으로 경로를 생성
|
67
|
+
|
68
|
+
:param inputName: 파싱할 입력 이름
|
69
|
+
:param inIncludeRealName: 실제 이름을 경로에 포함할지 여부
|
70
|
+
:return: 생성된 경로
|
26
71
|
"""
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
self.
|
32
|
-
|
33
|
-
|
72
|
+
parsedDict = self.parse_name(inputName)
|
73
|
+
nameParts = self.pathConfig.get_part_order()
|
74
|
+
folders = [
|
75
|
+
self._sanitize_folder_name(self.pathConfig.get_part(part).get_description_by_value(parsedDict[part]))
|
76
|
+
for part in nameParts if part in parsedDict and self.pathConfig.get_part(part).get_description_by_value(parsedDict[part])
|
77
|
+
]
|
78
|
+
if inIncludeRealName:
|
79
|
+
folders.append(self._sanitize_folder_name(parsedDict["RealName"]))
|
80
|
+
|
81
|
+
if self.rootPath:
|
82
|
+
fullPath = os.path.join(self.rootPath, *folders)
|
83
|
+
else:
|
84
|
+
fullPath = os.path.join(*folders) if folders else ""
|
85
|
+
return self._normalize_path(fullPath)
|
86
|
+
|
87
|
+
def parse_name(self, inName: str):
|
88
|
+
"""이름을 파싱하여 딕셔너리로 변환"""
|
89
|
+
return self.convert_to_dictionary(inName)
|
34
90
|
|
35
|
-
def set_root_path(self, inRootPath: str):
|
91
|
+
def set_root_path(self, inRootPath: str) -> str:
|
36
92
|
"""
|
37
93
|
루트 경로를 설정합니다.
|
38
94
|
입력된 경로를 정규화하고 유효성을 검증합니다.
|
@@ -42,25 +98,21 @@ class NameToPath(Naming):
|
|
42
98
|
:raises ValueError: 경로가 존재하지 않는 경우
|
43
99
|
"""
|
44
100
|
if inRootPath:
|
45
|
-
|
46
|
-
normalized_path = os.path.normpath(os.path.abspath(inRootPath))
|
47
|
-
|
48
|
-
# 경로 존재 여부 확인 (선택적)
|
101
|
+
normalized_path = self._normalize_path(inRootPath)
|
49
102
|
if not os.path.exists(normalized_path):
|
50
103
|
raise ValueError(f"경로가 존재하지 않습니다: {normalized_path}")
|
51
|
-
|
52
104
|
self.rootPath = normalized_path
|
53
105
|
return self.rootPath
|
54
106
|
else:
|
55
107
|
self.rootPath = None
|
56
108
|
return None
|
57
|
-
|
109
|
+
|
58
110
|
def combine(self, inPartsDict={}, inFilChar=os.sep) -> str:
|
59
111
|
"""
|
60
112
|
딕셔너리의 값들을 설정된 순서에 따라 문자열로 결합합니다. (인덱스 제외)
|
61
113
|
|
62
114
|
:param inPartsDict: 결합할 키-값 쌍을 포함하는 딕셔너리
|
63
|
-
:param inFilChar: 값들을 구분할 구분자 (기본값:
|
115
|
+
:param inFilChar: 값들을 구분할 구분자 (기본값: os.sep)
|
64
116
|
:return: 결합된 문자열
|
65
117
|
"""
|
66
118
|
# 결과 배열 초기화 (빈 문자열로)
|
@@ -75,39 +127,4 @@ class NameToPath(Naming):
|
|
75
127
|
|
76
128
|
# 배열을 문자열로 결합
|
77
129
|
newName = self._combine(combinedNameArray, inFilChar)
|
78
|
-
return newName
|
79
|
-
|
80
|
-
|
81
|
-
def gen_path(self, inStr):
|
82
|
-
"""
|
83
|
-
입력된 문자열을 기반으로 경로를 생성합니다.
|
84
|
-
|
85
|
-
:param inStr: 경로를 생성할 문자열 (이름)
|
86
|
-
:return: 생성된 경로 (문자열)
|
87
|
-
:raises ValueError: 루트 경로가 설정되지 않았거나 이름을 변환할 수 없는 경우
|
88
|
-
"""
|
89
|
-
if not self.rootPath:
|
90
|
-
raise ValueError("루트 경로가 설정되지 않았습니다.")
|
91
|
-
|
92
|
-
# 이름을 딕셔너리로 변환
|
93
|
-
nameDict = self.sourceNaming.convert_to_dictionary(inStr)
|
94
|
-
if not nameDict:
|
95
|
-
raise ValueError(f"이름을 변환할 수 없습니다: {inStr}")
|
96
|
-
print(f"Name Dictionary: {nameDict}")
|
97
|
-
|
98
|
-
pathDict = {}
|
99
|
-
|
100
|
-
# 선택된 NamePart 값들을 설명으로 변환하여 폴더 이름으로 사용
|
101
|
-
for key, value in nameDict.items():
|
102
|
-
namePart = self.sourceNaming.get_name_part(key)
|
103
|
-
if self.get_name_part(namePart.get_name()):
|
104
|
-
if namePart.get_type().value == NamePartType.REALNAME.value:
|
105
|
-
# 실제 이름인 경우, 해당 이름을 사용
|
106
|
-
pathDict[key] = value
|
107
|
-
else:
|
108
|
-
pathDict[key] = namePart.get_description_by_value(value)
|
109
|
-
|
110
|
-
combinedPath = self.combine(pathDict)
|
111
|
-
finalPath = os.path.join(self.rootPath, combinedPath)
|
112
|
-
|
113
|
-
return os.path.normpath(finalPath)
|
130
|
+
return newName
|