SafeRectDebugTool.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. using System;
  2. using System.Collections;
  3. using System.Reflection;
  4. using UnityEditor;
  5. using UnityEngine;
  6. public class SafeRectDebugTool : EditorWindow
  7. {
  8. private class DeviceInfo
  9. {
  10. public string name;
  11. public Vector2Int size;
  12. public Rect safeArea;
  13. public string maskTexturePath;
  14. }
  15. protected FieldInfo m_EditorSafeRectFieldInfo = null;
  16. protected FieldInfo m_EditorScreenOrientationFieldInfo = null;
  17. protected FieldInfo m_EditorMaskTextureFieldInfo = null;
  18. protected PropertyInfo m_GameView_SelectedSizeIndex_PropertyInfo = null;
  19. protected MethodInfo m_GetSizeOfMainGameViewMethodInfo = null;
  20. protected MethodInfo m_GameView_GetMainGameView_MethodInfo = null;
  21. protected MethodInfo m_GameView_UpdateZoomAreaAndParent_MethodInfo = null;
  22. protected Type m_GameViewSizeTypeType = null;
  23. protected Type m_GameViewSizeType = null;
  24. protected PropertyInfo m_GameViewSize_SizeType_PropertyInfo = null;
  25. protected PropertyInfo m_GameViewSize_Width_PropertyInfo = null;
  26. protected PropertyInfo m_GameViewSize_Height_PropertyInfo = null;
  27. protected ConstructorInfo m_GameViewSizeConstructorInfo = null;
  28. protected Type m_GameViewSizesType = null;
  29. protected Type m_GameViewSizeGroupType = null;
  30. protected MethodInfo m_GetTotalCountMethodInfo = null;
  31. protected MethodInfo m_GetGameViewSizeMethodInfo = null;
  32. protected MethodInfo m_AddCustomSizesMethodInfo = null;
  33. private SafeRectCheck m_SafeRectCheck;
  34. private object m_GameViewSizeType_FixedResolution_Object = null;
  35. private object m_CurrentGroupObject = null;
  36. private DeviceInfo[] m_DeviceInfos;
  37. private string[] m_DevicesNames;
  38. private string[] m_ScreenOrientationNames = {
  39. "Portrait",
  40. "PortraitUpsideDown",
  41. "LandscapeLeft",
  42. "LandscapeRight"
  43. };
  44. private ScreenOrientation[] m_ScreenOrientationValues = {
  45. ScreenOrientation.Portrait,
  46. ScreenOrientation.PortraitUpsideDown,
  47. ScreenOrientation.LandscapeLeft,
  48. ScreenOrientation.LandscapeRight,
  49. };
  50. private int m_DefaultScreenOrientationIndex = 0;
  51. private int m_CurScreenOrientationIndex = 0;
  52. private int m_CurDeviceIndex = 0;
  53. private bool m_Init = false;
  54. private void InitValue()
  55. {
  56. m_Init = true;
  57. m_SafeRectCheck = SafeRectCheck.Instance;
  58. m_EditorSafeRectFieldInfo = typeof(SafeRectCheck).GetField("m_EditorSafeRect", BindingFlags.Instance | BindingFlags.NonPublic);
  59. m_EditorScreenOrientationFieldInfo = typeof(SafeRectCheck).GetField("m_EditorScreenOrientation", BindingFlags.Instance | BindingFlags.NonPublic);
  60. ScreenOrientation screenOrientation = (ScreenOrientation)m_EditorScreenOrientationFieldInfo.GetValue(m_SafeRectCheck);
  61. m_EditorMaskTextureFieldInfo = typeof(SafeRectCheck).GetField("m_EditorMaskTexture", BindingFlags.Instance | BindingFlags.NonPublic);
  62. Type gameViewType = typeof(Editor).Assembly.GetType("UnityEditor.GameView");
  63. m_GetSizeOfMainGameViewMethodInfo = gameViewType.GetMethod("GetSizeOfMainGameView", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
  64. Vector2 screenSize = (Vector2)m_GetSizeOfMainGameViewMethodInfo.Invoke(null, null);
  65. m_GameView_SelectedSizeIndex_PropertyInfo = gameViewType.GetProperty("selectedSizeIndex", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  66. m_GameView_GetMainGameView_MethodInfo = gameViewType.GetMethod("GetMainGameView", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
  67. m_GameView_UpdateZoomAreaAndParent_MethodInfo = gameViewType.GetMethod("UpdateZoomAreaAndParent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  68. m_GameViewSizeTypeType = typeof(Editor).Assembly.GetType("UnityEditor.GameViewSizeType");
  69. m_GameViewSizeType_FixedResolution_Object = Enum.Parse(m_GameViewSizeTypeType, "FixedResolution");
  70. m_GameViewSizeType = typeof(Editor).Assembly.GetType("UnityEditor.GameViewSize");
  71. m_GameViewSize_SizeType_PropertyInfo = m_GameViewSizeType.GetProperty("sizeType");
  72. m_GameViewSize_Width_PropertyInfo = m_GameViewSizeType.GetProperty("width");
  73. m_GameViewSize_Height_PropertyInfo = m_GameViewSizeType.GetProperty("height");
  74. m_GameViewSizeConstructorInfo = m_GameViewSizeType.GetConstructor(new Type[] { m_GameViewSizeTypeType, typeof(int), typeof(int), typeof(string) });
  75. m_GameViewSizesType = typeof(Editor).Assembly.GetType("UnityEditor.GameViewSizes");
  76. var singleType = typeof(ScriptableSingleton<>).MakeGenericType(m_GameViewSizesType);
  77. var instanceProp = singleType.GetProperty("instance");
  78. var crrentGroupProp = m_GameViewSizesType.GetProperty("currentGroup");
  79. m_CurrentGroupObject = crrentGroupProp.GetValue(instanceProp.GetValue(null, null), null);
  80. m_GameViewSizeGroupType = typeof(Editor).Assembly.GetType("UnityEditor.GameViewSizeGroup");
  81. m_GetTotalCountMethodInfo = m_GameViewSizeGroupType.GetMethod("GetTotalCount");
  82. m_GetGameViewSizeMethodInfo = m_GameViewSizeGroupType.GetMethod("GetGameViewSize");
  83. m_AddCustomSizesMethodInfo = m_GameViewSizeGroupType.GetMethod("AddCustomSize");
  84. if (screenSize.x > screenSize.y)
  85. {
  86. m_DefaultScreenOrientationIndex = 2;
  87. screenSize = new Vector2(screenSize.y, screenSize.x);
  88. }
  89. else
  90. {
  91. m_DefaultScreenOrientationIndex = 0;
  92. }
  93. m_DeviceInfos = new DeviceInfo[] {
  94. new DeviceInfo {
  95. name = "None",
  96. size = new Vector2Int (Mathf.CeilToInt (screenSize.x), Mathf.CeilToInt (screenSize.y)),
  97. safeArea = new Rect (0, 0, screenSize.x, screenSize.y),
  98. maskTexturePath = string.Empty
  99. },
  100. new DeviceInfo {
  101. name = "Apple/iPad7",
  102. size = new Vector2Int (1620, 2160),
  103. safeArea = new Rect (0, 0, 1620, 2160),
  104. maskTexturePath = string.Empty
  105. },
  106. new DeviceInfo {
  107. name = "Apple/iPhoneX",
  108. size = new Vector2Int (1125, 2436),
  109. safeArea = new Rect (0, 120, 1125, 2215),
  110. maskTexturePath = "Assets/Editor/SafeRect/Texture/AppleiPhoneX_Overlay.png"
  111. },
  112. new DeviceInfo {
  113. name = "Huawei/MatePadPro",
  114. size = new Vector2Int (1600, 2560),
  115. safeArea = new Rect (0, 112, 1600, 2448),
  116. maskTexturePath = "Assets/Editor/SafeRect/Texture/HuaweiMatePadPro_Overlay.png"
  117. },
  118. new DeviceInfo {
  119. name = "Huawei/Mate20Pro",
  120. size = new Vector2Int (1440, 3120),
  121. safeArea = new Rect (0, 100, 1440, 3020),
  122. maskTexturePath = "Assets/Editor/SafeRect/Texture/HuaweiMate20Pro_Overlay.png"
  123. },
  124. new DeviceInfo {
  125. name = "OnePlus6T",
  126. size = new Vector2Int (1080, 2340),
  127. safeArea = new Rect (0, 79, 1080, 2261),
  128. maskTexturePath = "Assets/Editor/SafeRect/Texture/OnePlus6T_Overlay.png"
  129. },
  130. new DeviceInfo {
  131. name = "Samsung/GalaxyS10Plus",
  132. size = new Vector2Int (1440, 3040),
  133. safeArea = new Rect (0, 142, 1440, 2898),
  134. maskTexturePath = "Assets/Editor/SafeRect/Texture/SamsungGalaxyS10Plus_Overlay.png"
  135. },
  136. new DeviceInfo {
  137. name = "Samsung/GalaxyS10",
  138. size = new Vector2Int (1080, 2280),
  139. safeArea = new Rect (0, 112, 1080, 2168),
  140. maskTexturePath = "Assets/Editor/SafeRect/Texture/SamsungGalaxyS10_Overlay.png"
  141. },
  142. new DeviceInfo {
  143. name = "Samsung/GalaxyNote10Plus",
  144. size = new Vector2Int (1080, 2280),
  145. safeArea = new Rect (0, 85, 1080, 2195),
  146. maskTexturePath = "Assets/Editor/SafeRect/Texture/SamsungGalaxyNote10Plus_Overlay.png"
  147. },
  148. };
  149. m_DevicesNames = new string[m_DeviceInfos.Length];
  150. for (int i = 0; i < m_DeviceInfos.Length; i++)
  151. {
  152. m_DevicesNames[i] = m_DeviceInfos[i].name;
  153. }
  154. if (m_ScreenOrientationValues[m_DefaultScreenOrientationIndex] != screenOrientation)
  155. {
  156. m_CurScreenOrientationIndex = m_DefaultScreenOrientationIndex;
  157. ResetDevice();
  158. }
  159. }
  160. private void OnDestroy()
  161. {
  162. if (Application.isPlaying)
  163. {
  164. ResetDevice();
  165. }
  166. }
  167. public void ResetDevice()
  168. {
  169. if (m_Init)
  170. {
  171. m_Init = false;
  172. m_CurDeviceIndex = 0;
  173. m_CurScreenOrientationIndex = m_DefaultScreenOrientationIndex;
  174. RefreshValue();
  175. }
  176. }
  177. private void OnGUI()
  178. {
  179. if (!Application.isPlaying)
  180. {
  181. GUILayout.FlexibleSpace();
  182. EditorGUILayout.HelpBox("目前只能在播放模式下使用", MessageType.Warning);
  183. GUILayout.FlexibleSpace();
  184. return;
  185. }
  186. if (!SafeRectCheck.Instance) return;
  187. if (!m_SafeRectCheck) InitValue();
  188. EditorGUILayout.Space();
  189. int index = EditorGUILayout.Popup("模拟设备类型", m_CurDeviceIndex, m_DevicesNames);
  190. if (m_CurDeviceIndex != index)
  191. {
  192. m_CurDeviceIndex = index;
  193. RefreshValue();
  194. }
  195. EditorGUILayout.Space();
  196. index = EditorGUILayout.Popup("模拟设备方向", m_CurScreenOrientationIndex, m_ScreenOrientationNames);
  197. if (m_CurScreenOrientationIndex != index)
  198. {
  199. m_CurScreenOrientationIndex = index;
  200. RefreshValue();
  201. }
  202. EditorGUILayout.Space();
  203. }
  204. private void RefreshValue()
  205. {
  206. DeviceInfo deviceInfo = m_DeviceInfos[m_CurDeviceIndex];
  207. ScreenOrientation screenOrientation = m_ScreenOrientationValues[m_CurScreenOrientationIndex];
  208. int width = deviceInfo.size.x;
  209. int height = deviceInfo.size.y;
  210. Rect safeArea = new Rect(deviceInfo.safeArea);
  211. #if UNITY_2018_4_OR_NEWER
  212. safeArea.y = height - safeArea.y - safeArea.height;
  213. #endif
  214. int realWidth, realHeight;
  215. if (screenOrientation == ScreenOrientation.PortraitUpsideDown)
  216. {
  217. realWidth = width;
  218. realHeight = height;
  219. safeArea.x = width - safeArea.x - safeArea.width;
  220. safeArea.y = height - safeArea.y - safeArea.height;
  221. }
  222. else if (screenOrientation == ScreenOrientation.LandscapeLeft)
  223. {
  224. realWidth = height;
  225. realHeight = width;
  226. safeArea.x = height - safeArea.y - safeArea.height;
  227. safeArea.y = safeArea.x;
  228. safeArea.width = realWidth;
  229. safeArea.height = realHeight;
  230. }
  231. else if (screenOrientation == ScreenOrientation.LandscapeRight)
  232. {
  233. realWidth = height;
  234. realHeight = width;
  235. safeArea.x = safeArea.y;
  236. safeArea.y = width - safeArea.x - safeArea.width;
  237. safeArea.width = realWidth;
  238. safeArea.height = realHeight;
  239. }
  240. else
  241. {
  242. realWidth = width;
  243. realHeight = height;
  244. }
  245. if (!UIMgr.HasInstance())
  246. {
  247. UIMgr.Instance.InitMgr();
  248. }
  249. SetSize(realWidth, realHeight);
  250. m_EditorSafeRectFieldInfo.SetValue(m_SafeRectCheck, safeArea);
  251. m_EditorMaskTextureFieldInfo.SetValue(m_SafeRectCheck, AssetDatabase.LoadAssetAtPath<Texture2D>(deviceInfo.maskTexturePath));
  252. m_EditorScreenOrientationFieldInfo.SetValue(m_SafeRectCheck, screenOrientation);
  253. }
  254. private void SetSize(int width, int height)
  255. {
  256. int index = FindSize(width, height);
  257. if (index == -1)
  258. {
  259. AddCustomSize(width, height);
  260. }
  261. index = FindSize(width, height);
  262. if (index == -1) return;
  263. object gameViewObj = m_GameView_GetMainGameView_MethodInfo.Invoke(null, null);
  264. m_GameView_SelectedSizeIndex_PropertyInfo.SetValue(gameViewObj, index);
  265. m_GameView_UpdateZoomAreaAndParent_MethodInfo.Invoke(gameViewObj, null);
  266. }
  267. private void AddCustomSize(int width, int height)
  268. {
  269. object gameViewSizeObj = m_GameViewSizeConstructorInfo.Invoke(new object[] { m_GameViewSizeType_FixedResolution_Object, width, height, string.Empty });
  270. m_AddCustomSizesMethodInfo.Invoke(m_CurrentGroupObject, new object[] { gameViewSizeObj });
  271. }
  272. private bool ExistSize(int width, int height)
  273. {
  274. return FindSize(width, height) != -1;
  275. }
  276. private int FindSize(int width, int height)
  277. {
  278. int count = (int)m_GetTotalCountMethodInfo.Invoke(m_CurrentGroupObject, null);
  279. for (int i = 0; i < count; i++)
  280. {
  281. object gameViewSizeObj = m_GetGameViewSizeMethodInfo.Invoke(m_CurrentGroupObject, new object[] { i });
  282. object objSizeType = m_GameViewSize_SizeType_PropertyInfo.GetValue(gameViewSizeObj, null);
  283. int objWidth = (int)m_GameViewSize_Width_PropertyInfo.GetValue(gameViewSizeObj, null);
  284. int objHeight = (int)m_GameViewSize_Height_PropertyInfo.GetValue(gameViewSizeObj, null);
  285. if (width == objWidth && height == objHeight && ((int)m_GameViewSizeType_FixedResolution_Object == (int)objSizeType))
  286. {
  287. return i;
  288. }
  289. }
  290. return -1;
  291. }
  292. [InitializeOnLoadMethod]
  293. private static void OnRegister()
  294. {
  295. EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
  296. }
  297. private static void OnPlayModeStateChanged(PlayModeStateChange playModeStateChange)
  298. {
  299. if (playModeStateChange == PlayModeStateChange.ExitingPlayMode)
  300. {
  301. UnityEngine.Object[] wins = Resources.FindObjectsOfTypeAll(typeof(SafeRectDebugTool));
  302. SafeRectDebugTool win = wins.Length > 0 ? (SafeRectDebugTool)(wins[0]) : null;
  303. if (win)
  304. {
  305. win.ResetDevice();
  306. }
  307. }
  308. }
  309. [MenuItem("RO_Tool/移动设备模拟器")]
  310. private static SafeRectDebugTool OpenWindow()
  311. {
  312. var window = EditorWindow.GetWindow<SafeRectDebugTool>("移动设备模拟器");
  313. return window;
  314. }
  315. }