GridCoord.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using XUGL;
  5. namespace XCharts.Runtime
  6. {
  7. /// <summary>
  8. /// Grid component.
  9. /// ||Drawing grid in rectangular coordinate. Line chart, bar chart, and scatter chart can be drawn in grid.
  10. /// ||网格组件。
  11. /// 直角坐标系内绘图网格。可以在网格上绘制折线图,柱状图,散点图。
  12. /// </summary>
  13. [Serializable]
  14. [ComponentHandler(typeof(GridCoordHandler), true)]
  15. public class GridCoord : CoordSystem, IUpdateRuntimeData, ISerieContainer
  16. {
  17. [SerializeField] private bool m_Show = true;
  18. [SerializeField][Since("v3.8.0")] private int m_LayoutIndex = -1;
  19. [SerializeField] private float m_Left = 0.11f;
  20. [SerializeField] private float m_Right = 0.08f;
  21. [SerializeField] private float m_Top = 0.22f;
  22. [SerializeField] private float m_Bottom = 0.14f;
  23. [SerializeField] private Color32 m_BackgroundColor;
  24. [SerializeField] private bool m_ShowBorder = false;
  25. [SerializeField] private float m_BorderWidth = 0f;
  26. [SerializeField] private Color32 m_BorderColor;
  27. public GridCoordContext context = new GridCoordContext();
  28. /// <summary>
  29. /// Whether to show the grid in rectangular coordinate.
  30. /// ||是否显示直角坐标系网格。
  31. /// </summary>
  32. public bool show
  33. {
  34. get { return m_Show; }
  35. set { if (PropertyUtil.SetStruct(ref m_Show, value)) SetVerticesDirty(); }
  36. }
  37. /// <summary>
  38. /// The index of the grid layout component to which the grid belongs.
  39. /// The default is -1, which means that it does not belong to any grid layout component.
  40. /// When this value is set, the left, right, top, and bottom properties will be invalid.
  41. /// ||网格所属的网格布局组件的索引。默认为-1,表示不属于任何网格布局组件。当设置了该值时,left、right、top、bottom属性将失效。
  42. /// </summary>
  43. public int layoutIndex
  44. {
  45. get { return m_LayoutIndex; }
  46. set { if (PropertyUtil.SetStruct(ref m_LayoutIndex, value)) SetVerticesDirty(); }
  47. }
  48. /// <summary>
  49. /// Distance between grid component and the left side of the container.
  50. /// ||grid 组件离容器左侧的距离。
  51. /// </summary>
  52. public float left
  53. {
  54. get { return m_Left; }
  55. set { if (PropertyUtil.SetStruct(ref m_Left, value)) SetAllDirty(); }
  56. }
  57. /// <summary>
  58. /// Distance between grid component and the right side of the container.
  59. /// ||grid 组件离容器右侧的距离。
  60. /// </summary>
  61. public float right
  62. {
  63. get { return m_Right; }
  64. set { if (PropertyUtil.SetStruct(ref m_Right, value)) SetAllDirty(); }
  65. }
  66. /// <summary>
  67. /// Distance between grid component and the top side of the container.
  68. /// ||grid 组件离容器上侧的距离。
  69. /// </summary>
  70. public float top
  71. {
  72. get { return m_Top; }
  73. set { if (PropertyUtil.SetStruct(ref m_Top, value)) SetAllDirty(); }
  74. }
  75. /// <summary>
  76. /// Distance between grid component and the bottom side of the container.
  77. /// ||grid 组件离容器下侧的距离。
  78. /// </summary>
  79. public float bottom
  80. {
  81. get { return m_Bottom; }
  82. set { if (PropertyUtil.SetStruct(ref m_Bottom, value)) SetAllDirty(); }
  83. }
  84. /// <summary>
  85. /// Background color of grid, which is transparent by default.
  86. /// ||网格背景色,默认透明。
  87. /// </summary>
  88. public Color32 backgroundColor
  89. {
  90. get { return m_BackgroundColor; }
  91. set { if (PropertyUtil.SetColor(ref m_BackgroundColor, value)) SetVerticesDirty(); }
  92. }
  93. /// <summary>
  94. /// Whether to show the grid border.
  95. /// ||是否显示网格边框。
  96. /// </summary>
  97. public bool showBorder
  98. {
  99. get { return m_ShowBorder; }
  100. set { if (PropertyUtil.SetStruct(ref m_ShowBorder, value)) SetVerticesDirty(); }
  101. }
  102. /// <summary>
  103. /// Border width of grid.
  104. /// ||网格边框宽。
  105. /// </summary>
  106. public float borderWidth
  107. {
  108. get { return m_BorderWidth; }
  109. set { if (PropertyUtil.SetStruct(ref m_BorderWidth, value)) SetVerticesDirty(); }
  110. }
  111. /// <summary>
  112. /// The color of grid border.
  113. /// ||网格边框颜色。
  114. /// </summary>
  115. public Color32 borderColor
  116. {
  117. get { return m_BorderColor; }
  118. set { if (PropertyUtil.SetColor(ref m_BorderColor, value)) SetVerticesDirty(); }
  119. }
  120. public void UpdateRuntimeData(BaseChart chart)
  121. {
  122. var chartX = chart.chartX;
  123. var chartY = chart.chartY;
  124. var chartWidth = chart.chartWidth;
  125. var chartHeight = chart.chartHeight;
  126. if (layoutIndex >= 0)
  127. {
  128. var layout = chart.GetChartComponent<GridLayout>(layoutIndex);
  129. if (layout != null)
  130. {
  131. layout.UpdateRuntimeData(chart);
  132. layout.UpdateGridContext(index, ref chartX, ref chartY, ref chartWidth, ref chartHeight);
  133. }
  134. }
  135. var actualLeft = left <= 1 ? left * chartWidth : left;
  136. var actualBottom = bottom <= 1 ? bottom * chartHeight : bottom;
  137. var actualTop = top <= 1 ? top * chartHeight : top;
  138. var actualRight = right <= 1 ? right * chartWidth : right;
  139. context.x = chartX + actualLeft;
  140. context.y = chartY + actualBottom;
  141. context.width = chartWidth - actualLeft - actualRight;
  142. context.height = chartHeight - actualTop - actualBottom;
  143. context.position = new Vector3(context.x, context.y);
  144. context.center = new Vector3(context.x + context.width / 2, context.y + context.height / 2);
  145. }
  146. /// <summary>
  147. /// Whether the pointer is in the grid.
  148. /// ||指针是否在网格内。
  149. /// </summary>
  150. /// <returns></returns>
  151. public bool IsPointerEnter()
  152. {
  153. return context.isPointerEnter;
  154. }
  155. /// <summary>
  156. /// Whether the given position is in the grid.
  157. /// ||给定的位置是否在网格内。
  158. /// </summary>
  159. /// <param name="pos"></param>
  160. /// <returns></returns>
  161. public bool Contains(Vector3 pos)
  162. {
  163. return Contains(pos.x, pos.y);
  164. }
  165. /// <summary>
  166. /// Whether the given position is in the grid.
  167. /// ||给定的位置是否在网格内。
  168. /// </summary>
  169. /// <param name="pos"></param>
  170. /// <param name="isYAxis"></param>
  171. /// <returns></returns>
  172. [Since("v3.7.0")]
  173. public bool Contains(Vector3 pos, bool isYAxis)
  174. {
  175. return isYAxis ? ContainsY(pos.y) : ContainsX(pos.x);
  176. }
  177. /// <summary>
  178. /// Whether the given position is in the grid.
  179. /// ||给定的位置是否在网格内。
  180. /// </summary>
  181. /// <param name="x"></param>
  182. /// <param name="y"></param>
  183. /// <returns></returns>
  184. public bool Contains(float x, float y)
  185. {
  186. return ContainsX(x) && ContainsY(y);
  187. }
  188. /// <summary>
  189. /// Whether the given x is in the grid.
  190. /// ||给定的x是否在网格内。
  191. /// </summary>
  192. /// <param name="x"></param>
  193. /// <returns></returns>
  194. [Since("v3.7.0")]
  195. public bool ContainsX(float x)
  196. {
  197. return x >= context.x - 0.01f && x <= context.x + context.width + 0.01f;
  198. }
  199. /// <summary>
  200. /// Whether the given y is in the grid.
  201. /// ||给定的y是否在网格内。
  202. /// </summary>
  203. /// <param name="y"></param>
  204. /// <returns></returns>
  205. [Since("v3.7.0")]
  206. public bool ContainsY(float y)
  207. {
  208. return y >= context.y - 0.01f && y <= context.y + context.height + 0.01f;
  209. }
  210. /// <summary>
  211. /// Clamp the position of pos to the grid.
  212. /// ||将位置限制在网格内。
  213. /// </summary>
  214. /// <param name="pos"></param>
  215. [Since("v3.7.0")]
  216. public void Clamp(ref Vector3 pos)
  217. {
  218. ClampX(ref pos);
  219. ClampY(ref pos);
  220. }
  221. /// <summary>
  222. /// Clamp the x position of pos to the grid.
  223. /// ||将位置的X限制在网格内。
  224. /// </summary>
  225. /// <param name="pos"></param>
  226. [Since("v3.7.0")]
  227. public void ClampX(ref Vector3 pos)
  228. {
  229. if (pos.x < context.x) pos.x = context.x;
  230. else if (pos.x > context.x + context.width) pos.x = context.x + context.width;
  231. }
  232. /// <summary>
  233. /// Clamp the y position of pos to the grid.
  234. /// ||将位置的Y限制在网格内。
  235. /// </summary>
  236. /// <param name="pos"></param>
  237. [Since("v3.7.0")]
  238. public void ClampY(ref Vector3 pos)
  239. {
  240. if (pos.y < context.y) pos.y = context.y;
  241. else if (pos.y > context.y + context.height) pos.y = context.y + context.height;
  242. }
  243. /// <summary>
  244. /// Determines whether a given line segment will not intersect the Grid boundary at all.
  245. /// ||判断给定的线段是否与Grid边界是否完全不会相交。
  246. /// </summary>
  247. /// <param name="sp"></param>
  248. /// <param name="ep"></param>
  249. /// <returns></returns>
  250. [Since("v3.10.0")]
  251. public bool NotAnyIntersect(Vector3 sp, Vector3 ep)
  252. {
  253. if (sp.x < context.x && ep.x < context.x)
  254. return true;
  255. if (sp.x > context.x + context.width && ep.x > context.x + context.width)
  256. return true;
  257. if (sp.y < context.y && ep.y < context.y)
  258. return true;
  259. if (sp.y > context.y + context.height && ep.y > context.y + context.height)
  260. return true;
  261. return false;
  262. }
  263. /// <summary>
  264. /// 给定的线段和Grid边界的交点
  265. /// </summary>
  266. /// <param name="sp"></param>
  267. /// <param name="ep"></param>
  268. /// <returns></returns>
  269. public bool BoundaryPoint(Vector3 sp, Vector3 ep, ref Vector3 point)
  270. {
  271. if (Contains(sp) && Contains(ep))
  272. return false;
  273. if (sp.x < context.x && ep.x < context.x)
  274. return false;
  275. if (sp.x > context.x + context.width && ep.x > context.x + context.width)
  276. return false;
  277. if (sp.y < context.y && ep.y < context.y)
  278. return false;
  279. if (sp.y > context.y + context.height && ep.y > context.y + context.height)
  280. return false;
  281. var lb = new Vector3(context.x, context.y);
  282. var lt = new Vector3(context.x, context.y + context.height);
  283. var rt = new Vector3(context.x + context.width, context.y + context.height);
  284. var rb = new Vector3(context.x + context.width, context.y);
  285. if (UGLHelper.GetIntersection(sp, ep, rb, rt, ref point))
  286. return true;
  287. if (UGLHelper.GetIntersection(sp, ep, lt, rt, ref point))
  288. return true;
  289. if (UGLHelper.GetIntersection(sp, ep, lb, rb, ref point))
  290. return true;
  291. if (UGLHelper.GetIntersection(sp, ep, lb, lt, ref point))
  292. return true;
  293. return false;
  294. }
  295. /// <summary>
  296. /// 给定的线段和Grid边界的交点
  297. /// </summary>
  298. /// <param name="sp"></param>
  299. /// <param name="ep"></param>
  300. /// <returns></returns>
  301. public bool BoundaryPoint(Vector3 sp, Vector3 ep, ref List<Vector3> point)
  302. {
  303. if (Contains(sp) && Contains(ep))
  304. return false;
  305. var lb = new Vector3(context.x, context.y);
  306. var lt = new Vector3(context.x, context.y + context.height);
  307. var rt = new Vector3(context.x + context.width, context.y + context.height);
  308. var rb = new Vector3(context.x + context.width, context.y);
  309. var flag = false;
  310. if (UGLHelper.GetIntersection(sp, ep, lb, lt, ref point))
  311. flag = true;
  312. if (UGLHelper.GetIntersection(sp, ep, lt, rt, ref point))
  313. flag = true;
  314. if (UGLHelper.GetIntersection(sp, ep, lb, rb, ref point))
  315. flag = true;
  316. if (UGLHelper.GetIntersection(sp, ep, rb, rt, ref point))
  317. flag = true;
  318. return flag;
  319. }
  320. }
  321. }