창 올라타기

This commit is contained in:
2026-08-26 11:01:56 +09:00
parent 65024110df
commit cab0d772b1
18 changed files with 1335 additions and 31 deletions

View File

@@ -12,6 +12,52 @@
/// </summary>
public static class DesktopCursor
{
/// <summary>
/// 데스크톱 물리 좌표(Y 아래로) <-> Unity 화면 좌표(Y 위로) 변환에 필요한 정보.
/// 창 사각형을 매번 다시 묻지 않도록 한 번 만들어 재사용한다.
/// </summary>
public struct Mapping
{
public int Left, Top, Width, Height;
public float ScaleX, ScaleY;
public float ToScreenX(float desktopX) => (desktopX - Left) * ScaleX;
public float ToScreenY(float desktopY) => (Height - (desktopY - Top)) * ScaleY;
public Vector2 ToScreen(float desktopX, float desktopY)
=> new Vector2(ToScreenX(desktopX), ToScreenY(desktopY));
}
/// <summary>우리 창을 기준으로 한 좌표 변환 정보를 구한다.</summary>
public static bool TryGetMapping(System.IntPtr hwnd, out Mapping mapping)
{
mapping = default;
#if !UNITY_EDITOR && UNITY_STANDALONE_WIN
if (hwnd == System.IntPtr.Zero) return false;
if (!Win32.GetWindowRect(hwnd, out var rc)) return false;
if (rc.Width <= 0 || rc.Height <= 0) return false;
mapping = new Mapping
{
Left = rc.left,
Top = rc.top,
Width = rc.Width,
Height = rc.Height,
// 창 크기와 백버퍼 크기가 어긋날 경우를 대비해 비율로 환산한다.
ScaleX = Screen.width / (float)rc.Width,
ScaleY = Screen.height / (float)rc.Height,
};
return true;
#else
mapping = new Mapping
{
Left = 0, Top = 0, Width = Screen.width, Height = Screen.height,
ScaleX = 1f, ScaleY = 1f,
};
return true;
#endif
}
/// <summary>
/// 커서의 Unity 화면 좌표(좌하단 원점)를 구한다. 커서가 창 밖이면 false.
/// </summary>
@@ -20,22 +66,14 @@ public static bool TryGetScreenPosition(System.IntPtr hwnd, out Vector2 screenPo
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;
if (!TryGetMapping(hwnd, out Mapping map)) return false;
int w = rc.Width, h = rc.Height;
if (w <= 0 || h <= 0) return false;
// 창 밖이면 무효로 본다.
if (pt.x < map.Left || pt.y < map.Top ||
pt.x >= map.Left + map.Width || pt.y >= map.Top + map.Height) 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));
screenPos = map.ToScreen(pt.x, pt.y);
return true;
#else
// 에디터에서는 일반 마우스 입력으로 대체해 미리보기가 가능하게 한다.