pyjallib 0.1.5__py3-none-any.whl → 0.1.6__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 CHANGED
@@ -6,7 +6,7 @@ pyjallib Package
6
6
  Python library for game character development pipeline.
7
7
  """
8
8
 
9
- __version__ = '0.1.2'
9
+ __version__ = '0.1.6'
10
10
 
11
11
  # reload_modules 함수를 패키지 레벨에서 사용 가능하게 함
12
12
  from .namePart import NamePart, NamePartType
@@ -25,6 +25,10 @@
25
25
  "SkinBone",
26
26
  "Biped"
27
27
  ],
28
+ "koreanDescriptions": [
29
+ "",
30
+ ""
31
+ ],
28
32
  "isDirection": false
29
33
  },
30
34
  {
@@ -34,14 +38,22 @@
34
38
  "Dum",
35
39
  "Exp",
36
40
  "IK",
37
- "T"
41
+ "T",
42
+ "Rot",
43
+ "Pos",
44
+ "Lat",
45
+ "UpN"
38
46
  ],
39
47
  "weights": [
40
48
  5,
41
49
  10,
42
50
  15,
43
51
  20,
44
- 25
52
+ 25,
53
+ 30,
54
+ 35,
55
+ 40,
56
+ 45
45
57
  ],
46
58
  "type": "PREFIX",
47
59
  "descriptions": [
@@ -49,7 +61,22 @@
49
61
  "Dummy",
50
62
  "ExposeTM",
51
63
  "IK",
52
- "Target"
64
+ "Target",
65
+ "Rotation",
66
+ "Position",
67
+ "LookAt",
68
+ "UpNode"
69
+ ],
70
+ "koreanDescriptions": [
71
+ "",
72
+ "",
73
+ "",
74
+ "",
75
+ "",
76
+ "",
77
+ "",
78
+ "",
79
+ ""
53
80
  ],
54
81
  "isDirection": false
55
82
  },
@@ -68,6 +95,10 @@
68
95
  "Left",
69
96
  "Right"
70
97
  ],
98
+ "koreanDescriptions": [
99
+ "",
100
+ ""
101
+ ],
71
102
  "isDirection": true
72
103
  },
73
104
  {
@@ -85,6 +116,10 @@
85
116
  "Front",
86
117
  "Back"
87
118
  ],
119
+ "koreanDescriptions": [
120
+ "",
121
+ ""
122
+ ],
88
123
  "isDirection": true
89
124
  },
90
125
  {
@@ -93,6 +128,7 @@
93
128
  "weights": [],
94
129
  "type": "REALNAME",
95
130
  "descriptions": [],
131
+ "koreanDescriptions": [],
96
132
  "isDirection": false
97
133
  },
98
134
  {
@@ -101,6 +137,7 @@
101
137
  "weights": [],
102
138
  "type": "INDEX",
103
139
  "descriptions": [],
140
+ "koreanDescriptions": [],
104
141
  "isDirection": false
105
142
  },
106
143
  {
@@ -115,6 +152,9 @@
115
152
  "descriptions": [
116
153
  "Nub"
117
154
  ],
155
+ "koreanDescriptions": [
156
+ ""
157
+ ],
118
158
  "isDirection": false
119
159
  }
120
160
  ]
pyjallib/max/__init__.py CHANGED
@@ -27,6 +27,7 @@ from .skin import Skin
27
27
 
28
28
  from .twistBone import TwistBone
29
29
  from .groinBone import GroinBone
30
+ from .autoClavicle import AutoClavicle
30
31
 
31
32
  # 모듈 내보내기
32
33
  __all__ = [
@@ -44,5 +45,6 @@ __all__ = [
44
45
  'Bip',
45
46
  'Skin',
46
47
  'TwistBone',
47
- 'GroinBone'
48
+ 'GroinBone',
49
+ 'AutoClavicle'
48
50
  ]
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ 자동 쇄골(AutoClavicle) 모듈 - 3ds Max용 자동화된 쇄골 기능 제공
6
+ 원본 MAXScript의 autoclavicle.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 .helper import Helper
15
+ from .bone import Bone
16
+ from .constraint import Constraint
17
+ from .bip import Bip
18
+
19
+
20
+ class AutoClavicle:
21
+ """
22
+ 자동 쇄골(AutoClavicle) 관련 기능을 제공하는 클래스.
23
+ MAXScript의 _AutoClavicleBone 구조체 개념을 Python으로 재구현한 클래스이며,
24
+ 3ds Max의 기능들을 pymxs API를 통해 제어합니다.
25
+ """
26
+
27
+ def __init__(self, nameService=None, animService=None, helperService=None, boneService=None, constraintService=None, bipService=None):
28
+ """
29
+ 클래스 초기화
30
+
31
+ Args:
32
+ nameService: 이름 처리 서비스 (제공되지 않으면 새로 생성)
33
+ animService: 애니메이션 서비스 (제공되지 않으면 새로 생성)
34
+ helperService: 헬퍼 객체 서비스 (제공되지 않으면 새로 생성)
35
+ boneService: 뼈대 서비스 (제공되지 않으면 새로 생성)
36
+ constraintService: 제약 서비스 (제공되지 않으면 새로 생성)
37
+ bipService: Biped 서비스 (제공되지 않으면 새로 생성)
38
+ """
39
+ self.name = nameService if nameService else Name()
40
+ self.anim = animService if animService else Anim()
41
+ self.helper = helperService if helperService else Helper(nameService=self.name)
42
+ self.bone = boneService if boneService else Bone(nameService=self.name, animService=self.anim, helperService=self.helper)
43
+ self.const = constraintService if constraintService else Constraint(nameService=self.name, helperService=self.helper)
44
+ self.bip = bipService if bipService else Bip(animService=self.anim, nameService=self.name, boneService=self.bone)
45
+
46
+ self.bone_size = 2.0
47
+
48
+ def create_bones(self, inClavicle, inUpperArm, liftScale=0.8):
49
+ """
50
+ 자동 쇄골 뼈를 생성하고 설정합니다.
51
+
52
+ Args:
53
+ inClavicle: 쇄골 뼈 객체
54
+ inUpperArm: 상완 뼈 객체
55
+ liftScale: 들어올림 스케일 (기본값: 0.8)
56
+
57
+ Returns:
58
+ 생성된 자동 쇄골 뼈대 배열
59
+ """
60
+ # 쇄골과 상완 사이의 거리 계산
61
+ clavicleLength = rt.distance(inClavicle, inUpperArm)
62
+
63
+ # 임시 헬퍼 포인트 생성
64
+ tempHelperA = rt.Point()
65
+ tempHelperB = rt.Point()
66
+ tempHelperA.transform = inClavicle.transform
67
+ tempHelperB.transform = inClavicle.transform
68
+ self.anim.move_local(tempHelperB, clavicleLength/2.0, 0.0, 0.0)
69
+
70
+ # 자동 쇄골 이름 생성 및 뼈대 생성
71
+ autoClavicleName = self.name.replace_name_part("RealName", inClavicle.name, "AutoClavicle")
72
+ autoClavicleBones = self.bone.create_bone(
73
+ [tempHelperA, tempHelperB],
74
+ autoClavicleName,
75
+ end=True,
76
+ delPoint=True,
77
+ parent=False,
78
+ size=self.bone_size
79
+ )
80
+ autoClavicleBones[0].transform = inClavicle.transform
81
+ self.anim.move_local(autoClavicleBones[0], clavicleLength/2.0, 0.0, 0.0)
82
+ autoClavicleBones[0].parent = inClavicle
83
+
84
+ # LookAt 설정
85
+ ikGoal = self.helper.create_point(autoClavicleName, boxToggle=False, crossToggle=True)
86
+ ikGoal.transform = autoClavicleBones[1].transform
87
+ ikGoal.name = self.name.replace_name_part("Type", autoClavicleName, "T")
88
+ autClavicleLookAtConst = self.const.assign_lookat(autoClavicleBones[0], ikGoal)
89
+ autClavicleLookAtConst.upnode_world = False
90
+ autClavicleLookAtConst.pickUpNode = inClavicle
91
+ autClavicleLookAtConst.lookat_vector_length = 0.0
92
+
93
+ # 회전 헬퍼 포인트 생성
94
+ autoClavicleRotHelper = self.helper.create_point(self.name.replace_name_part("Type", autoClavicleName, "Rot"))
95
+ autoClavicleRotHelper.transform = autoClavicleBones[0].transform
96
+ autoClavicleRotHelper.parent = inClavicle
97
+
98
+ # 타겟 헬퍼 포인트 생성 (쇄골과 상완용)
99
+ rotTargetClavicle = self.helper.create_point(self.name.replace_name_part("Type", autoClavicleName, "T"))
100
+ rotTargetClavicle.transform = inClavicle.transform
101
+ self.anim.move_local(rotTargetClavicle, clavicleLength, 0.0, 0.0)
102
+
103
+ rotTargetUpperArm = self.helper.create_point(self.name.replace_name_part("Type", autoClavicleName, "T"))
104
+ rotTargetUpperArm.name = self.name.add_suffix_to_real_name(rotTargetUpperArm.name, "UArm")
105
+ rotTargetUpperArm.transform = inUpperArm.transform
106
+ self.anim.move_local(rotTargetUpperArm, (clavicleLength/2.0)*liftScale, 0.0, 0.0)
107
+
108
+ # 부모 설정
109
+ rotTargetClavicle.parent = inClavicle
110
+ rotTargetUpperArm.parent = inUpperArm
111
+
112
+ # LookAt 제약 설정
113
+ # self.const.assign_lookat_multi(autoClavicleRotHelper, [rotTargetClavicle, rotTargetUpperArm])
114
+ lookAtConst = self.const.assign_scripted_lookat(autoClavicleRotHelper, [rotTargetClavicle, rotTargetUpperArm])["lookAt"]
115
+
116
+ lookAtConst.upnode_world = False
117
+ lookAtConst.pickUpNode = inClavicle
118
+ lookAtConst.lookat_vector_length = 0.0
119
+
120
+ ikGoal.parent = autoClavicleRotHelper
121
+
122
+ return autoClavicleBones
@@ -675,7 +675,8 @@ class Constraint:
675
675
  # 객체 이름 생성
676
676
  if self.name:
677
677
  objName = self.name.get_string(oriObj.name)
678
- indexNum = self.name.get_index_as_digit(oriObj.name)
678
+ indexVal = self.name.get_index_as_digit(oriObj.name)
679
+ indexNum = 0 if indexVal is False else indexVal
679
680
  dummyName = self.name.add_prefix_to_real_name(objName, self.name.get_dummy_value())
680
681
 
681
682
  lookAtPointName = self.name.replace_Index(dummyName, str(indexNum))
@@ -752,6 +753,8 @@ class Constraint:
752
753
  x_controller.Update()
753
754
  y_controller.Update()
754
755
  z_controller.Update()
756
+
757
+ return {"lookAt":lookAtPoint_rot_controller, "x":x_controller, "y":y_controller, "z":z_controller}
755
758
 
756
759
  def assign_attachment(self, inPlacedObj, inSurfObj, bAlign=False, shiftAxis=(0, 0, 1), shiftAmount=3.0):
757
760
  """
