ResolutionMonitorEditor.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using UnityEditor;
  6. using UnityEditorInternal;
  7. using UnityEngine;
  8. namespace TheraBytes.BetterUi.Editor
  9. {
  10. [CustomEditor(typeof(ResolutionMonitor))]
  11. public class ResolutionMonitorEditor : UnityEditor.Editor
  12. {
  13. enum Category
  14. {
  15. ScreenConfigs,
  16. StaticMethods,
  17. DpiOverwrites,
  18. }
  19. string[] aspectRatioNames;
  20. ReorderableList dpiList;
  21. SerializedProperty curOptRes, curOptDpi, fallbackName, dpiManager, staticSizerMethods;
  22. Category category = Category.ScreenConfigs;
  23. Vector2 scroll;
  24. public static string GetButtonText(ScreenTypeConditions config)
  25. {
  26. bool isSimulatedConfig = config == ResolutionMonitor.SimulatedScreenConfig;
  27. bool isCurrentConfig = config == ResolutionMonitor.CurrentScreenConfiguration;
  28. return string.Format("{0}{1} {2}",
  29. (config.IsActive) ? "♦" : "◊",
  30. (isSimulatedConfig)
  31. ? " ⃰"
  32. : (isCurrentConfig) ? "¹" : " ",
  33. config.Name);
  34. }
  35. void OnEnable()
  36. {
  37. this.staticSizerMethods = serializedObject.FindProperty("staticSizerMethods");
  38. this.dpiManager = serializedObject.FindProperty("dpiManager");
  39. var dpiOverrides = dpiManager.FindPropertyRelative("overrides");
  40. this.curOptRes = serializedObject.FindProperty("optimizedResolutionFallback");
  41. this.curOptDpi = serializedObject.FindProperty("optimizedDpiFallback");
  42. this.fallbackName = serializedObject.FindProperty("fallbackName");
  43. this.aspectRatioNames = ((AspectRatio[])Enum.GetValues(typeof(AspectRatio)))
  44. .Select(o => o.ToShortDetailedString()).ToArray();
  45. dpiList = new ReorderableList(dpiManager.serializedObject, dpiOverrides);
  46. dpiList.drawHeaderCallback += (r) => EditorGUI.LabelField(r, "Device Model Name => DPI");
  47. dpiList.drawElementCallback += (r, i, a, f) =>
  48. {
  49. float tmp = EditorGUIUtility.labelWidth;
  50. EditorGUIUtility.labelWidth = 1;
  51. Rect nR = new Rect(r.x + 2, r.y + 2, 3 * (r.width - 6) / 4, r.height - 2);
  52. Rect vR = new Rect(r.x + nR.width + 4, r.y + 2, (r.width - 6) / 4, r.height - 2);
  53. SerializedProperty prop = dpiOverrides.GetArrayElementAtIndex(i);
  54. SerializedProperty name = prop.FindPropertyRelative("deviceModel");
  55. SerializedProperty dpi = prop.FindPropertyRelative("dpi");
  56. EditorGUI.PropertyField(nR, name, new GUIContent(""));
  57. EditorGUI.PropertyField(vR, dpi, new GUIContent(""));
  58. EditorGUIUtility.labelWidth = tmp;
  59. serializedObject.ApplyModifiedProperties();
  60. };
  61. dpiList.onAddCallback += (r) =>
  62. {
  63. dpiOverrides.arraySize++;
  64. r.index = dpiOverrides.arraySize - 1;
  65. serializedObject.ApplyModifiedProperties();
  66. };
  67. dpiList.onRemoveCallback += (r) =>
  68. {
  69. ReorderableList.defaultBehaviours.DoRemoveButton(r);
  70. serializedObject.ApplyModifiedProperties();
  71. };
  72. }
  73. public override void OnInspectorGUI()
  74. {
  75. ResolutionMonitor monitor = (ResolutionMonitor)target;
  76. scroll = EditorGUILayout.BeginScrollView(scroll);
  77. scroll.x = -10;
  78. DrawCategoryButton("Screen Configurations", Category.ScreenConfigs);
  79. if (category == Category.ScreenConfigs)
  80. {
  81. for (int i = 0; i < monitor.OptimizedScreens.Count; i++)
  82. {
  83. var config = monitor.OptimizedScreens[i];
  84. EditorGUILayout.BeginVertical("box");
  85. EditorGUILayout.BeginHorizontal();
  86. if (GUILayout.Button(GetButtonText(config), EditorStyles.largeLabel, GUILayout.Height(20), GUILayout.Width(150)))
  87. {
  88. ResolutionMonitor.SimulatedScreenConfig = (ResolutionMonitor.SimulatedScreenConfig == config) ? null : config;
  89. }
  90. GUILayout.FlexibleSpace();
  91. if (GUILayout.Button("¶x"))
  92. {
  93. SetNameOrDeleteOptimizedScreen popup = new SetNameOrDeleteOptimizedScreen(config, () => PopupWindow.focusedWindow.Close());
  94. PopupWindow.Show(new Rect(0, 0, 400, 300), popup);
  95. }
  96. EditorGUI.BeginDisabledGroup(i == 0);
  97. if (GUILayout.Button("▲"))
  98. {
  99. MoveToIndex(config, i - 1);
  100. }
  101. EditorGUI.EndDisabledGroup();
  102. EditorGUI.BeginDisabledGroup(i == monitor.OptimizedScreens.Count - 1);
  103. if (GUILayout.Button("▼"))
  104. {
  105. MoveToIndex(config, i + 1);
  106. }
  107. EditorGUI.EndDisabledGroup();
  108. EditorGUILayout.EndHorizontal();
  109. EditorGUILayout.BeginVertical("box");
  110. EditorGUILayout.LabelField("Optimized Screen Size", EditorStyles.boldLabel);
  111. Vector2 prevRes = config.OptimizedScreenInfo.Resolution;
  112. float prefDpi = config.OptimizedScreenInfo.Dpi;
  113. config.OptimizedScreenInfo.Resolution = EditorGUILayout.Vector2Field("Optimized Resolution", config.OptimizedScreenInfo.Resolution);
  114. config.OptimizedScreenInfo.Dpi = EditorGUILayout.FloatField("Optimized DPI", config.OptimizedScreenInfo.Dpi);
  115. if (prevRes != config.OptimizedScreenInfo.Resolution || prefDpi != config.OptimizedScreenInfo.Dpi)
  116. {
  117. ResolutionMonitor.MarkDirty();
  118. }
  119. EditorGUILayout.EndVertical();
  120. EditorGUILayout.BeginVertical("box");
  121. DrawConfigPart("Check Screen Orientation", config.CheckOrientation,
  122. (o) =>
  123. {
  124. o.ExpectedOrientation = (IsCertainScreenOrientation.Orientation)EditorGUILayout.EnumPopup("Orientation", o.ExpectedOrientation);
  125. });
  126. DrawConfigPart("Check Screen Size", config.CheckScreenSize,
  127. (o) =>
  128. {
  129. EditorGUILayout.BeginHorizontal();
  130. o.MeasureType = (IsScreenOfCertainSize.ScreenMeasure)EditorGUILayout.EnumPopup(o.MeasureType, GUILayout.MinWidth(95));
  131. o.Units = (IsScreenOfCertainSize.UnitType)EditorGUILayout.EnumPopup(o.Units, GUILayout.MinWidth(100));
  132. EditorGUILayout.EndHorizontal();
  133. EditorGUILayout.BeginHorizontal();
  134. EditorGUILayout.LabelField(">=", GUILayout.Width(50));
  135. o.MinSize = EditorGUILayout.FloatField(o.MinSize);
  136. EditorGUILayout.EndHorizontal();
  137. EditorGUILayout.BeginHorizontal();
  138. EditorGUILayout.LabelField("<", GUILayout.Width(50));
  139. o.MaxSize = EditorGUILayout.FloatField(o.MaxSize);
  140. EditorGUILayout.EndHorizontal();
  141. if (o.MinSize >= o.MaxSize)
  142. {
  143. EditorGUILayout.HelpBox("First Value must be smaller than second value.", MessageType.Error);
  144. }
  145. });
  146. DrawConfigPart("Check Aspect Ratio", config.CheckAspectRatio,
  147. (o) =>
  148. {
  149. int selector = -1;
  150. EditorGUILayout.BeginHorizontal();
  151. EditorGUILayout.LabelField(">=", GUILayout.Width(50));
  152. o.MinAspect = EditorGUILayout.FloatField(o.MinAspect, GUILayout.Width(70));
  153. selector = EditorGUILayout.Popup(selector, aspectRatioNames);
  154. if (selector != -1)
  155. {
  156. o.MinAspect = ((AspectRatio)selector).GetRatioValue();
  157. selector = -1;
  158. }
  159. EditorGUILayout.EndHorizontal();
  160. EditorGUILayout.BeginHorizontal();
  161. EditorGUILayout.LabelField("<=", GUILayout.Width(50));
  162. o.MaxAspect = EditorGUILayout.FloatField(o.MaxAspect, GUILayout.Width(70));
  163. selector = EditorGUILayout.Popup(selector, aspectRatioNames);
  164. if (selector != -1)
  165. {
  166. o.MaxAspect = ((AspectRatio)selector).GetRatioValue();
  167. selector = -1;
  168. }
  169. EditorGUILayout.EndHorizontal();
  170. o.Inverse = EditorGUILayout.ToggleLeft(" Inverse (ratio is not in given range)", o.Inverse);
  171. if (o.MinAspect >= o.MaxAspect)
  172. {
  173. EditorGUILayout.HelpBox("First Value must be smaller than second value.", MessageType.Error);
  174. }
  175. });
  176. DrawConfigPart("Check Device", config.CheckDeviceType,
  177. (o) =>
  178. {
  179. o.ExpectedDeviceInfo = (IsScreenOfCertainDeviceInfo.DeviceInfo)EditorGUILayout.EnumPopup("Device Info", o.ExpectedDeviceInfo);
  180. });
  181. DrawConfigPart("Check Tag", config.CheckScreenTag,
  182. (o) =>
  183. {
  184. o.ScreenTag = EditorGUILayout.TextField("Tag", o.ScreenTag);
  185. });
  186. // ADD FALLBACK
  187. string[] options = ResolutionMonitor.Instance.OptimizedScreens
  188. .Where(o => (config != o) && !(config.Fallbacks.Contains(o.Name)))
  189. .Select(o => o.Name)
  190. .ToArray();
  191. if (options.Length > 0 || config.Fallbacks.Count > 0)
  192. {
  193. Rect bgRect = EditorGUILayout.BeginVertical("box");
  194. EditorGUILayout.LabelField("Fallback Order", EditorStyles.boldLabel);
  195. if (options.Length > 0)
  196. {
  197. EditorGUILayout.BeginHorizontal();
  198. GUILayout.FlexibleSpace();
  199. Rect r = new Rect(bgRect.x + bgRect.width - 20, bgRect.y + 3, 20, 20);
  200. int idx = EditorGUI.Popup(r, -1, options, "OL Plus");
  201. if (idx != -1)
  202. {
  203. string name = options[idx];
  204. idx = -1;
  205. config.Fallbacks.Insert(0, name);
  206. }
  207. EditorGUILayout.EndHorizontal();
  208. }
  209. EditorGUI.indentLevel++;
  210. for (int k = 0; k < config.Fallbacks.Count; k++)
  211. {
  212. string name = config.Fallbacks[k];
  213. EditorGUILayout.BeginHorizontal();
  214. EditorGUILayout.LabelField(string.Format("{0}. {1}", k + 1, name));
  215. GUILayout.FlexibleSpace();
  216. EditorGUI.BeginDisabledGroup(k == 0);
  217. if (GUILayout.Button("↑"))
  218. {
  219. config.Fallbacks.RemoveAt(k);
  220. config.Fallbacks.Insert(k - 1, name);
  221. }
  222. EditorGUI.EndDisabledGroup();
  223. EditorGUI.BeginDisabledGroup(k == config.Fallbacks.Count - 1);
  224. if (GUILayout.Button("↓"))
  225. {
  226. config.Fallbacks.RemoveAt(k);
  227. config.Fallbacks.Insert(k + 1, name);
  228. }
  229. EditorGUI.EndDisabledGroup();
  230. if (GUILayout.Button("x"))
  231. {
  232. config.Fallbacks.RemoveAt(k);
  233. }
  234. EditorGUILayout.EndHorizontal();
  235. }
  236. EditorGUI.indentLevel--;
  237. EditorGUILayout.EndVertical();
  238. }
  239. EditorGUILayout.EndVertical();
  240. EditorGUILayout.EndVertical();
  241. }
  242. if (GUILayout.Button("+"))
  243. {
  244. SetNameOrDeleteOptimizedScreen popup = new SetNameOrDeleteOptimizedScreen(null, () => PopupWindow.focusedWindow.Close());
  245. PopupWindow.Show(new Rect(0, 0, 400, 175), popup);
  246. }
  247. // Screen Configuration Global Fallback
  248. EditorGUILayout.Separator();
  249. EditorGUILayout.BeginVertical("box");
  250. EditorGUILayout.LabelField("Fallback", EditorStyles.boldLabel);
  251. EditorGUILayout.PropertyField(fallbackName, new GUIContent("Fallback Name"));
  252. EditorGUILayout.BeginVertical("box");
  253. EditorGUILayout.LabelField("Optimized Screen Size", EditorStyles.boldLabel);
  254. EditorGUILayout.PropertyField(curOptRes, new GUIContent("Optimized Resolution"));
  255. EditorGUILayout.PropertyField(curOptDpi, new GUIContent("Optimized Dpi"));
  256. serializedObject.ApplyModifiedProperties();
  257. EditorGUILayout.EndVertical();
  258. EditorGUILayout.EndVertical();
  259. EditorGUILayout.Space();
  260. }
  261. // STATIC METHODS
  262. DrawCategoryButton("Static Sizer Methods", Category.StaticMethods);
  263. if (category == Category.StaticMethods)
  264. {
  265. EditorGUILayout.HelpBox(@"Static Sizer Methods should have the following declaration:", MessageType.Info);
  266. EditorGUILayout.SelectableLabel("public static float MethodName(Component caller, Vector2 optimizedResolution, Vector2 actualResolution, float optimizedDpi, float actualDpi)",
  267. GUI.skin.textField);
  268. for(int i = 0; i < 5; i++)
  269. {
  270. DrawStaticSizerMethod(staticSizerMethods, i);
  271. }
  272. EditorGUILayout.Space();
  273. }
  274. // DPI OVERRIDES
  275. DrawCategoryButton("DPI Overwrites", Category.DpiOverwrites);
  276. if (category == Category.DpiOverwrites)
  277. {
  278. EditorGUILayout.HelpBox(
  279. "Some devices have no or wrong DPI values assigned by the manufacturer. " +
  280. "Here these devices can be specified to assign the correct DPI value to them.", MessageType.Info);
  281. dpiList.DoLayoutList();
  282. EditorGUILayout.Space();
  283. }
  284. EditorGUILayout.EndScrollView();
  285. // SAVE
  286. GUILayout.FlexibleSpace();
  287. if (GUILayout.Button("Save", GUILayout.Height(50)))
  288. {
  289. serializedObject.ApplyModifiedProperties();
  290. EditorUtility.SetDirty(monitor);
  291. AssetDatabase.SaveAssets();
  292. }
  293. }
  294. private void DrawCategoryButton(string text, Category category)
  295. {
  296. string prefix = (this.category == category) ? "▼" : "►";
  297. if(GUILayout.Button(string.Format("{0} {1}", prefix, text), EditorStyles.boldLabel))
  298. {
  299. this.category = category;
  300. }
  301. }
  302. private void DrawStaticSizerMethod(SerializedProperty staticSizerMethods, int i)
  303. {
  304. SerializedProperty prop = staticSizerMethods.GetArrayElementAtIndex(i);
  305. SerializedProperty aProp = prop.FindPropertyRelative("assemblyName");
  306. SerializedProperty tProp = prop.FindPropertyRelative("typeName");
  307. SerializedProperty mProp = prop.FindPropertyRelative("methodName");
  308. EditorGUILayout.BeginVertical("box");
  309. EditorGUILayout.LabelField("Static Sizer Method " + (i + 1), EditorStyles.boldLabel);
  310. EditorGUILayout.PropertyField(aProp);
  311. EditorGUILayout.PropertyField(tProp);
  312. EditorGUILayout.PropertyField(mProp);
  313. EditorGUILayout.EndVertical();
  314. }
  315. private void MoveToIndex(ScreenTypeConditions config, int idx)
  316. {
  317. // this seems not to be done immediately, so the adjustment of idx is not required for some reason.
  318. ResolutionMonitor.Instance.OptimizedScreens.Remove(config);
  319. ResolutionMonitor.Instance.OptimizedScreens.Insert(idx, config);
  320. }
  321. void DrawConfigPart<T>(string title, T obj, Action<T> drawObject)
  322. where T : IIsActive
  323. {
  324. GUIStyle style = (obj.IsActive) ? EditorStyles.boldLabel : EditorStyles.label;
  325. obj.IsActive = EditorGUILayout.ToggleLeft(title, obj.IsActive, style);
  326. if (obj.IsActive)
  327. {
  328. EditorGUI.indentLevel += 1;
  329. drawObject(obj);
  330. EditorGUI.indentLevel -= 1;
  331. }
  332. }
  333. }
  334. }