pyjallib 0.1.10__py3-none-any.whl → 0.1.12__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/groinBone.py CHANGED
@@ -14,6 +14,8 @@ from .helper import Helper
14
14
  from .bone import Bone
15
15
  from .constraint import Constraint
16
16
 
17
+ from .boneChain import BoneChain
18
+
17
19
  class GroinBone:
18
20
  """
19
21
  고간 부 본 관련 기능을 위한 클래스
@@ -75,21 +77,15 @@ class GroinBone:
75
77
 
76
78
  Args:
77
79
  inPelvis: Biped 객체
80
+ inLThighTwist: 왼쪽 허벅지 트위스트 본
81
+ inRThighTwist: 오른쪽 허벅지 트위스트 본
78
82
  inPelvisWeight: 골반 가중치 (기본값: 40.0)
79
83
  inThighWeight: 허벅지 가중치 (기본값: 60.0)
80
84
 
81
85
  Returns:
82
- 성공 여부 (Boolean)
86
+ BoneChain: 생성된 고간 부 본 체인 객체 또는 실패 시 False
83
87
  """
84
- returnVal = {
85
- "Pelvis": None,
86
- "LThighTwist": None,
87
- "RThighTwist": None,
88
- "Bones": [],
89
- "Helpers": [],
90
- "PelvisWeight": inPelvisWeight,
91
- "ThighWeight": inThighWeight
92
- }
88
+
93
89
  if rt.isValidNode(inPelvis) == False or rt.isValidNode(inLThighTwist) == False or rt.isValidNode(inRThighTwist) == False:
94
90
  rt.messageBox("There is no valid node.")
95
91
  return False
@@ -98,10 +94,11 @@ class GroinBone:
98
94
  if inPelvis.name[0].islower():
99
95
  groinName = groinName.lower()
100
96
 
101
- groinBaseName = self.name.replace_name_part("RealName", inPelvis.name, groinBaseName)
97
+ groinBaseName = self.name.replace_name_part("RealName", inLThighTwist.name, groinName)
102
98
 
103
99
  pelvisHelperName = self.name.replace_name_part("Type", groinBaseName, self.name.get_name_part_value_by_description("Type", "Dummy"))
104
- pelvisHelperName = self.name.replace_name_part("Index", pelvisHelperName, "00")
100
+ pelvisHelperName = self.name.replace_name_part("Index", pelvisHelperName, "0")
101
+ pelvisHelperName = self.name.remove_name_part("Side", pelvisHelperName)
105
102
  pelvisHelper = self.helper.create_point(pelvisHelperName)
106
103
  pelvisHelper.transform = inPelvis.transform
107
104
  self.anim.rotate_local(pelvisHelper, 0.0, 0.0, -180.0)
@@ -110,7 +107,7 @@ class GroinBone:
110
107
 
111
108
  lThighTwistHelperName = self.name.replace_name_part("Type", groinBaseName, self.name.get_name_part_value_by_description("Type", "Dummy"))
112
109
  lThighTwistHelperName = self.name.replace_name_part("Side", lThighTwistHelperName, self.name.get_name_part_value_by_description("Side", "Left"))
113
- lThighTwistHelperName = self.name.replace_name_part("Index", lThighTwistHelperName, "00")
110
+ lThighTwistHelperName = self.name.replace_name_part("Index", lThighTwistHelperName, "0")
114
111
  lThighTwistHelper = self.helper.create_point(lThighTwistHelperName)
115
112
  lThighTwistHelper.transform = pelvisHelper.transform
116
113
  lThighTwistHelper.position = inLThighTwist.position
@@ -119,20 +116,22 @@ class GroinBone:
119
116
 
120
117
  rThighTwistHelperName = self.name.replace_name_part("Type", groinBaseName, self.name.get_name_part_value_by_description("Type", "Dummy"))
121
118
  rThighTwistHelperName = self.name.replace_name_part("Side", rThighTwistHelperName, self.name.get_name_part_value_by_description("Side", "Right"))
122
- rThighTwistHelperName = self.name.replace_name_part("Index", rThighTwistHelperName, "00")
119
+ rThighTwistHelperName = self.name.replace_name_part("Index", rThighTwistHelperName, "0")
123
120
  rThighTwistHelper = self.helper.create_point(rThighTwistHelperName)
