diff --git a/Assets/Scripts/YAMO_Scripts/RenameHumanoidBones.cs b/Assets/Scripts/YAMO_Scripts/RenameHumanoidBones.cs index ef006f7f..190ec637 100644 --- a/Assets/Scripts/YAMO_Scripts/RenameHumanoidBones.cs +++ b/Assets/Scripts/YAMO_Scripts/RenameHumanoidBones.cs @@ -25,6 +25,12 @@ public class RenameHumanoidBones : EditorWindow FindHumanoidBones(); } + // 믹사모 네이밍으로 일괄 변경 버튼 추가 + if (GUILayout.Button("믹사모 네이밍으로 일괄 변경")) + { + RenameToMixamo(); + } + if (selectedAnimator == null) { GUILayout.Label("No valid Humanoid Animator selected.", EditorStyles.helpBox); @@ -33,6 +39,27 @@ public class RenameHumanoidBones : EditorWindow GUILayout.Label("Selected GameObject: " + selectedAnimator.gameObject.name, EditorStyles.boldLabel); + // T포즈 관련 버튼들 추가 + EditorGUILayout.Space(); + GUILayout.Label("T-Pose Functions", EditorStyles.boldLabel); + + if (GUILayout.Button("Check T-Pose Conditions")) + { + CheckTPoseConditions(); + } + + if (GUILayout.Button("Apply Perfect T-Pose")) + { + ApplyPerfectTPose(); + } + + if (GUILayout.Button("Reset to Default Pose")) + { + ResetToDefaultPose(); + } + + EditorGUILayout.Space(); + if (humanoidBones.Count > 0) { scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition, GUILayout.Height(400)); @@ -124,4 +151,932 @@ public class RenameHumanoidBones : EditorWindow Debug.Log("Bone renaming completed."); } + + // T포즈 조건 검증 + private void CheckTPoseConditions() + { + if (selectedAnimator == null) + { + Debug.LogError("No valid Humanoid Animator selected."); + return; + } + + Debug.Log("=== T-Pose Conditions Check ==="); + + // 1. 몸통 뼈대들의 World X축 좌표가 0인지 확인 + CheckBodyAlignment(); + + // 2. 팔 뼈대들의 World Z축 좌표가 동일한지 확인 + CheckArmAlignment(); + + // 3. 다리 뼈대들의 World X축 좌표가 동일한지 확인 + CheckLegAlignment(); + + Debug.Log("=== T-Pose Conditions Check Complete ==="); + } + + private void CheckBodyAlignment() + { + Debug.Log("--- Body Alignment Check ---"); + + HumanBodyBones[] bodyBones = { + HumanBodyBones.Hips, + HumanBodyBones.Spine, + HumanBodyBones.Chest, + HumanBodyBones.UpperChest, + HumanBodyBones.Neck, + HumanBodyBones.Head + }; + + float targetX = 0f; + bool allAligned = true; + + foreach (var boneType in bodyBones) + { + Transform bone = selectedAnimator.GetBoneTransform(boneType); + if (bone != null) + { + float worldX = bone.position.x; + float difference = Mathf.Abs(worldX - targetX); + + Debug.Log($"{boneType}: World X = {worldX:F3} (Target: {targetX:F3}, Difference: {difference:F3})"); + + if (difference > 0.01f) + { + allAligned = false; + Debug.LogWarning($" -> {boneType} is not aligned! Difference: {difference:F3}"); + } + } + } + + if (allAligned) + { + Debug.Log("✓ Body bones are properly aligned on X-axis"); + } + else + { + Debug.LogWarning("✗ Body bones are NOT properly aligned on X-axis"); + } + } + + private void CheckArmAlignment() + { + Debug.Log("--- Arm Alignment Check ---"); + + HumanBodyBones[] leftArmBones = { + HumanBodyBones.LeftShoulder, + HumanBodyBones.LeftUpperArm, + HumanBodyBones.LeftLowerArm, + HumanBodyBones.LeftHand + }; + + HumanBodyBones[] rightArmBones = { + HumanBodyBones.RightShoulder, + HumanBodyBones.RightUpperArm, + HumanBodyBones.RightLowerArm, + HumanBodyBones.RightHand + }; + + CheckSideArmAlignment("Left Arm", leftArmBones); + CheckSideArmAlignment("Right Arm", rightArmBones); + } + + private void CheckSideArmAlignment(string sideName, HumanBodyBones[] armBones) + { + Debug.Log($"--- {sideName} Alignment Check ---"); + + float targetZ = 0f; + bool firstBone = true; + bool allAligned = true; + + foreach (var boneType in armBones) + { + Transform bone = selectedAnimator.GetBoneTransform(boneType); + if (bone != null) + { + float worldZ = bone.position.z; + + if (firstBone) + { + targetZ = worldZ; + firstBone = false; + } + + float difference = Mathf.Abs(worldZ - targetZ); + + Debug.Log($"{boneType}: World Z = {worldZ:F3} (Target: {targetZ:F3}, Difference: {difference:F3})"); + + if (difference > 0.01f) + { + allAligned = false; + Debug.LogWarning($" -> {boneType} is not aligned! Difference: {difference:F3}"); + } + } + } + + if (allAligned) + { + Debug.Log($"✓ {sideName} bones are properly aligned on Z-axis"); + } + else + { + Debug.LogWarning($"✗ {sideName} bones are NOT properly aligned on Z-axis"); + } + } + + private void CheckLegAlignment() + { + Debug.Log("--- Leg Alignment Check ---"); + + HumanBodyBones[] leftLegBones = { + HumanBodyBones.LeftUpperLeg, + HumanBodyBones.LeftLowerLeg, + HumanBodyBones.LeftFoot, + HumanBodyBones.LeftToes + }; + + HumanBodyBones[] rightLegBones = { + HumanBodyBones.RightUpperLeg, + HumanBodyBones.RightLowerLeg, + HumanBodyBones.RightFoot, + HumanBodyBones.RightToes + }; + + CheckSideLegAlignment("Left Leg", leftLegBones); + CheckSideLegAlignment("Right Leg", rightLegBones); + } + + private void CheckSideLegAlignment(string sideName, HumanBodyBones[] legBones) + { + Debug.Log($"--- {sideName} Alignment Check ---"); + + float targetX = 0f; + bool firstBone = true; + bool allAligned = true; + + foreach (var boneType in legBones) + { + Transform bone = selectedAnimator.GetBoneTransform(boneType); + if (bone != null) + { + float worldX = bone.position.x; + + if (firstBone) + { + targetX = worldX; + firstBone = false; + } + + float difference = Mathf.Abs(worldX - targetX); + + Debug.Log($"{boneType}: World X = {worldX:F3} (Target: {targetX:F3}, Difference: {difference:F3})"); + + if (difference > 0.01f) + { + allAligned = false; + Debug.LogWarning($" -> {boneType} is not aligned! Difference: {difference:F3}"); + } + } + } + + if (allAligned) + { + Debug.Log($"✓ {sideName} bones are properly aligned on X-axis"); + } + else + { + Debug.LogWarning($"✗ {sideName} bones are NOT properly aligned on X-axis"); + } + } + + // 완벽한 T포즈 적용 + private void ApplyPerfectTPose() + { + if (selectedAnimator == null) + { + Debug.LogError("No valid Humanoid Animator selected."); + return; + } + + Debug.Log("=== Applying Perfect T-Pose ==="); + + // Undo 시스템에 등록 + Undo.RecordObject(selectedAnimator.gameObject, "Apply T-Pose"); + + // 단계 1: 팔 부분 조정 + AdjustArmBones(); + + // 단계 2: 다리 부분 조정 + AdjustLegBones(); + + Debug.Log("Perfect T-Pose applied successfully!"); + } + + // 팔 뼈대 조정 (단계 1) + private void AdjustArmBones() + { + Debug.Log("Adjusting arm bones..."); + + // 왼쪽 팔 + AdjustSingleArm(HumanBodyBones.LeftUpperArm, HumanBodyBones.LeftLowerArm, HumanBodyBones.LeftHand, "Left"); + + // 오른쪽 팔 + AdjustSingleArm(HumanBodyBones.RightUpperArm, HumanBodyBones.RightLowerArm, HumanBodyBones.RightHand, "Right"); + } + + // 다리 뼈대 조정 (단계 2) + private void AdjustLegBones() + { + Debug.Log("Adjusting leg bones..."); + + // 왼쪽 다리 + AdjustSingleLeg(HumanBodyBones.LeftLowerLeg, HumanBodyBones.LeftFoot, "Left"); + + // 오른쪽 다리 + AdjustSingleLeg(HumanBodyBones.RightLowerLeg, HumanBodyBones.RightFoot, "Right"); + } + + private void AdjustSingleLeg(HumanBodyBones lowerLeg, HumanBodyBones foot, string side) + { + Debug.Log($"Adjusting {side} leg..."); + + // LowerLeg (무릎) 조정 + Transform lowerLegBone = selectedAnimator.GetBoneTransform(lowerLeg); + if (lowerLegBone != null) + { + // 로테이션은 건드리지 않음 (기존 회전값 유지) + + // 로컬 X, Z 포지션만 0으로 변경 + Vector3 localPos = lowerLegBone.localPosition; + localPos.x = 0f; + localPos.z = 0f; + lowerLegBone.localPosition = localPos; + + Debug.Log($"{side} LowerLeg - Local Rotation: {lowerLegBone.localRotation.eulerAngles}, Local Position: {lowerLegBone.localPosition}"); + } + + // Foot (발목) 조정 + Transform footBone = selectedAnimator.GetBoneTransform(foot); + if (footBone != null) + { + // 로테이션은 건드리지 않음 (기존 회전값 유지) + + // 로컬 X, Z 포지션만 0으로 변경 + Vector3 localPos = footBone.localPosition; + localPos.x = 0f; + localPos.z = 0f; + footBone.localPosition = localPos; + + Debug.Log($"{side} Foot - Local Rotation: {footBone.localRotation.eulerAngles}, Local Position: {footBone.localPosition}"); + } + + // 발가락 조정 + AdjustToes(side); + } + + private void AdjustToes(string side) + { + Debug.Log($"Adjusting {side} toes..."); + + HumanBodyBones toeBone; + + if (side == "Left") + { + toeBone = HumanBodyBones.LeftToes; + } + else // Right + { + toeBone = HumanBodyBones.RightToes; + } + + Transform bone = selectedAnimator.GetBoneTransform(toeBone); + if (bone != null) + { + // 로테이션은 건드리지 않음 (기존 회전값 유지) + + // 로컬 X, Z 포지션만 0으로 변경 + Vector3 localPos = bone.localPosition; + localPos.x = 0f; + localPos.z = 0f; + bone.localPosition = localPos; + + Debug.Log($"{side} Toes - Local Rotation: {bone.localRotation.eulerAngles}, Local Position: {bone.localPosition}"); + } + } + + private void AdjustSingleArm(HumanBodyBones upperArm, HumanBodyBones lowerArm, HumanBodyBones hand, string side) + { + Debug.Log($"Adjusting {side} arm..."); + + // UpperArm 조정 + Transform upperArmBone = selectedAnimator.GetBoneTransform(upperArm); + if (upperArmBone != null) + { + // 로컬 Rotation을 0,0,0으로 초기화 + upperArmBone.localRotation = Quaternion.identity; + + // 로컬 X, Z 포지션을 0으로 변경 + Vector3 localPos = upperArmBone.localPosition; + localPos.x = 0f; + localPos.z = 0f; + upperArmBone.localPosition = localPos; + + Debug.Log($"{side} UpperArm - Local Rotation: {upperArmBone.localRotation.eulerAngles}, Local Position: {upperArmBone.localPosition}"); + } + + // LowerArm 조정 + Transform lowerArmBone = selectedAnimator.GetBoneTransform(lowerArm); + if (lowerArmBone != null) + { + // 로컬 Rotation을 0,0,0으로 초기화 + lowerArmBone.localRotation = Quaternion.identity; + + // 로컬 X, Z 포지션을 0으로 변경 + Vector3 localPos = lowerArmBone.localPosition; + localPos.x = 0f; + localPos.z = 0f; + lowerArmBone.localPosition = localPos; + + Debug.Log($"{side} LowerArm - Local Rotation: {lowerArmBone.localRotation.eulerAngles}, Local Position: {lowerArmBone.localPosition}"); + } + + // Hand 조정 + Transform handBone = selectedAnimator.GetBoneTransform(hand); + if (handBone != null) + { + // 로컬 Rotation을 0,0,0으로 초기화 + handBone.localRotation = Quaternion.identity; + + // 로컬 X, Z 포지션을 0으로 변경 + Vector3 localPos = handBone.localPosition; + localPos.x = 0f; + localPos.z = 0f; + handBone.localPosition = localPos; + + Debug.Log($"{side} Hand - Local Rotation: {handBone.localRotation.eulerAngles}, Local Position: {handBone.localPosition}"); + } + + // 손가락 조정 (엄지손가락 제외) + AdjustFingers(side); + } + + private void AdjustFingers(string side) + { + Debug.Log($"Adjusting {side} fingers (excluding thumb)..."); + + // 엄지손가락을 제외한 손가락들 + HumanBodyBones[] fingerBones; + + if (side == "Left") + { + fingerBones = new HumanBodyBones[] + { + HumanBodyBones.LeftIndexProximal, + HumanBodyBones.LeftIndexIntermediate, + HumanBodyBones.LeftIndexDistal, + HumanBodyBones.LeftMiddleProximal, + HumanBodyBones.LeftMiddleIntermediate, + HumanBodyBones.LeftMiddleDistal, + HumanBodyBones.LeftRingProximal, + HumanBodyBones.LeftRingIntermediate, + HumanBodyBones.LeftRingDistal, + HumanBodyBones.LeftLittleProximal, + HumanBodyBones.LeftLittleIntermediate, + HumanBodyBones.LeftLittleDistal + }; + } + else // Right + { + fingerBones = new HumanBodyBones[] + { + HumanBodyBones.RightIndexProximal, + HumanBodyBones.RightIndexIntermediate, + HumanBodyBones.RightIndexDistal, + HumanBodyBones.RightMiddleProximal, + HumanBodyBones.RightMiddleIntermediate, + HumanBodyBones.RightMiddleDistal, + HumanBodyBones.RightRingProximal, + HumanBodyBones.RightRingIntermediate, + HumanBodyBones.RightRingDistal, + HumanBodyBones.RightLittleProximal, + HumanBodyBones.RightLittleIntermediate, + HumanBodyBones.RightLittleDistal + }; + } + + foreach (var fingerBone in fingerBones) + { + Transform bone = selectedAnimator.GetBoneTransform(fingerBone); + if (bone != null) + { + // 로컬 Rotation을 0,0,0으로 초기화 + bone.localRotation = Quaternion.identity; + + // 손가락 첫 마디(Proximal)는 X축을 유지, 나머지는 X, Z 포지션을 0으로 변경 + Vector3 localPos = bone.localPosition; + if (fingerBone.ToString().Contains("Proximal")) + { + // 첫 마디는 X축 유지, Z축만 0으로 + localPos.z = 0f; + } + else + { + // 두번째, 세번째 마디는 X, Z 모두 0으로 + localPos.x = 0f; + localPos.z = 0f; + } + bone.localPosition = localPos; + + Debug.Log($"{side} {fingerBone} - Local Rotation: {bone.localRotation.eulerAngles}, Local Position: {bone.localPosition}"); + } + } + + // 엄지손가락 두번째와 세번째 마디 조정 + AdjustThumbFingers(side); + } + + private void AdjustThumbFingers(string side) + { + Debug.Log($"Adjusting {side} thumb intermediate and distal..."); + + HumanBodyBones[] thumbBones; + + if (side == "Left") + { + thumbBones = new HumanBodyBones[] + { + HumanBodyBones.LeftThumbIntermediate, + HumanBodyBones.LeftThumbDistal + }; + } + else // Right + { + thumbBones = new HumanBodyBones[] + { + HumanBodyBones.RightThumbIntermediate, + HumanBodyBones.RightThumbDistal + }; + } + + foreach (var thumbBone in thumbBones) + { + Transform bone = selectedAnimator.GetBoneTransform(thumbBone); + if (bone != null) + { + // 로컬 Rotation을 0,0,0으로 초기화 + bone.localRotation = Quaternion.identity; + + // X, Z 포지션을 0으로 변경 + Vector3 localPos = bone.localPosition; + localPos.x = 0f; + localPos.z = 0f; + bone.localPosition = localPos; + + Debug.Log($"{side} {thumbBone} - Local Rotation: {bone.localRotation.eulerAngles}, Local Position: {bone.localPosition}"); + } + } + } + + // 뼈대들의 부모-자식 관계를 일시적으로 분리 + private Dictionary DetachBonesFromHierarchy() + { + Debug.Log("Detaching bones from hierarchy..."); + + Dictionary originalParents = new Dictionary(); + + // 모든 Humanoid 뼈대의 부모-자식 관계를 저장하고 분리 + for (int i = 0; i < HumanTrait.BoneCount; i++) + { + HumanBodyBones bone = (HumanBodyBones)i; + Transform boneTransform = selectedAnimator.GetBoneTransform(bone); + + if (boneTransform != null) + { + // 원래 부모를 저장 + originalParents[boneTransform] = boneTransform.parent; + + // 뼈대를 최상위 레벨로 이동 (계층구조에서 분리) + boneTransform.SetParent(null, true); + + Debug.Log($"Detached {bone} from parent: {originalParents[boneTransform]?.name ?? "None"}"); + } + } + + Debug.Log($"Detached {originalParents.Count} bones from hierarchy"); + return originalParents; + } + + // 뼈대들을 원래 부모-자식 관계로 복원 + private void RestoreBoneHierarchy(Dictionary originalParents) + { + Debug.Log("Restoring bone hierarchy..."); + + foreach (var kvp in originalParents) + { + Transform bone = kvp.Key; + Transform originalParent = kvp.Value; + + if (bone != null) + { + // 원래 부모로 복원 + bone.SetParent(originalParent, true); + Debug.Log($"Restored {bone.name} to parent: {originalParent?.name ?? "None"}"); + } + } + + Debug.Log("Bone hierarchy restored"); + } + + private void AlignBodyBones() + { + Debug.Log("Aligning body bones..."); + + HumanBodyBones[] bodyBones = { + HumanBodyBones.Hips, + HumanBodyBones.Spine, + HumanBodyBones.Chest, + HumanBodyBones.UpperChest, + HumanBodyBones.Neck, + HumanBodyBones.Head + }; + + foreach (var boneType in bodyBones) + { + Transform bone = selectedAnimator.GetBoneTransform(boneType); + if (bone != null) + { + // 현재 위치에서 X축만 0으로 조정 + Vector3 newPosition = bone.position; + newPosition.x = 0f; + bone.position = newPosition; + + // 회전을 0으로 설정 (똑바로 서있음) + bone.rotation = Quaternion.identity; + + Debug.Log($"Aligned {boneType} to X=0, rotation=0"); + } + } + } + + private void SetArmsToTPose() + { + Debug.Log("Setting arms to T-pose..."); + + // 왼쪽 팔 + SetArmToTPose(HumanBodyBones.LeftShoulder, HumanBodyBones.LeftUpperArm, + HumanBodyBones.LeftLowerArm, HumanBodyBones.LeftHand, true); + + // 오른쪽 팔 + SetArmToTPose(HumanBodyBones.RightShoulder, HumanBodyBones.RightUpperArm, + HumanBodyBones.RightLowerArm, HumanBodyBones.RightHand, false); + } + + private void SetArmToTPose(HumanBodyBones shoulder, HumanBodyBones upperArm, + HumanBodyBones lowerArm, HumanBodyBones hand, bool isLeft) + { + string side = isLeft ? "Left" : "Right"; + + // 어깨 위치 및 회전 조정 + Transform shoulderBone = selectedAnimator.GetBoneTransform(shoulder); + if (shoulderBone != null) + { + // 어깨를 몸통 중심에서 적절한 거리로 이동 + Vector3 shoulderPos = shoulderBone.position; + float shoulderOffset = isLeft ? -0.3f : 0.3f; + shoulderPos.x = shoulderOffset; + shoulderBone.position = shoulderPos; + + // 어깨를 Z축 기준으로 회전하여 팔이 수평이 되도록 함 + float shoulderZRotation = isLeft ? 90f : -90f; + shoulderBone.rotation = Quaternion.Euler(0, 0, shoulderZRotation); + + Debug.Log($"Positioned {side} shoulder at X={shoulderOffset}, Z rotation={shoulderZRotation}°"); + } + + // 상완 위치 및 회전 조정 + Transform upperArmBone = selectedAnimator.GetBoneTransform(upperArm); + if (upperArmBone != null) + { + // 상완을 어깨에서 수평으로 뻗도록 위치 조정 + Vector3 upperArmPos = upperArmBone.position; + float armLength = Vector3.Distance(shoulderBone.position, upperArmBone.position); + upperArmPos.x = isLeft ? -armLength : armLength; + upperArmBone.position = upperArmPos; + + // 상완을 완전히 펴기 위해 회전 조정 + upperArmBone.rotation = Quaternion.identity; + + Debug.Log($"Positioned {side} upper arm at X={upperArmPos.x}, rotation=0°"); + } + + // 하완 위치 및 회전 조정 + Transform lowerArmBone = selectedAnimator.GetBoneTransform(lowerArm); + if (lowerArmBone != null) + { + // 하완을 상완에서 수평으로 뻗도록 위치 조정 + Vector3 lowerArmPos = lowerArmBone.position; + float forearmLength = Vector3.Distance(upperArmBone.position, lowerArmBone.position); + lowerArmPos.x = isLeft ? -(upperArmBone.position.x + forearmLength) : (upperArmBone.position.x + forearmLength); + lowerArmBone.position = lowerArmPos; + + // 하완을 완전히 펴기 위해 회전 조정 + lowerArmBone.rotation = Quaternion.identity; + + Debug.Log($"Positioned {side} lower arm at X={lowerArmPos.x}, rotation=0°"); + } + + // 손 위치 및 회전 조정 + Transform handBone = selectedAnimator.GetBoneTransform(hand); + if (handBone != null) + { + // 손을 하완에서 수평으로 뻗도록 위치 조정 + Vector3 handPos = handBone.position; + float handLength = Vector3.Distance(lowerArmBone.position, handBone.position); + handPos.x = isLeft ? -(lowerArmBone.position.x + handLength) : (lowerArmBone.position.x + handLength); + handBone.position = handPos; + + // 손을 자연스럽게 펴기 위해 회전 조정 + handBone.rotation = Quaternion.identity; + + Debug.Log($"Positioned {side} hand at X={handPos.x}, rotation=0°"); + } + } + + private void AlignLegBones() + { + Debug.Log("Aligning leg bones..."); + + HumanBodyBones[] leftLegBones = { + HumanBodyBones.LeftUpperLeg, + HumanBodyBones.LeftLowerLeg, + HumanBodyBones.LeftFoot, + HumanBodyBones.LeftToes + }; + + HumanBodyBones[] rightLegBones = { + HumanBodyBones.RightUpperLeg, + HumanBodyBones.RightLowerLeg, + HumanBodyBones.RightFoot, + HumanBodyBones.RightToes + }; + + AlignSideLegBones("Left", leftLegBones, -0.2f); + AlignSideLegBones("Right", rightLegBones, 0.2f); + } + + private void AlignSideLegBones(string side, HumanBodyBones[] legBones, float targetX) + { + foreach (var boneType in legBones) + { + Transform bone = selectedAnimator.GetBoneTransform(boneType); + if (bone != null) + { + // 위치를 목표 X축으로 조정 + Vector3 newPosition = bone.position; + newPosition.x = targetX; + bone.position = newPosition; + + // 다리 뼈대들을 똑바로 세우기 위해 회전 조정 + bone.rotation = Quaternion.identity; + + Debug.Log($"Aligned {boneType} to X={targetX:F3}, rotation=0°"); + } + } + } + + private void SetFingersAndToesToTPose() + { + Debug.Log("Setting fingers and toes to T-pose..."); + + // 손가락 설정 (완전히 펴짐) + SetFingersToTPose(true); // 왼쪽 + SetFingersToTPose(false); // 오른쪽 + + // 발가락 설정 (자연스러운 상태) + SetToesToTPose(true); // 왼쪽 + SetToesToTPose(false); // 오른쪽 + } + + private void SetFingersToTPose(bool isLeft) + { + string side = isLeft ? "Left" : "Right"; + + // 모든 손가락 관절을 0도로 설정 + for (int finger = 0; finger < 5; finger++) + { + for (int joint = 0; joint < 3; joint++) + { + HumanBodyBones fingerBone = GetFingerBone(isLeft, finger, joint); + if (fingerBone != HumanBodyBones.LastBone) + { + Transform bone = selectedAnimator.GetBoneTransform(fingerBone); + if (bone != null) + { + bone.localRotation = Quaternion.identity; + } + } + } + } + + Debug.Log($"Set {side} fingers to straight position"); + } + + private void SetToesToTPose(bool isLeft) + { + string side = isLeft ? "Left" : "Right"; + + // 발가락을 자연스러운 상태로 설정 + HumanBodyBones toeBone = isLeft ? HumanBodyBones.LeftToes : HumanBodyBones.RightToes; + Transform bone = selectedAnimator.GetBoneTransform(toeBone); + if (bone != null) + { + bone.localRotation = Quaternion.identity; + Debug.Log($"Set {side} toes to natural position"); + } + } + + private HumanBodyBones GetFingerBone(bool isLeft, int finger, int joint) + { + if (finger == 0) // 엄지 + { + if (isLeft) + { + switch (joint) + { + case 0: return HumanBodyBones.LeftThumbProximal; + case 1: return HumanBodyBones.LeftThumbIntermediate; + case 2: return HumanBodyBones.LeftThumbDistal; + } + } + else + { + switch (joint) + { + case 0: return HumanBodyBones.RightThumbProximal; + case 1: return HumanBodyBones.RightThumbIntermediate; + case 2: return HumanBodyBones.RightThumbDistal; + } + } + } + else // 나머지 손가락들 + { + if (isLeft) + { + switch (finger) + { + case 1: return joint == 0 ? HumanBodyBones.LeftIndexProximal : + joint == 1 ? HumanBodyBones.LeftIndexIntermediate : + HumanBodyBones.LeftIndexDistal; + case 2: return joint == 0 ? HumanBodyBones.LeftMiddleProximal : + joint == 1 ? HumanBodyBones.LeftMiddleIntermediate : + HumanBodyBones.LeftMiddleDistal; + case 3: return joint == 0 ? HumanBodyBones.LeftRingProximal : + joint == 1 ? HumanBodyBones.LeftRingIntermediate : + HumanBodyBones.LeftRingDistal; + case 4: return joint == 0 ? HumanBodyBones.LeftLittleProximal : + joint == 1 ? HumanBodyBones.LeftLittleIntermediate : + HumanBodyBones.LeftLittleDistal; + } + } + else + { + switch (finger) + { + case 1: return joint == 0 ? HumanBodyBones.RightIndexProximal : + joint == 1 ? HumanBodyBones.RightIndexIntermediate : + HumanBodyBones.RightIndexDistal; + case 2: return joint == 0 ? HumanBodyBones.RightMiddleProximal : + joint == 1 ? HumanBodyBones.RightMiddleIntermediate : + HumanBodyBones.RightMiddleDistal; + case 3: return joint == 0 ? HumanBodyBones.RightRingProximal : + joint == 1 ? HumanBodyBones.RightRingIntermediate : + HumanBodyBones.RightRingDistal; + case 4: return joint == 0 ? HumanBodyBones.RightLittleProximal : + joint == 1 ? HumanBodyBones.RightLittleIntermediate : + HumanBodyBones.RightLittleDistal; + } + } + } + + return HumanBodyBones.LastBone; // 유효하지 않은 경우 + } + + // 기본 포즈로 리셋 + private void ResetToDefaultPose() + { + if (selectedAnimator == null) + { + Debug.LogError("No valid Humanoid Animator selected."); + return; + } + + Debug.Log("=== Resetting to Default Pose ==="); + + // Undo 시스템에 등록 + Undo.RecordObject(selectedAnimator.gameObject, "Reset to Default Pose"); + + // 모든 뼈대의 로컬 회전을 0으로 리셋 + for (int i = 0; i < HumanTrait.BoneCount; i++) + { + HumanBodyBones bone = (HumanBodyBones)i; + Transform boneTransform = selectedAnimator.GetBoneTransform(bone); + + if (boneTransform != null) + { + boneTransform.localRotation = Quaternion.identity; + } + } + + Debug.Log("Reset to default pose completed!"); + } + + // 믹사모 네이밍 매핑 및 일괄 변경 함수 추가 + private void RenameToMixamo() + { + if (selectedAnimator == null) + { + Debug.LogError("No valid Humanoid Animator selected."); + return; + } + + // HumanBodyBones와 믹사모 네이밍 매핑 + var mixamoMap = new Dictionary + { + { HumanBodyBones.Hips, "mixamorig:Hips" }, + { HumanBodyBones.LeftUpperLeg, "mixamorig:LeftUpLeg" }, + { HumanBodyBones.LeftLowerLeg, "mixamorig:LeftLeg" }, + { HumanBodyBones.LeftFoot, "mixamorig:LeftFoot" }, + { HumanBodyBones.LeftToes, "mixamorig:LeftToeBase" }, + { HumanBodyBones.RightUpperLeg, "mixamorig:RightUpLeg" }, + { HumanBodyBones.RightLowerLeg, "mixamorig:RightLeg" }, + { HumanBodyBones.RightFoot, "mixamorig:RightFoot" }, + { HumanBodyBones.RightToes, "mixamorig:RightToeBase" }, + { HumanBodyBones.Spine, "mixamorig:Spine" }, + { HumanBodyBones.Chest, "mixamorig:Spine1" }, + { HumanBodyBones.UpperChest, "mixamorig:Spine2" }, // UpperChest는 있는 경우만 + { HumanBodyBones.Neck, "mixamorig:Neck" }, + { HumanBodyBones.Head, "mixamorig:Head" }, + { HumanBodyBones.LeftShoulder, "mixamorig:LeftShoulder" }, + { HumanBodyBones.LeftUpperArm, "mixamorig:LeftArm" }, + { HumanBodyBones.LeftLowerArm, "mixamorig:LeftForeArm" }, + { HumanBodyBones.LeftHand, "mixamorig:LeftHand" }, + { HumanBodyBones.RightShoulder, "mixamorig:RightShoulder" }, + { HumanBodyBones.RightUpperArm, "mixamorig:RightArm" }, + { HumanBodyBones.RightLowerArm, "mixamorig:RightForeArm" }, + { HumanBodyBones.RightHand, "mixamorig:RightHand" }, + // 왼손 손가락 + { HumanBodyBones.LeftThumbProximal, "mixamorig:LeftHandThumb1" }, + { HumanBodyBones.LeftThumbIntermediate, "mixamorig:LeftHandThumb2" }, + { HumanBodyBones.LeftThumbDistal, "mixamorig:LeftHandThumb3" }, + // mixamo에는 Thumb4가 있으나, Unity에는 없음 + { HumanBodyBones.LeftIndexProximal, "mixamorig:LeftHandIndex1" }, + { HumanBodyBones.LeftIndexIntermediate, "mixamorig:LeftHandIndex2" }, + { HumanBodyBones.LeftIndexDistal, "mixamorig:LeftHandIndex3" }, + { HumanBodyBones.LeftMiddleProximal, "mixamorig:LeftHandMiddle1" }, + { HumanBodyBones.LeftMiddleIntermediate, "mixamorig:LeftHandMiddle2" }, + { HumanBodyBones.LeftMiddleDistal, "mixamorig:LeftHandMiddle3" }, + { HumanBodyBones.LeftRingProximal, "mixamorig:LeftHandRing1" }, + { HumanBodyBones.LeftRingIntermediate, "mixamorig:LeftHandRing2" }, + { HumanBodyBones.LeftRingDistal, "mixamorig:LeftHandRing3" }, + { HumanBodyBones.LeftLittleProximal, "mixamorig:LeftHandPinky1" }, + { HumanBodyBones.LeftLittleIntermediate, "mixamorig:LeftHandPinky2" }, + { HumanBodyBones.LeftLittleDistal, "mixamorig:LeftHandPinky3" }, + // 오른손 손가락 + { HumanBodyBones.RightThumbProximal, "mixamorig:RightHandThumb1" }, + { HumanBodyBones.RightThumbIntermediate, "mixamorig:RightHandThumb2" }, + { HumanBodyBones.RightThumbDistal, "mixamorig:RightHandThumb3" }, + { HumanBodyBones.RightIndexProximal, "mixamorig:RightHandIndex1" }, + { HumanBodyBones.RightIndexIntermediate, "mixamorig:RightHandIndex2" }, + { HumanBodyBones.RightIndexDistal, "mixamorig:RightHandIndex3" }, + { HumanBodyBones.RightMiddleProximal, "mixamorig:RightHandMiddle1" }, + { HumanBodyBones.RightMiddleIntermediate, "mixamorig:RightHandMiddle2" }, + { HumanBodyBones.RightMiddleDistal, "mixamorig:RightHandMiddle3" }, + { HumanBodyBones.RightRingProximal, "mixamorig:RightHandRing1" }, + { HumanBodyBones.RightRingIntermediate, "mixamorig:RightHandRing2" }, + { HumanBodyBones.RightRingDistal, "mixamorig:RightHandRing3" }, + { HumanBodyBones.RightLittleProximal, "mixamorig:RightHandPinky1" }, + { HumanBodyBones.RightLittleIntermediate, "mixamorig:RightHandPinky2" }, + { HumanBodyBones.RightLittleDistal, "mixamorig:RightHandPinky3" }, + }; + + // UpperChest가 없는 경우 무시 + foreach (var kvp in mixamoMap) + { + if (kvp.Key == HumanBodyBones.UpperChest) + { + var upperChest = selectedAnimator.GetBoneTransform(HumanBodyBones.UpperChest); + if (upperChest == null) continue; + upperChest.name = kvp.Value; + Debug.Log($"UpperChest 본이 있어 이름을 {kvp.Value}로 변경"); + continue; + } + var bone = selectedAnimator.GetBoneTransform(kvp.Key); + if (bone != null) + { + bone.name = kvp.Value; + Debug.Log($"{kvp.Key} 이름을 {kvp.Value}로 변경"); + } + } + Debug.Log("믹사모 네이밍으로 일괄 변경 완료!"); + } }