using UnityEngine; public class InputHandler : MonoBehaviour { private Vector2 lastMousePosition; private float lastScrollValue; private bool isRightMouseHeld; private bool isMiddleMouseHeld; private bool isOrbitActive; private bool isZoomActive; private bool isCtrlRightZoomActive; private bool isFOVActive; // 현재 활성화된 입력 모드 (충돌 방지) private InputMode currentMode = InputMode.None; // 포커스 복귀 시 입력 무시를 위한 변수 private int focusIgnoreFrames = 0; private const int FOCUS_IGNORE_FRAME_COUNT = 10; // 포커스 복귀 후 무시할 프레임 수 private enum InputMode { None, Orbit, // Alt + 우클릭 또는 Alt + 좌클릭 Zoom, // Ctrl + 좌클릭 CtrlRightZoom, // Ctrl + 우클릭 FOV, // Shift + 좌클릭 또는 Shift + 우클릭 Rotation, // 우클릭 Pan // 휠클릭 } // 카메라 컨트롤 시스템 참조 private CameraControlSystem cameraControlSystem; private void Start() { // CameraControlSystem 찾기 cameraControlSystem = FindAnyObjectByType(); if (cameraControlSystem == null) { Debug.LogWarning("[InputHandler] CameraControlSystem을 찾을 수 없습니다."); } } /// /// Unity 포커스 콜백 - 포커스 복귀 시 입력 무시 프레임 설정 /// private void OnApplicationFocus(bool hasFocus) { if (hasFocus) { // 포커스 복귀 시 누적된 스크롤 입력 무시 focusIgnoreFrames = FOCUS_IGNORE_FRAME_COUNT; } else { // 포커스 해제 시 상태 리셋 currentMode = InputMode.None; isOrbitActive = false; isZoomActive = false; isCtrlRightZoomActive = false; isFOVActive = false; isRightMouseHeld = false; isMiddleMouseHeld = false; lastScrollValue = 0f; } } private void Update() { // 포커스가 없으면 입력 무시 if (!Application.isFocused) { return; } // 포커스 복귀 후 무시 프레임 카운트다운 if (focusIgnoreFrames > 0) { focusIgnoreFrames--; // 무시 프레임 동안에는 스크롤 값을 계속 소비(버림) _ = Input.mouseScrollDelta; } // 마우스 버튼 Raw 상태 bool leftMouse = Input.GetMouseButton(0); bool rightMouse = Input.GetMouseButton(1); bool middleMouse = Input.GetMouseButton(2); bool altKey = Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt); bool ctrlKey = Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl); bool shiftKey = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift); // 모든 마우스 버튼이 해제되면 모드 리셋 if (!leftMouse && !rightMouse && !middleMouse) { currentMode = InputMode.None; } // 입력 우선순위에 따라 모드 결정 (이미 활성화된 모드가 없을 때만) if (currentMode == InputMode.None) { if (altKey && (rightMouse || leftMouse)) { currentMode = InputMode.Orbit; } else if (ctrlKey && rightMouse) { currentMode = InputMode.CtrlRightZoom; } else if (ctrlKey && leftMouse) { currentMode = InputMode.Zoom; } else if (shiftKey && (leftMouse || rightMouse)) { currentMode = InputMode.FOV; } else if (rightMouse) { currentMode = InputMode.Rotation; } else if (middleMouse) { currentMode = InputMode.Pan; } } // 현재 모드에 따라 상태 설정 isOrbitActive = (currentMode == InputMode.Orbit) && (rightMouse || leftMouse) && altKey; isZoomActive = (currentMode == InputMode.Zoom) && leftMouse && ctrlKey; isCtrlRightZoomActive = (currentMode == InputMode.CtrlRightZoom) && rightMouse && ctrlKey; isFOVActive = (currentMode == InputMode.FOV) && (leftMouse || rightMouse) && shiftKey; isRightMouseHeld = (currentMode == InputMode.Rotation) && rightMouse; isMiddleMouseHeld = (currentMode == InputMode.Pan) && middleMouse; // 모드가 해제되면 None으로 전환 if (currentMode == InputMode.Orbit && ((!rightMouse && !leftMouse) || !altKey)) { currentMode = InputMode.None; } else if (currentMode == InputMode.CtrlRightZoom && (!rightMouse || !ctrlKey)) { currentMode = InputMode.None; } else if (currentMode == InputMode.Zoom && (!leftMouse || !ctrlKey)) { currentMode = InputMode.None; } else if (currentMode == InputMode.FOV && ((!leftMouse && !rightMouse) || !shiftKey)) { currentMode = InputMode.None; } else if (currentMode == InputMode.Rotation && !rightMouse) { currentMode = InputMode.None; } else if (currentMode == InputMode.Pan && !middleMouse) { currentMode = InputMode.None; } // 마우스 위치 업데이트 lastMousePosition = Input.mousePosition; lastScrollValue = Input.mouseScrollDelta.y; } public bool IsRightMouseHeld() => isRightMouseHeld; public bool IsMiddleMouseHeld() => isMiddleMouseHeld; public bool IsOrbitActive() => isOrbitActive; public bool IsZoomActive() => isZoomActive; public bool IsCtrlRightZoomActive() => isCtrlRightZoomActive; public bool IsFOVActive() => isFOVActive; /// /// 현재 어떤 입력 모드도 활성화되지 않았는지 확인합니다. /// public bool IsIdle() => currentMode == InputMode.None; public Vector2 GetLookDelta() { // 포커스가 없으면 0 반환 if (!Application.isFocused) return Vector2.zero; return new Vector2( Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y") ); } public float GetZoomDelta() { // 포커스가 없거나 포커스 복귀 직후면 0 반환 (누적된 휠 값 무시) if (!Application.isFocused || focusIgnoreFrames > 0) return 0f; return Input.mouseScrollDelta.y; } public Vector2 GetMousePosition() { return Input.mousePosition; } // 카메라 컨트롤 시스템 관련 메서드들 public CameraControlSystem GetCameraControlSystem() { return cameraControlSystem; } public bool IsFunctionKeyPressed(KeyCode keyCode) { return Input.GetKeyDown(keyCode); } }