124
121
  rThighTwistHelper.transform = pelvisHelper.transform
125
122
  rThighTwistHelper.position = inRThighTwist.position
126
123
  rThighTwistHelper.parent = inRThighTwist
127
124
  self.helper.set_shape_to_box(rThighTwistHelper)
128
125
 
129
- groinBoneName = self.name.replace_name_part("Index", groinBaseName, "00")
130
- groinBones = self.bone.create_simple_bone(3.0, groinBoneName, size=2)
131
- groinBones[0].transform = pelvisHelper.transform
132
- groinBones[0].parent = inPelvis
126
+ groinBoneName = self.name.replace_name_part("Index", groinBaseName, "0")
127
+ groinBoneName = self.name.remove_name_part("Side", groinBoneName)
128
+ groinBone = self.bone.create_nub_bone(groinBoneName, 2)
129
+ groinBone.name = groinBoneName
130
+ groinBone.transform = pelvisHelper.transform
131
+ groinBone.parent = inPelvis
133
132
 
134
- self.const.assign_rot_const_multi(groinBones[0], [pelvisHelper, lThighTwistHelper, rThighTwistHelper])
135
- rotConst = self.const.get_rot_list_controller(groinBones[0])[1]
133
+ self.const.assign_rot_const_multi(groinBone, [pelvisHelper, lThighTwistHelper, rThighTwistHelper])
134
+ rotConst = self.const.get_rot_list_controller(groinBone)[1]
136
135
  rotConst.setWeight(1, inPelvisWeight)
137
136
  rotConst.setWeight(2, inThighWeight/2.0)
138
137
  rotConst.setWeight(3, inThighWeight/2.0)
@@ -141,20 +140,57 @@ class GroinBone:
141
140
  self.pelvis = inPelvis
142
141
  self.lThighTwist = inLThighTwist
143
142
  self.rThighTwist = inRThighTwist
144
- self.bones = groinBones
143
+ self.bones = [groinBone]
145
144
  self.helpers = [pelvisHelper, lThighTwistHelper, rThighTwistHelper]
146
145
  self.pelvisWeight = inPelvisWeight
147
146
  self.thighWeight = inThighWeight
148
147
 
149
- returnVal["Pelvis"] = inPelvis
150
- returnVal["LThighTwist"] = inLThighTwist
151
- returnVal["RThighTwist"] = inRThighTwist
152
- returnVal["Bones"] = groinBones
153
- returnVal["Helpers"] = [pelvisHelper, lThighTwistHelper, rThighTwistHelper]
154
- returnVal["PelvisWeight"] = inPelvisWeight
155
- returnVal["ThighWeight"] = inThighWeight
148
+ # BoneChain 구조에 맞는 결과 딕셔너리 생성
149
+ result = {
150
+ "Bones": [groinBone],
151
+ "Helpers": [pelvisHelper, lThighTwistHelper, rThighTwistHelper],
152
+ "SourceBones": [inPelvis, inLThighTwist, inRThighTwist],
153
+ "Parameters": [inPelvisWeight, inThighWeight]
154
+ }
156
155
 
157
156
  # 메소드 호출 후 데이터 초기화
158
157
  self.reset()
159
158
 
