213 lines
7.0 KiB
C#

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<CameraControlSystem>();
if (cameraControlSystem == null)
{
Debug.LogWarning("[InputHandler] CameraControlSystem을 찾을 수 없습니다.");
}
}
/// <summary>
/// Unity 포커스 콜백 - 포커스 복귀 시 입력 무시 프레임 설정
/// </summary>
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;
/// <summary>
/// 현재 어떤 입력 모드도 활성화되지 않았는지 확인합니다.
/// </summary>
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);
}
}