FR2_SplitView.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. //#define FR2_DEBUG
  2. using System;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEditor;
  6. using UnityEngine.Experimental.Rendering;
  7. namespace vietlabs.fr2
  8. {
  9. public class FR2_SplitView
  10. {
  11. private const float SPLIT_SIZE = 2f;
  12. private IWindow window;
  13. private bool dirty;
  14. public FR2_SplitView(IWindow w)
  15. {
  16. this.window = w;
  17. }
  18. [Serializable]
  19. public class Info
  20. {
  21. public GUIContent title;
  22. #if FR2_DEBUG
  23. public Color color;
  24. #endif
  25. public Rect rect;
  26. public float normWeight;
  27. public int stIndex;
  28. public bool visible = true;
  29. public float weight = 1f;
  30. public Action<Rect> draw;
  31. public void DoDraw()
  32. {
  33. #if FR2_DEBUG
  34. GUI2.Rect(rect, Color.white, 0.1f);
  35. #endif
  36. var drawRect = rect;
  37. if (title != null)
  38. {
  39. var titleRect = new Rect(rect.x, rect.y, rect.width, 16f);
  40. GUI2.Rect(titleRect, Color.black, 0.2f);
  41. titleRect.xMin += 4f;
  42. GUI.Label(titleRect, title, EditorStyles.boldLabel);
  43. drawRect.yMin += 16f;
  44. }
  45. draw(drawRect);
  46. }
  47. }
  48. public bool isHorz;
  49. public List<Info> splits = new List<Info>();
  50. public bool isVisible
  51. {
  52. get { return _visibleCount > 0; }
  53. }
  54. private int _visibleCount;
  55. private Rect _rect;
  56. public void CalculateWeight()
  57. {
  58. _visibleCount = 0;
  59. var _totalWeight = 0f;
  60. for (var i = 0; i < splits.Count; i++)
  61. {
  62. var info = splits[i];
  63. if (!info.visible) continue;
  64. info.stIndex = _visibleCount;
  65. _totalWeight += info.weight;
  66. _visibleCount++;
  67. }
  68. if (_visibleCount == 0 || _totalWeight == 0)
  69. {
  70. //Debug.LogWarning("Nothing visible!");
  71. return;
  72. }
  73. var cWeight = 0f;
  74. for (var i = 0; i < splits.Count; i++)
  75. {
  76. var info = splits[i];
  77. if (!info.visible) continue;
  78. cWeight += info.weight;
  79. info.normWeight = info.weight / _totalWeight;
  80. }
  81. }
  82. public void Draw(Rect rect)
  83. {
  84. if (rect.width > 0 || rect.height > 0)
  85. {
  86. _rect = rect;
  87. }
  88. if (dirty)
  89. {
  90. dirty = false;
  91. CalculateWeight();
  92. }
  93. var sz = (_visibleCount - 1) * SPLIT_SIZE;
  94. var dx = _rect.x;
  95. var dy = _rect.y;
  96. for (var i = 0; i < splits.Count; i++)
  97. {
  98. var info = splits[i];
  99. if (!info.visible) continue;
  100. var rr = new Rect
  101. (
  102. dx, dy,
  103. isHorz ? (_rect.width - sz) * info.normWeight : _rect.width,
  104. isHorz ? _rect.height : (_rect.height - sz) * info.normWeight
  105. );
  106. if (rr.width > 0 && rr.height > 0)
  107. {
  108. info.rect = rr;
  109. }
  110. if (info.draw != null) info.DoDraw();
  111. if (info.stIndex < _visibleCount - 1)
  112. {
  113. DrawSpliter(i, isHorz ? info.rect.xMax : info.rect.yMax);
  114. }
  115. if (isHorz)
  116. {
  117. dx += info.rect.width + SPLIT_SIZE;
  118. }
  119. else
  120. {
  121. dy += info.rect.height + SPLIT_SIZE;
  122. }
  123. }
  124. }
  125. public void DrawLayout()
  126. {
  127. var rect = StartLayout(isHorz);
  128. {
  129. Draw(rect);
  130. }
  131. EndLayout(isHorz);
  132. }
  133. private int resizeIndex = -1;
  134. void RefreshSpliterPos(int index, float px)
  135. {
  136. var sp1 = splits[index];
  137. var sp2 = splits[index + 1];
  138. var r1 = sp1.rect;
  139. var r2 = sp2.rect;
  140. var w1 = sp1.weight;
  141. var w2 = sp2.weight;
  142. var tt = w1 + w2;
  143. var dd = isHorz ? (r2.xMax - r1.xMin) : (r2.yMax - r1.yMin) - SPLIT_SIZE;
  144. var m = isHorz ? (Event.current.mousePosition.x - r1.x) : (Event.current.mousePosition.y - r1.y);
  145. var pct = Mathf.Min(0.9f, Mathf.Max(0.1f, m / dd));
  146. sp1.weight = tt * pct;
  147. sp2.weight = tt * (1 - pct);
  148. dirty = true;
  149. if (window != null) window.WillRepaint = true;
  150. }
  151. void DrawSpliter(int index, float px)
  152. {
  153. var dRect = _rect;
  154. if (isHorz)
  155. {
  156. dRect.x = px + SPLIT_SIZE;
  157. dRect.width = SPLIT_SIZE;
  158. }
  159. else
  160. {
  161. dRect.y = px;
  162. dRect.height = SPLIT_SIZE;
  163. }
  164. if (Event.current.type == EventType.Repaint || Event.current.type == EventType.MouseMove)
  165. {
  166. GUI2.Rect(dRect, Color.black, 0.4f);
  167. }
  168. var dRect2 = GUI2.Padding(dRect, -2f, -2f);
  169. EditorGUIUtility.AddCursorRect(dRect2, isHorz ? MouseCursor.ResizeHorizontal : MouseCursor.ResizeVertical);
  170. if( Event.current.type == EventType.MouseDown && dRect2.Contains(Event.current.mousePosition))
  171. {
  172. resizeIndex = index;
  173. RefreshSpliterPos(index, px);
  174. }
  175. if (resizeIndex == index)
  176. {
  177. RefreshSpliterPos(index, px);
  178. }
  179. if (Event.current.type == EventType.MouseUp)
  180. {
  181. resizeIndex = -1;
  182. }
  183. }
  184. Rect StartLayout(bool horz)
  185. {
  186. return horz
  187. ? EditorGUILayout.BeginHorizontal(GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true))
  188. : EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
  189. }
  190. void EndLayout(bool horz)
  191. {
  192. if (horz)
  193. {
  194. EditorGUILayout.EndHorizontal();
  195. }
  196. else
  197. {
  198. EditorGUILayout.EndVertical();
  199. }
  200. }
  201. }
  202. }