53 lines
2.0 KiB
C#
53 lines
2.0 KiB
C#
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
|
|
/// <summary>
|
|
/// OS 커서 위치를 Unity 화면 좌표로 변환한다.
|
|
///
|
|
/// 우리 창은 WS_EX_NOACTIVATE 라 포커스를 받지 않으므로 Unity 의 Mouse.position 을
|
|
/// 신뢰할 수 없다. 또 창 밖 좌표는 Unity 가 아예 모른다. 그래서 GetCursorPos 로
|
|
/// OS 커서를 직접 읽고 창 사각형 기준으로 환산한다.
|
|
///
|
|
/// 히트테스트와 시선 추적이 같은 변환을 쓰므로 여기 한 곳에만 둔다.
|
|
/// </summary>
|
|
public static class DesktopCursor
|
|
{
|
|
/// <summary>
|
|
/// 커서의 Unity 화면 좌표(좌하단 원점)를 구한다. 커서가 창 밖이면 false.
|
|
/// </summary>
|
|
public static bool TryGetScreenPosition(System.IntPtr hwnd, out Vector2 screenPos)
|
|
{
|
|
screenPos = default;
|
|
|
|
#if !UNITY_EDITOR && UNITY_STANDALONE_WIN
|
|
if (hwnd == System.IntPtr.Zero) return false;
|
|
if (!Win32.GetCursorPos(out var pt)) return false;
|
|
if (!Win32.GetWindowRect(hwnd, out var rc)) return false;
|
|
|
|
int w = rc.Width, h = rc.Height;
|
|
if (w <= 0 || h <= 0) return false;
|
|
|
|
// 창 기준 좌표 (좌상단 원점, Y 아래로)
|
|
int localX = pt.x - rc.left;
|
|
int localY = pt.y - rc.top;
|
|
if (localX < 0 || localY < 0 || localX >= w || localY >= h) return false;
|
|
|
|
// Unity 화면 좌표로. 창 크기와 백버퍼 크기가 어긋날 경우를 대비해 비율 환산.
|
|
screenPos = new Vector2(
|
|
localX * (Screen.width / (float)w),
|
|
(h - localY) * (Screen.height / (float)h));
|
|
return true;
|
|
#else
|
|
// 에디터에서는 일반 마우스 입력으로 대체해 미리보기가 가능하게 한다.
|
|
var mouse = Mouse.current;
|
|
if (mouse == null) return false;
|
|
|
|
Vector2 p = mouse.position.ReadValue();
|
|
if (p.x < 0f || p.y < 0f || p.x >= Screen.width || p.y >= Screen.height) return false;
|
|
|
|
screenPos = p;
|
|
return true;
|
|
#endif
|
|
}
|
|
}
|