pyjallib 0.1.0__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/max/name.py ADDED
@@ -0,0 +1,521 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ 3ds Max용 이름 처리 모듈
6
+ 3ds Max에 특화된 네이밍 기능 (pymxs 의존)
7
+ """
8
+
9
+ from pymxs import runtime as rt
10
+ from pyjallib.naming import Naming
11
+ from pyjallib.namePart import NamePart, NamePartType
12
+
13
+ class Name(Naming):
14
+ """
15
+ 3ds Max 노드 이름 관리를 위한 클래스
16
+ Naming 클래스를 상속받으며, Max 특화 기능 제공
17
+ """
18
+
19
+ def __init__(self, configPath=None):
20
+ """
21
+ 클래스 초기화
22
+
23
+ Args:
24
+ configPath: 설정 파일 경로 (기본값: None)
25
+ 설정 파일이 제공되면 해당 파일에서 설정을 로드함
26
+ """
27
+ # 기본 설정값
28
+ self._paddingNum = 2
29
+ self._configPath = configPath
30
+
31
+ # 기본 namePart 초기화 (각 부분에 사전 정의 값 직접 설정)
32
+ self._nameParts = []
33
+
34
+ if configPath:
35
+ # 사용자가 지정한 설정 파일 사용
36
+ self.load_from_config_file(configPath=configPath)
37
+ else:
38
+ # 설정 파일이 없는 경우, 기본 설정값으로 초기화
39
+ # Base 부분 (PREFIX 타입)
40
+ basePart = NamePart("Base", NamePartType.PREFIX,
41
+ ["b", "Bip001"],
42
+ ["SkinBone", "Biped"])
43
+ # Type 부분 (PREFIX 타입)
44
+ typePart = NamePart("Type", NamePartType.PREFIX,
45
+ ["P", "Dum", "Exp", "IK", "T"],
46
+ ["Parent", "Dummy", "ExposeTM", "IK", "Target"])
47
+ # Side 부분 (PREFIX 타입)
48
+ sidePart = NamePart("Side", NamePartType.PREFIX,
49
+ ["L", "R"],
50
+ ["Left", "Right"],
51
+ True)
52
+ # FrontBack 부분 (PREFIX 타입)
53
+ frontBackPart = NamePart("FrontBack", NamePartType.PREFIX,
54
+ ["F", "B"],
55
+ ["Front", "Back"],
56
+ True)
57
+ # RealName 부분 (REALNAME 타입)
58
+ realNamePart = NamePart("RealName", NamePartType.REALNAME, [], [])
59
+ # Index 부분 (INDEX 타입)
60
+ indexPart = NamePart("Index", NamePartType.INDEX, [], [])
61
+ # Nub 부분 (SUFFIX 타입)
62
+ nubPart = NamePart("Nub", NamePartType.SUFFIX,
63
+ ["Nub"],
64
+ ["Nub"])
65
+ # 기본 순서대로 설정
66
+ self._nameParts = [basePart, typePart, sidePart, frontBackPart, realNamePart, indexPart, nubPart]
67
+
68
+ # NamePart 직접 액세스 메소드들
69
+ # get_<NamePart 이름>_values 메소드들
70
+ def get_Base_values(self):
71
+ """
72
+ Base 부분의 사전 정의 값 목록 반환
73
+
74
+ Returns:
75
+ Base 부분의 사전 정의 값 목록
76
+ """
77
+ return self.get_name_part_predefined_values("Base")
78
+
79
+ def get_Type_values(self):
80
+ """
81
+ Type 부분의 사전 정의 값 목록 반환
82
+
83
+ Returns:
84
+ Type 부분의 사전 정의 값 목록
85
+ """
86
+ return self.get_name_part_predefined_values("Type")
87
+
88
+ def get_Side_values(self):
89
+ """
90
+ Side 부분의 사전 정의 값 목록 반환
91
+
92
+ Returns:
93
+ Side 부분의 사전 정의 값 목록
94
+ """
95
+ return self.get_name_part_predefined_values("Side")
96
+
97
+ def get_FrontBack_values(self):
98
+ """
99
+ FrontBack 부분의 사전 정의 값 목록 반환
100
+
101
+ Returns:
102
+ FrontBack 부분의 사전 정의 값 목록
103
+ """
104
+ return self.get_name_part_predefined_values("FrontBack")
105
+
106
+ def get_Nub_values(self):
107
+ """
108
+ Nub 부분의 사전 정의 값 목록 반환
109
+
110
+ Returns:
111
+ Nub 부분의 사전 정의 값 목록
112
+ """
113
+ return self.get_name_part_predefined_values("Nub")
114
+
115
+ # is_<NamePart 이름> 메소드들
116
+ def is_Base(self, inStr):
117
+ """
118
+ 문자열이 Base 부분의 사전 정의 값인지 확인
119
+
120
+ Args:
121
+ inStr: 확인할 문자열
122
+
123
+ Returns:
124
+ Base 부분의 사전 정의 값이면 True, 아니면 False
125
+ """
126
+ return self.is_in_name_part_predefined_values("Base", inStr)
127
+
128
+ def is_Type(self, inStr):
129
+ """
130
+ 문자열이 Type 부분의 사전 정의 값인지 확인
131
+
132
+ Args:
133
+ inStr: 확인할 문자열
134
+
135
+ Returns:
136
+ Type 부분의 사전 정의 값이면 True, 아니면 False
137
+ """
138
+ return self.is_in_name_part_predefined_values("Type", inStr)
139
+
140
+ def is_Side(self, inStr):
141
+ """
142
+ 문자열이 Side 부분의 사전 정의 값인지 확인
143
+
144
+ Args:
145
+ inStr: 확인할 문자열
146
+
147
+ Returns:
148
+ Side 부분의 사전 정의 값이면 True, 아니면 False
149
+ """
150
+ return self.is_in_name_part_predefined_values("Side", inStr)
151
+
152
+ def is_FrontBack(self, inStr):
153
+ """
154
+ 문자열이 FrontBack 부분의 사전 정의 값인지 확인
155
+
156
+ Args:
157
+ inStr: 확인할 문자열
158
+
159
+ Returns:
160
+ FrontBack 부분의 사전 정의 값이면 True, 아니면 False
161
+ """
162
+ return self.is_in_name_part_predefined_values("FrontBack", inStr)
163
+
164
+ def is_Nub(self, inStr):
165
+ """
166
+ 문자열이 Nub 부분의 사전 정의 값인지 확인
167
+
168
+ Args:
169
+ inStr: 확인할 문자열
170
+
171
+ Returns:
172
+ Nub 부분의 사전 정의 값이면 True, 아니면 False
173
+ """
174
+ return self.is_in_name_part_predefined_values("Nub", inStr)
175
+
176
+ # has_<NamePart 이름> 메소드들
177
+ def has_Base(self, inStr):
178
+ """
179
+ 문자열에 Base 부분의 사전 정의 값이 포함되어 있는지 확인
180
+
181
+ Args:
182
+ inStr: 확인할 문자열
183
+
184
+ Returns:
185
+ Base 부분의 사전 정의 값이 포함되어 있으면 True, 아니면 False
186
+ """
187
+ return self.has_name_part("Base", inStr)
188
+
189
+ def has_Type(self, inStr):
190
+ """
191
+ 문자열에 Type 부분의 사전 정의 값이 포함되어 있는지 확인
192
+
193
+ Args:
194
+ inStr: 확인할 문자열
195
+
196
+ Returns:
197
+ Type 부분의 사전 정의 값이 포함되어 있으면 True, 아니면 False
198
+ """
199
+ return self.has_name_part("Type", inStr)
200
+
201
+ def has_Side(self, inStr):
202
+ """
203
+ 문자열에 Side 부분의 사전 정의 값이 포함되어 있는지 확인
204
+
205
+ Args:
206
+ inStr: 확인할 문자열
207
+
208
+ Returns:
209
+ Side 부분의 사전 정의 값이 포함되어 있으면 True, 아니면 False
210
+ """
211
+ return self.has_name_part("Side", inStr)
212
+
213
+ def has_FrontBack(self, inStr):
214
+ """
215
+ 문자열에 FrontBack 부분의 사전 정의 값이 포함되어 있는지 확인
216
+
217
+ Args:
218
+ inStr: 확인할 문자열
219
+
220
+ Returns:
221
+ FrontBack 부분의 사전 정의 값이 포함되어 있으면 True, 아니면 False
222
+ """
223
+ return self.has_name_part("FrontBack", inStr)
224
+
225
+ def has_Nub(self, inStr):
226
+ """
227
+ 문자열에 Nub 부분의 사전 정의 값이 포함되어 있는지 확인
228
+
229
+ Args:
230
+ inStr: 확인할 문자열
231
+
232
+ Returns:
233
+ Nub 부분의 사전 정의 값이 포함되어 있으면 True, 아니면 False
234
+ """
235
+ return self.has_name_part("Nub", inStr)
236
+
237
+ # replace_<NamePart 이름> 메소드들
238
+ def replace_Base(self, inStr, inNewName):
239
+ """
240
+ 문자열의 Base 부분을 새 이름으로 변경
241
+
242
+ Args:
243
+ inStr: 처리할 문자열
244
+ inNewName: 새 이름
245
+
246
+ Returns:
247
+ 변경된 문자열
248
+ """
249
+ return self.replace_name_part("Base", inStr, inNewName)
250
+
251
+ def replace_Type(self, inStr, inNewName):
252
+ """
253
+ 문자열의 Type 부분을 새 이름으로 변경
254
+
255
+ Args:
256
+ inStr: 처리할 문자열
257
+ inNewName: 새 이름
258
+
259
+ Returns:
260
+ 변경된 문자열
261
+ """
262
+ return self.replace_name_part("Type", inStr, inNewName)
263
+
264
+ def replace_Side(self, inStr, inNewName):
265
+ """
266
+ 문자열의 Side 부분을 새 이름으로 변경
267
+
268
+ Args:
269
+ inStr: 처리할 문자열
270
+ inNewName: 새 이름
271
+
272
+ Returns:
273
+ 변경된 문자열
274
+ """
275
+ return self.replace_name_part("Side", inStr, inNewName)
276
+
277
+ def replace_FrontBack(self, inStr, inNewName):
278
+ """
279
+ 문자열의 FrontBack 부분을 새 이름으로 변경
280
+
281
+ Args:
282
+ inStr: 처리할 문자열
283
+ inNewName: 새 이름
284
+
285
+ Returns:
286
+ 변경된 문자열
287
+ """
288
+ return self.replace_name_part("FrontBack", inStr, inNewName)
289
+
290
+ def replace_RealName(self, inStr, inNewName):
291
+ """
292
+ 문자열의 RealName 부분을 새 이름으로 변경
293
+
294
+ Args:
295
+ inStr: 처리할 문자열
296
+ inNewName: 새 이름
297
+
298
+ Returns:
299
+ 변경된 문자열
300
+ """
301
+ return self.replace_name_part("RealName", inStr, inNewName)
302
+
303
+ def replace_Index(self, inStr, inNewName):
304
+ """
305
+ 문자열의 Index 부분을 새 이름으로 변경
306
+
307
+ Args:
308
+ inStr: 처리할 문자열
309
+ inNewName: 새 이름 (숫자 문자열)
310
+
311
+ Returns:
312
+ 변경된 문자열
313
+ """
314
+ return self.replace_name_part("Index", inStr, inNewName)
315
+
316
+ def replace_Nub(self, inStr, inNewName):
317
+ """
318
+ 문자열의 Nub 부분을 새 이름으로 변경
319
+
320
+ Args:
321
+ inStr: 처리할 문자열
322
+ inNewName: 새 이름
323
+
324
+ Returns:
325
+ 변경된 문자열
326
+ """
327
+ return self.replace_name_part("Nub", inStr, inNewName)
328
+
329
+ # remove_<NamePart 이름> 메소드들
330
+ def remove_Base(self, inStr):
331
+ """
332
+ 문자열에서 Base 부분 제거
333
+
334
+ Args:
335
+ inStr: 처리할 문자열
336
+
337
+ Returns:
338
+ Base 부분이 제거된 문자열
339
+ """
340
+ return self.remove_name_part("Base", inStr)
341
+
342
+ def remove_Type(self, inStr):
343
+ """
344
+ 문자열에서 Type 부분 제거
345
+
346
+ Args:
347
+ inStr: 처리할 문자열
348
+
349
+ Returns:
350
+ Type 부분이 제거된 문자열
351
+ """
352
+ return self.remove_name_part("Type", inStr)
353
+
354
+ def remove_Side(self, inStr):
355
+ """
356
+ 문자열에서 Side 부분 제거
357
+
358
+ Args:
359
+ inStr: 처리할 문자열
360
+
361
+ Returns:
362
+ Side 부분이 제거된 문자열
363
+ """
364
+ return self.remove_name_part("Side", inStr)
365
+
366
+ def remove_FrontBack(self, inStr):
367
+ """
368
+ 문자열에서 FrontBack 부분 제거
369
+
370
+ Args:
371
+ inStr: 처리할 문자열
372
+
373
+ Returns:
374
+ FrontBack 부분이 제거된 문자열
375
+ """
376
+ return self.remove_name_part("FrontBack", inStr)
377
+
378
+ def remove_Index(self, inStr):
379
+ """
380
+ 문자열에서 Index 부분 제거
381
+
382
+ Args:
383
+ inStr: 처리할 문자열
384
+
385
+ Returns:
386
+ Index 부분이 제거된 문자열
387
+ """
388
+ return self.remove_name_part("Index", inStr)
389
+
390
+ def remove_Nub(self, inStr):
391
+ """
392
+ 문자열에서 Nub 부분 제거
393
+
394
+ Args:
395
+ inStr: 처리할 문자열
396
+
397
+ Returns:
398
+ Nub 부분이 제거된 문자열
399
+ """
400
+ return self.remove_name_part("Nub", inStr)
401
+
402
+ # pymxs 의존적인 메소드 구현
403
+
404
+ def gen_unique_name(self, inStr):
405
+ """
406
+ 고유한 이름 생성
407
+
408
+ Args:
409
+ inStr: 기준 이름 문자열
410
+
411
+ Returns:
412
+ 고유한 이름 문자열
413
+ """
414
+ pattern_str = self.replace_Index(inStr, "*")
415
+
416
+ # pymxs를 사용하여 객체 이름을 패턴과 매칭하여 검색
417
+ matched_objects = []
418
+
419
+ # 모든 객체 중에서 패턴과 일치하는 이름 찾기
420
+ for obj in rt.objects:
421
+ if rt.matchPattern(obj.name, pattern=pattern_str):
422
+ matched_objects.append(obj)
423
+
424
+ return self.replace_Index(inStr, str(len(matched_objects) + 1))
425
+
426
+ def compare_name(self, inObjA, inObjB):
427
+ """
428
+ 두 객체의 이름 비교 (정렬용)
429
+
430
+ Args:
431
+ inObjA: 첫 번째 객체
432
+ inObjB: 두 번째 객체
433
+
434
+ Returns:
435
+ 비교 결과 (inObjA.name < inObjB.name: 음수, inObjA.name == inObjB.name: 0, inObjA.name > inObjB.name: 양수)
436
+ """
437
+ # Python에서는 대소문자 구분 없는 비교를 위해 lower() 사용
438
+ return 1 if inObjA.name.lower() > inObjB.name.lower() else -1 if inObjA.name.lower() < inObjB.name.lower() else 0
439
+
440
+ def sort_by_name(self, inArray):
441
+ """
442
+ 객체 배열을 이름 기준으로 정렬
443
+
444
+ Args:
445
+ inArray: 정렬할 객체 배열
446
+
447
+ Returns:
448
+ 이름 기준으로 정렬된 객체 배열
449
+ """
450
+ # Python의 sorted 함수와 key를 사용하여 이름 기준 정렬
451
+ return sorted(inArray, key=lambda obj: obj.name.lower())
452
+
453
+ def gen_mirroring_name(self, inStr):
454
+ """
455
+ 미러링된 이름 생성 (측면 또는 앞/뒤 변경)
456
+
457
+ 이름에서 Side와 FrontBack namePart를 자동으로 검색하고,
458
+ 발견된 값의 semanticmapping weight와 가장 차이가 큰 값으로 교체합니다.
459
+
460
+ Args:
461
+ inStr: 처리할 이름 문자열
462
+
463
+ Returns:
464
+ 미러링된 이름 문자열
465
+ """
466
+ return_name = super().gen_mirroring_name(inStr)
467
+
468
+ # 이름이 변경되지 않았다면 고유한 이름 생성
469
+ if return_name == inStr:
470
+ if self.has_Side(inStr) or self.has_FrontBack(inStr):
471
+ return_name = self.gen_unique_name(inStr)
472
+ else:
473
+ return_name = self.add_suffix_to_real_name(inStr, "Mirrored")
474
+
475
+ return return_name
476
+
477
+ # Type name Part에서 Description으로 지정된 predefined value를 가져오는 메소드들
478
+ def get_parent_value(self):
479
+ """
480
+ 부모 이름 문자열 반환
481
+
482
+ Returns:
483
+ 부모 이름 문자열
484
+ """
485
+ return self.get_name_part_value_by_description("Type", "Parent")
486
+
487
+ def get_dummy_value(self):
488
+ """
489
+ 더미 이름 문자열 반환
490
+
491
+ Returns:
492
+ 더미 이름 문자열
493
+ """
494
+ return self.get_name_part_value_by_description("Type", "Dummy")
495
+
496
+ def get_exposeTm_value(self):
497
+ """
498
+ ExposeTm 이름 문자열 반환
499
+
500
+ Returns:
501
+ ExposeTm 이름 문자열
502
+ """
503
+ return self.get_name_part_value_by_description("Type", "ExposeTM")
504
+
505
+ def get_ik_value(self):
506
+ """
507
+ IK 이름 문자열 반환
508
+
509
+ Returns:
510
+ IK 이름 문자열
511
+ """
512
+ return self.get_name_part_value_by_description("Type", "IK")
513
+
514
+ def get_target_value(self):
515
+ """
516
+ 타겟 이름 문자열 반환
517
+
518
+ Returns:
519
+ 타겟 이름 문자열
520
+ """
521
+ return self.get_name_part_value_by_description("Type", "Target")