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/__init__.py +17 -0
- pyjallib/max/__init__.py +46 -0
- pyjallib/max/align.py +112 -0
- pyjallib/max/anim.py +594 -0
- pyjallib/max/bip.py +508 -0
- pyjallib/max/bone.py +910 -0
- pyjallib/max/constraint.py +973 -0
- pyjallib/max/header.py +57 -0
- pyjallib/max/helper.py +433 -0
- pyjallib/max/layer.py +262 -0
- pyjallib/max/link.py +78 -0
- pyjallib/max/macro/jal_macro_align.py +155 -0
- pyjallib/max/macro/jal_macro_bone.py +358 -0
- pyjallib/max/macro/jal_macro_constraint.py +140 -0
- pyjallib/max/macro/jal_macro_helper.py +321 -0
- pyjallib/max/macro/jal_macro_link.py +55 -0
- pyjallib/max/macro/jal_macro_select.py +91 -0
- pyjallib/max/mirror.py +388 -0
- pyjallib/max/name.py +521 -0
- pyjallib/max/select.py +278 -0
- pyjallib/max/skin.py +996 -0
- pyjallib/max/twistBone.py +418 -0
- pyjallib/namePart.py +633 -0
- pyjallib/nameToPath.py +113 -0
- pyjallib/naming.py +1066 -0
- pyjallib/namingConfig.py +844 -0
- pyjallib/perforce.py +735 -0
- pyjallib/reloadModules.py +33 -0
- pyjallib-0.1.0.dist-info/METADATA +28 -0
- pyjallib-0.1.0.dist-info/RECORD +32 -0
- pyjallib-0.1.0.dist-info/WHEEL +5 -0
- pyjallib-0.1.0.dist-info/top_level.txt +1 -0
pyjallib/max/select.py
ADDED
@@ -0,0 +1,278 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
"""
|
5
|
+
선택 모듈 - 3ds Max용 객체 선택 관련 기능 제공
|
6
|
+
원본 MAXScript의 select.ms를 Python으로 변환하였으며, pymxs 모듈 기반으로 구현됨
|
7
|
+
"""
|
8
|
+
|
9
|
+
from pymxs import runtime as rt
|
10
|
+
|
11
|
+
# Import necessary service classes for default initialization
|
12
|
+
from .name import Name
|
13
|
+
from .bone import Bone
|
14
|
+
|
15
|
+
|
16
|
+
class Select:
|
17
|
+
"""
|
18
|
+
객체 선택 관련 기능을 제공하는 클래스.
|
19
|
+
MAXScript의 _Select 구조체 개념을 Python으로 재구현한 클래스이며,
|
20
|
+
3ds Max의 기능들을 pymxs API를 통해 제어합니다.
|
21
|
+
"""
|
22
|
+
|
23
|
+
def __init__(self, nameService=None, boneService=None):
|
24
|
+
"""
|
25
|
+
클래스 초기화
|
26
|
+
|
27
|
+
Args:
|
28
|
+
nameService: Name 서비스 인스턴스 (제공되지 않으면 새로 생성)
|
29
|
+
boneService: Bone 서비스 인스턴스 (제공되지 않으면 새로 생성)
|
30
|
+
"""
|
31
|
+
self.name = nameService if nameService else Name()
|
32
|
+
self.bone = boneService if boneService else Bone(nameService=self.name) # Pass the potentially newly created nameService
|
33
|
+
|
34
|
+
def set_selectionSet_to_all(self):
|
35
|
+
"""
|
36
|
+
모든 유형의 객체를 선택하도록 필터 설정
|
37
|
+
"""
|
38
|
+
rt.SetSelectFilter(1)
|
39
|
+
|
40
|
+
def set_selectionSet_to_bone(self):
|
41
|
+
"""
|
42
|
+
뼈대 객체만 선택하도록 필터 설정
|
43
|
+
"""
|
44
|
+
rt.SetSelectFilter(8)
|
45
|
+
|
46
|
+
def reset_selectionSet(self):
|
47
|
+
"""
|
48
|
+
선택 필터를 기본값으로 재설정
|
49
|
+
"""
|
50
|
+
rt.SetSelectFilter(1)
|
51
|
+
|
52
|
+
def set_selectionSet_to_helper(self):
|
53
|
+
"""
|
54
|
+
헬퍼 객체만 선택하도록 필터 설정
|
55
|
+
"""
|
56
|
+
rt.SetSelectFilter(6)
|
57
|
+
|
58
|
+
def set_selectionSet_to_point(self):
|
59
|
+
"""
|
60
|
+
포인트 객체만 선택하도록 필터 설정
|
61
|
+
"""
|
62
|
+
rt.SetSelectFilter(10)
|
63
|
+
|
64
|
+
def set_selectionSet_to_spline(self):
|
65
|
+
"""
|
66
|
+
스플라인 객체만 선택하도록 필터 설정
|
67
|
+
"""
|
68
|
+
rt.SetSelectFilter(3)
|
69
|
+
|
70
|
+
def set_selectionSet_to_mesh(self):
|
71
|
+
"""
|
72
|
+
메시 객체만 선택하도록 필터 설정
|
73
|
+
"""
|
74
|
+
rt.SetSelectFilter(2)
|
75
|
+
|
76
|
+
def filter_bip(self):
|
77
|
+
"""
|
78
|
+
현재 선택 항목에서 Biped 객체만 필터링하여 선택
|
79
|
+
"""
|
80
|
+
sel_array = rt.getCurrentSelection()
|
81
|
+
if len(sel_array) > 0:
|
82
|
+
filtered_sel = [item for item in sel_array if rt.classOf(item) == rt.Biped_Object]
|
83
|
+
rt.clearSelection()
|
84
|
+
rt.select(filtered_sel)
|
85
|
+
|
86
|
+
def filter_bone(self):
|
87
|
+
"""
|
88
|
+
현재 선택 항목에서 뼈대 객체만 필터링하여 선택
|
89
|
+
"""
|
90
|
+
sel_array = rt.getCurrentSelection()
|
91
|
+
if len(sel_array) > 0:
|
92
|
+
filtered_sel = [item for item in sel_array if rt.classOf(item) == rt.BoneGeometry]
|
93
|
+
rt.clearSelection()
|
94
|
+
rt.select(filtered_sel)
|
95
|
+
|
96
|
+
def filter_helper(self):
|
97
|
+
"""
|
98
|
+
현재 선택 항목에서 헬퍼 객체(Point, IK_Chain)만 필터링하여 선택
|
99
|
+
"""
|
100
|
+
sel_array = rt.getCurrentSelection()
|
101
|
+
if len(sel_array) > 0:
|
102
|
+
filtered_sel = [item for item in sel_array if rt.classOf(item) == rt.Point or rt.classOf(item) == rt.IK_Chain_Object]
|
103
|
+
rt.clearSelection()
|
104
|
+
rt.select(filtered_sel)
|
105
|
+
|
106
|
+
def filter_expTm(self):
|
107
|
+
"""
|
108
|
+
현재 선택 항목에서 ExposeTm 객체만 필터링하여 선택
|
109
|
+
"""
|
110
|
+
sel_array = rt.getCurrentSelection()
|
111
|
+
if len(sel_array) > 0:
|
112
|
+
filtered_sel = [item for item in sel_array if rt.classOf(item) == rt.ExposeTm]
|
113
|
+
rt.clearSelection()
|
114
|
+
rt.select(filtered_sel)
|
115
|
+
|
116
|
+
def filter_spline(self):
|
117
|
+
"""
|
118
|
+
현재 선택 항목에서 스플라인 객체만 필터링하여 선택
|
119
|
+
"""
|
120
|
+
sel_array = rt.getCurrentSelection()
|
121
|
+
if len(sel_array) > 0:
|
122
|
+
filtered_sel = [item for item in sel_array if rt.superClassOf(item) == rt.shape]
|
123
|
+
rt.clearSelection()
|
124
|
+
rt.select(filtered_sel)
|
125
|
+
|
126
|
+
def select_children(self, inObj, includeSelf=False):
|
127
|
+
"""
|
128
|
+
객체의 모든 자식을 선택
|
129
|
+
|
130
|
+
Args:
|
131
|
+
in_obj: 부모 객체
|
132
|
+
include_self: 자신도 포함할지 여부 (기본값: False)
|
133
|
+
|
134
|
+
Returns:
|
135
|
+
선택된 자식 객체 리스트
|
136
|
+
"""
|
137
|
+
children = self.bone.select_every_children(inObj=inObj, includeSelf=includeSelf)
|
138
|
+
|
139
|
+
return children
|
140
|
+
|
141
|
+
def distinguish_hierachy_objects(self, inArray):
|
142
|
+
"""
|
143
|
+
계층이 있는 객체와 없는 객체 구분
|
144
|
+
|
145
|
+
Args:
|
146
|
+
inArray: 검사할 객체 배열
|
147
|
+
|
148
|
+
Returns:
|
149
|
+
[계층이 없는 객체 배열, 계층이 있는 객체 배열]
|
150
|
+
"""
|
151
|
+
return_array = [[], []] # 첫 번째는 독립 객체, 두 번째는 계층 객체
|
152
|
+
|
153
|
+
for item in inArray:
|
154
|
+
if item.parent is None and item.children.count == 0:
|
155
|
+
return_array[0].append(item) # 부모와 자식이 없는 경우
|
156
|
+
else:
|
157
|
+
return_array[1].append(item) # 부모나 자식이 있는 경우
|
158
|
+
|
159
|
+
return return_array
|
160
|
+
|
161
|
+
def get_nonLinked_objects(self, inArray):
|
162
|
+
"""
|
163
|
+
링크(계층구조)가 없는 독립 객체만 반환
|
164
|
+
|
165
|
+
Args:
|
166
|
+
inArray: 검사할 객체 배열
|
167
|
+
|
168
|
+
Returns:
|
169
|
+
독립적인 객체 배열
|
170
|
+
"""
|
171
|
+
return self.distinguish_hierachy_objects(inArray)[0]
|
172
|
+
|
173
|
+
def get_linked_objects(self, inArray):
|
174
|
+
"""
|
175
|
+
링크(계층구조)가 있는 객체만 반환
|
176
|
+
|
177
|
+
Args:
|
178
|
+
inArray: 검사할 객체 배열
|
179
|
+
|
180
|
+
Returns:
|
181
|
+
계층 구조를 가진 객체 배열
|
182
|
+
"""
|
183
|
+
return self.distinguish_hierachy_objects(inArray)[1]
|
184
|
+
|
185
|
+
def sort_by_hierachy(self, inArray):
|
186
|
+
"""
|
187
|
+
객체를 계층 구조에 따라 정렬
|
188
|
+
|
189
|
+
Args:
|
190
|
+
inArray: 정렬할 객체 배열
|
191
|
+
|
192
|
+
Returns:
|
193
|
+
계층 순서대로 정렬된 객체 배열
|
194
|
+
"""
|
195
|
+
return self.bone.sort_bones_as_hierarchy(inArray)
|
196
|
+
|
197
|
+
def sort_by_index(self, inArray):
|
198
|
+
"""
|
199
|
+
객체를 이름에 포함된 인덱스 번호에 따라 정렬
|
200
|
+
|
201
|
+
Args:
|
202
|
+
inArray: 정렬할 객체 배열
|
203
|
+
|
204
|
+
Returns:
|
205
|
+
인덱스 순서대로 정렬된 객체 배열
|
206
|
+
"""
|
207
|
+
if len(inArray) == 0:
|
208
|
+
return []
|
209
|
+
|
210
|
+
nameArray = [item.name for item in inArray]
|
211
|
+
sortedNameArray = self.name.sort_by_index(nameArray)
|
212
|
+
|
213
|
+
sortedArray = [item for item in inArray]
|
214
|
+
|
215
|
+
for i, sortedName in enumerate(sortedNameArray):
|
216
|
+
foundIndex = nameArray.index(sortedName)
|
217
|
+
sortedArray[i] = inArray[foundIndex]
|
218
|
+
|
219
|
+
return sortedArray
|
220
|
+
|
221
|
+
def sort_objects(self, inArray):
|
222
|
+
"""
|
223
|
+
객체를 적절한 방법으로 정렬 (독립 객체와 계층 객체 모두 고려)
|
224
|
+
|
225
|
+
Args:
|
226
|
+
inArray: 정렬할 객체 배열
|
227
|
+
|
228
|
+
Returns:
|
229
|
+
정렬된 객체 배열
|
230
|
+
"""
|
231
|
+
returnArray = []
|
232
|
+
|
233
|
+
# 독립 객체와 계층 객체 분류
|
234
|
+
aloneObjArray = self.get_nonLinked_objects(inArray)
|
235
|
+
hierachyObjArray = self.get_linked_objects(inArray)
|
236
|
+
|
237
|
+
# 각각의 방식으로 정렬
|
238
|
+
sortedAloneObjArray = self.sort_by_index(aloneObjArray)
|
239
|
+
sortedHierachyObjArray = self.sort_by_hierachy(hierachyObjArray)
|
240
|
+
|
241
|
+
# 첫 인덱스 비교를 위한 초기화
|
242
|
+
firstIndexOfAloneObj = 10000
|
243
|
+
firstIndexOfHierachyObj = 10000
|
244
|
+
is_alone_importer = False
|
245
|
+
|
246
|
+
# 독립 객체의 첫 인덱스 확인
|
247
|
+
if len(sortedAloneObjArray) > 0:
|
248
|
+
index_digit = self.name.get_index_as_digit(sortedAloneObjArray[0].name)
|
249
|
+
if index_digit is False:
|
250
|
+
firstIndexOfAloneObj = 0
|
251
|
+
else:
|
252
|
+
firstIndexOfAloneObj = index_digit
|
253
|
+
|
254
|
+
# 계층 객체의 첫 인덱스 확인
|
255
|
+
if len(sortedHierachyObjArray) > 0:
|
256
|
+
index_digit = self.name.get_index_as_digit(sortedHierachyObjArray[0].name)
|
257
|
+
if index_digit is False:
|
258
|
+
firstIndexOfHierachyObj = 0
|
259
|
+
else:
|
260
|
+
firstIndexOfHierachyObj = index_digit
|
261
|
+
|
262
|
+
# 인덱스에 따라 순서 결정
|
263
|
+
if firstIndexOfAloneObj < firstIndexOfHierachyObj:
|
264
|
+
is_alone_importer = True
|
265
|
+
|
266
|
+
# 결정된 순서에 따라 배열 합치기
|
267
|
+
if is_alone_importer:
|
268
|
+
for item in sortedAloneObjArray:
|
269
|
+
returnArray.append(item)
|
270
|
+
for item in sortedHierachyObjArray:
|
271
|
+
returnArray.append(item)
|
272
|
+
else:
|
273
|
+
for item in sortedHierachyObjArray:
|
274
|
+
returnArray.append(item)
|
275
|
+
for item in sortedAloneObjArray:
|
276
|
+
returnArray.append(item)
|
277
|
+
|
278
|
+
return returnArray
|