160
- return returnVal
159
+ # BoneChain 객체 반환
160
+ return BoneChain.from_result(result)
161
+
162
+ def create_bones_from_chain(self, inBoneChain: BoneChain):
163
+ """
164
+ 기존 BoneChain 객체에서 고간 부 본을 생성합니다.
165
+ 기존 설정을 복원하거나 저장된 데이터에서 고간 부 본 셋업을 재생성할 때 사용합니다.
166
+
167
+ Args:
168
+ inBoneChain (BoneChain): 고간 부 본 정보를 포함한 BoneChain 객체
169
+
170
+ Returns:
171
+ BoneChain: 업데이트된 BoneChain 객체 또는 실패 시 None
172
+ """
173
+ if not inBoneChain or inBoneChain.is_empty():
174
+ return None
175
+
176
+ # 기존 객체 삭제
177
+ inBoneChain.delete()
178
+
179
+ # BoneChain에서 필요한 정보 추출
180
+ sourceBones = inBoneChain.sourceBones
181
+ parameters = inBoneChain.parameters
182
+
183
+ # 필수 소스 본 확인 (최소 3개: 골반, 좌허벅지트위스트, 우허벅지트위스트)
184
+ if len(sourceBones) < 3 or not rt.isValidNode(sourceBones[0]) or not rt.isValidNode(sourceBones[1]) or not rt.isValidNode(sourceBones[2]):
185
+ return None
186
+
187
+ # 파라미터 가져오기 (또는 기본값 사용)
188
+ pelvisWeight = parameters[0] if len(parameters) > 0 else 40.0
189
+ thighWeight = parameters[1] if len(parameters) > 1 else 60.0
190
+
191
+ # 새로운 고간 부 본 생성
192
+ inPelvis = sourceBones[0]
193
+ inLThighTwist = sourceBones[1]
194
+ inRThighTwist = sourceBones[2]
195
+
196
+ return self.create_bone(inPelvis, inLThighTwist, inRThighTwist, pelvisWeight, thighWeight)
pyjallib/max/hip.py CHANGED
@@ -15,6 +15,8 @@ from .helper import Helper
15
15
  from .bone import Bone
16
16
  from .constraint import Constraint
17
17
 
18
+ from .boneChain import BoneChain
19
+
18
20
 
19
21
  class Hip:
20
22
  """
@@ -222,18 +224,53 @@ class Hip:
222
224
 
223
225
  # 결과를 딕셔너리 형태로 준비
224
226
  result = {
225
- "Pelvis": inPelvis,
226
- "Thigh": inThigh,
227
- "ThighTwist": inThighTwist,
228
227
  "Bones": self.bones,
229
228
  "Helpers": self.helpers,
230
- "PelvisWeight": inPelvisWeight,
231
- "ThighWeight": inThighWeight,
232
- "PushAmount": pushAmount
229
+ "SourceBones": [inPelvis, inThigh, inThighTwist, inCalf],
230
+ "Parameters": [pushAmount, inPelvisWeight, inThighWeight]
233
231
  }
234
232
 
235
233
  # 메소드 호출 후 데이터 초기화
236
234
  self.reset()
237
235
 
238
- return result
236
+ return BoneChain.from_result(result)
237
+
238
+ def create_bones_from_chain(self, inBoneChain: BoneChain):
239
+ """
240
+ 기존 BoneChain 객체에서 Hip 본을 생성합니다.
241
+ 기존 설정을 복원하거나 저장된 데이터에서 Hip 셋업을 재생성할 때 사용합니다.
242
+
243
+ Args:
244
+ inBoneChain (BoneChain): Hip 정보를 포함한 BoneChain 객체
245
+
246
+ Returns:
247
+ BoneChain: 업데이트된 BoneChain 객체 또는 실패 시 None
248
+ """
249
+ if not inBoneChain or inBoneChain.is_empty():
250
+ return None
251
+
252
+ # 기존 객체 삭제
253
+ inBoneChain.delete()
254
+
255
+ # BoneChain에서 필요한 정보 추출
256
+ sourceBones = inBoneChain.sourceBones
257
+ parameters = inBoneChain.parameters
258
+
259
+ # 필수 소스 본 확인
260
+ if len(sourceBones) < 4 or not all(rt.isValidNode(bone) for bone in sourceBones[:4]):
261
+ return None
262
+
263
+ # 파라미터 가져오기 (또는 기본값 사용)
264
+ pushAmount = parameters[0] if len(parameters) > 0 else 5.0
265
+ pelvisWeight = parameters[1] if len(parameters) > 1 else 0.6
266
+ thighWeight = parameters[2] if len(parameters) > 2 else 0.4
267
+
268
+ # Hip 생성
269
+ inPelvis = sourceBones[0]
270
+ inThigh = sourceBones[1]
271
+ inThighTwist = sourceBones[2]
272
+ inCalf = sourceBones[3]
273
+
274
+ # 새로운 Hip 생성
275
+ return self.create_bone(inPelvis, inThigh, inThighTwist, inCalf, pushAmount, pelvisWeight, thighWeight)
239
276
 
pyjallib/max/kneeBone.py CHANGED
@@ -16,6 +16,8 @@ from .bone import Bone
16
16
  from .constraint import Constraint
17
17
  from .volumeBone import VolumeBone
18
18
 
19
+ from .boneChain import BoneChain
20
+
19
21
  class KneeBone:
20
22
  """
