ChartEditorHelper.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEditor;
  4. using UnityEngine;
  5. using XCharts.Runtime;
  6. namespace XCharts.Editor
  7. {
  8. public class HeaderMenuInfo
  9. {
  10. public string name;
  11. public Action action;
  12. public bool enable = true;
  13. public HeaderMenuInfo() { }
  14. public HeaderMenuInfo(string name, Action action)
  15. {
  16. this.name = name;
  17. this.action = action;
  18. }
  19. public HeaderMenuInfo(string name, Action action, bool enable)
  20. {
  21. this.name = name;
  22. this.action = action;
  23. this.enable = enable;
  24. }
  25. }
  26. public static class ChartEditorHelper
  27. {
  28. public const float HEADER_HEIGHT = 17f;
  29. public const float FOLDOUT_WIDTH = 13f;
  30. #if UNITY_2019_3_OR_NEWER
  31. public const float INDENT_WIDTH = 15;
  32. public const float BOOL_WIDTH = 15;
  33. public const float ARROW_WIDTH = 20;
  34. public const float GAP_WIDTH = 2;
  35. public const float DIFF_WIDTH = 0;
  36. #else
  37. public const float INDENT_WIDTH = 15;
  38. public const float BOOL_WIDTH = 15;
  39. public const float ARROW_WIDTH = 14f;
  40. public const float GAP_WIDTH = 0;
  41. public const float DIFF_WIDTH = 1;
  42. #endif
  43. static Dictionary<string, GUIContent> s_GUIContentCache;
  44. static ChartEditorHelper()
  45. {
  46. s_GUIContentCache = new Dictionary<string, GUIContent>();
  47. }
  48. public static void SecondField(Rect drawRect, SerializedProperty prop)
  49. {
  50. RectOffset offset = new RectOffset(-(int)EditorGUIUtility.labelWidth, 0, 0, 0);
  51. drawRect = offset.Add(drawRect);
  52. EditorGUI.PropertyField(drawRect, prop, GUIContent.none);
  53. drawRect = offset.Remove(drawRect);
  54. }
  55. public static void MakeTwoField(ref Rect drawRect, float rectWidth, SerializedProperty arrayProp,
  56. string name)
  57. {
  58. while (arrayProp.arraySize < 2) arrayProp.arraySize++;
  59. var prop1 = arrayProp.GetArrayElementAtIndex(0);
  60. var prop2 = arrayProp.GetArrayElementAtIndex(1);
  61. MakeTwoField(ref drawRect, rectWidth, prop1, prop2, name);
  62. }
  63. public static void MakeDivideList(ref Rect drawRect, float rectWidth, SerializedProperty arrayProp,
  64. string name, int showNum)
  65. {
  66. while (arrayProp.arraySize < showNum) arrayProp.arraySize++;
  67. EditorGUI.LabelField(drawRect, name);
  68. #if UNITY_2019_3_OR_NEWER
  69. var gap = 2;
  70. #else
  71. var gap = 0;
  72. #endif
  73. var startX = drawRect.x + EditorGUIUtility.labelWidth - EditorGUI.indentLevel * INDENT_WIDTH + gap;
  74. var dataWidTotal = (rectWidth - (startX + INDENT_WIDTH + 1));
  75. EditorGUI.DrawRect(new Rect(startX, drawRect.y, dataWidTotal, drawRect.height), Color.grey);
  76. var dataWid = dataWidTotal / showNum;
  77. var xWid = dataWid - gap;
  78. for (int i = 0; i < 1; i++)
  79. {
  80. drawRect.x = startX + i * xWid;
  81. drawRect.width = dataWid + (EditorGUI.indentLevel - 2) * 40.5f;
  82. EditorGUI.PropertyField(drawRect, arrayProp.GetArrayElementAtIndex(i), GUIContent.none);
  83. }
  84. drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
  85. }
  86. public static void MakeTwoField(ref Rect drawRect, float rectWidth, SerializedProperty prop1,
  87. SerializedProperty prop2, string name)
  88. {
  89. EditorGUI.LabelField(drawRect, name);
  90. var startX = drawRect.x + EditorGUIUtility.labelWidth - EditorGUI.indentLevel * INDENT_WIDTH + GAP_WIDTH;
  91. var diff = 13 + EditorGUI.indentLevel * 14;
  92. var offset = diff - INDENT_WIDTH;
  93. var tempWidth = (rectWidth - startX + diff) / 2;
  94. var centerXRect = new Rect(startX, drawRect.y, tempWidth, drawRect.height - 1);
  95. var centerYRect = new Rect(centerXRect.x + tempWidth - offset, drawRect.y, tempWidth - 1, drawRect.height - 1);
  96. EditorGUI.PropertyField(centerXRect, prop1, GUIContent.none);
  97. EditorGUI.PropertyField(centerYRect, prop2, GUIContent.none);
  98. drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
  99. }
  100. public static void MakeThreeField(ref Rect drawRect, float rectWidth, SerializedProperty prop1,
  101. SerializedProperty prop2, SerializedProperty prop3, string name)
  102. {
  103. EditorGUI.LabelField(drawRect, name);
  104. var startX = drawRect.x + EditorGUIUtility.labelWidth - EditorGUI.indentLevel * INDENT_WIDTH + GAP_WIDTH;
  105. var diff = 13 + EditorGUI.indentLevel * 14;
  106. var offset = diff - INDENT_WIDTH;
  107. var tempWidth = (rectWidth - startX + diff) / 3;
  108. var centerXRect = new Rect(startX, drawRect.y, tempWidth, drawRect.height - 1);
  109. var centerYRect = new Rect(centerXRect.x + tempWidth - offset, drawRect.y, tempWidth - 1, drawRect.height - 1);
  110. var centerZRect = new Rect(centerYRect.x + tempWidth - offset, drawRect.y, tempWidth - 1, drawRect.height - 1);
  111. EditorGUI.PropertyField(centerXRect, prop1, GUIContent.none);
  112. EditorGUI.PropertyField(centerYRect, prop2, GUIContent.none);
  113. EditorGUI.PropertyField(centerZRect, prop3, GUIContent.none);
  114. drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
  115. }
  116. public static void MakeVector2(ref Rect drawRect, float rectWidth, SerializedProperty prop, string name)
  117. {
  118. EditorGUI.LabelField(drawRect, name);
  119. var startX = drawRect.x + EditorGUIUtility.labelWidth - EditorGUI.indentLevel * INDENT_WIDTH + GAP_WIDTH;
  120. var diff = 14 + EditorGUI.indentLevel * 14;
  121. var offset = diff - INDENT_WIDTH;
  122. var tempWidth = (rectWidth - startX + diff) / 2;
  123. var centerXRect = new Rect(startX, drawRect.y, tempWidth, drawRect.height);
  124. var centerYRect = new Rect(centerXRect.x + tempWidth - offset, drawRect.y, tempWidth, drawRect.height);
  125. var x = EditorGUI.FloatField(centerXRect, prop.vector3Value.x);
  126. var y = EditorGUI.FloatField(centerYRect, prop.vector3Value.y);
  127. prop.vector3Value = new Vector3(x, y);
  128. drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
  129. }
  130. public static bool MakeFoldout(ref Rect drawRect, ref bool moduleToggle, string content,
  131. SerializedProperty prop = null, bool bold = false)
  132. {
  133. float defaultWidth = drawRect.width;
  134. float defaultX = drawRect.x;
  135. var style = bold ? EditorCustomStyles.foldoutStyle : UnityEditor.EditorStyles.foldout;
  136. drawRect.width = EditorGUIUtility.labelWidth - EditorGUI.indentLevel * INDENT_WIDTH;
  137. moduleToggle = EditorGUI.Foldout(drawRect, moduleToggle, content, true, style);
  138. MakeBool(drawRect, prop);
  139. drawRect.width = defaultWidth;
  140. drawRect.x = defaultX;
  141. return moduleToggle;
  142. }
  143. public static bool MakeFoldout(ref Rect drawRect, Dictionary<string, float> heights,
  144. Dictionary<string, bool> moduleToggle, string key, string content, SerializedProperty prop, bool bold = false)
  145. {
  146. float defaultWidth = drawRect.width;
  147. float defaultX = drawRect.x;
  148. var style = bold ? EditorCustomStyles.foldoutStyle : UnityEditor.EditorStyles.foldout;
  149. drawRect.width = EditorGUIUtility.labelWidth;
  150. moduleToggle[key] = EditorGUI.Foldout(drawRect, moduleToggle[key], content, true, style);
  151. if (prop != null)
  152. {
  153. if (prop.propertyType == SerializedPropertyType.Boolean)
  154. {
  155. MakeBool(drawRect, prop);
  156. }
  157. else
  158. {
  159. drawRect.x = EditorGUIUtility.labelWidth - EditorGUI.indentLevel * INDENT_WIDTH + ARROW_WIDTH;
  160. drawRect.width = defaultWidth - drawRect.x + ARROW_WIDTH - 2;
  161. EditorGUI.PropertyField(drawRect, prop, GUIContent.none);
  162. }
  163. }
  164. drawRect.width = defaultWidth;
  165. drawRect.x = defaultX;
  166. drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
  167. heights[key] += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
  168. return moduleToggle[key];
  169. }
  170. public static bool MakeComponentFoldout(ref Rect drawRect, Dictionary<string, float> heights,
  171. Dictionary<string, bool> moduleToggle, string key, string content, SerializedProperty prop,
  172. SerializedProperty prop2, bool propEnable, params HeaderMenuInfo[] menus)
  173. {
  174. var sourRect = drawRect;
  175. float defaultWidth = drawRect.width;
  176. float defaultX = drawRect.x;
  177. float headerHeight = DrawSplitterAndBackground(drawRect);
  178. drawRect.width = EditorGUIUtility.labelWidth;
  179. moduleToggle[key] = EditorGUI.Foldout(drawRect, moduleToggle[key], content, true, EditorStyles.foldout);
  180. if (prop != null)
  181. {
  182. if (prop.propertyType == SerializedPropertyType.Boolean)
  183. {
  184. if (!propEnable)
  185. using (new EditorGUI.DisabledScope(true))
  186. MakeBool(drawRect, prop);
  187. else
  188. MakeBool(drawRect, prop);
  189. if (prop2 != null && !moduleToggle[key])
  190. {
  191. drawRect.x = EditorGUIUtility.labelWidth - EditorGUI.indentLevel * INDENT_WIDTH + ARROW_WIDTH + BOOL_WIDTH;
  192. drawRect.width = defaultWidth - drawRect.x + ARROW_WIDTH;
  193. EditorGUI.PropertyField(drawRect, prop2, GUIContent.none);
  194. }
  195. }
  196. else
  197. {
  198. drawRect.x = EditorGUIUtility.labelWidth - EditorGUI.indentLevel * INDENT_WIDTH + ARROW_WIDTH;
  199. drawRect.width = defaultWidth - drawRect.x + ARROW_WIDTH - 2;
  200. EditorGUI.PropertyField(drawRect, prop, GUIContent.none);
  201. }
  202. }
  203. DrawMenu(sourRect, menus);
  204. drawRect.width = defaultWidth;
  205. drawRect.x = defaultX;
  206. drawRect.y += headerHeight;
  207. heights[key] += headerHeight;
  208. return moduleToggle[key];
  209. }
  210. public static void MakeBool(Rect drawRect, SerializedProperty boolProp, int index = 0, string name = null)
  211. {
  212. float defaultWidth = drawRect.width;
  213. float defaultX = drawRect.x;
  214. float boolWidth = index * (BOOL_WIDTH + GAP_WIDTH);
  215. drawRect.x = EditorGUIUtility.labelWidth - EditorGUI.indentLevel * INDENT_WIDTH + ARROW_WIDTH + boolWidth;
  216. drawRect.width = (EditorGUI.indentLevel + 1) * BOOL_WIDTH + index * 110;
  217. if (boolProp != null)
  218. {
  219. EditorGUI.PropertyField(drawRect, boolProp, GUIContent.none);
  220. if (!string.IsNullOrEmpty(name))
  221. {
  222. drawRect.x += BOOL_WIDTH;
  223. drawRect.width = 200;
  224. EditorGUI.LabelField(drawRect, name);
  225. }
  226. }
  227. drawRect.width = defaultWidth;
  228. drawRect.x = defaultX;
  229. }
  230. public static bool MakeFoldout(ref Rect drawRect, ref float height, ref Dictionary<string, bool> moduleToggle,
  231. SerializedProperty prop, string moduleName, string showPropName, bool bold = false)
  232. {
  233. var relativeProp = prop.FindPropertyRelative(showPropName);
  234. var flag = MakeFoldout(ref drawRect, ref moduleToggle, prop, moduleName, relativeProp, bold);
  235. drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
  236. height += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
  237. return flag;
  238. }
  239. public static bool MakeFoldout(ref Rect drawRect, ref Dictionary<string, bool> moduleToggle, SerializedProperty prop,
  240. string moduleName, SerializedProperty showProp = null, bool bold = false)
  241. {
  242. var key = prop.propertyPath;
  243. if (!moduleToggle.ContainsKey(key))
  244. {
  245. moduleToggle.Add(key, false);
  246. }
  247. var toggle = moduleToggle[key];
  248. float defaultWidth = drawRect.width;
  249. float defaultX = drawRect.x;
  250. #if UNITY_2019_3_OR_NEWER
  251. drawRect.width = EditorGUIUtility.labelWidth - EditorGUI.indentLevel * INDENT_WIDTH;
  252. #else
  253. drawRect.width = EditorGUIUtility.labelWidth;
  254. #endif
  255. var displayName = string.IsNullOrEmpty(moduleName) ? prop.displayName : moduleName;
  256. var foldoutStyle = bold ? EditorCustomStyles.foldoutStyle : UnityEditor.EditorStyles.foldout;
  257. toggle = EditorGUI.Foldout(drawRect, toggle, displayName, true, foldoutStyle);
  258. if (moduleToggle[key] != toggle)
  259. {
  260. moduleToggle[key] = toggle;
  261. }
  262. if (showProp != null)
  263. {
  264. drawRect.x = EditorGUIUtility.labelWidth - EditorGUI.indentLevel * INDENT_WIDTH + ARROW_WIDTH;
  265. if (showProp.propertyType == SerializedPropertyType.Boolean)
  266. {
  267. drawRect.width = (EditorGUI.indentLevel + 1) * BOOL_WIDTH;
  268. }
  269. else
  270. {
  271. drawRect.width = defaultWidth - drawRect.x + ARROW_WIDTH - GAP_WIDTH;
  272. }
  273. EditorGUI.PropertyField(drawRect, showProp, GUIContent.none);
  274. }
  275. drawRect.width = defaultWidth;
  276. drawRect.x = defaultX;
  277. return toggle;
  278. }
  279. public static bool MakeListWithFoldout(ref Rect drawRect, SerializedProperty listProp, bool foldout,
  280. bool showOrder, bool showSize, params HeaderMenuInfo[] menus)
  281. {
  282. var height = 0f;
  283. return MakeListWithFoldout(ref drawRect, ref height, listProp, foldout, showOrder, showSize, menus);
  284. }
  285. public static bool MakeListWithFoldout(ref Rect drawRect, ref float height, SerializedProperty listProp,
  286. bool foldout, bool showOrder, bool showSize, params HeaderMenuInfo[] menus)
  287. {
  288. var rawWidth = drawRect.width;
  289. var headerHeight = DrawSplitterAndBackground(drawRect);
  290. var foldoutRect = drawRect;
  291. foldoutRect.xMax -= 10;
  292. bool flag = EditorGUI.Foldout(foldoutRect, foldout, listProp.displayName, true);
  293. ChartEditorHelper.DrawMenu(drawRect, menus);
  294. height += headerHeight;
  295. drawRect.y += headerHeight;
  296. drawRect.width = rawWidth;
  297. if (flag)
  298. {
  299. MakeList(ref drawRect, ref height, listProp, showOrder, showSize);
  300. }
  301. return flag;
  302. }
  303. public static void MakeList(ref Rect drawRect, SerializedProperty listProp, bool showOrder = false,
  304. bool showSize = true)
  305. {
  306. var height = 0f;
  307. MakeList(ref drawRect, ref height, listProp, showOrder, showSize);
  308. }
  309. public static void MakeList(ref Rect drawRect, ref float height, SerializedProperty listProp,
  310. bool showOrder = false, bool showSize = true)
  311. {
  312. EditorGUI.indentLevel++;
  313. var listSize = listProp.arraySize;
  314. var iconWidth = 10;
  315. var iconGap = 0f;
  316. if (showSize)
  317. {
  318. var headerHeight = DrawSplitterAndBackground(drawRect);
  319. if (showOrder)
  320. {
  321. var elementRect = new Rect(drawRect.x, drawRect.y, drawRect.width - iconWidth + 2, drawRect.height);
  322. var oldColor = GUI.contentColor;
  323. GUI.contentColor = Color.black;
  324. GUI.contentColor = oldColor;
  325. listSize = listProp.arraySize;
  326. listSize = EditorGUI.IntField(elementRect, "Size", listSize);
  327. }
  328. else
  329. {
  330. listSize = EditorGUI.IntField(drawRect, "Size", listSize);
  331. }
  332. if (listSize < 0) listSize = 0;
  333. drawRect.y += headerHeight;
  334. height += headerHeight;
  335. if (listSize != listProp.arraySize)
  336. {
  337. while (listSize > listProp.arraySize) listProp.arraySize++;
  338. while (listSize < listProp.arraySize) listProp.arraySize--;
  339. }
  340. }
  341. if (listSize > 30 && !XCSettings.editorShowAllListData)
  342. {
  343. SerializedProperty element;
  344. int num = listSize > 10 ? 10 : listSize;
  345. for (int i = 0; i < num; i++)
  346. {
  347. element = listProp.GetArrayElementAtIndex(i);
  348. DrawSplitterAndBackground(drawRect);
  349. EditorGUI.PropertyField(drawRect, element, new GUIContent("Element " + i));
  350. drawRect.y += EditorGUI.GetPropertyHeight(element);
  351. height += EditorGUI.GetPropertyHeight(element);
  352. }
  353. if (num >= 10)
  354. {
  355. EditorGUI.LabelField(drawRect, "...");
  356. drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
  357. height += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
  358. element = listProp.GetArrayElementAtIndex(listSize - 1);
  359. DrawSplitterAndBackground(drawRect);
  360. EditorGUI.PropertyField(drawRect, element, new GUIContent("Element " + (listSize - 1)));
  361. drawRect.y += EditorGUI.GetPropertyHeight(element) + EditorGUIUtility.standardVerticalSpacing;
  362. height += EditorGUI.GetPropertyHeight(element) + EditorGUIUtility.standardVerticalSpacing;
  363. }
  364. }
  365. else
  366. {
  367. for (int i = 0; i < listProp.arraySize; i++)
  368. {
  369. SerializedProperty element = listProp.GetArrayElementAtIndex(i);
  370. DrawSplitterAndBackground(drawRect);
  371. if (showOrder)
  372. {
  373. var temp = INDENT_WIDTH + GAP_WIDTH + iconGap;
  374. var isSerie = "Serie".Equals(element.type);
  375. var elementRect = isSerie ?
  376. new Rect(drawRect.x, drawRect.y, drawRect.width + INDENT_WIDTH - 2 * iconGap, drawRect.height) :
  377. new Rect(drawRect.x, drawRect.y, drawRect.width - 4 * iconWidth, drawRect.height);
  378. EditorGUI.PropertyField(elementRect, element, new GUIContent("Element " + i));
  379. var iconRect = new Rect(drawRect.width - 4 * iconWidth + temp, drawRect.y, iconWidth, drawRect.height);
  380. var oldColor = GUI.contentColor;
  381. GUI.contentColor = Color.black;
  382. if (GUI.Button(iconRect, EditorCustomStyles.iconUp, EditorCustomStyles.invisibleButton))
  383. {
  384. if (i > 0) listProp.MoveArrayElement(i, i - 1);
  385. }
  386. iconRect = new Rect(drawRect.width - 3 * iconWidth + temp, drawRect.y, iconWidth, drawRect.height);
  387. if (GUI.Button(iconRect, EditorCustomStyles.iconDown, EditorCustomStyles.invisibleButton))
  388. {
  389. if (i < listProp.arraySize - 1) listProp.MoveArrayElement(i, i + 1);
  390. }
  391. iconRect = new Rect(drawRect.width - 2 * iconWidth + temp, drawRect.y, iconWidth, drawRect.height);
  392. if (GUI.Button(iconRect, EditorCustomStyles.iconAdd, EditorCustomStyles.invisibleButton))
  393. {
  394. if (i < listProp.arraySize && i >= 0) listProp.InsertArrayElementAtIndex(i);
  395. }
  396. iconRect = new Rect(drawRect.width - iconWidth + temp, drawRect.y, iconWidth, drawRect.height);
  397. if (GUI.Button(iconRect, EditorCustomStyles.iconRemove, EditorCustomStyles.invisibleButton))
  398. {
  399. if (i < listProp.arraySize && i >= 0) listProp.DeleteArrayElementAtIndex(i);
  400. }
  401. else
  402. {
  403. drawRect.y += EditorGUI.GetPropertyHeight(element);
  404. height += EditorGUI.GetPropertyHeight(element);
  405. }
  406. GUI.contentColor = oldColor;
  407. }
  408. else
  409. {
  410. EditorGUI.PropertyField(drawRect, element, new GUIContent("Element " + i));
  411. drawRect.y += EditorGUI.GetPropertyHeight(element);
  412. height += EditorGUI.GetPropertyHeight(element);
  413. }
  414. }
  415. }
  416. EditorGUI.indentLevel--;
  417. }
  418. public static bool PropertyField(ref Rect drawRect, Dictionary<string, float> heights, string key,
  419. SerializedProperty prop)
  420. {
  421. if (prop == null) return false;
  422. EditorGUI.PropertyField(drawRect, prop, true);
  423. var hig = EditorGUI.GetPropertyHeight(prop);
  424. drawRect.y += hig;
  425. heights[key] += hig;
  426. return true;
  427. }
  428. public static bool PropertyFieldWithMinValue(ref Rect drawRect, Dictionary<string, float> heights, string key,
  429. SerializedProperty prop, float minValue)
  430. {
  431. if (prop == null) return false;
  432. EditorGUI.PropertyField(drawRect, prop, true);
  433. if (prop.propertyType == SerializedPropertyType.Float && prop.floatValue < minValue)
  434. prop.floatValue = minValue;
  435. if (prop.propertyType == SerializedPropertyType.Integer && prop.intValue < minValue)
  436. prop.intValue = (int)minValue;
  437. var hig = EditorGUI.GetPropertyHeight(prop);
  438. drawRect.y += hig;
  439. heights[key] += hig;
  440. return true;
  441. }
  442. public static bool PropertyFieldWithMaxValue(ref Rect drawRect, Dictionary<string, float> heights, string key,
  443. SerializedProperty prop, float maxValue)
  444. {
  445. if (prop == null) return false;
  446. EditorGUI.PropertyField(drawRect, prop, true);
  447. if (prop.propertyType == SerializedPropertyType.Float && prop.floatValue > maxValue)
  448. prop.floatValue = maxValue;
  449. if (prop.propertyType == SerializedPropertyType.Integer && prop.intValue > maxValue)
  450. prop.intValue = (int)maxValue;
  451. var hig = EditorGUI.GetPropertyHeight(prop);
  452. drawRect.y += hig;
  453. heights[key] += hig;
  454. return true;
  455. }
  456. public static bool PropertyField(ref Rect drawRect, Dictionary<string, float> heights, string key,
  457. SerializedProperty parentProp, string relativeName)
  458. {
  459. return PropertyField(ref drawRect, heights, key, parentProp.FindPropertyRelative(relativeName));
  460. }
  461. public static bool PropertyFieldWithMinValue(ref Rect drawRect, Dictionary<string, float> heights, string key,
  462. SerializedProperty parentProp, string relativeName, float minValue)
  463. {
  464. var relativeProp = parentProp.FindPropertyRelative(relativeName);
  465. return PropertyFieldWithMinValue(ref drawRect, heights, key, relativeProp, minValue);
  466. }
  467. public static bool PropertyFieldWithMaxValue(ref Rect drawRect, Dictionary<string, float> heights, string key,
  468. SerializedProperty parentProp, string relativeName, float maxValue)
  469. {
  470. var relativeProp = parentProp.FindPropertyRelative(relativeName);
  471. return PropertyFieldWithMaxValue(ref drawRect, heights, key, relativeProp, maxValue);
  472. }
  473. public static GUIContent GetContent(string textAndTooltip)
  474. {
  475. if (string.IsNullOrEmpty(textAndTooltip))
  476. return GUIContent.none;
  477. GUIContent content;
  478. if (!s_GUIContentCache.TryGetValue(textAndTooltip, out content))
  479. {
  480. var s = textAndTooltip.Split('|');
  481. content = new GUIContent(s[0]);
  482. if (s.Length > 1 && !string.IsNullOrEmpty(s[1]))
  483. content.tooltip = s[1];
  484. s_GUIContentCache.Add(textAndTooltip, content);
  485. }
  486. return content;
  487. }
  488. public static void DrawSplitter()
  489. {
  490. var rect = GUILayoutUtility.GetRect(1f, 1f);
  491. rect.xMin = 0f;
  492. rect.width += 4f;
  493. DrawSplitter(rect);
  494. }
  495. public static void DrawSplitter(Rect rect)
  496. {
  497. if (Event.current.type != EventType.Repaint)
  498. return;
  499. EditorGUI.DrawRect(rect, EditorCustomStyles.splitter);
  500. }
  501. public static float DrawSplitterAndBackground(Rect drawRect, bool drawBackground = false)
  502. {
  503. float defaultWidth = drawRect.width;
  504. float defaultX = drawRect.x;
  505. var splitRect = drawRect;
  506. splitRect.y = drawRect.y;
  507. splitRect.x = EditorGUI.indentLevel * INDENT_WIDTH + 4;
  508. splitRect.xMax = drawRect.xMax;
  509. splitRect.height = 1f;
  510. DrawSplitter(splitRect);
  511. if (drawBackground)
  512. {
  513. var bgRect = drawRect;
  514. bgRect.y = drawRect.y;
  515. bgRect.x -= 10 - EditorGUI.indentLevel * INDENT_WIDTH;
  516. bgRect.xMax = drawRect.xMax;
  517. bgRect.height = HEADER_HEIGHT + (EditorGUI.indentLevel < 1 ? 2 : 0);
  518. EditorGUI.DrawRect(bgRect, EditorCustomStyles.headerBackground);
  519. }
  520. return HEADER_HEIGHT;
  521. }
  522. public static bool DrawHeader(string title, bool state, bool drawBackground, SerializedProperty activeField,
  523. Action<Rect> drawCallback, params HeaderMenuInfo[] menus)
  524. {
  525. var rect = GUILayoutUtility.GetRect(1f, HEADER_HEIGHT);
  526. var labelRect = DrawHeaderInternal(rect, title, ref state, drawBackground, activeField);
  527. DrawMenu(rect, menus);
  528. if (drawCallback != null)
  529. {
  530. drawCallback(rect);
  531. }
  532. var e = Event.current;
  533. if (e.type == EventType.MouseDown)
  534. {
  535. if (labelRect.Contains(e.mousePosition))
  536. {
  537. if (e.button == 0)
  538. {
  539. state = !state;
  540. e.Use();
  541. }
  542. }
  543. }
  544. return state;
  545. }
  546. internal static bool DrawHeader(string title, bool state, bool drawBackground, SerializedProperty activeField,
  547. Action<Rect> drawCallback, List<HeaderMenuInfo> menus)
  548. {
  549. var rect = GUILayoutUtility.GetRect(1f, HEADER_HEIGHT);
  550. var labelRect = DrawHeaderInternal(rect, title, ref state, drawBackground, activeField);
  551. DrawMenu(rect, menus);
  552. if (drawCallback != null)
  553. {
  554. drawCallback(rect);
  555. }
  556. var e = Event.current;
  557. if (e.type == EventType.MouseDown)
  558. {
  559. if (labelRect.Contains(e.mousePosition))
  560. {
  561. if (e.button == 0)
  562. {
  563. state = !state;
  564. e.Use();
  565. }
  566. }
  567. }
  568. return state;
  569. }
  570. private static Rect DrawHeaderInternal(Rect rect, string title, ref bool state, bool drawBackground, SerializedProperty activeField)
  571. {
  572. var splitRect = rect;
  573. splitRect.x = EditorGUI.indentLevel * INDENT_WIDTH + 4;
  574. splitRect.xMax = rect.xMax;
  575. splitRect.height = 1f;
  576. var backgroundRect = rect;
  577. backgroundRect.x = splitRect.x;
  578. backgroundRect.xMax = rect.xMax;
  579. var labelRect = rect;
  580. labelRect.xMin += 0f;
  581. labelRect.xMax -= 35f;
  582. var foldoutRect = rect;
  583. //foldoutRect.x -= 12f - EditorGUI.indentLevel * INDENT_WIDTH ;
  584. foldoutRect.x = rect.x - FOLDOUT_WIDTH + EditorGUI.indentLevel * INDENT_WIDTH + DIFF_WIDTH;
  585. foldoutRect.y += 1f;
  586. foldoutRect.width = FOLDOUT_WIDTH;
  587. foldoutRect.height = FOLDOUT_WIDTH;
  588. DrawSplitter(splitRect);
  589. if (drawBackground)
  590. EditorGUI.DrawRect(backgroundRect, EditorCustomStyles.headerBackground);
  591. if (!string.IsNullOrEmpty(title))
  592. EditorGUI.LabelField(labelRect, GetContent(title));
  593. state = GUI.Toggle(foldoutRect, state, GUIContent.none, EditorStyles.foldout);
  594. if (activeField != null)
  595. {
  596. var toggleRect = backgroundRect;
  597. toggleRect.x = rect.x + EditorGUIUtility.labelWidth - EditorGUI.indentLevel * INDENT_WIDTH + GAP_WIDTH;
  598. toggleRect.y += 1f;
  599. toggleRect.width = 13f;
  600. toggleRect.height = 13f;
  601. activeField.boolValue = GUI.Toggle(toggleRect, activeField.boolValue, GUIContent.none);
  602. }
  603. return labelRect;
  604. }
  605. internal static bool DrawHeader(string title, SerializedProperty group, SerializedProperty activeField,
  606. Action resetAction, Action removeAction, Action docAction)
  607. {
  608. if (group == null) return false;
  609. group.isExpanded = DrawHeader(title, group.isExpanded, false, activeField, null,
  610. new HeaderMenuInfo("Reset", resetAction),
  611. new HeaderMenuInfo("Remove", removeAction),
  612. new HeaderMenuInfo("HelpDoc", docAction));
  613. return group.isExpanded;
  614. }
  615. internal static bool DrawHeader(string title, SerializedProperty group, SerializedProperty activeField,
  616. params HeaderMenuInfo[] menus)
  617. {
  618. group.isExpanded = DrawHeader(title, group.isExpanded, false, activeField, null, menus);
  619. return group.isExpanded;
  620. }
  621. internal static bool DrawHeader(string title, SerializedProperty group, SerializedProperty activeField,
  622. List<HeaderMenuInfo> menus)
  623. {
  624. group.isExpanded = DrawHeader(title, group.isExpanded, false, activeField, null, menus);
  625. return group.isExpanded;
  626. }
  627. internal static void DrawMenu(Rect parentRect, params HeaderMenuInfo[] menus)
  628. {
  629. if (menus == null || menus.Length <= 0) return;
  630. var menuIcon = EditorCustomStyles.paneOptionsIcon;
  631. var menuRect = new Rect(parentRect.xMax - menuIcon.width, parentRect.y + 2f,
  632. menuIcon.width, menuIcon.height);
  633. GUI.DrawTexture(menuRect, menuIcon);
  634. var e = Event.current;
  635. if (e.type == EventType.MouseDown)
  636. {
  637. if (menuRect.Contains(e.mousePosition))
  638. {
  639. ShowHeaderContextMenu(new Vector2(menuRect.x, menuRect.yMax), menus);
  640. e.Use();
  641. }
  642. else if (parentRect.Contains(e.mousePosition))
  643. {
  644. if (e.button != 0)
  645. {
  646. ShowHeaderContextMenu(e.mousePosition, menus);
  647. e.Use();
  648. }
  649. }
  650. }
  651. }
  652. internal static void DrawMenu(Rect parentRect, List<HeaderMenuInfo> menus)
  653. {
  654. if (menus == null || menus.Count <= 0) return;
  655. var menuIcon = EditorCustomStyles.paneOptionsIcon;
  656. var menuRect = new Rect(parentRect.xMax - menuIcon.width, parentRect.y + 2f,
  657. menuIcon.width, menuIcon.height);
  658. GUI.DrawTexture(menuRect, menuIcon);
  659. var e = Event.current;
  660. if (e.type == EventType.MouseDown)
  661. {
  662. if (menuRect.Contains(e.mousePosition))
  663. {
  664. ShowHeaderContextMenu(new Vector2(menuRect.x, menuRect.yMax), menus);
  665. e.Use();
  666. }
  667. else if (parentRect.Contains(e.mousePosition))
  668. {
  669. if (e.button != 0)
  670. {
  671. ShowHeaderContextMenu(e.mousePosition, menus);
  672. e.Use();
  673. }
  674. }
  675. }
  676. }
  677. static void ShowHeaderContextMenu(Vector2 position, params HeaderMenuInfo[] menus)
  678. {
  679. if (menus == null || menus.Length <= 0) return;
  680. var menu = new GenericMenu();
  681. foreach (var info in menus)
  682. {
  683. if (info.enable)
  684. menu.AddItem(GetContent(info.name), false, () => info.action());
  685. else
  686. menu.AddDisabledItem(GetContent(info.name));
  687. }
  688. menu.DropDown(new Rect(position, Vector2.zero));
  689. }
  690. static void ShowHeaderContextMenu(Vector2 position, List<HeaderMenuInfo> menus)
  691. {
  692. if (menus == null || menus.Count <= 0) return;
  693. var menu = new GenericMenu();
  694. foreach (var info in menus)
  695. {
  696. if (info.enable)
  697. menu.AddItem(GetContent(info.name), false, () => info.action());
  698. else
  699. menu.AddDisabledItem(GetContent(info.name));
  700. }
  701. menu.DropDown(new Rect(position, Vector2.zero));
  702. }
  703. }
  704. }