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
@@ -0,0 +1,418 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
"""
|
5
|
+
트위스트 뼈대(Twist Bone) 모듈 - 3ds Max용 트위스트 뼈대 생성 관련 기능 제공
|
6
|
+
원본 MAXScript의 twistBone.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 .anim import Anim
|
14
|
+
from .constraint import Constraint
|
15
|
+
from .bip import Bip
|
16
|
+
|
17
|
+
|
18
|
+
class TwistBone:
|
19
|
+
"""
|
20
|
+
트위스트 뼈대(Twist Bone) 관련 기능을 제공하는 클래스.
|
21
|
+
MAXScript의 _TwistBone 구조체 개념을 Python으로 재구현한 클래스이며,
|
22
|
+
3ds Max의 기능들을 pymxs API를 통해 제어합니다.
|
23
|
+
"""
|
24
|
+
|
25
|
+
def __init__(self, nameService=None, animService=None, constService=None, bipService=None):
|
26
|
+
"""
|
27
|
+
클래스 초기화.
|
28
|
+
|
29
|
+
Args:
|
30
|
+
nameService: 이름 처리 서비스 (제공되지 않으면 새로 생성)
|
31
|
+
animService: 애니메이션 서비스 (제공되지 않으면 새로 생성)
|
32
|
+
constService: 제약 서비스 (제공되지 않으면 새로 생성)
|
33
|
+
bipService: 바이페드 서비스 (제공되지 않으면 새로 생성)
|
34
|
+
"""
|
35
|
+
self.name = nameService if nameService else Name()
|
36
|
+
self.anim = animService if animService else Anim()
|
37
|
+
# Ensure dependent services use the potentially newly created instances
|
38
|
+
self.const = constService if constService else Constraint(nameService=self.name)
|
39
|
+
self.bip = bipService if bipService else Bip(animService=self.anim, nameService=self.name) # Pass potentially new instances
|
40
|
+
|
41
|
+
# 표현식 초기화
|
42
|
+
self._init_expressions()
|
43
|
+
|
44
|
+
def _init_expressions(self):
|
45
|
+
"""표현식 초기화"""
|
46
|
+
# 허벅지(Thigh) 표현식
|
47
|
+
self.thighExpression = (
|
48
|
+
"try(\n"
|
49
|
+
"TM=Limb.transform*inverse Limb.parent.transform\n"
|
50
|
+
"vector=normalize (cross -TM.row1 [1,0,0])\n"
|
51
|
+
"angle=acos -(normalize TM.row1).x\n"
|
52
|
+
"(quat 0 1 0 0)*(quat angle vector)*inverse TM.rotation)\n"
|
53
|
+
"catch((quat 0 0 0 1))"
|
54
|
+
)
|
55
|
+
|
56
|
+
# 허벅지 추가 표현식
|
57
|
+
self.thighExtraExpression = (
|
58
|
+
"try(\n"
|
59
|
+
"(Limb.transform*inverse LimbParent.transform).rotation\n"
|
60
|
+
")catch((quat 0 0 0 1))"
|
61
|
+
)
|
62
|
+
|
63
|
+
# 종아리(Calf) 표현식
|
64
|
+
self.calfExpression = (
|
65
|
+
"try(\n"
|
66
|
+
"TM=Limb.transform*inverse Limb.parent.transform\n"
|
67
|
+
"vector=normalize (cross TM.row1 [1,0,0])\n"
|
68
|
+
"angle=acos (normalize TM.row1).x\n"
|
69
|
+
"TM.rotation*(quat -angle vector))\n"
|
70
|
+
"catch((quat 0 0 0 1))"
|
71
|
+
)
|
72
|
+
|
73
|
+
# 종아리 추가 표현식
|
74
|
+
self.calfExtraExpression = (
|
75
|
+
"try(dependson TB\n"
|
76
|
+
"TB.rotation.controller[1].value\n"
|
77
|
+
")catch((quat 0 0 0 1))"
|
78
|
+
)
|
79
|
+
|
80
|
+
# 상완(Upper Arm) 표현식
|
81
|
+
self.upperArmExpression = (
|
82
|
+
"try(\n"
|
83
|
+
"TM=Limb.transform*inverse Limb.parent.transform\n"
|
84
|
+
"vector=normalize (cross TM.row1 [1,0,0])\n"
|
85
|
+
"angle=acos (normalize TM.row1).x\n"
|
86
|
+
"(quat angle vector)*inverse TM.rotation)\n"
|
87
|
+
"catch((quat 0 0 0 1))"
|
88
|
+
)
|
89
|
+
|
90
|
+
# 상완 추가 표현식
|
91
|
+
self.upperArmExtraExpression = (
|
92
|
+
"try(\n"
|
93
|
+
"(Limb.transform*inverse LimbParent.transform).rotation\n"
|
94
|
+
")catch((quat 0 0 0 1))"
|
95
|
+
)
|
96
|
+
|
97
|
+
# 오른쪽 전완(Forearm) 표현식
|
98
|
+
self.rForeArmExpression = (
|
99
|
+
"try(\n"
|
100
|
+
"TM=(matrix3 [1,0,0] [0,0,-1] [0,1,0] [0,0,0])*Limb.transform*inverse Limb.parent.transform\n"
|
101
|
+
"vector=normalize (cross TM.row1 [1,0,0])\n"
|
102
|
+
"angle=acos (normalize TM.row1).x\n"
|
103
|
+
"TM.rotation*(quat -angle vector))\n"
|
104
|
+
"catch((quat 0 0 0 1))"
|
105
|
+
)
|
106
|
+
|
107
|
+
# 왼쪽 전완(Forearm) 표현식
|
108
|
+
self.lForeArmExpression = (
|
109
|
+
"try(\n"
|
110
|
+
"TM=(matrix3 [1,0,0] [0,0,1] [0,-1,0] [0,0,0])*Limb.transform*inverse Limb.parent.transform\n"
|
111
|
+
"vector=normalize (cross TM.row1 [1,0,0])\n"
|
112
|
+
"angle=acos (normalize TM.row1).x\n"
|
113
|
+
"TM.rotation*(quat -angle vector))\n"
|
114
|
+
"catch((quat 0 0 0 1))"
|
115
|
+
)
|
116
|
+
|
117
|
+
# 전완 추가 표현식
|
118
|
+
self.foreArmExtraExpression = (
|
119
|
+
"try(dependson TB\n"
|
120
|
+
"TB.rotation.controller[1].value\n"
|
121
|
+
")catch((quat 0 0 0 1))"
|
122
|
+
)
|
123
|
+
|
124
|
+
def create_bones(self, inObj, inChild, inTwistNum, inExpression, inExtraExpression, inControllerLimb, inWeightVar):
|
125
|
+
"""
|
126
|
+
트위스트 뼈대 체인 생성
|
127
|
+
|
128
|
+
Args:
|
129
|
+
inObj: 시작 객체
|
130
|
+
inChild: 끝 객체
|
131
|
+
inTwistNum: 트위스트 뼈대 개수
|
132
|
+
inExpression: 기본 회전 표현식
|
133
|
+
inExtraExpression: 추가 회전 표현식
|
134
|
+
inControllerLimb: 컨트롤러 대상 팔다리
|
135
|
+
inWeightVar: 가중치
|
136
|
+
|
137
|
+
Returns:
|
138
|
+
생성된 트위스트 뼈대 체인 배열
|
139
|
+
"""
|
140
|
+
Limb = inObj
|
141
|
+
distanceVar = rt.distance(Limb, inChild)
|
142
|
+
|
143
|
+
TBExpression = inExpression
|
144
|
+
ControllerLimb = inControllerLimb
|
145
|
+
weightVar = inWeightVar
|
146
|
+
|
147
|
+
boneChainArray = []
|
148
|
+
|
149
|
+
# 첫 번째 트위스트 뼈대 생성
|
150
|
+
TwistBone = rt.BoneSys.createBone(
|
151
|
+
Limb.transform.position,
|
152
|
+
inChild.transform.position,
|
153
|
+
rt.Point3(0, 0, 1)
|
154
|
+
)
|
155
|
+
boneName = self.name.get_string(inObj.name) + "Twist"
|
156
|
+
TwistBone.name = self.name.replace_Index(boneName, "0")
|
157
|
+
TwistBone.transform = Limb.transform
|
158
|
+
TwistBone.parent = Limb
|
159
|
+
TwistBone.length = distanceVar / inTwistNum
|
160
|
+
TwistBone.width = distanceVar / 8
|
161
|
+
TwistBone.height = TwistBone.width
|
162
|
+
TwistBone.taper = 0
|
163
|
+
TwistBone.sidefins = False
|
164
|
+
TwistBone.frontfin = False
|
165
|
+
TwistBone.backfin = False
|
166
|
+
|
167
|
+
# 회전 컨트롤러 설정
|
168
|
+
TBRotListController = self.const.assign_rot_list(TwistBone)
|
169
|
+
TBController = rt.Rotation_Script()
|
170
|
+
TBController.addNode("Limb", ControllerLimb)
|
171
|
+
TBController.setExpression(TBExpression)
|
172
|
+
|
173
|
+
rt.setPropertyController(TBRotListController, "Available", TBController)
|
174
|
+
TBRotListController.delete(1)
|
175
|
+
TBRotListController.setActive(TBRotListController.count)
|
176
|
+
TBRotListController.weight[0] = weightVar
|
177
|
+
|
178
|
+
boneChainArray.append(TwistBone)
|
179
|
+
|
180
|
+
# 추가 회전 컨트롤러 설정
|
181
|
+
TBExtraController = rt.Rotation_Script()
|
182
|
+
if rt.matchPattern(inExtraExpression, pattern="*\nTB.*"):
|
183
|
+
TBExtraController.addNode("TB", TwistBone)
|
184
|
+
else:
|
185
|
+
TBExtraController.addNode("Limb", Limb)
|
186
|
+
TBExtraController.addNode("LimbParent", TwistBone)
|
187
|
+
TBExtraController.setExpression(inExtraExpression)
|
188
|
+
|
189
|
+
PrevTBE = TwistBone
|
190
|
+
|
191
|
+
# 추가 트위스트 뼈대 생성 (2개 이상인 경우)
|
192
|
+
if inTwistNum > 1:
|
193
|
+
for j in range(2, inTwistNum):
|
194
|
+
TwistBoneExtra = rt.BoneSys.createBone(
|
195
|
+
rt.Point3(0, 0, 0),
|
196
|
+
rt.Point3(1, 0, 0),
|
197
|
+
rt.Point3(0, 0, 1)
|
198
|
+
)
|
199
|
+
matAux = rt.matrix3(1)
|
200
|
+
matAux.position = rt.Point3(distanceVar/inTwistNum, 0, 0)
|
201
|
+
TwistBoneExtra.transform = matAux * PrevTBE.transform
|
202
|
+
TwistBoneExtra.name = self.name.replace_Index(boneName, str(j-1))
|
203
|
+
TwistBoneExtra.parent = PrevTBE
|
204
|
+
TwistBoneExtra.length = distanceVar / inTwistNum
|
205
|
+
TwistBoneExtra.width = PrevTBE.width
|
206
|
+
TwistBoneExtra.height = PrevTBE.height
|
207
|
+
TwistBoneExtra.taper = 0
|
208
|
+
TwistBoneExtra.sidefins = False
|
209
|
+
TwistBoneExtra.frontfin = False
|
210
|
+
TwistBoneExtra.backfin = False
|
211
|
+
|
212
|
+
# 회전 컨트롤러 설정
|
213
|
+
TBExtraRotListController = self.const.assign_rot_list(TwistBoneExtra)
|
214
|
+
rt.setPropertyController(TBExtraRotListController, "Available", TBExtraController)
|
215
|
+
TBExtraRotListController.delete(1)
|
216
|
+
TBExtraRotListController.setActive(TBExtraRotListController.count)
|
217
|
+
TBExtraRotListController.weight[0] = 100 / (inTwistNum - 1)
|
218
|
+
|
219
|
+
PrevTBE = TwistBoneExtra
|
220
|
+
boneChainArray.append(TwistBoneExtra)
|
221
|
+
|
222
|
+
# 마지막 트위스트 뼈대 생성
|
223
|
+
TwistBoneEnd = rt.BoneSys.createBone(
|
224
|
+
rt.Point3(0, 0, 0),
|
225
|
+
rt.Point3(1, 0, 0),
|
226
|
+
rt.Point3(0, 0, 1)
|
227
|
+
)
|
228
|
+
matAux = rt.matrix3(1)
|
229
|
+
matAux.position = rt.Point3(distanceVar/inTwistNum, 0, 0)
|
230
|
+
TwistBoneEnd.transform = matAux * PrevTBE.transform
|
231
|
+
TwistBoneEnd.name = self.name.replace_Index(boneName, str(inTwistNum-1))
|
232
|
+
TwistBoneEnd.parent = inObj
|
233
|
+
TwistBoneEnd.length = distanceVar / inTwistNum
|
234
|
+
TwistBoneEnd.width = PrevTBE.width
|
235
|
+
TwistBoneEnd.height = PrevTBE.height
|
236
|
+
TwistBoneEnd.taper = 0
|
237
|
+
TwistBoneEnd.sidefins = False
|
238
|
+
TwistBoneEnd.frontfin = False
|
239
|
+
TwistBoneEnd.backfin = False
|
240
|
+
|
241
|
+
boneChainArray.append(TwistBoneEnd)
|
242
|
+
|
243
|
+
return boneChainArray
|
244
|
+
|
245
|
+
def reorder_bones(self, inBoneChainArray):
|
246
|
+
"""
|
247
|
+
뼈대 체인의 순서 재배치
|
248
|
+
|
249
|
+
Args:
|
250
|
+
inBoneChainArray: 재배치할 뼈대 체인 배열
|
251
|
+
|
252
|
+
Returns:
|
253
|
+
재배치된 뼈대 체인 배열
|
254
|
+
"""
|
255
|
+
boneChainArray = rt.deepcopy(inBoneChainArray)
|
256
|
+
returnBoneArray = []
|
257
|
+
|
258
|
+
# 첫 번째와 마지막 뼈대 가져오기
|
259
|
+
firstBone = boneChainArray[0]
|
260
|
+
lastBone = boneChainArray[-1]
|
261
|
+
returnBoneArray.append(lastBone)
|
262
|
+
|
263
|
+
# 뼈대가 2개 이상인 경우 위치 조정
|
264
|
+
if len(boneChainArray) > 1:
|
265
|
+
self.anim.move_local(firstBone, firstBone.length, 0, 0)
|
266
|
+
self.anim.move_local(lastBone, -(firstBone.length * (len(boneChainArray)-1)), 0, 0)
|
267
|
+
|
268
|
+
# 중간 뼈대들을 새 배열에 추가
|
269
|
+
for i in range(len(boneChainArray)-1):
|
270
|
+
returnBoneArray.append(boneChainArray[i])
|
271
|
+
|
272
|
+
# 새로운 순서대로 이름 재설정
|
273
|
+
for i in range(len(returnBoneArray)):
|
274
|
+
returnBoneArray[i].name = self.name.replace_Index(boneChainArray[i].name, str(i))
|
275
|
+
|
276
|
+
return returnBoneArray
|
277
|
+
|
278
|
+
def create_upperArm_type(self, inObj, inTwistNum):
|
279
|
+
"""
|
280
|
+
상완(Upper Arm) 타입의 트위스트 뼈대 생성
|
281
|
+
|
282
|
+
Args:
|
283
|
+
inObj: 상완 뼈대 객체
|
284
|
+
inTwistNum: 트위스트 뼈대 개수
|
285
|
+
|
286
|
+
Returns:
|
287
|
+
생성된 트위스트 뼈대 체인 또는 False(실패 시)
|
288
|
+
"""
|
289
|
+
if inObj.parent is None or inObj.children.count == 0:
|
290
|
+
return False
|
291
|
+
|
292
|
+
weightVal = 100.0
|
293
|
+
|
294
|
+
return self.create_bones(
|
295
|
+
inObj,
|
296
|
+
inObj.children[0],
|
297
|
+
inTwistNum,
|
298
|
+
self.upperArmExpression,
|
299
|
+
self.upperArmExtraExpression,
|
300
|
+
inObj,
|
301
|
+
weightVal
|
302
|
+
)
|
303
|
+
|
304
|
+
def create_foreArm_type(self, inObj, inTwistNum, reorder=True):
|
305
|
+
"""
|
306
|
+
전완(Forearm) 타입의 트위스트 뼈대 생성
|
307
|
+
|
308
|
+
Args:
|
309
|
+
inObj: 전완 뼈대 객체
|
310
|
+
inTwistNum: 트위스트 뼈대 개수
|
311
|
+
side: 좌/우측 ("left" 또는 "right", 기본값: "left")
|
312
|
+
|
313
|
+
Returns:
|
314
|
+
생성된 트위스트 뼈대 체인 또는 False(실패 시)
|
315
|
+
"""
|
316
|
+
if inObj.parent is None or inObj.children.count == 0:
|
317
|
+
return False
|
318
|
+
|
319
|
+
controllerLimb = None
|
320
|
+
weightVal = 100.0
|
321
|
+
|
322
|
+
# 좌/우측에 따른 표현식 선택
|
323
|
+
TBExpression = self.lForeArmExpression if self.bip.is_left_node(inObj) else self.rForeArmExpression
|
324
|
+
|
325
|
+
# Biped 컨트롤러 노드 설정
|
326
|
+
if self.bip.is_left_node(inObj):
|
327
|
+
controllerLimb = rt.biped.getNode(inObj.controller.rootNode, rt.Name("lArm"), link=4)
|
328
|
+
else:
|
329
|
+
controllerLimb = rt.biped.getNode(inObj.controller.rootNode, rt.Name("rArm"), link=4)
|
330
|
+
|
331
|
+
if inTwistNum > 1:
|
332
|
+
weightVal = 100 / (inTwistNum - 1)
|
333
|
+
|
334
|
+
createdBones = self.create_bones(
|
335
|
+
inObj,
|
336
|
+
controllerLimb,
|
337
|
+
inTwistNum,
|
338
|
+
TBExpression,
|
339
|
+
self.foreArmExtraExpression,
|
340
|
+
controllerLimb,
|
341
|
+
weightVal
|
342
|
+
)
|
343
|
+
|
344
|
+
return self.reorder_bones(createdBones) if reorder else createdBones
|
345
|
+
|
346
|
+
def create_thigh_type(self, inObj, inTwistNum):
|
347
|
+
"""
|
348
|
+
허벅지(Thigh) 타입의 트위스트 뼈대 생성
|
349
|
+
|
350
|
+
Args:
|
351
|
+
inObj: 허벅지 뼈대 객체
|
352
|
+
inTwistNum: 트위스트 뼈대 개수
|
353
|
+
|
354
|
+
Returns:
|
355
|
+
생성된 트위스트 뼈대 체인 또는 False(실패 시)
|
356
|
+
"""
|
357
|
+
if inObj.parent is None or inObj.children.count == 0:
|
358
|
+
return False
|
359
|
+
|
360
|
+
controllerLimb = None
|
361
|
+
weightVal = 100
|
362
|
+
|
363
|
+
return self.create_bones(
|
364
|
+
inObj,
|
365
|
+
inObj.children[0],
|
366
|
+
inTwistNum,
|
367
|
+
self.thighExpression,
|
368
|
+
self.thighExtraExpression,
|
369
|
+
inObj,
|
370
|
+
weightVal
|
371
|
+
)
|
372
|
+
|
373
|
+
def create_calf_type(self, inObj, inTwistNum, reorder=True):
|
374
|
+
"""
|
375
|
+
종아리(Calf) 타입의 트위스트 뼈대 생성
|
376
|
+
|
377
|
+
Args:
|
378
|
+
inObj: 종아리 뼈대 객체
|
379
|
+
inTwistNum: 트위스트 뼈대 개수
|
380
|
+
side: 좌/우측 ("left" 또는 "right", 기본값: "left")
|
381
|
+
|
382
|
+
Returns:
|
383
|
+
생성된 트위스트 뼈대 체인 또는 False(실패 시)
|
384
|
+
"""
|
385
|
+
if inObj.parent is None or inObj.children.count == 0:
|
386
|
+
return False
|
387
|
+
|
388
|
+
controllerLimb = None
|
389
|
+
weightVal = 100
|
390
|
+
|
391
|
+
# Biped 컨트롤러 노드 설정
|
392
|
+
if self.bip.is_left_node(inObj):
|
393
|
+
controllerLimb = rt.biped.getNode(inObj.controller.rootNode, rt.Name("lLeg"), link=3)
|
394
|
+
else:
|
395
|
+
controllerLimb = rt.biped.getNode(inObj.controller.rootNode, rt.Name("rLeg"), link=3)
|
396
|
+
|
397
|
+
# 복수 뼈대인 경우 가중치 조정
|
398
|
+
if inTwistNum > 1:
|
399
|
+
weightVal = 100 / (inTwistNum - 1)
|
400
|
+
|
401
|
+
createdBones = self.create_bones(
|
402
|
+
inObj,
|
403
|
+
controllerLimb,
|
404
|
+
inTwistNum,
|
405
|
+
self.calfExpression,
|
406
|
+
self.calfExtraExpression,
|
407
|
+
controllerLimb,
|
408
|
+
weightVal
|
409
|
+
)
|
410
|
+
|
411
|
+
return self.reorder_bones(createdBones) if reorder else createdBones
|
412
|
+
|
413
|
+
def create_bend_type(self):
|
414
|
+
"""
|
415
|
+
굽힘(Bend) 타입의 트위스트 뼈대 생성
|
416
|
+
(아직 구현되지 않음)
|
417
|
+
"""
|
418
|
+
pass
|