21
23
  자동 무릎 본(AutoKnee) 관련 기능을 제공하는 클래스.
@@ -310,17 +312,19 @@ class KneeBone:
310
312
  result = self.volumeBone.create_bones(self.calf, self.thigh, inVolumeSize=5.0, inRotAxises=["Z", "Z"], inTransAxises=["PosY", "NegY"], inTransScales=transScales)
311
313
 
312
314
  filteringChar = self.name._get_filtering_char(inCalf.name)
313
- calfName = self.name.get_name_part("RealName", inCalf.name+ filteringChar + "Vol")
315
+ calfName = self.name.get_RealName(inCalf.name)
316
+ calfName = calfName + filteringChar + "Vol"
314
317
  isLower = calfName[0].islower()
315
318
  replaceName = "Knee"
316
319
  if isLower:
317
320
  replaceName = replaceName.lower()
321
+ calfName = calfName.lower()
318
322
 
319
323
  for item in result["Bones"]:
320
- item.name.replace(calfName, replaceName)
324
+ item.name = item.name.replace(calfName, replaceName)
321
325
 
322
- result["rootBone"].name.replace(calfName, replaceName)
323
- result["RotHelper"].name.replace(calfName, replaceName)
326
+ result["RootBone"].name = result["RootBone"].name.replace(calfName, replaceName)
327
+ result["RotHelper"].name = result["RotHelper"].name.replace(calfName, replaceName)
324
328
 
325
329
  # 결과 저장
326
330
  if result and "Bones" in result:
@@ -379,7 +383,7 @@ class KneeBone:
379
383
 
380
384
  liftTwistBone = self.bone.create_nub_bone(liftTwistBoneName, 2)
381
385
  liftTwistBone.name = self.name.remove_name_part("Nub", liftTwistBone.name)
382
- liftTwistBone.name = self.name.replace_name_part("Index", liftTwistBone.name, self.name.get_name("Index", oriThighTwistBones.name))
386
+ liftTwistBone.name = self.name.replace_name_part("Index", liftTwistBone.name, self.name.get_name("Index", item.name))
383
387
 
384
388
  rt.setProperty(liftTwistBone, "transform", item.transform)
385
389
  liftTwistBone.parent = item
@@ -404,7 +408,7 @@ class KneeBone:
404
408
 
405
409
  liftTwistBone = self.bone.create_nub_bone(liftTwistBoneName, 2)
406
410
  liftTwistBone.name = self.name.remove_name_part("Nub", liftTwistBone.name)
407
- liftTwistBone.name = self.name.replace_name_part("Index", liftTwistBone.name, self.name.get_name("Index", oriClafTwistBones.name))
411
+ liftTwistBone.name = self.name.replace_name_part("Index", liftTwistBone.name, self.name.get_name("Index", item.name))
408
412
 
409
413
  rt.setProperty(liftTwistBone, "transform", item.transform)
410
414
  liftTwistBone.parent = item
@@ -420,7 +424,7 @@ class KneeBone:
420
424
  self.calfTwistBones.append(liftTwistBone)
421
425
  self.calfTwistHelpers.append(liftTwistHelper)
422
426
 
423
- def create_bone(self, inThigh, inCalf, inFoot, inLiftScale=0.05, inKneePopScale=1.0, inKneeBackScale=1.0):
427
+ def create_bone(self, inThigh, inCalf, inFoot, inLiftScale=0.05, inKneePopScale=0.1, inKneeBackScale=1.5):
424
428
  """
425
429
  자동 무릎 본 시스템의 모든 요소를 생성하는 주요 메서드입니다.
426
430
 
@@ -441,7 +445,7 @@ class KneeBone:
441
445
  inKneeBackScale: 무릎 뒤쪽 돌출 스케일 (1.0이 기본값)
442
446
 
443
447
  Returns:
444
- bool: 자동 무릎 본 시스템 생성 성공 여부
448
+ BoneChain: 생성된 자동 무릎 본 체인 객체
445
449
  """
