VisualMap.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. namespace XCharts.Runtime
  4. {
  5. [System.Serializable]
  6. public class VisualMapRange : ChildComponent
  7. {
  8. [SerializeField] private double m_Min;
  9. [SerializeField] private double m_Max;
  10. [SerializeField] private string m_Label;
  11. [SerializeField] private Color32 m_Color;
  12. /// <summary>
  13. /// 范围最小值
  14. /// </summary>
  15. public double min { get { return m_Min; } set { m_Min = value; } }
  16. /// <summary>
  17. /// 范围最大值
  18. /// </summary>
  19. public double max { get { return m_Max; } set { m_Max = value; } }
  20. /// <summary>
  21. /// 文字描述
  22. /// </summary>
  23. public string label { get { return m_Label; } set { m_Label = value; } }
  24. /// <summary>
  25. /// 颜色
  26. /// </summary>
  27. public Color32 color { get { return m_Color; } set { m_Color = value; } }
  28. public bool Contains(double value, double minMaxRange)
  29. {
  30. if (m_Min == 0 && m_Max == 0) return false;
  31. var cmin = System.Math.Abs(m_Min) < 1 ? minMaxRange * m_Min : m_Min;
  32. var cmax = System.Math.Abs(m_Max) < 1 ? minMaxRange * m_Max : m_Max;
  33. return value >= cmin && value < cmax;
  34. }
  35. }
  36. /// <summary>
  37. /// VisualMap component. Mapping data to visual elements such as colors.
  38. /// ||视觉映射组件。用于进行『视觉编码』,也就是将数据映射到视觉元素(视觉通道)。
  39. /// </summary>
  40. [System.Serializable]
  41. [ComponentHandler(typeof(VisualMapHandler), true)]
  42. public class VisualMap : MainComponent
  43. {
  44. /// <summary>
  45. /// 类型。分为连续型和分段型。
  46. /// </summary>
  47. public enum Type
  48. {
  49. /// <summary>
  50. /// 连续型。
  51. /// </summary>
  52. Continuous,
  53. /// <summary>
  54. /// 分段型。
  55. /// </summary>
  56. Piecewise
  57. }
  58. /// <summary>
  59. /// 选择模式
  60. /// </summary>
  61. public enum SelectedMode
  62. {
  63. /// <summary>
  64. /// 多选。
  65. /// </summary>
  66. Multiple,
  67. /// <summary>
  68. /// 单选。
  69. /// </summary>
  70. Single
  71. }
  72. [SerializeField] private bool m_Show = true;
  73. [SerializeField] private bool m_ShowUI = false;
  74. [SerializeField] private Type m_Type = Type.Continuous;
  75. [SerializeField] private SelectedMode m_SelectedMode = SelectedMode.Multiple;
  76. [SerializeField] private int m_SerieIndex = 0;
  77. [SerializeField] private double m_Min = 0;
  78. [SerializeField] private double m_Max = 0;
  79. [SerializeField] private double[] m_Range = new double[2] { 0, 0 };
  80. [SerializeField] private string[] m_Text = new string[2] { "", "" };
  81. [SerializeField] private float[] m_TextGap = new float[2] { 10f, 10f };
  82. [SerializeField] private int m_SplitNumber = 5;
  83. [SerializeField] private bool m_Calculable = false;
  84. [SerializeField] private bool m_Realtime = true;
  85. [SerializeField] private float m_ItemWidth = 20f;
  86. [SerializeField] private float m_ItemHeight = 140f;
  87. [SerializeField] private float m_ItemGap = 10f;
  88. [SerializeField] private float m_BorderWidth = 0;
  89. [SerializeField] private int m_Dimension = -1;
  90. [SerializeField] private bool m_HoverLink = true;
  91. [SerializeField] private bool m_AutoMinMax = true;
  92. [SerializeField] private Orient m_Orient = Orient.Horizonal;
  93. [SerializeField] private Location m_Location = Location.defaultLeft;
  94. [SerializeField] private bool m_WorkOnLine = true;
  95. [SerializeField] private bool m_WorkOnArea = false;
  96. [SerializeField] private List<VisualMapRange> m_OutOfRange = new List<VisualMapRange>() { new VisualMapRange() { color = Color.gray } };
  97. [SerializeField] private List<VisualMapRange> m_InRange = new List<VisualMapRange>();
  98. public VisualMapContext context = new VisualMapContext();
  99. /// <summary>
  100. /// Whether to enable components.
  101. /// ||组件是否生效。
  102. /// </summary>
  103. public bool show
  104. {
  105. get { return m_Show; }
  106. set { if (PropertyUtil.SetStruct(ref m_Show, value)) SetVerticesDirty(); }
  107. }
  108. /// <summary>
  109. /// Whether to display components. If set to false, it will not show up, but the data mapping function still exists.
  110. /// ||是否显示组件。如果设置为 false,不会显示,但是数据映射的功能还存在。
  111. /// </summary>
  112. public bool showUI
  113. {
  114. get { return m_ShowUI; }
  115. set { if (PropertyUtil.SetStruct(ref m_ShowUI, value)) SetVerticesDirty(); }
  116. }
  117. /// <summary>
  118. /// the type of visualmap component.
  119. /// ||组件类型。
  120. /// </summary>
  121. public Type type
  122. {
  123. get { return m_Type; }
  124. set { if (PropertyUtil.SetStruct(ref m_Type, value)) SetVerticesDirty(); }
  125. }
  126. /// <summary>
  127. /// the selected mode for Piecewise visualMap.
  128. /// ||选择模式。
  129. /// </summary>
  130. public SelectedMode selectedMode
  131. {
  132. get { return m_SelectedMode; }
  133. set { if (PropertyUtil.SetStruct(ref m_SelectedMode, value)) SetVerticesDirty(); }
  134. }
  135. /// <summary>
  136. /// the serie index of visualMap.
  137. /// ||影响的serie索引。
  138. /// </summary>
  139. public int serieIndex
  140. {
  141. get { return m_SerieIndex; }
  142. set { if (PropertyUtil.SetStruct(ref m_SerieIndex, value)) SetVerticesDirty(); }
  143. }
  144. /// <summary>
  145. /// The minimum allowed. 'min' must be user specified. [visualmap.min, visualmap.max] forms the "domain" of the visualMap.
  146. /// ||
  147. /// 允许的最小值。`autoMinMax`为`false`时必须指定。[visualMap.min, visualMap.max] 形成了视觉映射的『定义域』。
  148. /// </summary>
  149. public double min
  150. {
  151. get { return m_Min; }
  152. set { if (PropertyUtil.SetStruct(ref m_Min, value)) SetVerticesDirty(); }
  153. }
  154. /// <summary>
  155. /// The maximum allowed. 'max' must be user specified. [visualmap.min, visualmap.max] forms the "domain" of the visualMap.
  156. /// ||
  157. /// 允许的最大值。`autoMinMax`为`false`时必须指定。[visualMap.min, visualMax.max] 形成了视觉映射的『定义域』。
  158. /// </summary>
  159. public double max
  160. {
  161. get { return m_Max; }
  162. set { m_Max = (value < min ? min + 1 : value); SetVerticesDirty(); }
  163. }
  164. /// <summary>
  165. /// Specifies the position of the numeric value corresponding to the handle. Range should be within the range of [min,max].
  166. /// ||
  167. /// 指定手柄对应数值的位置。range 应在[min,max]范围内。
  168. /// </summary>
  169. public double[] range { get { return m_Range; } }
  170. /// <summary>
  171. /// Text on both ends.
  172. /// ||两端的文本,如 ['High', 'Low']。
  173. /// </summary>
  174. public string[] text { get { return m_Text; } }
  175. /// <summary>
  176. /// The distance between the two text bodies.
  177. /// ||两端文字主体之间的距离,单位为px。
  178. /// </summary>
  179. public float[] textGap { get { return m_TextGap; } }
  180. /// <summary>
  181. /// For continuous data, it is automatically evenly divided into several segments
  182. /// and automatically matches the size of inRange color list when the default is 0.
  183. /// ||
  184. /// 对于连续型数据,自动平均切分成几段,默认为0时自动匹配inRange颜色列表大小。
  185. /// </summary>
  186. public int splitNumber
  187. {
  188. get { return m_SplitNumber; }
  189. set { if (PropertyUtil.SetStruct(ref m_SplitNumber, value)) SetVerticesDirty(); }
  190. }
  191. /// <summary>
  192. /// Whether the handle used for dragging is displayed (the handle can be dragged to adjust the selected range).
  193. /// ||
  194. /// 是否显示拖拽用的手柄(手柄能拖拽调整选中范围)。
  195. /// </summary>
  196. public bool calculable
  197. {
  198. get { return m_Calculable; }
  199. set { if (PropertyUtil.SetStruct(ref m_Calculable, value)) SetVerticesDirty(); }
  200. }
  201. /// <summary>
  202. /// Whether to update in real time while dragging.
  203. /// ||
  204. /// 拖拽时,是否实时更新。
  205. /// </summary>
  206. public bool realtime
  207. {
  208. get { return m_Realtime; }
  209. set { if (PropertyUtil.SetStruct(ref m_Realtime, value)) SetVerticesDirty(); }
  210. }
  211. /// <summary>
  212. /// The width of the figure, that is, the width of the color bar.
  213. /// ||
  214. /// 图形的宽度,即颜色条的宽度。
  215. /// </summary>
  216. public float itemWidth
  217. {
  218. get { return m_ItemWidth; }
  219. set { if (PropertyUtil.SetStruct(ref m_ItemWidth, value)) SetVerticesDirty(); }
  220. }
  221. /// <summary>
  222. /// The height of the figure, that is, the height of the color bar.
  223. /// ||
  224. /// 图形的高度,即颜色条的高度。
  225. /// </summary>
  226. public float itemHeight
  227. {
  228. get { return m_ItemHeight; }
  229. set { if (PropertyUtil.SetStruct(ref m_ItemHeight, value)) SetVerticesDirty(); }
  230. }
  231. /// <summary>
  232. /// 每个图元之间的间隔距离。
  233. /// </summary>
  234. public float itemGap
  235. {
  236. get { return m_ItemGap; }
  237. set { if (PropertyUtil.SetStruct(ref m_ItemGap, value)) SetVerticesDirty(); }
  238. }
  239. /// <summary>
  240. /// Border line width.
  241. /// ||
  242. /// 边框线宽,单位px。
  243. /// </summary>
  244. public float borderWidth
  245. {
  246. get { return m_BorderWidth; }
  247. set { if (PropertyUtil.SetStruct(ref m_BorderWidth, value)) SetVerticesDirty(); }
  248. }
  249. /// <summary>
  250. /// Specifies "which dimension" of the data to map to the visual element. "Data" is series.data.
  251. /// ||Starting at 1, the default is 0 to take the last dimension in data.
  252. /// ||
  253. /// 指定用数据的『哪个维度』,映射到视觉元素上。『数据』即 series.data。从1开始,默认为0取 data 中最后一个维度。
  254. /// </summary>
  255. public int dimension
  256. {
  257. get { return m_Dimension; }
  258. set { if (PropertyUtil.SetStruct(ref m_Dimension, value)) SetVerticesDirty(); }
  259. }
  260. /// <summary>
  261. /// When the hoverLink function is turned on, when the mouse hovers over the visualMap component,
  262. /// the corresponding value of the mouse position is highlighted in the corresponding graphic element in the diagram.
  263. /// ||Conversely, when the mouse hovers over a graphic element in a diagram,
  264. /// the corresponding value of the visualMap component is triangulated in the corresponding position.
  265. /// ||
  266. /// 打开 hoverLink 功能时,鼠标悬浮到 visualMap 组件上时,鼠标位置对应的数值 在 图表中对应的图形元素,会高亮。
  267. /// 反之,鼠标悬浮到图表中的图形元素上时,在 visualMap 组件的相应位置会有三角提示其所对应的数值。
  268. /// </summary>
  269. public bool hoverLink
  270. {
  271. get { return m_HoverLink; }
  272. set { if (PropertyUtil.SetStruct(ref m_HoverLink, value)) SetVerticesDirty(); }
  273. }
  274. /// <summary>
  275. /// Automatically set min, Max value
  276. /// 自动设置min,max的值
  277. /// </summary>
  278. public bool autoMinMax
  279. {
  280. get { return m_AutoMinMax; }
  281. set { if (PropertyUtil.SetStruct(ref m_AutoMinMax, value)) SetVerticesDirty(); }
  282. }
  283. /// <summary>
  284. /// Specify whether the layout of component is horizontal or vertical.
  285. /// ||
  286. /// 布局方式是横还是竖。
  287. /// </summary>
  288. public Orient orient
  289. {
  290. get { return m_Orient; }
  291. set { if (PropertyUtil.SetStruct(ref m_Orient, value)) SetVerticesDirty(); }
  292. }
  293. /// <summary>
  294. /// The location of component.
  295. /// ||组件显示的位置。
  296. /// </summary>
  297. public Location location
  298. {
  299. get { return m_Location; }
  300. set { if (PropertyUtil.SetClass(ref m_Location, value)) SetVerticesDirty(); }
  301. }
  302. /// <summary>
  303. /// Whether the visualmap is work on linestyle of linechart.
  304. /// ||组件是否对LineChart的LineStyle有效。
  305. /// </summary>
  306. public bool workOnLine
  307. {
  308. get { return m_WorkOnLine; }
  309. set { if (PropertyUtil.SetStruct(ref m_WorkOnLine, value)) SetVerticesDirty(); }
  310. }
  311. /// <summary>
  312. /// Whether the visualmap is work on areaStyle of linechart.
  313. /// ||组件是否对LineChart的AreaStyle有效。
  314. /// </summary>
  315. public bool workOnArea
  316. {
  317. get { return m_WorkOnArea; }
  318. set { if (PropertyUtil.SetStruct(ref m_WorkOnArea, value)) SetVerticesDirty(); }
  319. }
  320. /// <summary>
  321. /// Defines a visual color outside of the selected range.
  322. /// ||定义 在选中范围外 的视觉颜色。
  323. /// </summary>
  324. public List<VisualMapRange> outOfRange
  325. {
  326. get { return m_OutOfRange; }
  327. set { if (value != null) { m_OutOfRange = value; SetVerticesDirty(); } }
  328. }
  329. /// <summary>
  330. /// 分段式每一段的相关配置。
  331. /// </summary>
  332. public List<VisualMapRange> inRange
  333. {
  334. get { return m_InRange; }
  335. set { if (value != null) { m_InRange = value; SetVerticesDirty(); } }
  336. }
  337. public override bool vertsDirty { get { return m_VertsDirty || location.anyDirty; } }
  338. public override void ClearVerticesDirty()
  339. {
  340. base.ClearVerticesDirty();
  341. location.ClearVerticesDirty();
  342. }
  343. public override void ClearComponentDirty()
  344. {
  345. base.ClearComponentDirty();
  346. location.ClearComponentDirty();
  347. }
  348. public double rangeMin
  349. {
  350. get
  351. {
  352. if (m_Range[0] == 0 && m_Range[1] == 0) return min;
  353. else if (m_Range[0] < min || m_Range[0] > max) return min;
  354. else return m_Range[0];
  355. }
  356. set
  357. {
  358. if (value >= min && value <= m_Range[1]) m_Range[0] = value;
  359. }
  360. }
  361. public double rangeMax
  362. {
  363. get
  364. {
  365. if (m_Range[0] == 0 && m_Range[1] == 0) return max;
  366. if (m_Range[1] >= m_Range[0] && m_Range[1] < max) return m_Range[1];
  367. else return max;
  368. }
  369. set
  370. {
  371. if (value >= m_Range[0] && value <= max) m_Range[1] = value;
  372. }
  373. }
  374. public float runtimeRangeMinHeight { get { return (float) ((rangeMin - min) / (max - min) * itemHeight); } }
  375. public float runtimeRangeMaxHeight { get { return (float) ((rangeMax - min) / (max - min) * itemHeight); } }
  376. public void AddColors(List<Color32> colors)
  377. {
  378. m_InRange.Clear();
  379. foreach (var color in colors)
  380. {
  381. m_InRange.Add(new VisualMapRange()
  382. {
  383. color = color
  384. });
  385. }
  386. }
  387. public void AddColors(List<string> colors)
  388. {
  389. m_InRange.Clear();
  390. foreach (var str in colors)
  391. {
  392. m_InRange.Add(new VisualMapRange()
  393. {
  394. color = ThemeStyle.GetColor(str)
  395. });
  396. }
  397. }
  398. public Color32 GetColor(double value)
  399. {
  400. int index = GetIndex(value);
  401. if (index == -1)
  402. {
  403. if (m_OutOfRange.Count > 0)
  404. return m_OutOfRange[0].color;
  405. else
  406. return ChartConst.clearColor32;
  407. }
  408. if (m_Type == VisualMap.Type.Piecewise)
  409. {
  410. return m_InRange[index].color;
  411. }
  412. else
  413. {
  414. int splitNumber = m_InRange.Count;
  415. var diff = (m_Max - m_Min) / (splitNumber - 1);
  416. var nowMin = m_Min + index * diff;
  417. var rate = (value - nowMin) / diff;
  418. if (index == splitNumber - 1)
  419. return m_InRange[index].color;
  420. else
  421. return Color32.Lerp(m_InRange[index].color, m_InRange[index + 1].color, (float) rate);
  422. }
  423. }
  424. private bool IsNeedPieceColor(double value, out int index)
  425. {
  426. bool flag = false;
  427. index = -1;
  428. for (int i = 0; i < m_InRange.Count; i++)
  429. {
  430. var range = m_InRange[i];
  431. if (range.min != 0 || range.max != 0)
  432. {
  433. flag = true;
  434. if (range.Contains(value, max - min))
  435. {
  436. index = i;
  437. return true;
  438. }
  439. }
  440. }
  441. return flag;
  442. }
  443. private Color32 GetPiecesColor(double value)
  444. {
  445. foreach (var piece in m_InRange)
  446. {
  447. if (piece.Contains(value, max - min))
  448. {
  449. return piece.color;
  450. }
  451. }
  452. if (m_OutOfRange.Count > 0)
  453. return m_OutOfRange[0].color;
  454. else
  455. return ChartConst.clearColor32;
  456. }
  457. public int GetIndex(double value)
  458. {
  459. int splitNumber = m_InRange.Count;
  460. if (splitNumber <= 0)
  461. return -1;
  462. var index = -1;
  463. if (IsNeedPieceColor(value, out index))
  464. {
  465. return index;
  466. }
  467. value = MathUtil.Clamp(value, m_Min, m_Max);
  468. var diff = (m_Max - m_Min) / (splitNumber - 1);
  469. for (int i = 0; i < splitNumber; i++)
  470. {
  471. if (value <= m_Min + (i + 1) * diff)
  472. {
  473. index = i;
  474. break;
  475. }
  476. }
  477. return index;
  478. }
  479. public bool IsPiecewise()
  480. {
  481. return m_Type == VisualMap.Type.Piecewise;
  482. }
  483. public bool IsInSelectedValue(double value)
  484. {
  485. if (context.pointerIndex < 0)
  486. return true;
  487. else
  488. return context.pointerIndex == GetIndex(value);
  489. }
  490. public double GetValue(Vector3 pos, Rect chartRect)
  491. {
  492. var vertical = orient == Orient.Vertical;
  493. var centerPos = new Vector3(chartRect.x, chartRect.y) + location.GetPosition(chartRect.width, chartRect.height);
  494. var pos1 = centerPos + (vertical ? Vector3.down : Vector3.left) * itemHeight / 2;
  495. var pos2 = centerPos + (vertical ? Vector3.up : Vector3.right) * itemHeight / 2;
  496. if (vertical)
  497. {
  498. if (pos.y < pos1.y)
  499. return min;
  500. else if (pos.y > pos2.y)
  501. return max;
  502. else
  503. return min + (pos.y - pos1.y) / (pos2.y - pos1.y) * (max - min);
  504. }
  505. else
  506. {
  507. if (pos.x < pos1.x)
  508. return min;
  509. else if (pos.x > pos2.x)
  510. return max;
  511. else
  512. return min + (pos.x - pos1.x) / (pos2.x - pos1.x) * (max - min);
  513. }
  514. }
  515. public bool IsInRect(Vector3 local, Rect chartRect, float triangleLen = 20)
  516. {
  517. var centerPos = new Vector3(chartRect.x, chartRect.y) + location.GetPosition(chartRect.width, chartRect.height);
  518. var diff = calculable ? triangleLen : 0;
  519. if (local.x >= centerPos.x - itemWidth / 2 - diff &&
  520. local.x <= centerPos.x + itemWidth / 2 + diff &&
  521. local.y >= centerPos.y - itemHeight / 2 - diff &&
  522. local.y <= centerPos.y + itemHeight / 2 + diff)
  523. {
  524. return true;
  525. }
  526. else
  527. {
  528. return false;
  529. }
  530. }
  531. public bool IsInRangeRect(Vector3 local, Rect chartRect)
  532. {
  533. var centerPos = new Vector3(chartRect.x, chartRect.y) + location.GetPosition(chartRect.width, chartRect.height);
  534. if (orient == Orient.Vertical)
  535. {
  536. var pos1 = centerPos + Vector3.down * itemHeight / 2;
  537. return local.x >= centerPos.x - itemWidth / 2 &&
  538. local.x <= centerPos.x + itemWidth / 2 &&
  539. local.y >= pos1.y + runtimeRangeMinHeight &&
  540. local.y <= pos1.y + runtimeRangeMaxHeight;
  541. }
  542. else
  543. {
  544. var pos1 = centerPos + Vector3.left * itemHeight / 2;
  545. return local.x >= pos1.x + runtimeRangeMinHeight &&
  546. local.x <= pos1.x + runtimeRangeMaxHeight &&
  547. local.y >= centerPos.y - itemWidth / 2 &&
  548. local.y <= centerPos.y + itemWidth / 2;
  549. }
  550. }
  551. public bool IsInRangeMinRect(Vector3 local, Rect chartRect, float triangleLen)
  552. {
  553. var centerPos = new Vector3(chartRect.x, chartRect.y) + location.GetPosition(chartRect.width, chartRect.height);
  554. if (orient == Orient.Vertical)
  555. {
  556. var radius = triangleLen / 2;
  557. var pos1 = centerPos + Vector3.down * itemHeight / 2;
  558. var cpos = new Vector3(pos1.x + itemWidth / 2 + radius, pos1.y + runtimeRangeMinHeight - radius);
  559. return local.x >= cpos.x - radius &&
  560. local.x <= cpos.x + radius &&
  561. local.y >= cpos.y - radius &&
  562. local.y <= cpos.y + radius;
  563. }
  564. else
  565. {
  566. var radius = triangleLen / 2;
  567. var pos1 = centerPos + Vector3.left * itemHeight / 2;
  568. var cpos = new Vector3(pos1.x + runtimeRangeMinHeight, pos1.y + itemWidth / 2 + radius);
  569. return local.x >= cpos.x - radius &&
  570. local.x <= cpos.x + radius &&
  571. local.y >= cpos.y - radius &&
  572. local.y <= cpos.y + radius;
  573. }
  574. }
  575. public bool IsInRangeMaxRect(Vector3 local, Rect chartRect, float triangleLen)
  576. {
  577. var centerPos = new Vector3(chartRect.x, chartRect.y) + location.GetPosition(chartRect.width, chartRect.height);
  578. if (orient == Orient.Vertical)
  579. {
  580. var radius = triangleLen / 2;
  581. var pos1 = centerPos + Vector3.down * itemHeight / 2;
  582. var cpos = new Vector3(pos1.x + itemWidth / 2 + radius, pos1.y + runtimeRangeMaxHeight + radius);
  583. return local.x >= cpos.x - radius &&
  584. local.x <= cpos.x + radius &&
  585. local.y >= cpos.y - radius &&
  586. local.y <= cpos.y + radius;
  587. }
  588. else
  589. {
  590. var radius = triangleLen / 2;
  591. var pos1 = centerPos + Vector3.left * itemHeight / 2;
  592. var cpos = new Vector3(pos1.x + runtimeRangeMaxHeight + radius, pos1.y + itemWidth / 2 + radius);
  593. return local.x >= cpos.x - radius &&
  594. local.x <= cpos.x + radius &&
  595. local.y >= cpos.y - radius &&
  596. local.y <= cpos.y + radius;
  597. }
  598. }
  599. }
  600. }