Want to get the location of the GameView Window

I’m trying to make a macro recorder/player for the Unity editor, and I’m having trouble with the mouse input. I’m using this library (https://inputsimulator.codeplex.com/) to set the mouse position and simulate clicks, as I couldn’t find a way to do it in Unity. The problem is that I need to know the location of the currently active game view in order to determine where on the monitor to position the cursor.

The following code:

public static EditorWindow GetMainGameView()
{
    System.Reflection.Assembly assembly = typeof(UnityEditor.EditorWindow).Assembly;
    Type type = assembly.GetType("UnityEditor.GameView");
    EditorWindow gameview = EditorWindow.GetWindow(type);
    return gameview;
}

gets me a reference to the GameView, but I couldn’t find the information I needed in that class (position.x and position.y only tell me the offset of the drawing area relative to the tab). So does anyone know how I can find the GameView location relative to the monitor in Windows?

I think I got it figured out …

EDIT: changed it all again.

EDIT 2: added a windows implementation of wkwan’s idea (see comments)

The short way on Windows:

  • parameters: master.width / master.height is the resolution we wanted to have
  • Screen.width / Screen.height is what Unity is running atm.

This solution is used to convert screen-coordinate input into pixel-exact positions referring to a (master.width, master.height) - resolution.

[StructLayout( LayoutKind.Sequential )]
public struct POINT
{
	public int X;
	public int Y;
	public static implicit operator Vector2( POINT p )
	{
		return new Vector2( p.X, p.Y );
	}
}
[DllImport( "user32.dll" )][return: MarshalAs( UnmanagedType.Bool )]
static extern bool GetCursorPos( out POINT lpPoint );

public static void Init( PanoramaMaster master )
{
	Vector2 inputCursor = Input.mousePosition;
	// flip input Cursor y (as the Reference "0" is the last scanline)
	inputCursor.y = Screen.height - 1 - inputCursor.y;
	POINT p;
	GetCursorPos( out p );
	renderRegionOffset = p - inputCursor;
	renderRegionScale = new Vector2( (float) master.width / Screen.width, (float) master.height / Screen.height );
	Debug.Log( "Scale:  " + renderRegionScale + "

Offset: " + renderRegionOffset + "
" );
}

Don’t do it like this:
Earlier I came up with the following function, which gets the offset of the gameView’s rendering region within its containing window’s client region. I.e. Unity, or the window around a stand-alone gameview. Then I found some nice WinAPI references to find the missing pieces (window position, size of decorations):

[DllImport( "user32.dll" )]
static extern int GetSystemMetrics( SystemMetric smIndex );
[DllImport( "user32.dll" )]
static extern IntPtr GetActiveWindow();
[DllImport( "user32.dll", SetLastError = true )]
static extern bool GetWindowRect( IntPtr hwnd, out RECT lpRect );
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
    public int Left, Top, Right, Bottom;
    
    public override string ToString()
    {
        return string.Format( System.Globalization.CultureInfo.CurrentCulture, "{{Left={0},Top={1},Right={2},Bottom={3}}}", Left, Top, Right, Bottom );
    }
}
public enum SystemMetric : int
{
    SM_CXSCREEN = 0,  // 0x00
    SM_CYSCREEN = 1,  // 0x01
    SM_CXVSCROLL = 2,  // 0x02
    SM_CYHSCROLL = 3,  // 0x03
    SM_CYCAPTION = 4,  // 0x04
    SM_CXBORDER = 5,  // 0x05
    SM_CYBORDER = 6,  // 0x06
    // [...] shortened ...
}

public static Vector2 PixelOffsetFromScreen()
{
    System.Type T = System.Type.GetType( "UnityEditor.GameView,UnityEditor" );

    EditorWindow gameview = EditorWindow.GetWindow( T );
    Rect Pom = gameview.position;

    System.Reflection.MethodInfo RenderRect = T.GetMethod( "GetMainGameViewRenderRect", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static );
    Rect ReRe = (Rect) RenderRect.Invoke( null, null );

    RECT WinR;
    GetWindowRect( GetActiveWindow(), out WinR );
    int bw = GetSystemMetrics( SystemMetric.SM_CXBORDER );
    int bh = GetSystemMetrics( SystemMetric.SM_CYBORDER );
    int ch = GetSystemMetrics( SystemMetric.SM_CYCAPTION );
    // try to retrieve the Window's client rect and its position on screen
    Vector2 Res;
    Res = new Vector2( WinR.Left + bw + Pom.xMin + ReRe.xMin, WinR.Top + ch + bh + Pom.yMin + ReRe.yMin );
    return Res;
}

The final cut it needs: make it also work with a compiled game, where there’s no editor available …