446
450
  if not rt.isValidNode(inThigh) or not rt.isValidNode(inCalf) or not rt.isValidNode(inFoot):
447
451
  return False
@@ -454,30 +458,61 @@ class KneeBone:
454
458
  self.create_middle_bone(inThigh, inCalf, inKneePopScale=inKneePopScale, inKneeBackScale=inKneeBackScale)
455
459
  self.create_twist_bones(inThigh, inCalf)
456
460
 
457
- # 결과를 딕셔너리 형태로 준비
461
+ # 모든 생성된 본들 수집
462
+ all_bones = self.thighTwistBones + self.calfTwistBones + self.middleBones
463
+ all_helpers = [self.lookAtHleper, self.thighRotHelper, self.calfRotHelper,
464
+ self.thighRotRootHelper, self.calfRotRootHelper] + self.thighTwistHelpers + self.calfTwistHelpers
465
+
466
+ # 결과를 BoneChain 형태로 준비
458
467
  result = {
459
- "Thigh": inThigh,
460
- "Calf": inCalf,
461
- "Foot": inFoot,
462
- "LookAtHelper": self.lookAtHleper,
463
- "ThighRotHelper": self.thighRotHelper,
464
- "CalfRotHelper": self.calfRotHelper,
465
- "ThighRotRootHelper": self.thighRotRootHelper,
466
- "CalfRotRootHelper": self.calfRotRootHelper,
467
- "ThighTwistBones": self.thighTwistBones,
468
- "CalfTwistBones": self.calfTwistBones,
469
- "ThighTwistHelpers": self.thighTwistHelpers,
470
- "CalfTwistHelpers": self.calfTwistHelpers,
471
- "MiddleBones": self.middleBones,
472
- "LiftScale": inLiftScale,
473
- "KneePopScale": inKneePopScale,
474
- "KneeBackScale": inKneeBackScale
468
+ "Bones": all_bones,
469
+ "Helpers": all_helpers,
470
+ "SourceBones": [inThigh, inCalf, inFoot],
471
+ "Parameters": [inLiftScale, inKneePopScale, inKneeBackScale]
475
472
  }
476
473
 
477
474
  # 메소드 호출 후 데이터 초기화
478
475
  self.reset()
479
476
 
480
- return result
477
+ return BoneChain.from_result(result)
478
+
479
+ def create_bones_from_chain(self, inBoneChain: BoneChain):
480
+ """
481
+ 기존 BoneChain 객체에서 자동 무릎 본을 생성합니다.
482
+ 기존 설정을 복원하거나 저장된 데이터에서 무릎 셋업을 재생성할 때 사용합니다.
483
+
484
+ Args:
485
+ inBoneChain (BoneChain): 자동 무릎 본 정보를 포함한 BoneChain 객체
486
+
487
+ Returns:
488
+ BoneChain: 업데이트된 BoneChain 객체 또는 실패 시 None
489
+ """
490
+ if not inBoneChain or inBoneChain.is_empty():
491
+ return None
492
+
493
+ # 기존 객체 삭제
494
+ inBoneChain.delete()
495
+
496
+ # BoneChain에서 필요한 정보 추출
497
+ sourceBones = inBoneChain.sourceBones
498
+ parameters = inBoneChain.parameters
499
+
500
+ # 필수 소스 본 확인
501
+ if len(sourceBones) < 3 or not rt.isValidNode(sourceBones[0]) or not rt.isValidNode(sourceBones[1]) or not rt.isValidNode(sourceBones[2]):
502
+ return None
503
+
504
+ # 파라미터 가져오기 (또는 기본값 사용)
505
+ liftScale = parameters[0] if len(parameters) > 0 else 0.05
506
+ kneePopScale = parameters[1] if len(parameters) > 1 else 0.1
507
+ kneeBackScale = parameters[2] if len(parameters) > 2 else 1.5
508
+
509
+ # 무릎 본 생성
510
+ inThigh = sourceBones[0]
511
+ inCalf = sourceBones[1]
512
+ inFoot = sourceBones[2]
513
+
514
+ # 새로운 자동 무릎 본 생성
515
+ return self.create_bone(inThigh, inCalf, inFoot, liftScale, kneePopScale, kneeBackScale)
481
516
 
