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
@@ -0,0 +1,363 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
"""
|
5
|
+
볼륨 뼈대 체인(Volume Bone Chain) 모듈 - 3ds Max 캐릭터 리깅을 위한 볼륨 본 시스템
|
6
|
+
|
7
|
+
이 모듈은 VolumeBone 클래스가 생성한 볼륨 본 세트를 관리하고 제어하는 기능을 제공합니다.
|
8
|
+
관절 회전 시 부피 감소를 방지하기 위한 보조 본 시스템으로, 특히 캐릭터 팔다리나
|
9
|
+
관절 부위의 자연스러운 움직임을 구현하는 데 유용합니다.
|
10
|
+
|
11
|
+
Examples:
|
12
|
+
# 기본 볼륨 체인 생성 예시
|
13
|
+
from pyjallib.max import VolumeBone, VolumeBoneChain
|
14
|
+
from pymxs import runtime as rt
|
15
|
+
|
16
|
+
# 캐릭터에서 팔꿈치 뼈대와 상위 부모 가져오기
|
17
|
+
elbow_bone = rt.getNodeByName("L_Elbow_Bone")
|
18
|
+
upper_arm = rt.getNodeByName("L_UpperArm_Bone")
|
19
|
+
|
20
|
+
# VolumeBone 클래스 인스턴스 생성
|
21
|
+
volume_bone = VolumeBone()
|
22
|
+
|
23
|
+
# 다양한 옵션으로 볼륨 뼈대 생성
|
24
|
+
volume_result = volume_bone.create_bones(
|
25
|
+
elbow_bone, # 관절 본
|
26
|
+
upper_arm, # 관절 부모
|
27
|
+
inRotScale=0.7, # 회전 영향도 (0.0 ~ 1.0)
|
28
|
+
inVolumeSize=10.0, # 볼륨 크기
|
29
|
+
inRotAxises=["X", "Z"], # 회전 감지 축 (여러 축 지정 가능)
|
30
|
+
inTransAxises=["PosY", "PosZ"], # 이동 방향 축
|
31
|
+
inTransScales=[1.0, 0.8] # 각 방향별 이동 스케일
|
32
|
+
)
|
33
|
+
|
34
|
+
# 생성된 뼈대로 VolumeBoneChain 인스턴스 생성
|
35
|
+
chain = VolumeBoneChain.from_volume_bone_result(volume_result)
|
36
|
+
|
37
|
+
# 체인 속성 및 관리 기능 사용
|
38
|
+
print(f"볼륨 크기: {chain.get_volume_size()}")
|
39
|
+
print(f"볼륨 본 개수: {len(chain.bones)}")
|
40
|
+
|
41
|
+
# 볼륨 속성 동적 업데이트
|
42
|
+
chain.update_volume_size(15.0) # 볼륨 크기 변경
|
43
|
+
chain.update_rot_scale(0.5) # 회전 영향도 변경
|
44
|
+
|
45
|
+
# 회전 축 업데이트
|
46
|
+
chain.update_rot_axises(["Y", "Z"])
|
47
|
+
|
48
|
+
# 이동 축 업데이트
|
49
|
+
chain.update_trans_axises(["PosX", "PosZ"])
|
50
|
+
|
51
|
+
# 이동 스케일 업데이트
|
52
|
+
chain.update_trans_scales([0.7, 1.2])
|
53
|
+
|
54
|
+
# 필요 없어지면 체인의 모든 뼈대 삭제
|
55
|
+
# chain.delete_all()
|
56
|
+
"""
|
57
|
+
|
58
|
+
import copy
|
59
|
+
|
60
|
+
from pymxs import runtime as rt
|
61
|
+
from pyjallib.max.header import get_pyjallibmaxheader
|
62
|
+
jal = get_pyjallibmaxheader()
|
63
|
+
|
64
|
+
class VolumeBoneChain:
|
65
|
+
"""
|
66
|
+
볼륨 본 체인 관리 클래스
|
67
|
+
|
68
|
+
VolumeBone 클래스로 생성된 볼륨 본들의 집합을 관리하는 클래스입니다.
|
69
|
+
볼륨 본의 크기 조절, 회전 및 이동 축 변경, 스케일 조정 등의 기능을 제공하며,
|
70
|
+
여러 개의 볼륨 본을 하나의 논리적 체인으로 관리합니다.
|
71
|
+
생성된 볼륨 본 체인은 캐릭터 관절의 자연스러운 변형을 위해 사용됩니다.
|
72
|
+
"""
|
73
|
+
|
74
|
+
def __init__(self, inResult):
|
75
|
+
"""
|
76
|
+
볼륨 본 체인 클래스 초기화
|
77
|
+
|
78
|
+
VolumeBone 클래스의 create_bones 메서드로부터 생성된 결과 딕셔너리를
|
79
|
+
받아 볼륨 본 체인을 구성합니다.
|
80
|
+
|
81
|
+
Args:
|
82
|
+
inResult: VolumeBone 클래스의 create_bones 메서드가 반환한 결과 딕셔너리
|
83
|
+
(루트 본, 회전 헬퍼, 회전 축, 이동 축, 볼륨 크기 등의 정보 포함)
|
84
|
+
"""
|
85
|
+
self.rootBone = inResult.get("RootBone", None)
|
86
|
+
self.rotHelper = inResult.get("RotHelper", None)
|
87
|
+
self.rotScale = inResult.get("RotScale", 0.0)
|
88
|
+
self.limb = inResult.get("Limb", None)
|
89
|
+
self.limbParent = inResult.get("LimbParent", None)
|
90
|
+
self.bones = inResult.get("Bones", [])
|
91
|
+
self.rotAxises = inResult.get("RotAxises", [])
|
92
|
+
self.transAxises = inResult.get("TransAxises", [])
|
93
|
+
self.transScales = inResult.get("TransScales", [])
|
94
|
+
self.volumeSize = inResult.get("VolumeSize", 0.0)
|
95
|
+
|
96
|
+
def get_volume_size(self):
|
97
|
+
"""
|
98
|
+
볼륨 뼈대의 크기 가져오기
|
99
|
+
|
100
|
+
볼륨 본 생성 시 설정된 크기 값을 반환합니다. 이 값은 관절의 볼륨감 정도를
|
101
|
+
결정합니다.
|
102
|
+
|
103
|
+
Returns:
|
104
|
+
float: 현재 설정된 볼륨 크기 값
|
105
|
+
"""
|
106
|
+
return self.volumeSize
|
107
|
+
|
108
|
+
def is_empty(self):
|
109
|
+
"""
|
110
|
+
체인이 비어있는지 확인
|
111
|
+
|
112
|
+
볼륨 본 체인에 본이 하나라도 존재하는지 확인합니다.
|
113
|
+
|
114
|
+
Returns:
|
115
|
+
bool: 체인이 비어있으면 True, 하나 이상의 본이 있으면 False
|
116
|
+
"""
|
117
|
+
return len(self.bones) == 0
|
118
|
+
|
119
|
+
def clear(self):
|
120
|
+
"""체인의 모든 뼈대 및 헬퍼 참조 제거"""
|
121
|
+
self.rootBone = None
|
122
|
+
self.rotHelper = None
|
123
|
+
self.rotScale = 0.0
|
124
|
+
self.limb = None
|
125
|
+
self.limbParent = None
|
126
|
+
self.bones = []
|
127
|
+
self.rotAxises = []
|
128
|
+
self.transAxises = []
|
129
|
+
self.transScales = []
|
130
|
+
self.volumeSize = 0.0
|
131
|
+
|
132
|
+
def delete_all(self):
|
133
|
+
"""
|
134
|
+
체인의 모든 뼈대와 헬퍼를 3ds Max 씬에서 삭제
|
135
|
+
|
136
|
+
Returns:
|
137
|
+
삭제 성공 여부 (boolean)
|
138
|
+
"""
|
139
|
+
if self.is_empty():
|
140
|
+
return False
|
141
|
+
|
142
|
+
try:
|
143
|
+
# 루트 본 삭제
|
144
|
+
if self.rootBone:
|
145
|
+
rt.delete(self.rootBone)
|
146
|
+
|
147
|
+
# 회전 헬퍼 삭제
|
148
|
+
if self.rotHelper:
|
149
|
+
rt.delete(self.rotHelper)
|
150
|
+
|
151
|
+
# 뼈대 삭제
|
152
|
+
for bone in self.bones:
|
153
|
+
rt.delete(bone)
|
154
|
+
|
155
|
+
self.rotAxises = []
|
156
|
+
self.transAxises = []
|
157
|
+
self.transScales = []
|
158
|
+
|
159
|
+
self.clear()
|
160
|
+
return True
|
161
|
+
except:
|
162
|
+
return False
|
163
|
+
|
164
|
+
def update_volume_size(self, inNewSize):
|
165
|
+
"""
|
166
|
+
볼륨 뼈대의 크기 업데이트
|
167
|
+
|
168
|
+
Args:
|
169
|
+
inNewSize: 새로운 볼륨 크기 값
|
170
|
+
|
171
|
+
Returns:
|
172
|
+
업데이트 성공 여부 (boolean)
|
173
|
+
"""
|
174
|
+
if self.is_empty() or self.limb is None:
|
175
|
+
return False
|
176
|
+
|
177
|
+
try:
|
178
|
+
# 필요한 값들 백업
|
179
|
+
limb = self.limb
|
180
|
+
limbParent = self.limbParent
|
181
|
+
rotScale = self.rotScale
|
182
|
+
rotAxises = copy.deepcopy(self.rotAxises)
|
183
|
+
transAxises = copy.deepcopy(self.transAxises)
|
184
|
+
transScales = copy.deepcopy(self.transScales)
|
185
|
+
|
186
|
+
self.delete_all()
|
187
|
+
# VolumeBone 클래스를 통해 새로운 볼륨 뼈대 생성
|
188
|
+
result = jal.volumeBone.create_bones(limb, limbParent, inVolumeSize=inNewSize,
|
189
|
+
inRotScale=rotScale, inRotAxises=rotAxises,
|
190
|
+
inTransAxises=transAxises, inTransScales=transScales)
|
191
|
+
|
192
|
+
# 속성들 한번에 업데이트
|
193
|
+
for key, value in result.items():
|
194
|
+
if hasattr(self, key):
|
195
|
+
setattr(self, key, value)
|
196
|
+
|
197
|
+
self.volumeSize = inNewSize
|
198
|
+
|
199
|
+
return True
|
200
|
+
except:
|
201
|
+
return False
|
202
|
+
|
203
|
+
def update_rot_axises(self, inNewRotAxises):
|
204
|
+
"""
|
205
|
+
볼륨 뼈대의 회전 축을 업데이트
|
206
|
+
|
207
|
+
Args:
|
208
|
+
inNewRotAxises: 새로운 회전 축 리스트
|
209
|
+
|
210
|
+
Returns:
|
211
|
+
업데이트 성공 여부 (boolean)
|
212
|
+
"""
|
213
|
+
if self.is_empty() or self.limb is None:
|
214
|
+
return False
|
215
|
+
|
216
|
+
try:
|
217
|
+
# 필요한 값들 백업
|
218
|
+
limb = self.limb
|
219
|
+
limbParent = self.limbParent
|
220
|
+
rotScale = self.rotScale
|
221
|
+
volumeSize = self.volumeSize
|
222
|
+
transAxises = copy.deepcopy(self.transAxises)
|
223
|
+
transScales = copy.deepcopy(self.transScales)
|
224
|
+
|
225
|
+
self.delete_all()
|
226
|
+
# VolumeBone 클래스를 통해 새로운 볼륨 뼈대 생성
|
227
|
+
result = jal.volumeBone.create_bones(limb, limbParent, inVolumeSize=volumeSize,
|
228
|
+
inRotScale=rotScale, inRotAxises=inNewRotAxises,
|
229
|
+
inTransAxises=transAxises, inTransScales=transScales)
|
230
|
+
|
231
|
+
# 속성들 한번에 업데이트
|
232
|
+
for key, value in result.items():
|
233
|
+
if hasattr(self, key):
|
234
|
+
setattr(self, key, value)
|
235
|
+
|
236
|
+
return True
|
237
|
+
except:
|
238
|
+
return False
|
239
|
+
|
240
|
+
def update_trans_axises(self, inNewTransAxises):
|
241
|
+
"""
|
242
|
+
볼륨 뼈대의 이동 축을 업데이트
|
243
|
+
|
244
|
+
Args:
|
245
|
+
inNewTransAxises: 새로운 이동 축 리스트
|
246
|
+
|
247
|
+
Returns:
|
248
|
+
업데이트 성공 여부 (boolean)
|
249
|
+
"""
|
250
|
+
if self.is_empty() or self.limb is None:
|
251
|
+
return False
|
252
|
+
|
253
|
+
try:
|
254
|
+
# 필요한 값들 백업
|
255
|
+
limb = self.limb
|
256
|
+
limbParent = self.limbParent
|
257
|
+
rotScale = self.rotScale
|
258
|
+
volumeSize = self.volumeSize
|
259
|
+
rotAxises = copy.deepcopy(self.rotAxises)
|
260
|
+
transScales = copy.deepcopy(self.transScales)
|
261
|
+
|
262
|
+
self.delete_all()
|
263
|
+
# VolumeBone 클래스를 통해 새로운 볼륨 뼈대 생성
|
264
|
+
result = jal.volumeBone.create_bones(limb, limbParent, inVolumeSize=volumeSize,
|
265
|
+
inRotScale=rotScale, inRotAxises=rotAxises,
|
266
|
+
inTransAxises=inNewTransAxises, inTransScales=transScales)
|
267
|
+
|
268
|
+
# 속성들 한번에 업데이트
|
269
|
+
for key, value in result.items():
|
270
|
+
if hasattr(self, key):
|
271
|
+
setattr(self, key, value)
|
272
|
+
|
273
|
+
return True
|
274
|
+
except:
|
275
|
+
return False
|
276
|
+
|
277
|
+
def update_trans_scales(self, inNewTransScales):
|
278
|
+
"""
|
279
|
+
볼륨 뼈대의 이동 스케일을 업데이트
|
280
|
+
|
281
|
+
Args:
|
282
|
+
inNewTransScales: 새로운 이동 스케일 리스트
|
283
|
+
|
284
|
+
Returns:
|
285
|
+
업데이트 성공 여부 (boolean)
|
286
|
+
"""
|
287
|
+
if self.is_empty() or self.limb is None:
|
288
|
+
return False
|
289
|
+
|
290
|
+
try:
|
291
|
+
# 필요한 값들 백업
|
292
|
+
limb = self.limb
|
293
|
+
limbParent = self.limbParent
|
294
|
+
rotScale = self.rotScale
|
295
|
+
volumeSize = self.volumeSize
|
296
|
+
rotAxises = copy.deepcopy(self.rotAxises)
|
297
|
+
transAxises = copy.deepcopy(self.transAxises)
|
298
|
+
|
299
|
+
self.delete_all()
|
300
|
+
# VolumeBone 클래스를 통해 새로운 볼륨 뼈대 생성
|
301
|
+
result = jal.volumeBone.create_bones(limb, limbParent, inVolumeSize=volumeSize,
|
302
|
+
inRotScale=rotScale, inRotAxises=rotAxises,
|
303
|
+
inTransAxises=transAxises, inTransScales=inNewTransScales)
|
304
|
+
|
305
|
+
# 속성들 한번에 업데이트
|
306
|
+
for key, value in result.items():
|
307
|
+
if hasattr(self, key):
|
308
|
+
setattr(self, key, value)
|
309
|
+
|
310
|
+
return True
|
311
|
+
except:
|
312
|
+
return False
|
313
|
+
|
314
|
+
def update_rot_scale(self, inNewRotScale):
|
315
|
+
"""
|
316
|
+
볼륨 뼈대의 회전 스케일을 업데이트
|
317
|
+
|
318
|
+
Args:
|
319
|
+
inNewRotScale: 새로운 회전 스케일 값
|
320
|
+
|
321
|
+
Returns:
|
322
|
+
업데이트 성공 여부 (boolean)
|
323
|
+
"""
|
324
|
+
if self.is_empty() or self.limb is None:
|
325
|
+
return False
|
326
|
+
|
327
|
+
try:
|
328
|
+
# 필요한 값들 백업
|
329
|
+
limb = self.limb
|
330
|
+
limbParent = self.limbParent
|
331
|
+
volumeSize = self.volumeSize
|
332
|
+
rotAxises = copy.deepcopy(self.rotAxises)
|
333
|
+
transAxises = copy.deepcopy(self.transAxises)
|
334
|
+
transScales = copy.deepcopy(self.transScales)
|
335
|
+
|
336
|
+
self.delete_all()
|
337
|
+
# VolumeBone 클래스를 통해 새로운 볼륨 뼈대 생성
|
338
|
+
result = jal.volumeBone.create_bones(limb, limbParent, inVolumeSize=volumeSize,
|
339
|
+
inRotScale=inNewRotScale, inRotAxises=rotAxises,
|
340
|
+
inTransAxises=transAxises, inTransScales=transScales)
|
341
|
+
|
342
|
+
# 속성들 한번에 업데이트
|
343
|
+
for key, value in result.items():
|
344
|
+
if hasattr(self, key):
|
345
|
+
setattr(self, key, value)
|
346
|
+
|
347
|
+
return True
|
348
|
+
except:
|
349
|
+
return False
|
350
|
+
|
351
|
+
@classmethod
|
352
|
+
def from_volume_bone_result(cls, inResult):
|
353
|
+
"""
|
354
|
+
VolumeBone 클래스의 결과로부터 VolumeBoneChain 인스턴스 생성
|
355
|
+
|
356
|
+
Args:
|
357
|
+
inResult: VolumeBone 클래스의 메서드가 반환한 결과 딕셔너리
|
358
|
+
|
359
|
+
Returns:
|
360
|
+
VolumeBoneChain 인스턴스
|
361
|
+
"""
|
362
|
+
chain = cls(inResult)
|
363
|
+
return chain
|
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
|
@@ -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
|
|
@@ -0,0 +1,46 @@
|
|
1
|
+
pyjallib/__init__.py,sha256=pix9ja-vl7MYU3dJ4pgQicVCVwd1SyiQxD-BgWPILY8,461
|
2
|
+
pyjallib/namePart.py,sha256=lKIiOVkWrtAW-D3nuv--vHmdAnlQeVPaXLYUDhcr8QU,24177
|
3
|
+
pyjallib/nameToPath.py,sha256=aBeezepLYdpv3VYxnQ2c4ZWzz2WjticXjkdbAIlVa1k,4676
|
4
|
+
pyjallib/naming.py,sha256=gJcD4wLAySFExlLiVQzF-amCbFbUnOwmxoio8Eyfrbw,36756
|
5
|
+
pyjallib/namingConfig.py,sha256=3w8Xjs_HR3R0K25eySivJn58N9MZwfpk80ySZYVI7Qw,34005
|
6
|
+
pyjallib/perforce.py,sha256=K_FAeDvecdaMT4INUcDluSB6k2NQ8R1NaddTzqLu-q0,24211
|
7
|
+
pyjallib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
|
+
pyjallib/reloadModules.py,sha256=RAEG3IxzJ0TlsjvnZwJt56JOkc2j8voqAnRbfQuZ44g,1151
|
9
|
+
pyjallib/ConfigFiles/namingConfig.json,sha256=Ov4bbVJb6qodPaooU63e11YUMGXXPWFAA4AQq1sLBYU,1486
|
10
|
+
pyjallib/max/__init__.py,sha256=Zh3ZZD1ELmS1zFALW47OYlgdhBdZ7b1C_bCrN7vTuIw,1403
|
11
|
+
pyjallib/max/align.py,sha256=HKjCViQCuicGmtvHB6xxVv4BEGEBGtV2gO3NvR_6R2A,5183
|
12
|
+
pyjallib/max/anim.py,sha256=QTpR8T047IMpV40wnMMNo080wY9rHMV9k7ISrh4P61I,26083
|
13
|
+
pyjallib/max/autoClavicle.py,sha256=9Y-ytNP5Wv40JX1Cvm_13oAhfyug_uCpafAdcX1U2bk,8178
|
14
|
+
pyjallib/max/autoClavicleChain.py,sha256=fjBpd4ads148bRBxkXfG5auC4x2Ec198yk-Wpv9V3Js,5098
|
15
|
+
pyjallib/max/bip.py,sha256=wT1Lg_j2BVoLtRqVN3Rhm5WHj-_OHK_3hcl8PYjy8RY,27117
|
16
|
+
pyjallib/max/bone.py,sha256=JgwnnWSbTa77ml4-CNtQkdROCgBUlNBkInD7g5WJgVI,48579
|
17
|
+
pyjallib/max/constraint.py,sha256=93g-X0aZHtZMKXVKr8xMjIhbKou61yc2b3ubQKJquBs,40589
|
18
|
+
pyjallib/max/groinBone.py,sha256=4MvLkXFfdMioyFr4jOMemR26IxNyHtEHOpYRvbsNx9k,7386
|
19
|
+
pyjallib/max/groinBoneChain.py,sha256=E75yHfvse3QJ-Yo__OUBox_dbv_j-bOSzxr_FwetDZA,5604
|
20
|
+
pyjallib/max/header.py,sha256=nuNCVfm5bfYMS0KxB8IRR67D30CXXHRUXHfFYkLG0jU,4120
|
21
|
+
pyjallib/max/helper.py,sha256=Na3jFRwLsjHh4rz0Tk_r_CwHQxOA6n8LhDRA9x5xcSk,18018
|
22
|
+
pyjallib/max/hip.py,sha256=7Mw2Fu_vgWkdm-5m8KoRXDOmphK8apiOiBQQQV1u2KU,11144
|
23
|
+
pyjallib/max/kneeBone.py,sha256=BPob7KL62_B0_ErHIGkVa-DkBMHau_-dhmBHSQgeWkY,22832
|
24
|
+
pyjallib/max/layer.py,sha256=e9Mn8h7xf0oBYST3QIpyBpLMl8qpWTExO9Y6yH6rKc0,8795
|
25
|
+
pyjallib/max/link.py,sha256=J3z9nkP8ZxAh9yYhR16tjQFCJTCYZMSB0MGbSHfA7uI,2592
|
26
|
+
pyjallib/max/mirror.py,sha256=TcbfZXSk-VJQstNqAmD6VGCqYBF9bMuJtFTg-6SiGdQ,14505
|
27
|
+
pyjallib/max/morph.py,sha256=I8HRYx4NznL6GZL4CbT9iTv05SeaBW_mJJ4PzMxCBkw,12664
|
28
|
+
pyjallib/max/name.py,sha256=DcJt2td-N7vfUGyWazdGTD4-0JW-noa7z5nwc6SHm6I,15337
|
29
|
+
pyjallib/max/select.py,sha256=HMJD2WNX3zVBEeYrj0UX2YXM3fHNItfw6UtQSItNsoU,9487
|
30
|
+
pyjallib/max/skin.py,sha256=5mBzG2wSUxoGlkFeb9Ys8uUxOwuZRGeqUMTI9LiWWZU,41937
|
31
|
+
pyjallib/max/twistBone.py,sha256=RnyqXVq4LQRqk-QxaB_gKBkJ9ih5A0c8yvbErpOFGeE,16275
|
32
|
+
pyjallib/max/twistBoneChain.py,sha256=A0F-43SbB-qdjo6U5TcenXapHcGIc4gxatxKiWnNv7M,5503
|
33
|
+
pyjallib/max/volumeBone.py,sha256=fCFJ8YTrjhLkZdpkEekT45VN17DtTJngzJT5uHYZVno,12336
|
34
|
+
pyjallib/max/volumeBoneChain.py,sha256=bS6OwPDSCk0Wrm0Hv9OZ9uGdygikMs98Z-S1koAGrKQ,13481
|
35
|
+
pyjallib/max/ConfigFiles/3DSMaxNamingConfig.json,sha256=PBUYawCELG0aLNRdTh6j-Yka4eNdmpF4P8iRyp0Ngpg,3717
|
36
|
+
pyjallib/max/ConfigFiles/Default_3DSMaxNamingConfig.json,sha256=PBUYawCELG0aLNRdTh6j-Yka4eNdmpF4P8iRyp0Ngpg,3717
|
37
|
+
pyjallib/max/macro/jal_macro_align.py,sha256=_Iqwskz0i4AVlP_AhDrqHwhLml6zoDWkVAxPF3AKqEQ,4286
|
38
|
+
pyjallib/max/macro/jal_macro_bone.py,sha256=I3MYM7fk-_LQonORRD0hJoip0TAk0suS-xDBamhySPQ,12422
|
39
|
+
pyjallib/max/macro/jal_macro_constraint.py,sha256=jJnNHCjsFJNYRqaBEPjzW-dnCDJT6JRZXH7dqBPkeiw,4160
|
40
|
+
pyjallib/max/macro/jal_macro_helper.py,sha256=hd8e5x56aq7Qt0g-hP5bY0p-njVy8ja77_qMPZyvDag,12906
|
41
|
+
pyjallib/max/macro/jal_macro_link.py,sha256=E8i3z2xsrQiGDEz4Qoxc75hkpalzS95mOMcIic0J-Fc,1193
|
42
|
+
pyjallib/max/macro/jal_macro_select.py,sha256=jeSFR_mqqudTTrZE1rU6qifJ4g441cYxXWcHPTWh1CU,2289
|
43
|
+
pyjallib/max/ui/Container.py,sha256=QSk3oCqhfiR4aglSSkherRGAyPFqMRUt83L-0ENBz-s,5571
|
44
|
+
pyjallib-0.1.10.dist-info/METADATA,sha256=WRIWnsOSWqSf4NdHVw8RkNAqb6uPE-N78eFUD67q8fQ,870
|
45
|
+
pyjallib-0.1.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
46
|
+
pyjallib-0.1.10.dist-info/RECORD,,
|