using UnityEngine; using UnityEditor; using UnityRawInput; using System.Collections.Generic; using System.Linq; using Unity.Cinemachine; [CustomEditor(typeof(CameraManager))] public class CameraManagerEditor : Editor { private HashSet currentKeys = new HashSet(); private bool isApplicationPlaying; private bool isListening = false; private void OnEnable() { isApplicationPlaying = Application.isPlaying; } private void OnDisable() { StopListening(); } private void StartListening() { if (!isApplicationPlaying) { currentKeys.Clear(); isListening = true; Debug.Log("키보드 입력 감지 시작"); } } private void StopListening() { isListening = false; } public override void OnInspectorGUI() { CameraManager manager = (CameraManager)target; EditorGUILayout.Space(10); EditorGUILayout.BeginVertical(EditorStyles.helpBox); EditorGUILayout.LabelField("카메라 프리셋 관리", EditorStyles.boldLabel); EditorGUILayout.Space(5); // 프리셋 추가 버튼 if (GUILayout.Button("새 프리셋 추가", GUILayout.Height(30))) { // Scene에 있는 CinemachineCamera 컴포넌트를 가져와서 새 프리셋 생성 var newCamera = FindFirstObjectByType(); if (newCamera != null) { manager.cameraPresets.Add(new CameraManager.CameraPreset(newCamera)); EditorUtility.SetDirty(target); } else { EditorUtility.DisplayDialog("알림", "Scene에 CinemachineCamera가 없습니다.", "확인"); } } EditorGUILayout.Space(10); // 프리셋 리스트 for (int i = 0; i < manager.cameraPresets.Count; i++) { var preset = manager.cameraPresets[i]; EditorGUILayout.BeginVertical(GUI.skin.box); // 프리셋 헤더 EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField($"프리셋 {i + 1}", EditorStyles.boldLabel, GUILayout.Width(60)); // 프리셋 이름 필드 preset.presetName = EditorGUILayout.TextField(preset.presetName); // 삭제 버튼 if (GUILayout.Button("삭제", GUILayout.Width(50))) { if (EditorUtility.DisplayDialog("프리셋 삭제", $"프리셋 {preset.presetName}을(를) 삭제하시겠습니까?", "삭제", "취소")) { manager.cameraPresets.RemoveAt(i); EditorUtility.SetDirty(target); continue; } } EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(5); // 프리셋 설정 EditorGUI.indentLevel++; // 가상 카메라 필드 preset.virtualCamera = (CinemachineCamera)EditorGUILayout.ObjectField( "가상 카메라", preset.virtualCamera, typeof(CinemachineCamera), true); // 핫키 설정 UI EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("핫키", GUILayout.Width(100)); if (preset.hotkey.isRecording) { EditorGUILayout.LabelField("키를 눌렀다 떼면 저장됩니다...", EditorStyles.helpBox); } else { EditorGUILayout.LabelField(preset.hotkey.ToString()); if (GUILayout.Button("레코딩", GUILayout.Width(60))) { foreach (var otherPreset in manager.cameraPresets) { otherPreset.hotkey.isRecording = false; } preset.hotkey.isRecording = true; preset.hotkey.rawKeys.Clear(); StartListening(); } if (GUILayout.Button("초기화", GUILayout.Width(60))) { preset.hotkey.rawKeys.Clear(); EditorUtility.SetDirty(target); } } EditorGUILayout.EndHorizontal(); EditorGUI.indentLevel--; EditorGUILayout.EndVertical(); EditorGUILayout.Space(5); } EditorGUILayout.EndVertical(); // 키 입력 감지 로직 if (isListening) { var e = Event.current; if (e != null) { if (e.type == EventType.KeyDown && e.keyCode != KeyCode.None) { // 마우스 버튼 제외 if (e.keyCode != KeyCode.Mouse0 && e.keyCode != KeyCode.Mouse1 && e.keyCode != KeyCode.Mouse2) { AddKey(e.keyCode); e.Use(); // 이벤트 소비 } } else if (e.type == EventType.KeyUp && currentKeys.Contains(e.keyCode)) { var recordingPreset = manager.cameraPresets.FirstOrDefault(p => p.hotkey.isRecording); if (recordingPreset != null) { recordingPreset.hotkey.isRecording = false; EditorUtility.SetDirty(target); StopListening(); Repaint(); } e.Use(); // 이벤트 소비 } } } } private void AddKey(KeyCode keyCode) { if (!currentKeys.Contains(keyCode)) { currentKeys.Add(keyCode); var recordingPreset = ((CameraManager)target).cameraPresets.FirstOrDefault(p => p.hotkey.isRecording); if (recordingPreset != null) { // KeyCode를 RawKey로 변환 var rawKeys = new List(); foreach (var key in currentKeys) { if (RawKeySetup.KeyMapping.TryGetValue(key, out RawKey rawKey)) { rawKeys.Add(rawKey); } else { Debug.LogWarning($"맵핑되지 않은 키: {key}"); } } recordingPreset.hotkey.rawKeys = rawKeys; EditorUtility.SetDirty(target); Repaint(); } } } }