482
517
  def reset(self):
483
518
  """
@@ -273,7 +273,7 @@ def jal_bone_nub_create():
273
273
  for item in non_bone_array:
274
274
  jal.bone.create_nub_bone_on_obj(item)
275
275
  else:
276
- jal.bone.create_nub_bone("Temp Nub", 2)
276
+ jal.bone.create_nub_bone("Temp", 2)
277
277
 
278
278
  # Register macroscripts
279
279
  macroScript_Category = "jalTools"
pyjallib/max/twistBone.py CHANGED
@@ -19,6 +19,8 @@ from .constraint import Constraint
19
19
  from .bip import Bip
20
20
  from .bone import Bone
21
21
 
22
+ from .boneChain import BoneChain
23
+
22
24
 
23
25
  class TwistBone:
24
26
  """
@@ -121,12 +123,7 @@ class TwistBone:
121
123
  twistNum (int, optional): 생성할 트위스트 뼈대의 개수. 기본값은 4입니다.
122
124
 
123
125
  Returns:
124
- dict: 생성된 트위스트 뼈대 정보를 담고 있는 사전 객체입니다.
125
- "Bones": 생성된 뼈대 객체들의 배열
126
- "Type": "Upper" (상체 타입)
127
- "Limb": 부모 객체 참조
128
- "Child": 자식 객체 참조
129
- "TwistNum": 생성된 트위스트 뼈대 개수
126
+ BoneChain: 생성된 트위스트 뼈대 BoneChain 객체
130
127
  """
131
128
  limb = inObj
132
129
  distance = rt.distance(limb, inChild)
@@ -134,7 +131,6 @@ class TwistBone:
134
131
  inObjXAxisVec = inObj.objectTransform.row1
135
132
  distanceDir = 1.0 if rt.dot(inObjXAxisVec, facingDirVec) > 0 else -1.0
136
133
  offssetAmount = (distance / twistNum) * distanceDir
137
- weightVal = 100.0 / (twistNum-1)
138
134
 
139
135
  boneChainArray = []
140
136
 
@@ -172,6 +168,8 @@ class TwistBone:
172
168
  lastBone.parent = limb
173
169
  self.anim.move_local(lastBone, offssetAmount*(twistNum-1), 0, 0)
174
170
 
171
+ weightVal = 100.0 / (twistNum-1)
172
+
175
173
  if twistNum > 2:
176
174
  for i in range(1, twistNum-1):
177
175
  twistExtraBone = self.bone.create_nub_bone(boneName, 2)
@@ -197,25 +195,18 @@ class TwistBone:
197
195
 
198
196
  boneChainArray.append(lastBone)
199
197
 
200
- # 결과를 멤버 변수에 저장
201
- self.limb = inObj
202
- self.child = inChild
203
- self.twistNum = twistNum
204
- self.bones = boneChainArray
205
- self.twistType = "Upper"
206
-
207
- returnVal = {
198
+ # 결과를 BoneChain 형태로 준비
199
+ result = {
208
200
  "Bones": boneChainArray,
209
- "Type": "Upper",
210
- "Limb": inObj,
211
- "Child": inChild,
212
- "TwistNum": twistNum
201
+ "Helpers": [],
202
+ "SourceBones": [inObj, inChild],
203
+ "Parameters": [twistNum, "Upper"]
213
204
  }
214
205
 
215
206
  # 메소드 호출 후 데이터 초기화
216
207
  self.reset()
217
208
 
218
- return returnVal
209
+ return BoneChain.from_result(result)
219
210
 
220
211
  def create_lower_limb_bones(self, inObj, inChild, twistNum=4):
221
212
  """
@@ -231,12 +222,7 @@ class TwistBone:
231
222
  twistNum (int, optional): 생성할 트위스트 뼈대의 개수. 기본값은 4입니다.
232
223
 
233
224
  Returns:
