using UnityEngine; using UnityEditor; [CustomEditor(typeof(FingerShapedController))] public class FingerShapedControllerEditor : Editor { private bool showLeftHand = true; private bool showRightHand = true; private const float SLIDER_HEIGHT = 100f; private const float SLIDER_WIDTH = 25f; private const float SPACING = 5f; public override void OnInspectorGUI() { FingerShapedController controller = (FingerShapedController)target; // 활성화/비활성화 토글 EditorGUI.BeginChangeCheck(); bool isEnabled = EditorGUILayout.Toggle("손가락 제어 활성화", controller.enabled); if (EditorGUI.EndChangeCheck()) { controller.enabled = isEnabled; EditorUtility.SetDirty(controller); } if (!controller.enabled) return; serializedObject.Update(); // 왼손/오른손 컨트롤 DrawHandControls("왼손", "left", ref showLeftHand); EditorGUILayout.Space(SPACING); DrawHandControls("오른손", "right", ref showRightHand); EditorGUILayout.Space(SPACING); // 프리셋 버튼들 DrawPresetButtons(controller); serializedObject.ApplyModifiedProperties(); } private void DrawHandControls(string label, string prefix, ref bool foldout) { EditorGUILayout.BeginVertical(EditorStyles.helpBox); // 헤더 줄 EditorGUILayout.BeginHorizontal(); // 폴드아웃과 활성화 토글을 나란히 배치 EditorGUILayout.BeginHorizontal(GUILayout.Width(200)); foldout = EditorGUILayout.Foldout(foldout, label, true); SerializedProperty handEnabledProp = serializedObject.FindProperty($"{prefix}HandEnabled"); bool handEnabled = EditorGUILayout.Toggle("제어 활성화", handEnabledProp.boolValue); if (handEnabled != handEnabledProp.boolValue) { handEnabledProp.boolValue = handEnabled; if (handEnabled && !((FingerShapedController)target).enabled) { ((FingerShapedController)target).enabled = true; } } EditorGUILayout.EndHorizontal(); // 초기화 버튼 if (GUILayout.Button("초기화", GUILayout.Width(60))) { ResetHandValues(prefix); } EditorGUILayout.EndHorizontal(); // 해당 손이 활성화된 경우에만 컨트롤 표시 if (foldout && handEnabledProp.boolValue) { EditorGUILayout.Space(SPACING); DrawFingerSliders(prefix); EditorGUILayout.Space(SPACING); DrawSpreadSlider(prefix); } EditorGUILayout.EndVertical(); } private void DrawFingerSliders(string prefix) { string[] fingerNames = { "Thumb", "Index", "Middle", "Ring", "Pinky" }; float totalWidth = (SLIDER_WIDTH + SPACING) * fingerNames.Length; EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); EditorGUILayout.BeginHorizontal(GUILayout.Width(totalWidth)); for (int i = 0; i < fingerNames.Length; i++) { EditorGUILayout.BeginVertical(GUILayout.Width(SLIDER_WIDTH)); // 손가락 이름 GUILayout.Label(GetKoreanFingerName(fingerNames[i]), EditorStyles.centeredGreyMiniLabel, GUILayout.Width(SLIDER_WIDTH)); // 값 표시 SerializedProperty prop = serializedObject.FindProperty($"{prefix}{fingerNames[i]}Curl"); GUILayout.Label(prop.floatValue.ToString("F1"), EditorStyles.centeredGreyMiniLabel, GUILayout.Width(SLIDER_WIDTH)); // 세로 슬라이더를 중앙에 배치 EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); prop.floatValue = GUILayout.VerticalSlider( prop.floatValue, 1f, -1f, GUILayout.Width(SLIDER_WIDTH), GUILayout.Height(SLIDER_HEIGHT) ); GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); if (i < fingerNames.Length - 1) GUILayout.Space(SPACING); } EditorGUILayout.EndHorizontal(); GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); } private string GetKoreanFingerName(string englishName) { switch (englishName) { case "Thumb": return "엄지"; case "Index": return "검지"; case "Middle": return "중지"; case "Ring": return "약지"; case "Pinky": return "새끼"; default: return englishName; } } private void DrawSpreadSlider(string prefix) { SerializedProperty spreadProp = serializedObject.FindProperty($"{prefix}SpreadFingers"); EditorGUILayout.BeginHorizontal(); GUILayout.Space(15); EditorGUILayout.LabelField("벌리기", GUILayout.Width(50)); spreadProp.floatValue = EditorGUILayout.Slider(spreadProp.floatValue, -1f, 1f); GUILayout.Space(15); EditorGUILayout.EndHorizontal(); } private void DrawPresetButtons(FingerShapedController controller) { EditorGUILayout.LabelField("손 모양 프리셋", EditorStyles.boldLabel); string[,] presets = { {"가위", "바위", "보"}, {"브이", "검지", "초기화"} }; for (int row = 0; row < 2; row++) { EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); // 왼쪽 여백 추가 for (int col = 0; col < 3; col++) { if (GUILayout.Button(presets[row, col], GUILayout.Height(30), GUILayout.Width(100))) { ApplyPreset(controller, presets[row, col]); } if (col < 2) // 마지막 버튼 이전까지만 간격 추가 { GUILayout.Space(10); } } GUILayout.FlexibleSpace(); // 오른쪽 여백 추가 EditorGUILayout.EndHorizontal(); if (row < 1) // 행 사이 간격 { GUILayout.Space(5); } } } private void ResetHandValues(string prefix) { string[] props = { "ThumbCurl", "IndexCurl", "MiddleCurl", "RingCurl", "PinkyCurl", "SpreadFingers" }; foreach (var prop in props) { serializedObject.FindProperty($"{prefix}{prop}").floatValue = 0f; } } private void ApplyPreset(FingerShapedController controller, string presetName) { // 프리셋 적용 시 양손 모두 활성화 if (!controller.enabled) { controller.enabled = true; } switch (presetName) { case "가위": SetPreset(controller, 1f, 1f, -1f, -1f, -1f, 0.3f); break; case "바위": SetPreset(controller, -1f, -1f, -1f, -1f, -1f, 0f); break; case "보": SetPreset(controller, 1f, 1f, 1f, 1f, 1f, 1f); break; case "브이": SetPreset(controller, -1f, 1f, 1f, -1f, -1f, 1f); break; case "검지": SetPreset(controller, -1f, 1f, -1f, -1f, -1f, 0f); break; case "초기화": SetPreset(controller, 0.8f, 0.8f, 0.8f, 0.8f, 0.8f, 0.8f); break; } } private void SetPreset(FingerShapedController controller, float thumb, float index, float middle, float ring, float pinky, float spread) { // 왼손이 활성화된 경우에만 왼손 값 설정 if (controller.leftHandEnabled) { controller.leftThumbCurl = thumb; controller.leftIndexCurl = index; controller.leftMiddleCurl = middle; controller.leftRingCurl = ring; controller.leftPinkyCurl = pinky; controller.leftSpreadFingers = spread; } // 오른손이 활성화된 경우에만 오른손 값 설정 if (controller.rightHandEnabled) { controller.rightThumbCurl = thumb; controller.rightIndexCurl = index; controller.rightMiddleCurl = middle; controller.rightRingCurl = ring; controller.rightPinkyCurl = pinky; controller.rightSpreadFingers = spread; } EditorUtility.SetDirty(controller); } }