ro-webgl/Assets/Editor/SafeRect/SafeRectDebugTool.cs
2021-12-21 09:40:39 +08:00

352 lines
14 KiB
C#

using System;
using System.Collections;
using System.Reflection;
using UnityEditor;
using UnityEngine;
public class SafeRectDebugTool : EditorWindow
{
private class DeviceInfo
{
public string name;
public Vector2Int size;
public Rect safeArea;
public string maskTexturePath;
}
protected FieldInfo m_EditorSafeRectFieldInfo = null;
protected FieldInfo m_EditorScreenOrientationFieldInfo = null;
protected FieldInfo m_EditorMaskTextureFieldInfo = null;
protected PropertyInfo m_GameView_SelectedSizeIndex_PropertyInfo = null;
protected MethodInfo m_GetSizeOfMainGameViewMethodInfo = null;
protected MethodInfo m_GameView_GetMainGameView_MethodInfo = null;
protected MethodInfo m_GameView_UpdateZoomAreaAndParent_MethodInfo = null;
protected Type m_GameViewSizeTypeType = null;
protected Type m_GameViewSizeType = null;
protected PropertyInfo m_GameViewSize_SizeType_PropertyInfo = null;
protected PropertyInfo m_GameViewSize_Width_PropertyInfo = null;
protected PropertyInfo m_GameViewSize_Height_PropertyInfo = null;
protected ConstructorInfo m_GameViewSizeConstructorInfo = null;
protected Type m_GameViewSizesType = null;
protected Type m_GameViewSizeGroupType = null;
protected MethodInfo m_GetTotalCountMethodInfo = null;
protected MethodInfo m_GetGameViewSizeMethodInfo = null;
protected MethodInfo m_AddCustomSizesMethodInfo = null;
private SafeRectCheck m_SafeRectCheck;
private object m_GameViewSizeType_FixedResolution_Object = null;
private object m_CurrentGroupObject = null;
private DeviceInfo[] m_DeviceInfos;
private string[] m_DevicesNames;
private string[] m_ScreenOrientationNames = {
"Portrait",
"PortraitUpsideDown",
"LandscapeLeft",
"LandscapeRight"
};
private ScreenOrientation[] m_ScreenOrientationValues = {
ScreenOrientation.Portrait,
ScreenOrientation.PortraitUpsideDown,
ScreenOrientation.LandscapeLeft,
ScreenOrientation.LandscapeRight,
};
private int m_DefaultScreenOrientationIndex = 0;
private int m_CurScreenOrientationIndex = 0;
private int m_CurDeviceIndex = 0;
private bool m_Init = false;
private void InitValue()
{
m_Init = true;
m_SafeRectCheck = SafeRectCheck.Instance;
m_EditorSafeRectFieldInfo = typeof(SafeRectCheck).GetField("m_EditorSafeRect", BindingFlags.Instance | BindingFlags.NonPublic);
m_EditorScreenOrientationFieldInfo = typeof(SafeRectCheck).GetField("m_EditorScreenOrientation", BindingFlags.Instance | BindingFlags.NonPublic);
ScreenOrientation screenOrientation = (ScreenOrientation)m_EditorScreenOrientationFieldInfo.GetValue(m_SafeRectCheck);
m_EditorMaskTextureFieldInfo = typeof(SafeRectCheck).GetField("m_EditorMaskTexture", BindingFlags.Instance | BindingFlags.NonPublic);
Type gameViewType = typeof(Editor).Assembly.GetType("UnityEditor.GameView");
m_GetSizeOfMainGameViewMethodInfo = gameViewType.GetMethod("GetSizeOfMainGameView", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
Vector2 screenSize = (Vector2)m_GetSizeOfMainGameViewMethodInfo.Invoke(null, null);
m_GameView_SelectedSizeIndex_PropertyInfo = gameViewType.GetProperty("selectedSizeIndex", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
m_GameView_GetMainGameView_MethodInfo = gameViewType.GetMethod("GetMainGameView", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
m_GameView_UpdateZoomAreaAndParent_MethodInfo = gameViewType.GetMethod("UpdateZoomAreaAndParent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
m_GameViewSizeTypeType = typeof(Editor).Assembly.GetType("UnityEditor.GameViewSizeType");
m_GameViewSizeType_FixedResolution_Object = Enum.Parse(m_GameViewSizeTypeType, "FixedResolution");
m_GameViewSizeType = typeof(Editor).Assembly.GetType("UnityEditor.GameViewSize");
m_GameViewSize_SizeType_PropertyInfo = m_GameViewSizeType.GetProperty("sizeType");
m_GameViewSize_Width_PropertyInfo = m_GameViewSizeType.GetProperty("width");
m_GameViewSize_Height_PropertyInfo = m_GameViewSizeType.GetProperty("height");
m_GameViewSizeConstructorInfo = m_GameViewSizeType.GetConstructor(new Type[] { m_GameViewSizeTypeType, typeof(int), typeof(int), typeof(string) });
m_GameViewSizesType = typeof(Editor).Assembly.GetType("UnityEditor.GameViewSizes");
var singleType = typeof(ScriptableSingleton<>).MakeGenericType(m_GameViewSizesType);
var instanceProp = singleType.GetProperty("instance");
var crrentGroupProp = m_GameViewSizesType.GetProperty("currentGroup");
m_CurrentGroupObject = crrentGroupProp.GetValue(instanceProp.GetValue(null, null), null);
m_GameViewSizeGroupType = typeof(Editor).Assembly.GetType("UnityEditor.GameViewSizeGroup");
m_GetTotalCountMethodInfo = m_GameViewSizeGroupType.GetMethod("GetTotalCount");
m_GetGameViewSizeMethodInfo = m_GameViewSizeGroupType.GetMethod("GetGameViewSize");
m_AddCustomSizesMethodInfo = m_GameViewSizeGroupType.GetMethod("AddCustomSize");
if (screenSize.x > screenSize.y)
{
m_DefaultScreenOrientationIndex = 2;
screenSize = new Vector2(screenSize.y, screenSize.x);
}
else
{
m_DefaultScreenOrientationIndex = 0;
}
m_DeviceInfos = new DeviceInfo[] {
new DeviceInfo {
name = "None",
size = new Vector2Int (Mathf.CeilToInt (screenSize.x), Mathf.CeilToInt (screenSize.y)),
safeArea = new Rect (0, 0, screenSize.x, screenSize.y),
maskTexturePath = string.Empty
},
new DeviceInfo {
name = "Apple/iPad7",
size = new Vector2Int (1620, 2160),
safeArea = new Rect (0, 0, 1620, 2160),
maskTexturePath = string.Empty
},
new DeviceInfo {
name = "Apple/iPhoneX",
size = new Vector2Int (1125, 2436),
safeArea = new Rect (0, 120, 1125, 2215),
maskTexturePath = "Assets/Editor/SafeRect/Texture/AppleiPhoneX_Overlay.png"
},
new DeviceInfo {
name = "Huawei/MatePadPro",
size = new Vector2Int (1600, 2560),
safeArea = new Rect (0, 112, 1600, 2448),
maskTexturePath = "Assets/Editor/SafeRect/Texture/HuaweiMatePadPro_Overlay.png"
},
new DeviceInfo {
name = "Huawei/Mate20Pro",
size = new Vector2Int (1440, 3120),
safeArea = new Rect (0, 100, 1440, 3020),
maskTexturePath = "Assets/Editor/SafeRect/Texture/HuaweiMate20Pro_Overlay.png"
},
new DeviceInfo {
name = "OnePlus6T",
size = new Vector2Int (1080, 2340),
safeArea = new Rect (0, 79, 1080, 2261),
maskTexturePath = "Assets/Editor/SafeRect/Texture/OnePlus6T_Overlay.png"
},
new DeviceInfo {
name = "Samsung/GalaxyS10Plus",
size = new Vector2Int (1440, 3040),
safeArea = new Rect (0, 142, 1440, 2898),
maskTexturePath = "Assets/Editor/SafeRect/Texture/SamsungGalaxyS10Plus_Overlay.png"
},
new DeviceInfo {
name = "Samsung/GalaxyS10",
size = new Vector2Int (1080, 2280),
safeArea = new Rect (0, 112, 1080, 2168),
maskTexturePath = "Assets/Editor/SafeRect/Texture/SamsungGalaxyS10_Overlay.png"
},
new DeviceInfo {
name = "Samsung/GalaxyNote10Plus",
size = new Vector2Int (1080, 2280),
safeArea = new Rect (0, 85, 1080, 2195),
maskTexturePath = "Assets/Editor/SafeRect/Texture/SamsungGalaxyNote10Plus_Overlay.png"
},
};
m_DevicesNames = new string[m_DeviceInfos.Length];
for (int i = 0; i < m_DeviceInfos.Length; i++)
{
m_DevicesNames[i] = m_DeviceInfos[i].name;
}
if (m_ScreenOrientationValues[m_DefaultScreenOrientationIndex] != screenOrientation)
{
m_CurScreenOrientationIndex = m_DefaultScreenOrientationIndex;
ResetDevice();
}
}
private void OnDestroy()
{
if (Application.isPlaying)
{
ResetDevice();
}
}
public void ResetDevice()
{
if (m_Init)
{
m_Init = false;
m_CurDeviceIndex = 0;
m_CurScreenOrientationIndex = m_DefaultScreenOrientationIndex;
RefreshValue();
}
}
private void OnGUI()
{
if (!Application.isPlaying)
{
GUILayout.FlexibleSpace();
EditorGUILayout.HelpBox("目前只能在播放模式下使用", MessageType.Warning);
GUILayout.FlexibleSpace();
return;
}
if (!SafeRectCheck.Instance) return;
if (!m_SafeRectCheck) InitValue();
EditorGUILayout.Space();
int index = EditorGUILayout.Popup("模拟设备类型", m_CurDeviceIndex, m_DevicesNames);
if (m_CurDeviceIndex != index)
{
m_CurDeviceIndex = index;
RefreshValue();
}
EditorGUILayout.Space();
index = EditorGUILayout.Popup("模拟设备方向", m_CurScreenOrientationIndex, m_ScreenOrientationNames);
if (m_CurScreenOrientationIndex != index)
{
m_CurScreenOrientationIndex = index;
RefreshValue();
}
EditorGUILayout.Space();
}
private void RefreshValue()
{
DeviceInfo deviceInfo = m_DeviceInfos[m_CurDeviceIndex];
ScreenOrientation screenOrientation = m_ScreenOrientationValues[m_CurScreenOrientationIndex];
int width = deviceInfo.size.x;
int height = deviceInfo.size.y;
Rect safeArea = new Rect(deviceInfo.safeArea);
#if UNITY_2018_4_OR_NEWER
safeArea.y = height - safeArea.y - safeArea.height;
#endif
int realWidth, realHeight;
if (screenOrientation == ScreenOrientation.PortraitUpsideDown)
{
realWidth = width;
realHeight = height;
safeArea.x = width - safeArea.x - safeArea.width;
safeArea.y = height - safeArea.y - safeArea.height;
}
else if (screenOrientation == ScreenOrientation.LandscapeLeft)
{
realWidth = height;
realHeight = width;
safeArea.x = height - safeArea.y - safeArea.height;
safeArea.y = safeArea.x;
safeArea.width = realWidth;
safeArea.height = realHeight;
}
else if (screenOrientation == ScreenOrientation.LandscapeRight)
{
realWidth = height;
realHeight = width;
safeArea.x = safeArea.y;
safeArea.y = width - safeArea.x - safeArea.width;
safeArea.width = realWidth;
safeArea.height = realHeight;
}
else
{
realWidth = width;
realHeight = height;
}
if (!UIMgr.HasInstance())
{
UIMgr.Instance.InitMgr();
}
SetSize(realWidth, realHeight);
m_EditorSafeRectFieldInfo.SetValue(m_SafeRectCheck, safeArea);
m_EditorMaskTextureFieldInfo.SetValue(m_SafeRectCheck, AssetDatabase.LoadAssetAtPath<Texture2D>(deviceInfo.maskTexturePath));
m_EditorScreenOrientationFieldInfo.SetValue(m_SafeRectCheck, screenOrientation);
}
private void SetSize(int width, int height)
{
int index = FindSize(width, height);
if (index == -1)
{
AddCustomSize(width, height);
}
index = FindSize(width, height);
if (index == -1) return;
object gameViewObj = m_GameView_GetMainGameView_MethodInfo.Invoke(null, null);
m_GameView_SelectedSizeIndex_PropertyInfo.SetValue(gameViewObj, index);
m_GameView_UpdateZoomAreaAndParent_MethodInfo.Invoke(gameViewObj, null);
}
private void AddCustomSize(int width, int height)
{
object gameViewSizeObj = m_GameViewSizeConstructorInfo.Invoke(new object[] { m_GameViewSizeType_FixedResolution_Object, width, height, string.Empty });
m_AddCustomSizesMethodInfo.Invoke(m_CurrentGroupObject, new object[] { gameViewSizeObj });
}
private bool ExistSize(int width, int height)
{
return FindSize(width, height) != -1;
}
private int FindSize(int width, int height)
{
int count = (int)m_GetTotalCountMethodInfo.Invoke(m_CurrentGroupObject, null);
for (int i = 0; i < count; i++)
{
object gameViewSizeObj = m_GetGameViewSizeMethodInfo.Invoke(m_CurrentGroupObject, new object[] { i });
object objSizeType = m_GameViewSize_SizeType_PropertyInfo.GetValue(gameViewSizeObj, null);
int objWidth = (int)m_GameViewSize_Width_PropertyInfo.GetValue(gameViewSizeObj, null);
int objHeight = (int)m_GameViewSize_Height_PropertyInfo.GetValue(gameViewSizeObj, null);
if (width == objWidth && height == objHeight && ((int)m_GameViewSizeType_FixedResolution_Object == (int)objSizeType))
{
return i;
}
}
return -1;
}
[InitializeOnLoadMethod]
private static void OnRegister()
{
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
}
private static void OnPlayModeStateChanged(PlayModeStateChange playModeStateChange)
{
if (playModeStateChange == PlayModeStateChange.ExitingPlayMode)
{
UnityEngine.Object[] wins = Resources.FindObjectsOfTypeAll(typeof(SafeRectDebugTool));
SafeRectDebugTool win = wins.Length > 0 ? (SafeRectDebugTool)(wins[0]) : null;
if (win)
{
win.ResetDevice();
}
}
}
[MenuItem("RO_Tool/移动设备模拟器")]
private static SafeRectDebugTool OpenWindow()
{
var window = EditorWindow.GetWindow<SafeRectDebugTool>("移动设备模拟器");
return window;
}
}