234
- dict: 생성된 트위스트 뼈대 정보를 담고 있는 사전 객체입니다.
235
- "Bones": 생성된 뼈대 객체들의 배열
236
- "Type": "Lower" (하체 타입)
237
- "Limb": 부모 객체 참조
238
- "Child": 자식 객체 참조
239
- "TwistNum": 생성된 트위스트 뼈대 개수
225
+ BoneChain: 생성된 트위스트 뼈대 BoneChain 객체
240
226
  """
241
227
  limb = inChild
242
228
  distance = rt.distance(inObj, inChild)
@@ -244,7 +230,6 @@ class TwistBone:
244
230
  inObjXAxisVec = inObj.objectTransform.row1
245
231
  distanceDir = 1.0 if rt.dot(inObjXAxisVec, facingDirVec) > 0 else -1.0
246
232
  offssetAmount = (distance / twistNum) * distanceDir
247
- weightVal = 100.0 / (twistNum-1)
248
233
 
249
234
  boneChainArray = []
250
235
 
@@ -281,6 +266,8 @@ class TwistBone:
281
266
  lastBone.parent = inObj
282
267
  self.anim.move_local(lastBone, 0, 0, 0)
283
268
 
269
+ weightVal = 100.0 / (twistNum-1)
270
+
284
271
  if twistNum > 2:
285
272
  for i in range(1, twistNum-1):
286
273
  twistExtraBone = self.bone.create_nub_bone(boneName, 2)
@@ -306,22 +293,54 @@ class TwistBone:
306
293
 
307
294
  boneChainArray.append(lastBone)
308
295
 
309
- # 결과를 멤버 변수에 저장
310
- self.limb = inObj
311
- self.child = inChild
312
- self.twistNum = twistNum
313
- self.bones = boneChainArray
314
- self.twistType = "Lower"
315
-
316
- returnVal = {
296
+ # 결과를 BoneChain 형태로 준비
297
+ result = {
317
298
  "Bones": boneChainArray,
318
- "Type": "Lower",
319
- "Limb": inObj,
320
- "Child": inChild,
321
- "TwistNum": twistNum
299
+ "Helpers": [],
300
+ "SourceBones": [inObj, inChild],
301
+ "Parameters": [twistNum, "Lower"]
322
302
  }
323
303
 
324
304
  # 메소드 호출 후 데이터 초기화
325
305
  self.reset()
326
306
 
327
- return returnVal
307
+ return BoneChain.from_result(result)
308
+
309
+ def create_bones_from_chain(self, inBoneChain: BoneChain):
310
+ """
311
+ 기존 BoneChain 객체에서 트위스트 본을 생성합니다.
312
+ 기존 설정을 복원하거나 저장된 데이터에서 트위스트 본 셋업을 재생성할 때 사용합니다.
313
+
314
+ Args:
315
+ inBoneChain (BoneChain): 트위스트 본 정보를 포함한 BoneChain 객체
316
+
317
+ Returns:
318
+ BoneChain: 업데이트된 BoneChain 객체 또는 실패 시 None
319
+ """
320
+ if not inBoneChain or inBoneChain.is_empty():
321
+ return None
322
+
323
+ # 기존 객체 삭제
324
+ inBoneChain.delete()
325
+
326
+ # BoneChain에서 필요한 정보 추출
327
+ sourceBones = inBoneChain.sourceBones
328
+ parameters = inBoneChain.parameters
329
+
330
+ # 필수 소스 본 확인
331
+ if len(sourceBones) < 2 or not rt.isValidNode(sourceBones[0]) or not rt.isValidNode(sourceBones[1]):
332
+ return None
333
+
334
+ # 파라미터 가져오기 (또는 기본값 사용)
335
+ twistNum = parameters[0] if len(parameters) > 0 else 4
336
+ twistType = parameters[1] if len(parameters) > 1 else "Upper"
337
+
338
+ # 본 생성
339
+ inObj = sourceBones[0]
340
+ inChild = sourceBones[1]
341
+
342
+ # 타입에 따라 적절한 방식으로 트위스트 본 생성
343
+ if twistType == "Upper":
344
+ return self.create_upper_limb_bones(inObj, inChild, twistNum)
345
+ else:
346
+ return self.create_lower_limb_bones(inObj, inChild, twistNum)