using UnityEngine; using UnityEditor; using System.IO; using UniHumanoid; using UniGLTF; [System.Serializable] public class HumanPoseData { public Vector3 bodyPosition; public Quaternion bodyRotation; public float[] muscles; } public class HumanPoseClipApplier : EditorWindow { private Animator targetAnimator; private HumanPoseClip poseClip; private string jsonPath; private bool useJsonFile = false; [MenuItem("Tools/Animation Tools/Human Pose Clip Applier")] public static void ShowWindow() { GetWindow("Human Pose Clip Applier"); } private void OnGUI() { GUILayout.Label("Apply Human Pose Clip to Animator", EditorStyles.boldLabel); EditorGUILayout.Space(); targetAnimator = (Animator)EditorGUILayout.ObjectField("Target Animator", targetAnimator, typeof(Animator), true); EditorGUILayout.Space(); useJsonFile = EditorGUILayout.Toggle("Use JSON File", useJsonFile); if (useJsonFile) { EditorGUILayout.BeginHorizontal(); jsonPath = EditorGUILayout.TextField("JSON File Path", jsonPath); if (GUILayout.Button("Browse", GUILayout.Width(60))) { string path = EditorUtility.OpenFilePanel("Select JSON File", "", "json"); if (!string.IsNullOrEmpty(path)) { jsonPath = path; } } EditorGUILayout.EndHorizontal(); } else { poseClip = (HumanPoseClip)EditorGUILayout.ObjectField("Pose Clip", poseClip, typeof(HumanPoseClip), false); } EditorGUILayout.Space(); bool canApply = targetAnimator != null && ((useJsonFile && !string.IsNullOrEmpty(jsonPath)) || (!useJsonFile && poseClip != null)); GUI.enabled = canApply; if (GUILayout.Button("Apply Pose Clip")) { ApplyPoseClip(); } GUI.enabled = true; } private void ApplyPoseClip() { if (targetAnimator == null) { EditorUtility.DisplayDialog("Error", "Please select an Animator!", "OK"); return; } HumanPose pose; if (useJsonFile) { if (string.IsNullOrEmpty(jsonPath) || !File.Exists(jsonPath)) { EditorUtility.DisplayDialog("Error", "Please select a valid JSON file!", "OK"); return; } // JSON 파일에서 데이터 로드 string jsonContent = File.ReadAllText(jsonPath); HumanPoseData poseData = JsonUtility.FromJson(jsonContent); // HumanPose로 변환 pose = new HumanPose { bodyPosition = poseData.bodyPosition, bodyRotation = poseData.bodyRotation, muscles = poseData.muscles }; } else if (poseClip != null) { pose = poseClip.GetPose(); } else { EditorUtility.DisplayDialog("Error", "Please select a Pose Clip!", "OK"); return; } var animator = targetAnimator; var avatar = animator.avatar; if (avatar == null || !avatar.isHuman) { EditorUtility.DisplayDialog("Error", "Selected Animator must have a Humanoid Avatar!", "OK"); return; } try { // HumanPoseHandler를 사용하여 포즈 데이터 적용 var handler = new HumanPoseHandler(avatar, animator.transform); // 포즈 적용 handler.SetHumanPose(ref pose); // 변경사항 저장 EditorUtility.SetDirty(animator); Debug.Log("Pose clip has been applied to the Animator"); EditorUtility.DisplayDialog("Success", "Pose clip has been applied to the Animator", "OK"); } catch (System.Exception e) { Debug.LogError($"Error applying pose clip: {e.Message}"); EditorUtility.DisplayDialog("Error", $"Failed to apply pose clip: {e.Message}", "OK"); } } }