pyjallib 0.1.3__py3-none-any.whl → 0.1.5__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/__init__.py CHANGED
@@ -26,6 +26,7 @@ from .bip import Bip
26
26
  from .skin import Skin
27
27
 
28
28
  from .twistBone import TwistBone
29
+ from .groinBone import GroinBone
29
30
 
30
31
  # 모듈 내보내기
31
32
  __all__ = [
@@ -42,5 +43,6 @@ __all__ = [
42
43
  'Link',
43
44
  'Bip',
44
45
  'Skin',
45
- 'TwistBone'
46
+ 'TwistBone',
47
+ 'GroinBone'
46
48
  ]
pyjallib/max/bip.py CHANGED
@@ -436,12 +436,11 @@ class Bip:
436
436
  if colNum > 0:
437
437
  rt.biped.deleteAllCopyCollections(inBipRoot.controller)
438
438
 
439
- def link_base_skeleton(self):
439
+ def link_base_skeleton(self, skinBoneBaseName="b"):
440
440
  """
441
441
  기본 스켈레톤 링크 (Biped와 일반 뼈대 연결)
442
442
  """
443
443
  rt.setWaitCursor()
444
- skinBoneBaseName = "b"
445
444
 
446
445
  bipSkel = self.get_bips()
447
446
  baseSkel = [None] * len(bipSkel)
@@ -473,12 +472,11 @@ class Bip:
473
472
 
474
473
  rt.setArrowCursor()
475
474
 
476
- def unlink_base_skeleton(self):
475
+ def unlink_base_skeleton(self, skinBoneBaseName="b"):
477
476
  """
478
477
  기본 스켈레톤 링크 해제
479
478
  """
480
479
  rt.setWaitCursor()
481
- skinBoneBaseName = "b"
482
480
 
483
481
  bipSkel = self.get_bips()
484
482
  baseSkel = [None] * len(bipSkel)
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ 고간 부 본 모듈 - 3ds Max용 트위스트 뼈대 생성 관련 기능 제공
6
+ """
7
+
8
+ from pymxs import runtime as rt
9
+
10
+ # Import necessary service classes for default initialization
11
+ from .name import Name
12
+ from .anim import Anim
13
+ from .constraint import Constraint
14
+ from .bip import Bip
15
+ from .bone import Bone
16
+ from .helper import Helper
17
+ from .twistBone import TwistBone
18
+
19
+ class GroinBone:
20
+ """
21
+ 고간 부 본 관련 기능을 위한 클래스
22
+ 3DS Max에서 고간 부 본을 생성하고 관리하는 기능을 제공합니다.
23
+ """
24
+
25
+ def __init__(self, nameService=None, animService=None, helperService=None, constService=None, bipService=None, boneService=None, twistBoneService=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)
40
+ self.bone = boneService if boneService else Bone(nameService=self.name, animService=self.anim)
41
+ self.twistBone = twistBoneService if twistBoneService else TwistBone(nameService=self.name, animService=self.anim, constService=self.const, bipService=self.bip, boneService=self.bone)
42
+ self.helper = helperService if helperService else Helper(nameService=self.name)
43
+
44
+ def create_bone(self, inObj):
45
+ """
46
+ 고간 부 본을 생성하는 메소드.
47
+
48
+ Args:
49
+ name: 생성할 본의 이름
50
+ parent: 부모 본 (제공되지 않으면 None)
51
+
52
+ Returns:
53
+ 생성된 본 객체
54
+ """
55
+ if self.bip.is_biped_object(inObj) == False:
56
+ rt.messageBox("This is not a biped object.")
57
+ return False
58
+
59
+ bipObj = self.bip.get_com(inObj)
60
+
61
+ lThigh = self.bip.get_grouped_nodes(inObj, "lLeg")[0]
62
+ rThigh = self.bip.get_grouped_nodes(inObj, "rLeg")[0]
63
+ pelvis = self.bip.get_grouped_nodes(inObj, "pelvis")[0]
64
+
65
+ lThighTwists = self.twistBone.get_thigh_type(lThigh)
66
+ rThighTwists = self.twistBone.get_thigh_type(rThigh)
67
+
68
+ if len(lThighTwists) == 0 or len(rThighTwists) == 0:
69
+ rt.messageBox("There is no twist bone.")
70
+ return False
71
+
72
+ pelvisHelper = self.helper.create_point(bipObj.name + " Dum Groin 00")
73
+ pelvisHelper.transform = bipObj.transform
74
+ self.anim.rotate_local(pelvisHelper, 90, 0, 0)
75
+ self.anim.rotate_local(pelvisHelper, 0, 0, -90)
76
+ pelvisHelper.parent = pelvis
77
+ self.helper.set_shape_to_box(pelvisHelper)
78
+
79
+ groinBones = self.bone.create_simple_bone(3.0, bipObj.name +" Groin 00", size=2)
80
+ groinBones[0].transform = pelvisHelper.transform
81
+ groinBones[0].parent = pelvis
82
+
83
+ self.const.assign_rot_const_multi(groinBones[0], [pelvisHelper, lThigh, rThigh])
84
+ rotConst = self.const.get_rot_list_controller(groinBones[0])[1]
85
+ rotConst.setWeight(1, 40.0)
86
+ rotConst.setWeight(2, 30.0)
87
+ rotConst.setWeight(3, 30.0)
88
+
89
+
90
+
pyjallib/max/header.py CHANGED
@@ -25,6 +25,7 @@ from .bip import Bip
25
25
  from .skin import Skin
26
26
 
27
27
  from .twistBone import TwistBone
28
+ from .groinBone import GroinBone
28
29
 
29
30
  class Header:
30
31
  """
@@ -63,7 +64,8 @@ class Header:
63
64
  self.bip = Bip(animService=self.anim, nameService=self.name, boneService=self.bone)
64
65
  self.skin = Skin()
65
66
 
66
- self.twistBone = TwistBone(nameService=self.name, animService=self.anim, constService=self.constraint, bipService=self.bip)
67
+ self.twistBone = TwistBone(nameService=self.name, animService=self.anim, constService=self.constraint, bipService=self.bip, boneService=self.bone)
68
+ self.groinBone = GroinBone(nameService=self.name, animService=self.anim, helperService=self.helper, constService=self.constraint, bipService=self.bip, boneService=self.bone, twistBoneService=self.twistBone)
67
69
 
68
70
  # 모듈 레벨에서 전역 인스턴스 생성
69
71
  jal = Header.get_instance()
pyjallib/max/helper.py CHANGED
@@ -431,3 +431,57 @@ class Helper:
431
431
  inObj.centermarker = False
432
432
  inObj.axistripod = False
433
433
  inObj.cross = False
434
+
435
+ def get_shape(self, inObj):
436
+ """
437
+ 헬퍼 객체의 시각적 형태 속성을 가져옵니다.
438
+ inObj (object): 형태 정보를 가져올 대상 3ds Max 헬퍼 객체.
439
+ dict: 헬퍼의 형태 속성을 나타내는 딕셔너리.
440
+ - "size" (float): 크기
441
+ - "centermarker" (bool): 센터 마커 활성화 여부
442
+ - "axistripod" (bool): 축 삼각대 활성화 여부
443
+ - "cross" (bool): 십자 표시 활성화 여부
444
+ - "box" (bool): 박스 표시 활성화 여부
445
+ `inObj`가 `rt.ExposeTm` 또는 `rt.Point` 타입의 객체인 경우 해당 객체의
446
+ 속성값을 반영하며, 그렇지 않은 경우 미리 정의된 기본값을 반환합니다.
447
+ """
448
+ returnDict = {
449
+ "size": 2.0,
450
+ "centermarker": False,
451
+ "axistripod": False,
452
+ "cross": True,
453
+ "box": False
454
+ }
455
+ if rt.classOf(inObj) == rt.ExposeTm or rt.classOf(inObj) == rt.Point:
456
+ returnDict["size"] = inObj.size
457
+ returnDict["centermarker"] = inObj.centermarker
458
+ returnDict["axistripod"] = inObj.axistripod
459
+ returnDict["cross"] = inObj.cross
460
+ returnDict["box"] = inObj.box
461
+
462
+ return returnDict
463
+
464
+ def set_shape(self, inObj, inShapeDict):
465
+ """
466
+ 헬퍼 객체의 표시 형태를 설정합니다.
467
+ `rt.ExposeTm` 또는 `rt.Point` 타입의 헬퍼 객체에 대해 크기, 센터 마커, 축 삼각대, 십자, 박스 표시 여부를 설정합니다.
468
+ inObj (rt.ExposeTm | rt.Point): 설정을 적용할 헬퍼 객체입니다.
469
+ inShapeDict (dict): 헬퍼의 형태를 정의하는 딕셔너리입니다.
470
+ 다음 키와 값을 포함해야 합니다:
471
+ - "size" (float | int): 헬퍼의 크기.
472
+ - "centermarker" (bool): 센터 마커 표시 여부 (True/False).
473
+ - "axistripod" (bool): 축 삼각대(axis tripod) 표시 여부 (True/False).
474
+ - "cross" (bool): 십자(cross) 표시 여부 (True/False).
475
+ - "box" (bool): 박스(box) 표시 여부 (True/False).
476
+ rt.ExposeTm | rt.Point | None: 형태가 설정된 객체를 반환합니다.
477
+ 만약 `inObj`가 `rt.ExposeTm` 또는 `rt.Point` 타입이 아닐 경우,
478
+ 아무 작업도 수행하지 않고 `None`을 반환합니다.
479
+ """
480
+ if rt.classOf(inObj) == rt.ExposeTm or rt.classOf(inObj) == rt.Point:
481
+ inObj.size = inShapeDict["size"]
482
+ inObj.centermarker = inShapeDict["centermarker"]
483
+ inObj.axistripod = inShapeDict["axistripod"]
484
+ inObj.cross = inShapeDict["cross"]
485
+ inObj.box = inShapeDict["box"]
486
+
487
+ return inObj
pyjallib/max/layer.py CHANGED
@@ -65,7 +65,7 @@ class Layer:
65
65
  Returns:
66
66
  레이어에 포함된 노드 배열 또는 빈 배열
67
67
  """
68
- returnVal = rt.Array()
68
+ returnVal = []
69
69
  layer = rt.ILayerManager.getLayerObject(inLayerNum)
70
70
  if layer is not None:
71
71
  layerNodes = rt.refs.dependents(layer)
@@ -15,7 +15,7 @@ class HelperTypeSelDialog(QtWidgets.QDialog):
15
15
  self.changeHelperType = False
16
16
 
17
17
  self.setWindowTitle("Helper Type")
18
- self.setMinimumWidth(100)
18
+ self.setMinimumWidth(150)
19
19
 
20
20
  self.layout = QtWidgets.QVBoxLayout(self)
21
21
 
@@ -41,6 +41,7 @@ class HelperTypeSelDialog(QtWidgets.QDialog):
41
41
  class ModifyHelperShapeDialog(QtWidgets.QDialog):
42
42
  def __init__(self, parent=QtWidgets.QWidget.find(rt.windows.getMAXHWND())):
43
43
  super(ModifyHelperShapeDialog, self).__init__(parent)
44
+ self.defaultHelperShapes = []
44
45
  self.helperArray = []
45
46
 
46
47
  self.setWindowTitle("Modify Helper Shape")
@@ -55,6 +56,8 @@ class ModifyHelperShapeDialog(QtWidgets.QDialog):
55
56
  self.size_spinbox = QtWidgets.QDoubleSpinBox()
56
57
  self.size_spinbox.setValue(1.0) # Default value
57
58
  self.size_spinbox.setSingleStep(0.1)
59
+ # Install event filter for mouse tracking
60
+ self.size_spinbox.installEventFilter(self)
58
61
  sizeLayout.addWidget(sizeLabel)
59
62
  sizeLayout.addWidget(self.size_spinbox)
60
63
 
@@ -62,6 +65,8 @@ class ModifyHelperShapeDialog(QtWidgets.QDialog):
62
65
  self.add_spinbox = QtWidgets.QDoubleSpinBox()
63
66
  self.add_spinbox.setValue(0.0) # Default value
64
67
  self.add_spinbox.setSingleStep(0.1)
68
+ # Install event filter for mouse tracking
69
+ self.add_spinbox.installEventFilter(self)
65
70
  addLayout.addWidget(addLabel)
66
71
  addLayout.addWidget(self.add_spinbox)
67
72
 
@@ -91,6 +96,7 @@ class ModifyHelperShapeDialog(QtWidgets.QDialog):
91
96
  self.layout.addWidget(shapeGroup) # Add the group box to the layout instead of the raw radioLayout
92
97
  self.layout.addLayout(buttonLayout)
93
98
 
99
+ # Replace incorrect stepUp/stepDown connections with proper valueChanged connections
94
100
  self.size_spinbox.valueChanged.connect(self.change_helper_size)
95
101
  self.add_spinbox.valueChanged.connect(self.add_helper_size)
96
102
  self.add_spinbox.editingFinished.connect(self.reset_add_spinbox)
@@ -100,8 +106,10 @@ class ModifyHelperShapeDialog(QtWidgets.QDialog):
100
106
  self.radio_axis.toggled.connect(self.change_helper_shape)
101
107
  self.radio_center.toggled.connect(self.change_helper_shape)
102
108
 
103
- self.ok_button.clicked.connect(self.accept)
104
- self.cancel_button.clicked.connect(self.reject)
109
+ # Make the dialog apply changes immediately without needing to click OK
110
+ # by removing the requirement for explicit acceptance
111
+ self.ok_button.clicked.connect(self.close) # Just close instead of accept
112
+ self.cancel_button.clicked.connect(self.restore_helper_shape)
105
113
 
106
114
  def change_helper_size(self):
107
115
  if len(self.helperArray) == 0:
@@ -131,6 +139,21 @@ class ModifyHelperShapeDialog(QtWidgets.QDialog):
131
139
  elif self.radio_center.isChecked():
132
140
  jal.helper.set_shape_to_center(obj)
133
141
 
142
+ def save_helper_shape(self):
143
+ if len(self.helperArray) == 0:
144
+ return
145
+ for obj in self.helperArray:
146
+ shape = jal.helper.get_shape(obj)
147
+ self.defaultHelperShapes.append(shape)
148
+
149
+ def restore_helper_shape(self):
150
+ if len(self.helperArray) == 0 or len(self.defaultHelperShapes) == 0:
151
+ return
152
+ for i, obj in enumerate(self.helperArray):
153
+ jal.helper.set_shape(obj, self.defaultHelperShapes[i])
154
+
155
+ self.reject() # Close the dialog without accepting
156
+
134
157
  def jal_create_parentHelper():
135
158
  jal.helper.create_parent_helper()
136
159
 
@@ -229,17 +252,22 @@ def jal_modify_helperShape():
229
252
 
230
253
  # Assuming the first selected object is the one to modify
231
254
  helperObj = helperArray[0]
255
+ helperObjShape = jal.helper.get_shape(helperObj)
232
256
 
233
257
  modDialog = ModifyHelperShapeDialog()
234
258
 
235
259
  # Set initial values from the selected helper (if possible)
236
260
  modDialog.size_spinbox.setValue(helperObj.size)
261
+ modDialog.radio_box.setChecked(helperObjShape["box"])
262
+ modDialog.radio_cross.setChecked(helperObjShape["cross"])
263
+ modDialog.radio_axis.setChecked(helperObjShape["axistripod"])
264
+ modDialog.radio_center.setChecked(helperObjShape["centermarker"])
237
265
 
238
266
  modDialog.helperArray = helperArray
267
+ modDialog.save_helper_shape()
239
268
 
240
- result = modDialog.exec_()
269
+ modDialog.show()
241
270
 
242
- modDialog.deleteLater()
243
271
  modDialog = None
244
272
  gc.collect()
245
273
 
pyjallib/max/twistBone.py CHANGED
@@ -13,6 +13,7 @@ from .name import Name
13
13
  from .anim import Anim
14
14
  from .constraint import Constraint
15
15
  from .bip import Bip
16
+ from .bone import Bone
16
17
 
17
18
 
18
19
  class TwistBone:
@@ -22,7 +23,7 @@ class TwistBone:
22
23
  3ds Max의 기능들을 pymxs API를 통해 제어합니다.
23
24
  """
24
25
 
25
- def __init__(self, nameService=None, animService=None, constService=None, bipService=None):
26
+ def __init__(self, nameService=None, animService=None, constService=None, bipService=None, boneService=None):
26
27
  """
27
28
  클래스 초기화.
28
29
 
@@ -37,6 +38,7 @@ class TwistBone:
37
38
  # Ensure dependent services use the potentially newly created instances
38
39
  self.const = constService if constService else Constraint(nameService=self.name)
39
40
  self.bip = bipService if bipService else Bip(animService=self.anim, nameService=self.name) # Pass potentially new instances
41
+ self.bone = boneService if boneService else Bone(nameService=self.name, animService=self.anim)
40
42
 
41
43
  # 표현식 초기화
42
44
  self._init_expressions()
@@ -415,4 +417,128 @@ class TwistBone:
415
417
  굽힘(Bend) 타입의 트위스트 뼈대 생성
416
418
  (아직 구현되지 않음)
417
419
  """
418
- pass
420
+ pass
421
+
422
+ def get_upperArm_type(self, inObj):
423
+ """
424
+ 상완(Upper Arm) 타입의 트위스트 뼈대 가져오기
425
+
426
+ Args:
427
+ inObj: 상완 뼈대 객체
428
+
429
+ Returns:
430
+ 상완 타입의 트위스트 뼈대 또는 False(실패 시)
431
+ """
432
+ returnVal = []
433
+
434
+ parentBipObj = None
435
+
436
+ if not self.bip.is_biped_object(inObj):
437
+ return returnVal
438
+
439
+ if self.bip.is_left_node(inObj):
440
+ parentBipObj = rt.biped.getNode(inObj.controller.rootNode, rt.Name("lArm"), link=2)
441
+ else:
442
+ parentBipObj = rt.biped.getNode(inObj.controller.rootNode, rt.Name("rArm"), link=2)
443
+
444
+ children = self.bone.get_every_children(parentBipObj)
445
+ for child in children:
446
+ if rt.matchPattern(child.name, pattern="*Twist*") and rt.classOf(child) == rt.BoneGeometry:
447
+ returnVal.append(child)
448
+
449
+ returnVal = self.name.sort_by_name(returnVal)
450
+
451
+ return returnVal
452
+
453
+ def get_foreArm_type(self, inObj):
454
+ """
455
+ 전완(Forearm) 타입의 트위스트 뼈대 가져오기
456
+
457
+ Args:
458
+ inObj: 전완 뼈대 객체
459
+
460
+ Returns:
461
+ 전완 타입의 트위스트 뼈대 또는 False(실패 시)
462
+ """
463
+ returnVal = []
464
+
465
+ parentBipObj = None
466
+
467
+ if not self.bip.is_biped_object(inObj):
468
+ return returnVal
469
+
470
+ if self.bip.is_left_node(inObj):
471
+ parentBipObj = rt.biped.getNode(inObj.controller.rootNode, rt.Name("lArm"), link=3)
472
+ else:
473
+ parentBipObj = rt.biped.getNode(inObj.controller.rootNode, rt.Name("rArm"), link=3)
474
+
475
+ children = self.bone.get_every_children(parentBipObj)
476
+ for child in children:
477
+ if rt.matchPattern(child.name, pattern="*Twist*") and rt.classOf(child) == rt.BoneGeometry:
478
+ returnVal.append(child)
479
+
480
+ returnVal = self.name.sort_by_name(returnVal)
481
+
482
+ return returnVal
483
+
484
+ def get_thigh_type(self, inObj):
485
+ """
486
+ 허벅지(Thigh) 타입의 트위스트 뼈대 가져오기
487
+
488
+ Args:
489
+ inObj: 허벅지 뼈대 객체
490
+
491
+ Returns:
492
+ 허벅지 타입의 트위스트 뼈대 또는 False(실패 시)
493
+ """
494
+ returnVal = []
495
+
496
+ parentBipObj = None
497
+
498
+ if not self.bip.is_biped_object(inObj):
499
+ return returnVal
500
+
501
+ if self.bip.is_left_node(inObj):
502
+ parentBipObj = rt.biped.getNode(inObj.controller.rootNode, rt.Name("lLeg"), link=1)
503
+ else:
504
+ parentBipObj = rt.biped.getNode(inObj.controller.rootNode, rt.Name("rLeg"), link=1)
505
+
506
+ children = self.bone.get_every_children(parentBipObj)
507
+ for child in children:
508
+ if rt.matchPattern(child.name, pattern="*Twist*") and rt.classOf(child) == rt.BoneGeometry:
509
+ returnVal.append(child)
510
+
511
+ returnVal = self.name.sort_by_name(returnVal)
512
+
513
+ return returnVal
514
+
515
+ def get_calf_type(self, inObj):
516
+ """
517
+ 종아리(Calf) 타입의 트위스트 뼈대 가져오기
518
+
519
+ Args:
520
+ inObj: 종아리 뼈대 객체
521
+
522
+ Returns:
523
+ 종아리 타입의 트위스트 뼈대 또는 False(실패 시)
524
+ """
525
+ returnVal = []
526
+
527
+ parentBipObj = None
528
+
529
+ if not self.bip.is_biped_object(inObj):
530
+ return returnVal
531
+
532
+ if self.bip.is_left_node(inObj):
533
+ parentBipObj = rt.biped.getNode(inObj.controller.rootNode, rt.Name("lLeg"), link=2)
534
+ else:
535
+ parentBipObj = rt.biped.getNode(inObj.controller.rootNode, rt.Name("rLeg"), link=2)
536
+
537
+ children = self.bone.get_every_children(parentBipObj)
538
+ for child in children:
539
+ if rt.matchPattern(child.name, pattern="*Twist*") and rt.classOf(child) == rt.BoneGeometry:
540
+ returnVal.append(child)
541
+
542
+ returnVal = self.name.sort_by_name(returnVal)
543
+
544
+ return returnVal
@@ -1,9 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyjallib
3
- Version: 0.1.3
3
+ Version: 0.1.5
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
7
+ Requires-Dist: p4python>=2024.2.2682690
7
8
  Description-Content-Type: text/markdown
8
9
 
9
10
  # pyjallib
@@ -7,28 +7,29 @@ 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=usuGjRQHOigvWVCPjVV2FcRvNtGBvULkF_tPUELLmcs,775
10
+ pyjallib/max/__init__.py,sha256=S0BQMblJxtxVB6fa8eNgp5n3b7IYvWlTMN0DbkMMVLw,827
11
11
  pyjallib/max/align.py,sha256=HKjCViQCuicGmtvHB6xxVv4BEGEBGtV2gO3NvR_6R2A,5183
12
12
  pyjallib/max/anim.py,sha256=-shQeE0WeAeCefc8FoI63dNDLHhz0uzOJ4shp5AL_Cs,25135
13
- pyjallib/max/bip.py,sha256=Tx9cbeiuwctYpKMMCDUARz4eP-zb6XfSKY1TXrwoqk8,16987
13
+ pyjallib/max/bip.py,sha256=m6eA-rg-MghYSxbzj-YXa0KJFPm1wiOsOqyJu76_hlY,16967
14
14
  pyjallib/max/bone.py,sha256=GYs3Uohc0AMkLWZAqZTc1DET-WDgZlvlkhSUaBeszvk,33161
15
15
  pyjallib/max/constraint.py,sha256=QJHkSAPv7mxq2m58ni0OFc0mfrwrx91CsqupQXPfwr0,39876
16
- pyjallib/max/header.py,sha256=CfjcRmXouCNENFycTdHSx68FLa3eoIKttC8XvIp48JY,2229
17
- pyjallib/max/helper.py,sha256=DGoGNX1fuDRkBnndQSFYgxeYrkOfJdnkf5EVBKqsJqc,15566
18
- pyjallib/max/layer.py,sha256=ogfj6qhK1ZY0_-MvxSH3nyUu9A93-0g-z5x1QWpXGcs,8803
16
+ pyjallib/max/groinBone.py,sha256=rEZQ7tAXgcZ3NedFacIyvfG07nI8rgF_pVufy-hnKuo,3830
17
+ pyjallib/max/header.py,sha256=VAeTBUEjQiMRxjGm9vM7tHwdmJhxbiYsJhGLPChFSBo,2502
18
+ pyjallib/max/helper.py,sha256=s_rEhY1wNUrwyEN6osuUuOsnqFAQo8_X0Dcf3R89NY0,18526
19
+ pyjallib/max/layer.py,sha256=e9Mn8h7xf0oBYST3QIpyBpLMl8qpWTExO9Y6yH6rKc0,8795
19
20
  pyjallib/max/link.py,sha256=J3z9nkP8ZxAh9yYhR16tjQFCJTCYZMSB0MGbSHfA7uI,2592
20
21
  pyjallib/max/mirror.py,sha256=j8LnsXowyTINzvtWsvCNaDsQ6v7u2RjlY50R8v5JCuc,14517
21
22
  pyjallib/max/name.py,sha256=z_fclfutesFxhk2hVliqZGnRQauKcB8LJpRbKQ5cYAc,16703
22
23
  pyjallib/max/select.py,sha256=HMJD2WNX3zVBEeYrj0UX2YXM3fHNItfw6UtQSItNsoU,9487
23
24
  pyjallib/max/skin.py,sha256=5mBzG2wSUxoGlkFeb9Ys8uUxOwuZRGeqUMTI9LiWWZU,41937
24
- pyjallib/max/twistBone.py,sha256=To9k9DHfnpVmBBevXLsSefDNIXt_RUxyCSE9UgL6Bs8,15853
25
+ pyjallib/max/twistBone.py,sha256=0Z-Z-OiTPM0fXAnzgol0tiY7Kms6-qrEuVCHsCVVbUc,20338
25
26
  pyjallib/max/ConfigFiles/3DSMaxNamingConfig.json,sha256=lfD5ltvSBOYdqtVpkdgJxL3srEzQ3jBCMeK-Ae2GLUA,2751
26
27
  pyjallib/max/macro/jal_macro_align.py,sha256=t0gQjybkHYAvPtjT5uWjUQd1vsXIsxOkdYfhFWduxJU,4270
27
28
  pyjallib/max/macro/jal_macro_bone.py,sha256=QS492tskLrARGIFDmbKEwJw7122xJga0ZP5z8WVVRn8,12422
28
29
  pyjallib/max/macro/jal_macro_constraint.py,sha256=0gpfan7hXES9jhnpZVlxWtCbqUCyGxjtSmVMbp7nUh8,4160
29
- pyjallib/max/macro/jal_macro_helper.py,sha256=dhTVLeO3xz6tBdmJtpupgpZRCos8-kcqZBg8ff2QZgE,11504
30
+ pyjallib/max/macro/jal_macro_helper.py,sha256=ODwAl4C6WK2UE45dqpfw90TgN5vDjLJvODvYeO8tj4o,12906
30
31
  pyjallib/max/macro/jal_macro_link.py,sha256=xkgcCX0fJw4vLfMYybtfUklT3dgcO0tHfpt2X9BfWLw,1193
31
32
  pyjallib/max/macro/jal_macro_select.py,sha256=-r24l84XmDEM4W6H0r1jOBErp3q0UxNrr0m9oAHSgkE,2289
32
- pyjallib-0.1.3.dist-info/METADATA,sha256=lPxMWhK8AhGOILDJWKIvyB3xc0Sbs5zud8luBDqEFhA,829
33
- pyjallib-0.1.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
34
- pyjallib-0.1.3.dist-info/RECORD,,
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,,