pyjallib/max/header.py CHANGED
@@ -26,6 +26,7 @@ from .skin import Skin
26
26
 
27
27
  from .twistBone import TwistBone
28
28
  from .groinBone import GroinBone
29
+ from .autoClavicle import AutoClavicle
29
30
 
30
31
  class Header:
31
32
  """
@@ -66,6 +67,7 @@ class Header:
66
67
 
67
68
  self.twistBone = TwistBone(nameService=self.name, animService=self.anim, constService=self.constraint, bipService=self.bip, boneService=self.bone)
68
69
  self.groinBone = GroinBone(nameService=self.name, animService=self.anim, helperService=self.helper, constService=self.constraint, bipService=self.bip, boneService=self.bone, twistBoneService=self.twistBone)
70
+ self.autoClavicle = AutoClavicle(nameService=self.name, animService=self.anim, helperService=self.helper, boneService=self.bone, constraintService=self.constraint, bipService=self.bip)
69
71
 
70
72
  # 모듈 레벨에서 전역 인스턴스 생성
71
73
  jal = Header.get_instance()
pyjallib/naming.py CHANGED
@@ -352,11 +352,12 @@ class Naming:
352
352
  partValues = partObj.get_predefined_values()
353
353
 
354
354
  if partType == NamePartType.PREFIX or partType == NamePartType.SUFFIX:
355
- foundIndex = partObj._descriptions.index(inDescription)
356
- if foundIndex >= 0:
355
+ try:
356
+ foundIndex = partObj._descriptions.index(inDescription)
357
357
  return partValues[foundIndex]
358
-
359
- return ""
358
+ except ValueError:
359
+ # Description not found in the list
360
+ return ""
360
361
 
361
362
  def pick_name(self, inNamePartName, inStr):
362
363
  nameArray = self._split_to_array(inStr)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyjallib
3
- Version: 0.1.5
3
+ Version: 0.1.6
4
4
  Summary: A utility library for 3D game character development pipelines.
5
5
  Author-email: Dongseok Kim <jalnagakds@gmail.com>
6
6
  Requires-Python: >=3.10
@@ -1,20 +1,21 @@
1
- pyjallib/__init__.py,sha256=nuApOEfpw0H0-z0v_SJswZlD1KR3nrBiNrnk1-y8_k8,460
1
+ pyjallib/__init__.py,sha256=Vn47aG6w0P4VzzOm7lnSp7G38YVsI40nTwg5CClgdR4,460
2
2
  pyjallib/namePart.py,sha256=D1hnFNnZbrNicAiW2ZUaIT0LU5pro3uFYrFYOEjt7_Y,24001
3
3
  pyjallib/nameToPath.py,sha256=61EWrc0Wc1K1Qsc4G6jewIccI0IHbiZWroRcU_lX1Wc,4664
4
- pyjallib/naming.py,sha256=W1y8a-Xa2qpAR1f-lFcJeg1uEYGJF2QbVXvsaQ1VpnM,36549
4
+ pyjallib/naming.py,sha256=jJ6w0n_nnUE2uZy_I4KFsMx95Ij3_KvSjhVvQQplxpw,36621
5
5
  pyjallib/namingConfig.py,sha256=6Wyk3h1dFrzOslSoqjLftSUqt7U00tnR2WcgxYWVx5I,33969
6
6
  pyjallib/perforce.py,sha256=YnKAKlbBss4cl66R4nQbr-bsYjTneLzGYaZ187kOSpA,29872
7
7
  pyjallib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  pyjallib/reloadModules.py,sha256=RAEG3IxzJ0TlsjvnZwJt56JOkc2j8voqAnRbfQuZ44g,1151
9
9
  pyjallib/ConfigFiles/namingConfig.json,sha256=Ov4bbVJb6qodPaooU63e11YUMGXXPWFAA4AQq1sLBYU,1486
10
- pyjallib/max/__init__.py,sha256=S0BQMblJxtxVB6fa8eNgp5n3b7IYvWlTMN0DbkMMVLw,827
10
+ pyjallib/max/__init__.py,sha256=JofFmmSDMs8hWSAnS3yKw9y_o0IniQiKfzLtVUI9v8w,888
11
11
  pyjallib/max/align.py,sha256=HKjCViQCuicGmtvHB6xxVv4BEGEBGtV2gO3NvR_6R2A,5183
12
12
  pyjallib/max/anim.py,sha256=-shQeE0WeAeCefc8FoI63dNDLHhz0uzOJ4shp5AL_Cs,25135
13
+ pyjallib/max/autoClavicle.py,sha256=rJtXVcTEksstaXF4s1i-0FwhVkPWJFRxlVq8Gyw45Rg,5792
13
14
  pyjallib/max/bip.py,sha256=m6eA-rg-MghYSxbzj-YXa0KJFPm1wiOsOqyJu76_hlY,16967
14
15
  pyjallib/max/bone.py,sha256=GYs3Uohc0AMkLWZAqZTc1DET-WDgZlvlkhSUaBeszvk,33161
15
- pyjallib/max/constraint.py,sha256=QJHkSAPv7mxq2m58ni0OFc0mfrwrx91CsqupQXPfwr0,39876
16
+ pyjallib/max/constraint.py,sha256=WXB6fJ0er4EIZBZ7voQK_bFeqtgjopCKCpwiBn3QyiI,40055
16
17
  pyjallib/max/groinBone.py,sha256=rEZQ7tAXgcZ3NedFacIyvfG07nI8rgF_pVufy-hnKuo,3830
17
- pyjallib/max/header.py,sha256=VAeTBUEjQiMRxjGm9vM7tHwdmJhxbiYsJhGLPChFSBo,2502
18
+ pyjallib/max/header.py,sha256=06rzzaOGDtxQGD4SwAFX8nlxNn8lP_gQ_qY0FGZYBFk,2736
18
19
  pyjallib/max/helper.py,sha256=s_rEhY1wNUrwyEN6osuUuOsnqFAQo8_X0Dcf3R89NY0,18526
19
20
  pyjallib/max/layer.py,sha256=e9Mn8h7xf0oBYST3QIpyBpLMl8qpWTExO9Y6yH6rKc0,8795
20
21
  pyjallib/max/link.py,sha256=J3z9nkP8ZxAh9yYhR16tjQFCJTCYZMSB0MGbSHfA7uI,2592
@@ -23,13 +24,13 @@ pyjallib/max/name.py,sha256=z_fclfutesFxhk2hVliqZGnRQauKcB8LJpRbKQ5cYAc,16703
23
24
  pyjallib/max/select.py,sha256=HMJD2WNX3zVBEeYrj0UX2YXM3fHNItfw6UtQSItNsoU,9487
24
25
  pyjallib/max/skin.py,sha256=5mBzG2wSUxoGlkFeb9Ys8uUxOwuZRGeqUMTI9LiWWZU,41937
25
26
  pyjallib/max/twistBone.py,sha256=0Z-Z-OiTPM0fXAnzgol0tiY7Kms6-qrEuVCHsCVVbUc,20338
26
- pyjallib/max/ConfigFiles/3DSMaxNamingConfig.json,sha256=lfD5ltvSBOYdqtVpkdgJxL3srEzQ3jBCMeK-Ae2GLUA,2751
27
+ pyjallib/max/ConfigFiles/3DSMaxNamingConfig.json,sha256=_gIsm80fGazA6jUsoBAVxukGNydj6MDgBgGmzb0WQa4,3717
27
28
  pyjallib/max/macro/jal_macro_align.py,sha256=t0gQjybkHYAvPtjT5uWjUQd1vsXIsxOkdYfhFWduxJU,4270
28
29
  pyjallib/max/macro/jal_macro_bone.py,sha256=QS492tskLrARGIFDmbKEwJw7122xJga0ZP5z8WVVRn8,12422
29
30
  pyjallib/max/macro/jal_macro_constraint.py,sha256=0gpfan7hXES9jhnpZVlxWtCbqUCyGxjtSmVMbp7nUh8,4160
30
31
  pyjallib/max/macro/jal_macro_helper.py,sha256=ODwAl4C6WK2UE45dqpfw90TgN5vDjLJvODvYeO8tj4o,12906
31
32
  pyjallib/max/macro/jal_macro_link.py,sha256=xkgcCX0fJw4vLfMYybtfUklT3dgcO0tHfpt2X9BfWLw,1193
32
33
  pyjallib/max/macro/jal_macro_select.py,sha256=-r24l84XmDEM4W6H0r1jOBErp3q0UxNrr0m9oAHSgkE,2289
33
- pyjallib-0.1.5.dist-info/METADATA,sha256=yMpDJ1XRQxM-1o2vklLJUM8eDPSQdr22mATxqDNlN90,869
34
- pyjallib-0.1.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
35
- pyjallib-0.1.5.dist-info/RECORD,,
34
+ pyjallib-0.1.6.dist-info/METADATA,sha256=CcIpikrV2_YUnr8eiNH2Aggz2DKCsqWx_d81e5N9ORM,869
35
+ pyjallib-0.1.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
36
+ pyjallib-0.1.6.dist-info/RECORD,,