#if UNITY_EDITOR using GameCore; using System; using System.Reflection; using UnityEditor; using UnityEngine; using static GlobalUtils; public static class GameViewUtils { static object gameViewSizesInstance; static MethodInfo getGroup; static MethodInfo snapZoom; static MethodInfo updateZoom; static GameViewUtils() { var sizesType = typeof(Editor).Assembly.GetType("UnityEditor.GameViewSizes"); var singleType = typeof(ScriptableSingleton<>).MakeGenericType(sizesType); var instanceProp = singleType.GetProperty("instance"); getGroup = sizesType.GetMethod("GetGroup"); gameViewSizesInstance = instanceProp.GetValue(null, null); var viewType = typeof(Editor).Assembly.GetType("UnityEditor.GameView"); snapZoom = viewType.GetMethod("SnapZoom", BindingFlags.Instance | BindingFlags.NonPublic); updateZoom = viewType.GetMethod("UpdateZoomAreaAndParent", BindingFlags.Instance | BindingFlags.NonPublic); } public enum GameViewSizeType { AspectRatio, FixedResolution } //[MenuItem("Test/AddSize")] //public static void AddTestSize() //{ // AddCustomSize(GameViewSizeType.AspectRatio, GameViewSizeGroupType.Standalone, 123, 456, "Test size"); //} //[MenuItem("Test/SizeTextQuery")] //public static void SizeTextQueryTest() //{ // Debug.Log(SizeExists(GameViewSizeGroupType.Standalone, "Test size")); //} //[MenuItem("Test/Query16:9Test")] //public static void WidescreenQueryTest() //{ // Debug.Log(SizeExists(GameViewSizeGroupType.Standalone, "16:9")); //} //[MenuItem("Test/Set16:9")] //public static void SetWidescreenTest() //{ // SetSize(FindSize(GameViewSizeGroupType.Standalone, "16:9")); //} //[MenuItem("Test/SetTestSize")] //public static void SetTestSize() //{ // int idx = FindSize(GameViewSizeGroupType.Standalone, 123, 456); // if (idx != -1) // SetSize(idx); //} // Set Game View windows resolution index public static void SetSize(int index) { var gvWndType = typeof(Editor).Assembly.GetType("UnityEditor.GameView"); var selectedSizeIndexProp = gvWndType.GetProperty("selectedSizeIndex", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); var gvWnd = EditorWindow.GetWindow(gvWndType); selectedSizeIndexProp.SetValue(gvWnd, index, null); // Update zoom to make sure minScale is reflect the right value updateZoom.Invoke(gvWnd, null); var minScaleProperty = gvWndType.GetProperty("minScale", BindingFlags.Instance | BindingFlags.NonPublic); var set_scale = (float)minScaleProperty.GetValue(gvWnd, null); SnapZoom(gvWnd, set_scale); // Another way to setup game view window scale /*var areaField = gvWndType.GetField("m_ZoomArea", BindingFlags.Instance | BindingFlags.NonPublic); var areaObj = areaField.GetValue(gvWnd); var scaleField = areaObj.GetType().GetField("m_Scale", BindingFlags.Instance | BindingFlags.NonPublic); scaleField.SetValue(areaObj, new Vector2(set_scale, set_scale));*/ } // Set Game View windows resolution index public static void SetSize(int index, EditorWindow gameview_window) { var gvWndType = typeof(Editor).Assembly.GetType("UnityEditor.GameView"); var selectedSizeIndexProp = gvWndType.GetProperty("selectedSizeIndex", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); selectedSizeIndexProp.SetValue(gameview_window, index, null); // Update zoom to make sure minScale is reflect the right value updateZoom.Invoke(gameview_window, null); var minScaleProperty = gvWndType.GetProperty("minScale", BindingFlags.Instance | BindingFlags.NonPublic); var set_scale = (float)minScaleProperty.GetValue(gameview_window, null); SnapZoom(gameview_window, set_scale); // Another way to setup game view window scale /*var areaField = gvWndType.GetField("m_ZoomArea", BindingFlags.Instance | BindingFlags.NonPublic); var areaObj = areaField.GetValue(gvWnd); var scaleField = areaObj.GetType().GetField("m_Scale", BindingFlags.Instance | BindingFlags.NonPublic); scaleField.SetValue(areaObj, new Vector2(set_scale, set_scale));*/ } public static void AddCustomSize(GameViewSizeType viewSizeType, GameViewSizeGroupType sizeGroupType, int width, int height, string text) { // GameViewSizes group = gameViewSizesInstance.GetGroup(sizeGroupTyge); // group.AddCustomSize(new GameViewSize(viewSizeType, width, height, text); var group = GetGroup(sizeGroupType); var addCustomSize = getGroup.ReturnType.GetMethod("AddCustomSize"); // or group.GetType(). var gvsType = typeof(Editor).Assembly.GetType("UnityEditor.GameViewSize"); var ctor = gvsType.GetConstructor(new Type[] { typeof(int), typeof(int), typeof(int), typeof(string) }); var newSize = ctor.Invoke(new object[] { (int)viewSizeType, width, height, text }); addCustomSize.Invoke(group, new object[] { newSize }); } public static bool SizeExists(GameViewSizeGroupType sizeGroupType, string text) { return FindSize(sizeGroupType, text) != -1; } public static int FindSize(GameViewSizeGroupType sizeGroupType, string text) { // GameViewSizes group = gameViewSizesInstance.GetGroup(sizeGroupType); // string[] texts = group.GetDisplayTexts(); // for loop... var group = GetGroup(sizeGroupType); var getDisplayTexts = group.GetType().GetMethod("GetDisplayTexts"); var displayTexts = getDisplayTexts.Invoke(group, null) as string[]; for (int i = 0; i < displayTexts.Length; i++) { string display = displayTexts[i]; // the text we get is "Name (W:H)" if the size has a name, or just "W:H" e.g. 16:9 // so if we're querying a custom size text we substring to only get the name // You could see the outputs by just logging // Debug.Log(display); int pren = display.IndexOf('('); if (pren != -1) { display = display.Substring(0, pren - 1); // -1 to remove the space that's before the prens. This is very implementation-depdenent } if (display == text) { return i; } } return -1; } public static bool SizeExists(GameViewSizeGroupType sizeGroupType, int width, int height) { return FindSize(sizeGroupType, width, height) != -1; } public static int FindSize(GameViewSizeGroupType sizeGroupType, int width, int height) { // goal: // GameViewSizes group = gameViewSizesInstance.GetGroup(sizeGroupType); // int sizesCount = group.GetBuiltinCount() + group.GetCustomCount(); // iterate through the sizes via group.GetGameViewSize(int index) var group = GetGroup(sizeGroupType); var groupType = group.GetType(); var getBuiltinCount = groupType.GetMethod("GetBuiltinCount"); var getCustomCount = groupType.GetMethod("GetCustomCount"); int sizesCount = (int)getBuiltinCount.Invoke(group, null) + (int)getCustomCount.Invoke(group, null); var getGameViewSize = groupType.GetMethod("GetGameViewSize"); var gvsType = getGameViewSize.ReturnType; var widthProp = gvsType.GetProperty("width"); var heightProp = gvsType.GetProperty("height"); var indexValue = new object[1]; for (int i = 0; i < sizesCount; i++) { indexValue[0] = i; var size = getGameViewSize.Invoke(group, indexValue); int sizeWidth = (int)widthProp.GetValue(size, null); int sizeHeight = (int)heightProp.GetValue(size, null); if (sizeWidth == width && sizeHeight == height) { return i; } } return -1; } static object GetGroup(GameViewSizeGroupType type) { return getGroup.Invoke(gameViewSizesInstance, new object[] { (int)type }); } static void SnapZoom(object gameviwe_window, float new_zoom) { snapZoom.Invoke(gameviwe_window, new object[] { new_zoom }); } public static GameViewSizeGroupType GetCurrentGroupType() { var getCurrentGroupTypeProp = gameViewSizesInstance.GetType().GetProperty("currentGroupType"); return (GameViewSizeGroupType)(int)getCurrentGroupTypeProp.GetValue(gameViewSizesInstance, null); } public static void switchOrientation() { int width = Screen.height; int height = Screen.width; int index = FindSize(GetCurrentGroupType(), width, height); if (index == -1) { AddCustomSize(GameViewSizeType.FixedResolution, GetCurrentGroupType(), width, height, ""); index = FindSize(GetCurrentGroupType(), width, height); } if (index != -1) { SetSize(index); } else { Debug.LogError($"[GameViewUtils]switchOrientation: can not find or add resoulution for {width}x{height}"); } } public static ScreenType GetGameViewType(EditorWindow gameview_window) { var type = ScreenType.INVALID; var gvWndType = typeof(Editor).Assembly.GetType("UnityEditor.GameView"); var gameViewSizeType = typeof(Editor).Assembly.GetType("UnityEditor.GameViewSize"); var widthProp = gameViewSizeType.GetProperty("width"); var heightProp = gameViewSizeType.GetProperty("height"); var gameViewSizeProperty = gvWndType.GetProperty("currentGameViewSize", BindingFlags.Instance | BindingFlags.NonPublic); var gameViewSize = gameViewSizeProperty.GetValue(gameview_window, null); int sizeWidth = (int)widthProp.GetValue(gameViewSize, null); int sizeHeight = (int)heightProp.GetValue(gameViewSize, null); if(sizeWidth >= sizeHeight) { type = ScreenType.LANDSCAPE; } else { type = ScreenType.PORTRAIT; } return type; } } #endif