pyjallib 0.1.7__py3-none-any.whl → 0.1.9__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/3DSMaxNamingConfig.json +2 -2
- pyjallib/max/__init__.py +8 -1
- pyjallib/max/autoClavicle.py +85 -42
- pyjallib/max/bone.py +14 -7
- pyjallib/max/constraint.py +68 -40
- pyjallib/max/groinBone.py +51 -20
- pyjallib/max/header.py +8 -4
- pyjallib/max/helper.py +6 -0
- pyjallib/max/hip.py +366 -0
- pyjallib/max/morph.py +406 -0
- pyjallib/max/twistBone.py +1 -1
- pyjallib/max/ui/Container.py +153 -0
- pyjallib/max/volumePreserveBone.py +209 -0
- pyjallib/p4module.py +488 -0
- pyjallib/perforce.py +446 -653
- {pyjallib-0.1.7.dist-info → pyjallib-0.1.9.dist-info}/METADATA +1 -1
- {pyjallib-0.1.7.dist-info → pyjallib-0.1.9.dist-info}/RECORD +19 -14
- {pyjallib-0.1.7.dist-info → pyjallib-0.1.9.dist-info}/WHEEL +0 -0
pyjallib/max/hip.py
ADDED
@@ -0,0 +1,366 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
"""
|
5
|
+
Hip 모듈 - 3ds Max용 Hip 관련 기능 제공
|
6
|
+
원본 MAXScript의 hip.ms를 Python으로 변환하였으며, pymxs 모듈 기반으로 구현됨
|
7
|
+
"""
|
8
|
+
|
9
|
+
from pymxs import runtime as rt
|
10
|
+
from .header import jal
|
11
|
+
|
12
|
+
|
13
|
+
class Hip:
|
14
|
+
"""
|
15
|
+
Hip 관련 기능을 제공하는 클래스.
|
16
|
+
MAXScript의 _Hip 구조체 개념을 Python으로 재구현한 클래스이며,
|
17
|
+
3ds Max의 기능들을 pymxs API를 통해 제어합니다.
|
18
|
+
"""
|
19
|
+
|
20
|
+
def __init__(self):
|
21
|
+
"""
|
22
|
+
클래스 초기화.
|
23
|
+
|
24
|
+
Args:
|
25
|
+
nameService: 이름 처리 서비스 (제공되지 않으면 새로 생성)
|
26
|
+
animService: 애니메이션 서비스 (제공되지 않으면 새로 생성)
|
27
|
+
helperService: 헬퍼 객체 관련 서비스 (제공되지 않으면 새로 생성)
|
28
|
+
boneService: 뼈대 관련 서비스 (제공되지 않으면 새로 생성)
|
29
|
+
constraintService: 제약 관련 서비스 (제공되지 않으면 새로 생성)
|
30
|
+
bipService: Biped 관련 서비스 (제공되지 않으면 새로 생성)
|
31
|
+
"""
|
32
|
+
# 서비스 초기화
|
33
|
+
self.name = jal.name
|
34
|
+
self.anim = jal.anim
|
35
|
+
self.helper = jal.helper
|
36
|
+
self.bone = jal.bone
|
37
|
+
self.const = jal.constraint
|
38
|
+
self.bip = jal.bip
|
39
|
+
|
40
|
+
# 기본 속성 초기화
|
41
|
+
self.bone_size = 2.0
|
42
|
+
self.bone_array = []
|
43
|
+
self.pelvis_weight = 60.0
|
44
|
+
self.thigh_weight = 40.0
|
45
|
+
self.x_axis_offset = 0.1
|
46
|
+
|
47
|
+
# 객체 참조 초기화
|
48
|
+
self.spine_dummy = None
|
49
|
+
self.l_hip_dummy = None
|
50
|
+
self.l_hip_target_dummy = None
|
51
|
+
self.l_hip_exp = None
|
52
|
+
self.r_hip_dummy = None
|
53
|
+
self.r_hip_target_dummy = None
|
54
|
+
self.r_hip_exp = None
|
55
|
+
|
56
|
+
self.pelvis = None
|
57
|
+
self.spine = None
|
58
|
+
self.l_thigh = None
|
59
|
+
self.l_thigh_twist = None
|
60
|
+
self.r_thigh = None
|
61
|
+
self.r_thigh_twist = None
|
62
|
+
|
63
|
+
self.helper_array = []
|
64
|
+
|
65
|
+
def init(self, in_bip, in_l_thigh_twist, in_r_thigh_twist,
|
66
|
+
in_x_axis_offset=0.1,
|
67
|
+
in_pelvis_weight=60.0, in_thigh_weight=40.0,
|
68
|
+
in_bone_size=2.0):
|
69
|
+
|
70
|
+
self.bone_size = in_bone_size
|
71
|
+
self.x_axis_offset = in_x_axis_offset
|
72
|
+
|
73
|
+
self.pelvis_weight = in_pelvis_weight
|
74
|
+
self.thigh_weight = in_thigh_weight
|
75
|
+
|
76
|
+
self.pelvis = self.bip.get_grouped_nodes(in_bip, "pelvis")[0]
|
77
|
+
self.spine = rt.biped.getNode(in_bip, rt.Name("spine"), link=1)
|
78
|
+
self.l_thigh = rt.biped.getNode(in_bip, rt.Name("lleg"), link=1)
|
79
|
+
self.r_thigh = rt.biped.getNode(in_bip, rt.Name("rleg"), link=1)
|
80
|
+
self.l_thigh_twist = in_l_thigh_twist
|
81
|
+
self.r_thigh_twist = in_r_thigh_twist
|
82
|
+
|
83
|
+
self.bone_array = []
|
84
|
+
self.helper_array = []
|
85
|
+
|
86
|
+
def assign_position_script(self, in_obj, in_exp, in_scale="0.1"):
|
87
|
+
"""
|
88
|
+
위치 스크립트 컨트롤러 할당
|
89
|
+
|
90
|
+
Args:
|
91
|
+
in_obj: 대상 객체
|
92
|
+
in_exp: 표현식 객체 (ExposeTm)
|
93
|
+
in_scale: 스케일 값 (문자열)
|
94
|
+
"""
|
95
|
+
# 위치 리스트 컨트롤러 할당
|
96
|
+
pos_list = self.const.assign_pos_list(in_obj)
|
97
|
+
|
98
|
+
# 위치 스크립트 컨트롤러 생성
|
99
|
+
pos_script = rt.position_script()
|
100
|
+
rt.setPropertyController(pos_list, "Available", pos_script)
|
101
|
+
pos_list.setActive(pos_list.count)
|
102
|
+
|
103
|
+
# 표현식 객체 추가 및 스크립트 설정
|
104
|
+
pos_script.AddNode("exp", in_exp)
|
105
|
+
script_str = ""
|
106
|
+
script_str += "zRotValue = amin 0.0 exp.localEulerZ\n"
|
107
|
+
script_str += f"result = [0, zRotValue * {in_scale}, 0]\n"
|
108
|
+
script_str += "result"
|
109
|
+
|
110
|
+
pos_script.SetExpression(script_str)
|
111
|
+
pos_script.Update()
|
112
|
+
|
113
|
+
# 마지막 컨트롤러 활성화
|
114
|
+
self.const.set_active_last(in_obj)
|
115
|
+
|
116
|
+
def update_position_script_scale_value(self, in_obj, in_val):
|
117
|
+
"""
|
118
|
+
위치 스크립트 스케일 값 업데이트
|
119
|
+
|
120
|
+
Args:
|
121
|
+
in_obj: 대상 객체
|
122
|
+
in_val: 새 스케일 값
|
123
|
+
"""
|
124
|
+
# 위치 리스트 컨트롤러 가져오기
|
125
|
+
pos_list = self.const.get_pos_list_controller(in_obj)
|
126
|
+
|
127
|
+
if pos_list is not None and pos_list.count >= 3:
|
128
|
+
# 위치 스크립트 컨트롤러 가져오기
|
129
|
+
pos_script = rt.getPropertyController(pos_list, "Controller3")
|
130
|
+
|
131
|
+
# pos_script가 Position_Script 형태인지 확인
|
132
|
+
if rt.classOf(pos_script) == rt.Position_Script:
|
133
|
+
new_scale = str(in_val)
|
134
|
+
script_str = ""
|
135
|
+
script_str += "zRotValue = amin 0.0 exp.localEulerZ\n"
|
136
|
+
script_str += f"result = [0, zRotValue * {new_scale}, 0]\n"
|
137
|
+
script_str += "result"
|
138
|
+
|
139
|
+
pos_script.SetExpression(script_str)
|
140
|
+
pos_script.Update()
|
141
|
+
|
142
|
+
def gen_helpers(self):
|
143
|
+
"""
|
144
|
+
헬퍼 객체 생성
|
145
|
+
|
146
|
+
Returns:
|
147
|
+
생성된 헬퍼 객체 배열
|
148
|
+
"""
|
149
|
+
self.spine_dummy = self.helper.create_point(
|
150
|
+
self.name.combine(in_base=self.base_name,
|
151
|
+
in_type=self.name.get_dummyStr(),
|
152
|
+
in_real_name="HipSpine",
|
153
|
+
in_index="0",
|
154
|
+
in_fil_char=self.filtering_char),
|
155
|
+
box_toggle=True, cross_toggle=False, axis_toggle=False
|
156
|
+
)
|
157
|
+
|
158
|
+
self.l_hip_dummy = self.helper.create_point(
|
159
|
+
self.name.combine(in_base=self.base_name,
|
160
|
+
in_type=self.name.get_dummyStr(),
|
161
|
+
in_side=self.name.get_leftStr(),
|
162
|
+
in_real_name="Hip",
|
163
|
+
in_index="0",
|
164
|
+
in_fil_char=self.filtering_char),
|
165
|
+
box_toggle=True, cross_toggle=False, axis_toggle=False
|
166
|
+
)
|
167
|
+
|
168
|
+
self.l_hip_target_dummy = self.helper.create_point(
|
169
|
+
self.name.combine(in_base=self.base_name,
|
170
|
+
in_type=self.name.get_dummyStr(),
|
171
|
+
in_side=self.name.get_leftStr(),
|
172
|
+
in_real_name="HipTgt",
|
173
|
+
in_index="0",
|
174
|
+
in_fil_char=self.filtering_char),
|
175
|
+
box_toggle=False, cross_toggle=True, axis_toggle=False
|
176
|
+
)
|
177
|
+
|
178
|
+
# ExposeTm 객체 생성
|
179
|
+
self.l_hip_exp = rt.ExposeTm(
|
180
|
+
name=self.name.combine(in_base=self.base_name,
|
181
|
+
in_type=self.name.get_exposeTMStr(),
|
182
|
+
in_side=self.name.get_leftStr(),
|
183
|
+
in_real_name="Hip",
|
184
|
+
in_index="0",
|
185
|
+
in_fil_char=self.filtering_char),
|
186
|
+
size=1,
|
187
|
+
boxToggle=True,
|
188
|
+
crossToggle=False,
|
189
|
+
wirecolor=rt.color(14, 255, 2)
|
190
|
+
)
|
191
|
+
|
192
|
+
self.r_hip_dummy = self.helper.create_point(
|
193
|
+
self.name.combine(in_base=self.base_name,
|
194
|
+
in_type=self.name.get_dummyStr(),
|
195
|
+
in_side=self.name.get_rightStr(),
|
196
|
+
in_real_name="Hip",
|
197
|
+
in_index="0",
|
198
|
+
in_fil_char=self.filtering_char),
|
199
|
+
box_toggle=True, cross_toggle=False, axis_toggle=False
|
200
|
+
)
|
201
|
+
|
202
|
+
self.r_hip_target_dummy = self.helper.create_point(
|
203
|
+
self.name.combine(in_base=self.base_name,
|
204
|
+
in_type=self.name.get_dummyStr(),
|
205
|
+
in_side=self.name.get_rightStr(),
|
206
|
+
in_real_name="HipTgt",
|
207
|
+
in_index="0",
|
208
|
+
in_fil_char=self.filtering_char),
|
209
|
+
box_toggle=False, cross_toggle=True, axis_toggle=False
|
210
|
+
)
|
211
|
+
|
212
|
+
# ExposeTm 객체 생성
|
213
|
+
self.r_hip_exp = rt.ExposeTm(
|
214
|
+
name=self.name.combine(in_base=self.base_name,
|
215
|
+
in_type=self.name.get_exposeTMStr(),
|
216
|
+
in_side=self.name.get_rightStr(),
|
217
|
+
in_real_name="Hip",
|
218
|
+
in_index="0",
|
219
|
+
in_fil_char=self.filtering_char),
|
220
|
+
size=1,
|
221
|
+
boxToggle=True,
|
222
|
+
crossToggle=False,
|
223
|
+
wirecolor=rt.color(14, 255, 2)
|
224
|
+
)
|
225
|
+
|
226
|
+
self.helper_array = []
|
227
|
+
self.helper_array.append(self.spine_dummy)
|
228
|
+
self.helper_array.append(self.l_hip_dummy)
|
229
|
+
self.helper_array.append(self.l_hip_target_dummy)
|
230
|
+
self.helper_array.append(self.l_hip_exp)
|
231
|
+
self.helper_array.append(self.r_hip_dummy)
|
232
|
+
self.helper_array.append(self.r_hip_target_dummy)
|
233
|
+
self.helper_array.append(self.r_hip_exp)
|
234
|
+
|
235
|
+
return self.helper_array
|
236
|
+
|
237
|
+
def create(self):
|
238
|
+
"""
|
239
|
+
Hip 리깅 생성
|
240
|
+
"""
|
241
|
+
self.gen_helpers()
|
242
|
+
|
243
|
+
self.l_hip_dummy.transform = self.l_thigh_twist.transform
|
244
|
+
self.r_hip_dummy.transform = self.r_thigh_twist.transform
|
245
|
+
|
246
|
+
self.const.assign_pos_const(self.spine_dummy, self.spine)
|
247
|
+
self.const.assign_rot_const_multi(self.spine_dummy, [self.l_thigh_twist, self.r_thigh_twist])
|
248
|
+
self.const.collapse(self.spine_dummy)
|
249
|
+
|
250
|
+
self.l_hip_dummy.parent = self.pelvis
|
251
|
+
self.l_hip_target_dummy.parent = self.pelvis
|
252
|
+
self.l_hip_exp.parent = self.pelvis
|
253
|
+
self.r_hip_dummy.parent = self.pelvis
|
254
|
+
self.r_hip_target_dummy.parent = self.pelvis
|
255
|
+
self.r_hip_exp.parent = self.pelvis
|
256
|
+
self.spine_dummy.parent = self.pelvis
|
257
|
+
|
258
|
+
# 왼쪽 hip dummy의 rotation constraint 설정
|
259
|
+
self.const.assign_rot_list(self.l_hip_dummy)
|
260
|
+
rot_const = rt.Orientation_Constraint()
|
261
|
+
rot_list = self.const.get_rot_list_controller(self.l_hip_dummy)
|
262
|
+
rt.setPropertyController(rot_list, "Available", rot_const)
|
263
|
+
rot_list.setActive(rot_list.count)
|
264
|
+
|
265
|
+
# Constraint 타겟 추가
|
266
|
+
rot_const.appendTarget(self.spine_dummy, self.pelvis_weight)
|
267
|
+
rot_const.appendTarget(self.l_thigh_twist, self.thigh_weight)
|
268
|
+
rot_const.relative = True
|
269
|
+
|
270
|
+
# 오른쪽 hip dummy의 rotation constraint 설정
|
271
|
+
self.const.assign_rot_list(self.r_hip_dummy)
|
272
|
+
rot_const = rt.Orientation_Constraint()
|
273
|
+
rot_list = self.const.get_rot_list_controller(self.r_hip_dummy)
|
274
|
+
rt.setPropertyController(rot_list, "Available", rot_const)
|
275
|
+
rot_list.setActive(rot_list.count)
|
276
|
+
|
277
|
+
# Constraint 타겟 추가
|
278
|
+
rot_const.appendTarget(self.spine_dummy, self.pelvis_weight)
|
279
|
+
rot_const.appendTarget(self.r_thigh_twist, self.thigh_weight)
|
280
|
+
rot_const.relative = True
|
281
|
+
|
282
|
+
self.l_hip_target_dummy.transform = self.l_hip_dummy.transform
|
283
|
+
self.l_hip_exp.transform = self.l_hip_dummy.transform
|
284
|
+
self.r_hip_target_dummy.transform = self.r_hip_dummy.transform
|
285
|
+
self.r_hip_exp.transform = self.r_hip_dummy.transform
|
286
|
+
|
287
|
+
self.l_hip_exp.exposeNode = self.l_hip_dummy
|
288
|
+
self.l_hip_exp.localReferenceNode = self.l_hip_target_dummy
|
289
|
+
self.l_hip_exp.useParent = False
|
290
|
+
|
291
|
+
self.r_hip_exp.exposeNode = self.r_hip_dummy
|
292
|
+
self.r_hip_exp.localReferenceNode = self.r_hip_target_dummy
|
293
|
+
self.r_hip_exp.useParent = False
|
294
|
+
|
295
|
+
self.bone_array = []
|
296
|
+
|
297
|
+
# 왼쪽 Hip 본 생성
|
298
|
+
l_hip_bone = self.bone.create_simple_bone(
|
299
|
+
(self.bone_size * 2),
|
300
|
+
self.name.combine(
|
301
|
+
in_base=self.base_name,
|
302
|
+
in_side=self.name.get_leftStr(),
|
303
|
+
in_real_name="Hip",
|
304
|
+
in_fil_char=self.filtering_char
|
305
|
+
),
|
306
|
+
size=self.bone_size
|
307
|
+
)
|
308
|
+
|
309
|
+
l_hip_bone[0].transform = self.l_thigh.transform
|
310
|
+
self.anim.rotate_local(
|
311
|
+
l_hip_bone[0],
|
312
|
+
(self.rot_dir[0] * 0),
|
313
|
+
(self.rot_dir[1] * 0),
|
314
|
+
(self.rot_dir[2] * 90)
|
315
|
+
)
|
316
|
+
l_hip_bone[0].parent = self.l_hip_dummy
|
317
|
+
self.bone_array.append(l_hip_bone[0])
|
318
|
+
self.bone_array.append(l_hip_bone[1])
|
319
|
+
|
320
|
+
# 오른쪽 Hip 본 생성
|
321
|
+
r_hip_bone = self.bone.create_simple_bone(
|
322
|
+
(self.bone_size * 2),
|
323
|
+
self.name.combine(
|
324
|
+
in_base=self.base_name,
|
325
|
+
in_side=self.name.get_rightStr(),
|
326
|
+
in_real_name="Hip",
|
327
|
+
in_fil_char=self.filtering_char
|
328
|
+
),
|
329
|
+
size=self.bone_size
|
330
|
+
)
|
331
|
+
|
332
|
+
r_hip_bone[0].transform = self.r_thigh.transform
|
333
|
+
self.anim.rotate_local(
|
334
|
+
r_hip_bone[0],
|
335
|
+
(self.rot_dir[0] * 0),
|
336
|
+
(self.rot_dir[1] * 0),
|
337
|
+
(self.rot_dir[2] * 90)
|
338
|
+
)
|
339
|
+
r_hip_bone[0].parent = self.r_hip_dummy
|
340
|
+
self.bone_array.append(r_hip_bone[0])
|
341
|
+
self.bone_array.append(r_hip_bone[1])
|
342
|
+
|
343
|
+
# 위치 스크립트 설정
|
344
|
+
self.assign_position_script(l_hip_bone[0], self.l_hip_exp, in_scale=str(self.x_axis_offset))
|
345
|
+
self.assign_position_script(r_hip_bone[0], self.r_hip_exp, in_scale=str(self.x_axis_offset))
|
346
|
+
|
347
|
+
def del_all(self):
|
348
|
+
"""
|
349
|
+
모든 생성된 본과 헬퍼 객체 삭제
|
350
|
+
"""
|
351
|
+
self.bone.delete_bones_safely(self.bone_array)
|
352
|
+
self.bone.delete_bones_safely(self.helper_array)
|
353
|
+
|
354
|
+
def set_weight(self, in_pelvis_weight, in_thigh_weight):
|
355
|
+
"""
|
356
|
+
골반과 허벅지 가중치 설정
|
357
|
+
|
358
|
+
Args:
|
359
|
+
in_pelvis_weight: 골반 가중치
|
360
|
+
in_thigh_weight: 허벅지 가중치
|
361
|
+
"""
|
362
|
+
self.del_all()
|
363
|
+
self.pelvis_weight = in_pelvis_weight
|
364
|
+
self.thigh_weight = in_thigh_weight
|
365
|
+
|
366
|
+
self.create()
|