pyjallib 0.1.9__py3-none-any.whl → 0.1.11__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 +7 -7
- pyjallib/max/ConfigFiles/Default_3DSMaxNamingConfig.json +161 -0
- pyjallib/max/__init__.py +31 -20
- pyjallib/max/anim.py +60 -36
- pyjallib/max/autoClavicle.py +122 -122
- pyjallib/max/bip.py +213 -14
- pyjallib/max/bone.py +378 -16
- pyjallib/max/boneChain.py +182 -0
- pyjallib/max/groinBone.py +148 -73
- pyjallib/max/header.py +42 -6
- pyjallib/max/helper.py +3 -21
- pyjallib/max/hip.py +276 -366
- pyjallib/max/kneeBone.py +552 -0
- pyjallib/max/macro/jal_macro_align.py +11 -10
- pyjallib/max/macro/jal_macro_bone.py +3 -2
- 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 +264 -462
- pyjallib/max/volumeBone.py +324 -0
- pyjallib/namePart.py +16 -16
- pyjallib/nameToPath.py +1 -1
- pyjallib/naming.py +16 -17
- pyjallib/namingConfig.py +3 -3
- pyjallib/perforce.py +127 -9
- {pyjallib-0.1.9.dist-info → pyjallib-0.1.11.dist-info}/METADATA +1 -1
- pyjallib-0.1.11.dist-info/RECORD +43 -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.11.dist-info}/WHEEL +0 -0
@@ -0,0 +1,324 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
"""
|
5
|
+
관절 부피 유지 본(Volume preserve Bone) 모듈 - 3ds Max용 관절의 부피를 유지하기 위해 추가되는 중간본들을 위한 모듈
|
6
|
+
|
7
|
+
이 모듈은 3ds Max에서 캐릭터 애니메이션 과정에서 관절 변형 시 발생하는 부피 감소 문제를 해결하기 위한
|
8
|
+
부피 유지 본 시스템을 제공합니다. 관절이 회전할 때 볼륨감을 자동으로 유지하는 보조 본을 생성하여
|
9
|
+
더 자연스러운 캐릭터 애니메이션을 구현할 수 있습니다.
|
10
|
+
"""
|
11
|
+
|
12
|
+
from pymxs import runtime as rt
|
13
|
+
|
14
|
+
# Import necessary service classes for default initialization
|
15
|
+
from .name import Name
|
16
|
+
from .anim import Anim
|
17
|
+
from .helper import Helper
|
18
|
+
from .bone import Bone
|
19
|
+
from .constraint import Constraint
|
20
|
+
|
21
|
+
from .boneChain import BoneChain
|
22
|
+
|
23
|
+
|
24
|
+
class VolumeBone: # Updated class name to match the new file name
|
25
|
+
"""
|
26
|
+
관절 부피 유지 본(Volume preserve Bone) 클래스
|
27
|
+
|
28
|
+
3ds Max에서 관절의 부피를 유지하기 위해 추가되는 중간본들을 위한 클래스입니다.
|
29
|
+
이 클래스는 관절이 회전할 때 자동으로 부피감을 유지하도록 하는 보조 본 시스템을 생성하고
|
30
|
+
관리합니다. 부모 관절과 자식 관절 사이에 부피 유지 본을 배치하여 관절 변형 시 부피 감소를
|
31
|
+
방지하고 더 자연스러운 움직임을 구현합니다.
|
32
|
+
"""
|
33
|
+
def __init__(self, nameService=None, animService=None, constraintService=None, boneService=None, helperService=None):
|
34
|
+
"""
|
35
|
+
클래스 초기화.
|
36
|
+
|
37
|
+
필요한 서비스 객체들을 초기화하거나 외부에서 제공받습니다.
|
38
|
+
각 서비스 객체들은 본 생성, 이름 관리, 애니메이션 제어, 제약 조건 적용 등의
|
39
|
+
기능을 담당합니다.
|
40
|
+
|
41
|
+
Args:
|
42
|
+
nameService: 이름 처리 서비스 (제공되지 않으면 새로 생성)
|
43
|
+
animService: 애니메이션 서비스 (제공되지 않으면 새로 생성)
|
44
|
+
constraintService: 제약 서비스 (제공되지 않으면 새로 생성)
|
45
|
+
boneService: 뼈대 서비스 (제공되지 않으면 새로 생성)
|
46
|
+
helperService: 헬퍼 서비스 (제공되지 않으면 새로 생성)
|
47
|
+
"""
|
48
|
+
# 서비스 인스턴스 설정 또는 생성
|
49
|
+
self.name = nameService if nameService else Name()
|
50
|
+
self.anim = animService if animService else Anim()
|
51
|
+
|
52
|
+
# 종속성이 있는 서비스들은 이미 생성된 서비스들을 전달
|
53
|
+
self.const = constraintService if constraintService else Constraint(nameService=self.name)
|
54
|
+
self.bone = boneService if boneService else Bone(nameService=self.name, animService=self.anim)
|
55
|
+
self.helper = helperService if helperService else Helper(nameService=self.name)
|
56
|
+
|
57
|
+
self.rootBone = None
|
58
|
+
self.rotHelper = None
|
59
|
+
self.limb = None
|
60
|
+
self.limbParent = None
|
61
|
+
self.bones = []
|
62
|
+
self.rotAxises = []
|
63
|
+
self.transAxises = []
|
64
|
+
self.transScales = []
|
65
|
+
self.volumeSize = 5.0
|
66
|
+
self.rotScale = 0.5
|
67
|
+
|
68
|
+
self.posScriptExpression = (
|
69
|
+
"localLimbTm = limb.transform * inverse limbParent.transform\n"
|
70
|
+
"localDeltaTm = localLimbTm * inverse localRotRefTm\n"
|
71
|
+
"\n"
|
72
|
+
"q = localDeltaTm.rotation\n"
|
73
|
+
"\n"
|
74
|
+
"eulerRot = (quatToEuler q order:5)\n"
|
75
|
+
"swizzledRot = (eulerAngles eulerRot.y eulerRot.z eulerRot.x)\n"
|
76
|
+
"saturatedTwist = abs ((swizzledRot.x*axis.x + swizzledRot.y*axis.y + swizzledRot.z*axis.z)/180.0)\n"
|
77
|
+
"\n"
|
78
|
+
"trAxis * saturatedTwist * volumeSize * transScale\n"
|
79
|
+
)
|
80
|
+
|
81
|
+
def reset(self):
|
82
|
+
"""
|
83
|
+
클래스의 주요 컴포넌트들을 초기화합니다.
|
84
|
+
서비스가 아닌 클래스 자체의 작업 데이터를 초기화하는 함수입니다.
|
85
|
+
|
86
|
+
Returns:
|
87
|
+
self: 메소드 체이닝을 위한 자기 자신 반환
|
88
|
+
"""
|
89
|
+
self.rootBone = None
|
90
|
+
self.rotHelper = None
|
91
|
+
self.limb = None
|
92
|
+
self.limbParent = None
|
93
|
+
self.bones = []
|
94
|
+
self.rotAxises = []
|
95
|
+
self.transAxises = []
|
96
|
+
self.transScales = []
|
97
|
+
self.volumeSize = 5.0
|
98
|
+
self.rotScale = 0.5
|
99
|
+
|
100
|
+
return self
|
101
|
+
|
102
|
+
def create_root_bone(self, inObj, inParent, inRotScale=0.5):
|
103
|
+
if rt.isValidNode(inObj) == False or rt.isValidNode(inParent) == False:
|
104
|
+
return False
|
105
|
+
|
106
|
+
if rt.isValidNode(self.rootBone) and rt.isValidNode(self.rotHelper):
|
107
|
+
return self.rootBone
|
108
|
+
|
109
|
+
rootBoneName = inObj.name
|
110
|
+
filteringChar = self.name._get_filtering_char(rootBoneName)
|
111
|
+
rootBoneName = self.name.add_suffix_to_real_name(rootBoneName, filteringChar+"Vol"+filteringChar+"Root")
|
112
|
+
|
113
|
+
rootBone = self.bone.create_nub_bone(rootBoneName, 2)
|
114
|
+
rootBone.name = self.name.remove_name_part("Nub", rootBone.name)
|
115
|
+
if rootBone.name[0].islower():
|
116
|
+
rootBone.name = rootBone.name.lower()
|
117
|
+
rootBoneName = rootBoneName.lower()
|
118
|
+
|
119
|
+
rt.setProperty(rootBone, "transform", inObj.transform)
|
120
|
+
rootBone.parent = inObj
|
121
|
+
|
122
|
+
rotHelper = self.helper.create_point(rootBoneName)
|
123
|
+
rotHelper.name = self.name.replace_name_part("Type", rotHelper.name, self.name.get_name_part_value_by_description("Type", "Dummy"))
|
124
|
+
rt.setProperty(rotHelper, "transform", inObj.transform)
|
125
|
+
rotHelper.parent = inParent
|
126
|
+
|
127
|
+
oriConst = self.const.assign_rot_const_multi(rootBone, [inObj, rotHelper])
|
128
|
+
oriConst.setWeight(1, inRotScale * 100.0)
|
129
|
+
oriConst.setWeight(2, (1.0 - inRotScale) * 100.0)
|
130
|
+
|
131
|
+
self.rootBone = rootBone
|
132
|
+
self.rotHelper = rotHelper
|
133
|
+
self.limb = inObj
|
134
|
+
self.limbParent = inParent
|
135
|
+
|
136
|
+
return self.rootBone
|
137
|
+
|
138
|
+
def create_bone(self, inObj, inParent, inRotScale=0.5, inVolumeSize=5.0, inRotAxis="Z", inTransAxis="PosY", inTransScale=1.0, useRootBone=True, inRootBone=None):
|
139
|
+
if rt.isValidNode(inObj) == False or rt.isValidNode(inParent) == False:
|
140
|
+
return False
|
141
|
+
|
142
|
+
if useRootBone:
|
143
|
+
if rt.isValidNode(self.rootBone) == False and rt.isValidNode(self.rotHelper) == False:
|
144
|
+
return False
|
145
|
+
self.rootBone = inRootBone if inRootBone else self.create_root_bone(inObj, inParent, inRotScale)
|
146
|
+
else:
|
147
|
+
self.create_root_bone(inObj, inParent, inRotScale)
|
148
|
+
|
149
|
+
self.limb = inObj
|
150
|
+
self.limbParent = inParent
|
151
|
+
|
152
|
+
volBoneName = inObj.name
|
153
|
+
filteringChar = self.name._get_filtering_char(volBoneName)
|
154
|
+
volBoneName = self.name.add_suffix_to_real_name(volBoneName, filteringChar + "Vol" + filteringChar + inRotAxis + filteringChar+ inTransAxis)
|
155
|
+
|
156
|
+
volBone = self.bone.create_nub_bone(volBoneName, 2)
|
157
|
+
volBone.name = self.name.remove_name_part("Nub", volBone.name)
|
158
|
+
if volBone.name[0].islower():
|
159
|
+
volBone.name = volBone.name.lower()
|
160
|
+
volBoneName = volBoneName.lower()
|
161
|
+
rt.setProperty(volBone, "transform", self.rootBone.transform)
|
162
|
+
|
163
|
+
volBoneTrDir = rt.Point3(0.0, 0.0, 0.0)
|
164
|
+
if inTransAxis == "PosX":
|
165
|
+
volBoneTrDir = rt.Point3(1.0, 0.0, 0.0)
|
166
|
+
elif inTransAxis == "NegX":
|
167
|
+
volBoneTrDir = rt.Point3(-1.0, 0.0, 0.0)
|
168
|
+
elif inTransAxis == "PosY":
|
169
|
+
volBoneTrDir = rt.Point3(0.0, 1.0, 0.0)
|
170
|
+
elif inTransAxis == "NegY":
|
171
|
+
volBoneTrDir = rt.Point3(0.0, -1.0, 0.0)
|
172
|
+
elif inTransAxis == "PosZ":
|
173
|
+
volBoneTrDir = rt.Point3(0.0, 0.0, 1.0)
|
174
|
+
elif inTransAxis == "NegZ":
|
175
|
+
volBoneTrDir = rt.Point3(0.0, 0.0, -1.0)
|
176
|
+
|
177
|
+
self.anim.move_local(volBone, volBoneTrDir[0]*inVolumeSize, volBoneTrDir[1]*inVolumeSize, volBoneTrDir[2]*inVolumeSize)
|
178
|
+
volBone.parent = self.rootBone
|
179
|
+
|
180
|
+
rotAxis = rt.Point3(0.0, 0.0, 0.0)
|
181
|
+
if inRotAxis == "X":
|
182
|
+
rotAxis = rt.Point3(1.0, 0.0, 0.0)
|
183
|
+
elif inRotAxis == "Y":
|
184
|
+
rotAxis = rt.Point3(0.0, 1.0, 0.0)
|
185
|
+
elif inRotAxis == "Z":
|
186
|
+
rotAxis = rt.Point3(0.0, 0.0, 1.0)
|
187
|
+
|
188
|
+
# localRotRefTm = self.limb.transform * rt.inverse(self.limbParent.transform)
|
189
|
+
localRotRefTm = self.limb.transform * rt.inverse(self.rotHelper.transform)
|
190
|
+
volBonePosConst = self.const.assign_pos_script_controller(volBone)
|
191
|
+
volBonePosConst.addNode("limb", self.limb)
|
192
|
+
# volBonePosConst.addNode("limbParent", self.limbParent)
|
193
|
+
volBonePosConst.addNode("limbParent", self.rotHelper)
|
194
|
+
volBonePosConst.addConstant("axis", rotAxis)
|
195
|
+
volBonePosConst.addConstant("transScale", rt.Float(inTransScale))
|
196
|
+
volBonePosConst.addConstant("volumeSize", rt.Float(inVolumeSize))
|
197
|
+
volBonePosConst.addConstant("localRotRefTm", localRotRefTm)
|
198
|
+
volBonePosConst.addConstant("trAxis", volBoneTrDir)
|
199
|
+
volBonePosConst.setExpression(self.posScriptExpression)
|
200
|
+
volBonePosConst.update()
|
201
|
+
|
202
|
+
return True
|
203
|
+
|
204
|
+
def create_bones(self, inObj, inParent, inRotScale=0.5, inVolumeSize=5.0, inRotAxises=["Z"], inTransAxises=["PosY"], inTransScales=[1.0]):
|
205
|
+
"""
|
206
|
+
여러 개의 부피 유지 본을 생성합니다.
|
207
|
+
|
208
|
+
Args:
|
209
|
+
inObj: 본을 생성할 객체
|
210
|
+
inParent: 부모 객체
|
211
|
+
inRotScale: 회전 비율
|
212
|
+
inVolumeSize: 부피 크기
|
213
|
+
inRotAxises: 회전 축 리스트
|
214
|
+
inTransAxises: 변환 축 리스트
|
215
|
+
inTransScales: 변환 비율 리스트
|
216
|
+
|
217
|
+
Returns:
|
218
|
+
BoneChain: 생성된 볼륨 본 체인 객체
|
219
|
+
"""
|
220
|
+
if rt.isValidNode(inObj) == False or rt.isValidNode(inParent) == False:
|
221
|
+
return None
|
222
|
+
|
223
|
+
if len(inRotAxises) != len(inTransAxises) or len(inRotAxises) != len(inTransScales):
|
224
|
+
return None
|
225
|
+
|
226
|
+
rootBone = self.create_root_bone(inObj, inParent, inRotScale=inRotScale)
|
227
|
+
|
228
|
+
# 볼륨 본들 생성
|
229
|
+
bones = []
|
230
|
+
for i in range(len(inRotAxises)):
|
231
|
+
self.create_bone(inObj, inParent, inRotScale, inVolumeSize, inRotAxises[i], inTransAxises[i], inTransScales[i], useRootBone=True, inRootBone=rootBone)
|
232
|
+
|
233
|
+
# 생성된 본의 이름 패턴으로 찾기
|
234
|
+
volBoneName = inObj.name
|
235
|
+
filteringChar = self.name._get_filtering_char(volBoneName)
|
236
|
+
volBoneName = self.name.add_suffix_to_real_name(volBoneName,
|
237
|
+
filteringChar + "Vol" + filteringChar + inRotAxises[i] +
|
238
|
+
filteringChar + inTransAxises[i])
|
239
|
+
|
240
|
+
if volBoneName[0].islower():
|
241
|
+
volBoneName = volBoneName.lower()
|
242
|
+
|
243
|
+
volBone = rt.getNodeByName(self.name.remove_name_part("Nub", volBoneName))
|
244
|
+
if rt.isValidNode(volBone):
|
245
|
+
bones.append(volBone)
|
246
|
+
|
247
|
+
# 모든 생성된 본들 모음
|
248
|
+
all_bones = [rootBone] + bones
|
249
|
+
rotHelper = self.rotHelper
|
250
|
+
|
251
|
+
# BoneChain에 필요한 형태의 결과 딕셔너리 생성
|
252
|
+
result = {
|
253
|
+
"Bones": all_bones,
|
254
|
+
"Helpers": [rotHelper],
|
255
|
+
"SourceBones": [inObj, inParent],
|
256
|
+
"Parameters": [inRotScale, inVolumeSize] + inRotAxises + inTransAxises + inTransScales
|
257
|
+
}
|
258
|
+
|
259
|
+
# 메소드 호출 후 데이터 초기화
|
260
|
+
self.reset()
|
261
|
+
|
262
|
+
return BoneChain.from_result(result)
|
263
|
+
|
264
|
+
def create_bones_from_chain(self, inBoneChain: BoneChain):
|
265
|
+
"""
|
266
|
+
기존 BoneChain 객체에서 볼륨 본을 생성합니다.
|
267
|
+
기존 설정을 복원하거나 저장된 데이터에서 볼륨 본 셋업을 재생성할 때 사용합니다.
|
268
|
+
|
269
|
+
Args:
|
270
|
+
inBoneChain (BoneChain): 볼륨 본 정보를 포함한 BoneChain 객체
|
271
|
+
|
272
|
+
Returns:
|
273
|
+
BoneChain: 업데이트된 BoneChain 객체 또는 실패 시 None
|
274
|
+
"""
|
275
|
+
if not inBoneChain or inBoneChain.is_empty():
|
276
|
+
return None
|
277
|
+
|
278
|
+
# 기존 객체 삭제
|
279
|
+
inBoneChain.delete()
|
280
|
+
|
281
|
+
# BoneChain에서 필요한 정보 추출
|
282
|
+
sourceBones = inBoneChain.sourceBones
|
283
|
+
parameters = inBoneChain.parameters
|
284
|
+
|
285
|
+
# 필수 소스 본 확인
|
286
|
+
if len(sourceBones) < 2 or not rt.isValidNode(sourceBones[0]) or not rt.isValidNode(sourceBones[1]):
|
287
|
+
return None
|
288
|
+
|
289
|
+
# 최소 필요 파라미터 확인
|
290
|
+
if len(parameters) < 2:
|
291
|
+
return None
|
292
|
+
|
293
|
+
# 파라미터 가져오기
|
294
|
+
inRotScale = parameters[0]
|
295
|
+
inVolumeSize = parameters[1]
|
296
|
+
|
297
|
+
# 회전축, 변환축, 변환비율을 파라미터에서 추출
|
298
|
+
# 최소한 하나의 축 세트는 필요
|
299
|
+
param_count = len(parameters)
|
300
|
+
if param_count <= 2:
|
301
|
+
# 기본 값 사용
|
302
|
+
inRotAxises = ["Z"]
|
303
|
+
inTransAxises = ["PosY"]
|
304
|
+
inTransScales = [1.0]
|
305
|
+
else:
|
306
|
+
# 파라미터 중간을 3등분하여 각 목록 추출
|
307
|
+
axis_count = (param_count - 2) // 3
|
308
|
+
|
309
|
+
inRotAxises = parameters[2:2+axis_count]
|
310
|
+
inTransAxises = parameters[2+axis_count:2+axis_count*2]
|
311
|
+
inTransScales = parameters[2+axis_count*2:2+axis_count*3]
|
312
|
+
|
313
|
+
# 리스트 길이가 일치하지 않으면 기본값으로 보완
|
314
|
+
if len(inRotAxises) != len(inTransAxises) or len(inRotAxises) != len(inTransScales):
|
315
|
+
min_len = min(len(inRotAxises), len(inTransAxises), len(inTransScales))
|
316
|
+
inRotAxises = inRotAxises[:min_len] if min_len > 0 else ["Z"]
|
317
|
+
inTransAxises = inTransAxises[:min_len] if min_len > 0 else ["PosY"]
|
318
|
+
inTransScales = inTransScales[:min_len] if min_len > 0 else [1.0]
|
319
|
+
|
320
|
+
# 새로운 볼륨 본 생성
|
321
|
+
inObj = sourceBones[0]
|
322
|
+
inParent = sourceBones[1]
|
323
|
+
|
324
|
+
return self.create_bones(inObj, inParent, inRotScale, inVolumeSize, inRotAxises, inTransAxises, inTransScales)
|
pyjallib/namePart.py
CHANGED
@@ -69,13 +69,13 @@ class NamePart:
|
|
69
69
|
|
70
70
|
def _initialize_type_defaults(self):
|
71
71
|
"""타입에 따른 기본 설정을 초기화합니다."""
|
72
|
-
if self._type == NamePartType.INDEX:
|
72
|
+
if self._type.value == NamePartType.INDEX.value:
|
73
73
|
# Index 타입은 숫자만 처리하므로 predefined values는 사용하지 않음
|
74
74
|
self._predefinedValues = []
|
75
75
|
self._descriptions = []
|
76
76
|
self._koreanDescriptions = [] # Clear korean descriptions
|
77
77
|
self._weights = []
|
78
|
-
elif self._type == NamePartType.REALNAME:
|
78
|
+
elif self._type.value == NamePartType.REALNAME.value:
|
79
79
|
# RealName 타입은 predefined values를 사용하지 않음
|
80
80
|
self._predefinedValues = []
|
81
81
|
self._descriptions = []
|
@@ -88,7 +88,7 @@ class NamePart:
|
|
88
88
|
값들은 5부터 시작해서 5씩 증가하는 가중치를 갖습니다.
|
89
89
|
"""
|
90
90
|
# REALNAME이나 INDEX 타입인 경우 weights를 사용하지 않음
|
91
|
-
if self._type == NamePartType.REALNAME or self._type == NamePartType.INDEX:
|
91
|
+
if self._type.value == NamePartType.REALNAME.value or self._type.value == NamePartType.INDEX.value:
|
92
92
|
self._weights = []
|
93
93
|
return
|
94
94
|
|
@@ -144,8 +144,8 @@ class NamePart:
|
|
144
144
|
Returns:
|
145
145
|
PREFIX 타입이면 True, 아니면 False
|
146
146
|
"""
|
147
|
-
return self._type == NamePartType.PREFIX
|
148
|
-
|
147
|
+
return self._type.value == NamePartType.PREFIX.value
|
148
|
+
|
149
149
|
def is_suffix(self):
|
150
150
|
"""
|
151
151
|
이름 부분이 SUFFIX 타입인지 확인합니다.
|
@@ -153,8 +153,8 @@ class NamePart:
|
|
153
153
|
Returns:
|
154
154
|
SUFFIX 타입이면 True, 아니면 False
|
155
155
|
"""
|
156
|
-
return self._type == NamePartType.SUFFIX
|
157
|
-
|
156
|
+
return self._type.value == NamePartType.SUFFIX.value
|
157
|
+
|
158
158
|
def is_realname(self):
|
159
159
|
"""
|
160
160
|
이름 부분이 REALNAME 타입인지 확인합니다.
|
@@ -162,8 +162,8 @@ class NamePart:
|
|
162
162
|
Returns:
|
163
163
|
REALNAME 타입이면 True, 아니면 False
|
164
164
|
"""
|
165
|
-
return self._type == NamePartType.REALNAME
|
166
|
-
|
165
|
+
return self._type.value == NamePartType.REALNAME.value
|
166
|
+
|
167
167
|
def is_index(self):
|
168
168
|
"""
|
169
169
|
이름 부분이 INDEX 타입인지 확인합니다.
|
@@ -171,7 +171,7 @@ class NamePart:
|
|
171
171
|
Returns:
|
172
172
|
INDEX 타입이면 True, 아니면 False
|
173
173
|
"""
|
174
|
-
return self._type == NamePartType.INDEX
|
174
|
+
return self._type.value == NamePartType.INDEX.value
|
175
175
|
|
176
176
|
def add_predefined_value(self, inValue, inDescription="", inKoreanDescription=""):
|
177
177
|
"""
|
@@ -186,7 +186,7 @@ class NamePart:
|
|
186
186
|
추가 성공 여부 (이미 존재하는 경우 False)
|
187
187
|
"""
|
188
188
|
# REALNAME이나 INDEX 타입인 경우 predefined values를 사용하지 않음
|
189
|
-
if self._type == NamePartType.REALNAME or self._type == NamePartType.INDEX:
|
189
|
+
if self._type.value == NamePartType.REALNAME.value or self._type.value == NamePartType.INDEX.value:
|
190
190
|
return False
|
191
191
|
|
192
192
|
if inValue not in self._predefinedValues:
|
@@ -228,9 +228,9 @@ class NamePart:
|
|
228
228
|
inKoreanDescriptions: 설정할 값들의 한국어 설명 목록 (기본값: None, 빈 문자열로 초기화)
|
229
229
|
"""
|
230
230
|
# REALNAME이나 INDEX 타입인 경우 predefined values를 사용하지 않음
|
231
|
-
if self._type == NamePartType.REALNAME or self._type == NamePartType.INDEX:
|
231
|
+
if self._type.value == NamePartType.REALNAME.value or self._type.value == NamePartType.INDEX.value:
|
232
232
|
return
|
233
|
-
|
233
|
+
|
234
234
|
self._predefinedValues = inValues.copy() if inValues else []
|
235
235
|
|
236
236
|
# 설명 세팅
|
@@ -399,15 +399,15 @@ class NamePart:
|
|
399
399
|
유효하면 True, 아니면 False
|
400
400
|
"""
|
401
401
|
# INDEX 타입은 숫자 문자열만 유효
|
402
|
-
if self._type == NamePartType.INDEX:
|
402
|
+
if self._type.value == NamePartType.INDEX.value:
|
403
403
|
return isinstance(inValue, str) and inValue.isdigit()
|
404
404
|
|
405
405
|
# PREFIX와 SUFFIX 타입은 predefined values 중 하나여야 함
|
406
|
-
if (self._type == NamePartType.PREFIX or self._type == NamePartType.SUFFIX) and self._predefinedValues:
|
406
|
+
if (self._type.value == NamePartType.PREFIX.value or self._type.value == NamePartType.SUFFIX.value) and self._predefinedValues:
|
407
407
|
return inValue in self._predefinedValues
|
408
408
|
|
409
409
|
# REALNAME 타입은 모든 문자열 유효
|
410
|
-
if self._type == NamePartType.REALNAME:
|
410
|
+
if self._type.value == NamePartType.REALNAME.value:
|
411
411
|
return isinstance(inValue, str)
|
412
412
|
|
413
413
|
# 정의되지 않은 타입이면 기존 동작대로 처리
|
pyjallib/nameToPath.py
CHANGED
@@ -101,7 +101,7 @@ class NameToPath(Naming):
|
|
101
101
|
for key, value in nameDict.items():
|
102
102
|
namePart = self.sourceNaming.get_name_part(key)
|
103
103
|
if self.get_name_part(namePart.get_name()):
|
104
|
-
if namePart.get_type() == NamePartType.REALNAME:
|
104
|
+
if namePart.get_type().value == NamePartType.REALNAME.value:
|
105
105
|
# 실제 이름인 경우, 해당 이름을 사용
|
106
106
|
pathDict[key] = value
|
107
107
|
else:
|
pyjallib/naming.py
CHANGED
@@ -325,7 +325,7 @@ class Naming:
|
|
325
325
|
|
326
326
|
partValues = partObj.get_predefined_values()
|
327
327
|
|
328
|
-
if partType == NamePartType.PREFIX or partType == NamePartType.SUFFIX:
|
328
|
+
if partType.value == NamePartType.PREFIX.value or partType.value == NamePartType.SUFFIX.value:
|
329
329
|
return any(item in inStr for item in partValues)
|
330
330
|
|
331
331
|
return False
|
@@ -351,7 +351,7 @@ class Naming:
|
|
351
351
|
|
352
352
|
partValues = partObj.get_predefined_values()
|
353
353
|
|
354
|
-
if partType == NamePartType.PREFIX or partType == NamePartType.SUFFIX:
|
354
|
+
if partType.value == NamePartType.PREFIX.value or partType.value == NamePartType.SUFFIX.value:
|
355
355
|
try:
|
356
356
|
foundIndex = partObj._descriptions.index(inDescription)
|
357
357
|
return partValues[foundIndex]
|
@@ -371,24 +371,24 @@ class Naming:
|
|
371
371
|
partType = partObj.get_type()
|
372
372
|
if not partType:
|
373
373
|
return returnStr
|
374
|
-
|
374
|
+
|
375
375
|
partValues = partObj.get_predefined_values()
|
376
|
-
if partType != NamePartType.INDEX and partType != NamePartType.REALNAME and not partValues:
|
376
|
+
if partType.value != NamePartType.INDEX.value and partType.value != NamePartType.REALNAME.value and not partValues:
|
377
377
|
return returnStr
|
378
378
|
|
379
|
-
if partType == NamePartType.PREFIX:
|
379
|
+
if partType.value == NamePartType.PREFIX.value:
|
380
380
|
for item in nameArray:
|
381
381
|
if item in partValues:
|
382
382
|
returnStr = item
|
383
383
|
break
|
384
384
|
|
385
|
-
if partType == NamePartType.SUFFIX:
|
385
|
+
if partType.value == NamePartType.SUFFIX.value:
|
386
386
|
for i in range(len(nameArray) - 1, -1, -1):
|
387
387
|
if nameArray[i] in partValues:
|
388
388
|
returnStr = nameArray[i]
|
389
389
|
break
|
390
|
-
|
391
|
-
if partType == NamePartType.INDEX:
|
390
|
+
|
391
|
+
if partType.value == NamePartType.INDEX.value:
|
392
392
|
if self.get_name_part_index("Index") > self.get_name_part_index("RealName"):
|
393
393
|
for i in range(len(nameArray) - 1, -1, -1):
|
394
394
|
if nameArray[i].isdigit():
|
@@ -399,7 +399,6 @@ class Naming:
|
|
399
399
|
if item.isdigit():
|
400
400
|
returnStr = item
|
401
401
|
break
|
402
|
-
|
403
402
|
return returnStr
|
404
403
|
|
405
404
|
def get_name(self, inNamePartName, inStr):
|
@@ -424,7 +423,7 @@ class Naming:
|
|
424
423
|
partIndex = self.get_name_part_index(inNamePartName)
|
425
424
|
foundIndex = nameArray.index(foundName)
|
426
425
|
|
427
|
-
if partType == NamePartType.PREFIX:
|
426
|
+
if partType.value == NamePartType.PREFIX.value:
|
428
427
|
if foundIndex >= 0:
|
429
428
|
prevNameParts = self._nameParts[:partIndex]
|
430
429
|
prevNames = [self.pick_name(part.get_name(), inStr) for part in prevNameParts]
|
@@ -434,8 +433,8 @@ class Naming:
|
|
434
433
|
prevNamesInNameArray.remove(prevName)
|
435
434
|
if len(prevNamesInNameArray) == 0 :
|
436
435
|
returnStr = foundName
|
437
|
-
|
438
|
-
if partType == NamePartType.SUFFIX:
|
436
|
+
|
437
|
+
if partType.value == NamePartType.SUFFIX.value:
|
439
438
|
if foundIndex >= 0:
|
440
439
|
nextNameParts = self._nameParts[partIndex + 1:]
|
441
440
|
nextNames = [self.pick_name(part.get_name(), inStr) for part in nextNameParts]
|
@@ -445,8 +444,8 @@ class Naming:
|
|
445
444
|
nextNamesInNameArray.remove(nextName)
|
446
445
|
if len(nextNamesInNameArray) == 0 :
|
447
446
|
returnStr = foundName
|
448
|
-
|
449
|
-
if partType == NamePartType.INDEX:
|
447
|
+
|
448
|
+
if partType.value == NamePartType.INDEX.value:
|
450
449
|
returnStr = self.pick_name(inNamePartName, inStr)
|
451
450
|
|
452
451
|
return returnStr
|
@@ -495,7 +494,7 @@ class Naming:
|
|
495
494
|
for part in self._nameParts:
|
496
495
|
partName = part.get_name()
|
497
496
|
partType = part.get_type()
|
498
|
-
if partType != NamePartType.REALNAME:
|
497
|
+
if partType.value != NamePartType.REALNAME.value:
|
499
498
|
foundName = self.get_name(partName, inStr)
|
500
499
|
nonRealNameArray.append(foundName)
|
501
500
|
|
@@ -946,13 +945,13 @@ class Naming:
|
|
946
945
|
for part in self._nameParts:
|
947
946
|
partName = part.get_name()
|
948
947
|
partType = part.get_type()
|
949
|
-
if (partType != NamePartType.REALNAME
|
948
|
+
if (partType.value != NamePartType.REALNAME.value and partType.value != NamePartType.INDEX.value) and part.is_direction():
|
950
949
|
partIndex = self.get_name_part_index(partName)
|
951
950
|
foundName = self.get_name(partName, inStr)
|
952
951
|
opositeName = part.get_most_different_weight_value(foundName)
|
953
952
|
if opositeName and foundName != opositeName:
|
954
953
|
nameArray[partIndex] = opositeName
|
955
|
-
|
954
|
+
|
956
955
|
returnName = self._combine(nameArray, self._get_filtering_char(inStr))
|
957
956
|
|
958
957
|
return returnName
|
pyjallib/namingConfig.py
CHANGED
@@ -104,7 +104,7 @@ class NamingConfig:
|
|
104
104
|
RealName 파트의 인덱스, 없으면 -1
|
105
105
|
"""
|
106
106
|
for i, part in enumerate(self.name_parts):
|
107
|
-
if part.get_type() == NamePartType.REALNAME:
|
107
|
+
if part.get_type().value == NamePartType.REALNAME.value:
|
108
108
|
return i
|
109
109
|
return -1
|
110
110
|
|
@@ -325,12 +325,12 @@ class NamingConfig:
|
|
325
325
|
return False
|
326
326
|
|
327
327
|
# 필수 RealName 부분은 항상 REALNAME 타입이어야 함
|
328
|
-
if part_name == "RealName" and part_type != NamePartType.REALNAME:
|
328
|
+
if part_name == "RealName" and part_type.value != NamePartType.REALNAME.value:
|
329
329
|
print("오류: RealName 부분은 반드시 REALNAME 타입이어야 합니다.")
|
330
330
|
return False
|
331
331
|
|
332
332
|
# Index 부분은 항상 INDEX 타입이어야 함
|
333
|
-
if part_name == "Index" and part_type != NamePartType.INDEX:
|
333
|
+
if part_name == "Index" and part_type.value != NamePartType.INDEX.value:
|
334
334
|
print("오류: Index 부분은 반드시 INDEX 타입이어야 합니다.")
|
335
335
|
return False
|
336
336
|
|