BaseChart.cs 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091
  1. /************************************************/
  2. /* */
  3. /* Copyright (c) 2018 - 2021 monitor1394 */
  4. /* https://github.com/monitor1394 */
  5. /* */
  6. /************************************************/
  7. using System.Linq;
  8. using UnityEngine;
  9. using UnityEngine.UI;
  10. using System.Collections.Generic;
  11. using System;
  12. using UnityEngine.EventSystems;
  13. using XUGL;
  14. namespace XCharts
  15. {
  16. /// <summary>
  17. /// the layout is horizontal or vertical.
  18. /// 垂直还是水平布局方式。
  19. /// </summary>
  20. public enum Orient
  21. {
  22. /// <summary>
  23. /// 水平
  24. /// </summary>
  25. Horizonal,
  26. /// <summary>
  27. /// 垂直
  28. /// </summary>
  29. Vertical
  30. }
  31. public partial class BaseChart : BaseGraph
  32. {
  33. protected static readonly string s_TitleObjectName = "title";
  34. protected static readonly string s_SubTitleObjectName = "title_sub";
  35. protected static readonly string s_LegendObjectName = "legend";
  36. protected static readonly string s_SerieLabelObjectName = "label";
  37. protected static readonly string s_SerieTitleObjectName = "serie";
  38. [SerializeField] protected string m_ChartName;
  39. [SerializeField] protected ChartTheme m_Theme;
  40. [SerializeField] protected Settings m_Settings;
  41. [SerializeField] protected List<Title> m_Titles = new List<Title>() { Title.defaultTitle };
  42. [SerializeField] protected List<Legend> m_Legends = new List<Legend>() { Legend.defaultLegend };
  43. [SerializeField] protected List<Tooltip> m_Tooltips = new List<Tooltip>() { Tooltip.defaultTooltip };
  44. [SerializeField] protected List<Grid> m_Grids = new List<Grid>();
  45. [SerializeField] protected List<XAxis> m_XAxes = new List<XAxis>();
  46. [SerializeField] protected List<YAxis> m_YAxes = new List<YAxis>();
  47. [SerializeField] protected List<DataZoom> m_DataZooms = new List<DataZoom>();
  48. [SerializeField] protected List<VisualMap> m_VisualMaps = new List<VisualMap>();
  49. [SerializeField] protected List<Vessel> m_Vessels = new List<Vessel>();
  50. [SerializeField] protected List<Polar> m_Polars = new List<Polar>();
  51. [SerializeField] protected List<RadiusAxis> m_RadiusAxes = new List<RadiusAxis>();
  52. [SerializeField] protected List<AngleAxis> m_AngleAxes = new List<AngleAxis>();
  53. [SerializeField] protected List<Radar> m_Radars = new List<Radar>();
  54. [SerializeField] protected Series m_Series = Series.defaultSeries;
  55. protected float m_ChartWidth;
  56. protected float m_ChartHeight;
  57. protected float m_ChartX;
  58. protected float m_ChartY;
  59. protected Vector3 m_ChartPosition = Vector3.zero;
  60. protected Vector2 m_ChartMinAnchor;
  61. protected Vector2 m_ChartMaxAnchor;
  62. protected Vector2 m_ChartPivot;
  63. protected Vector2 m_ChartSizeDelta;
  64. protected Rect m_ChartRect = new Rect(0, 0, 0, 0);
  65. protected Action<VertexHelper> m_OnCustomDrawBaseCallback;
  66. protected Action<VertexHelper> m_OnCustomDrawTopCallback;
  67. protected Action<VertexHelper, Serie> m_OnCustomDrawSerieBeforeCallback;
  68. protected Action<VertexHelper, Serie> m_OnCustomDrawSerieAfterCallback;
  69. protected Action<PointerEventData, int, int> m_OnPointerClickPie;
  70. protected bool m_RefreshLabel = false;
  71. internal bool m_ReinitLabel = false;
  72. internal bool m_ReinitTitle = false;
  73. internal bool m_CheckAnimation = false;
  74. internal bool m_IsPlayingAnimation = false;
  75. internal protected List<string> m_LegendRealShowName = new List<string>();
  76. protected List<Painter> m_PainterList = new List<Painter>();
  77. internal Painter m_PainterTop;
  78. protected GameObject m_SerieLabelRoot;
  79. private Theme m_CheckTheme = 0;
  80. protected List<IDrawSerie> m_DrawSeries = new List<IDrawSerie>();
  81. protected List<IComponentHandler> m_ComponentHandlers = new List<IComponentHandler>();
  82. protected override void InitComponent()
  83. {
  84. base.InitComponent();
  85. InitTitles();
  86. InitLegends();
  87. InitSerieLabel();
  88. InitSerieTitle();
  89. InitTooltip();
  90. m_DrawSeries.Clear();
  91. m_DrawSeries.Add(new DrawSeriePie(this));
  92. m_DrawSeries.Add(new DrawSerieRing(this));
  93. m_DrawSeries.Add(new DrawSerieGauge(this));
  94. m_DrawSeries.Add(new DrawSerieLiquid(this));
  95. m_DrawSeries.Add(new DrawSerieRadar(this));
  96. foreach (var draw in m_DrawSeries) draw.InitComponent();
  97. m_ComponentHandlers.Clear();
  98. m_ComponentHandlers.Add(new VisualMapHandler(this));
  99. m_ComponentHandlers.Add(new DataZoomHandler(this));
  100. foreach (var draw in m_ComponentHandlers) draw.Init();
  101. }
  102. protected override void Awake()
  103. {
  104. if (m_Settings == null) m_Settings = Settings.DefaultSettings;
  105. if (m_Series == null) m_Series = Series.defaultSeries; ;
  106. if (m_Titles.Count == 0) m_Titles = new List<Title>() { Title.defaultTitle };
  107. if (m_Legends.Count == 0) m_Legends = new List<Legend>() { Legend.defaultLegend };
  108. if (m_Tooltips.Count == 0) m_Tooltips = new List<Tooltip>() { Tooltip.defaultTooltip };
  109. CheckTheme();
  110. base.Awake();
  111. AnimationReset();
  112. AnimationFadeIn();
  113. XChartsMgr.Instance.AddChart(this);
  114. }
  115. #if UNITY_EDITOR
  116. protected override void Reset()
  117. {
  118. base.Reset();
  119. m_Theme = null;
  120. m_Settings = null;
  121. m_Series = null;
  122. m_Titles.Clear();
  123. m_Legends.Clear();
  124. m_Tooltips.Clear();
  125. var sizeDelta = rectTransform.sizeDelta;
  126. if (sizeDelta.x < 580 && sizeDelta.y < 300)
  127. {
  128. rectTransform.sizeDelta = new Vector2(580, 300);
  129. }
  130. ChartHelper.HideAllObject(transform);
  131. Awake();
  132. }
  133. #endif
  134. protected override void Start()
  135. {
  136. RefreshChart();
  137. }
  138. protected override void Update()
  139. {
  140. CheckTheme();
  141. base.Update();
  142. CheckPainter();
  143. CheckTooltip();
  144. CheckRefreshChart();
  145. CheckRefreshLabel();
  146. Internal_CheckAnimation();
  147. foreach (var draw in m_DrawSeries) draw.Update();
  148. foreach (var draw in m_ComponentHandlers) draw.Update();
  149. }
  150. public Painter GetPainter(int index)
  151. {
  152. if (index >= 0 && index < m_PainterList.Count)
  153. {
  154. return m_PainterList[index];
  155. }
  156. return null;
  157. }
  158. public void RefreshBasePainter()
  159. {
  160. m_Painter.Refresh();
  161. }
  162. public void RefreshTopPainter()
  163. {
  164. m_PainterTop.Refresh();
  165. }
  166. public void RefreshPainter(int index)
  167. {
  168. var painter = GetPainter(index);
  169. RefreshPainter(painter);
  170. }
  171. public void RefreshPainter(Serie serie)
  172. {
  173. RefreshPainter(GetPainterIndexBySerie(serie));
  174. }
  175. internal override void RefreshPainter(Painter painter)
  176. {
  177. base.RefreshPainter(painter);
  178. if (painter != null && painter.type == Painter.Type.Serie)
  179. {
  180. m_PainterTop.Refresh();
  181. }
  182. }
  183. public void SetPainterActive(int index, bool flag)
  184. {
  185. var painter = GetPainter(index);
  186. if (painter == null) return;
  187. painter.SetActive(flag, m_DebugMode);
  188. }
  189. protected virtual void CheckTheme()
  190. {
  191. if (m_Theme == null)
  192. {
  193. m_Theme = ChartTheme.Default;
  194. }
  195. else
  196. {
  197. if (m_Theme.colorPalette.Count == 0)
  198. {
  199. m_Theme.ResetTheme();
  200. }
  201. if (m_CheckTheme != m_Theme.theme)
  202. {
  203. m_CheckTheme = m_Theme.theme;
  204. m_Theme.CopyTheme(m_CheckTheme);
  205. #if UNITY_EDITOR
  206. UnityEditor.EditorUtility.SetDirty(this);
  207. #endif
  208. SetAllComponentDirty();
  209. OnThemeChanged();
  210. }
  211. }
  212. }
  213. protected override void CheckComponent()
  214. {
  215. base.CheckComponent();
  216. if (m_Series.anyDirty)
  217. {
  218. if (SeriesHelper.IsLabelDirty(m_Series)) m_ReinitLabel = true;
  219. if (SeriesHelper.IsNeedLabelUpdate(m_Series) && !m_RefreshChart) m_RefreshLabel = true;
  220. foreach (var serie in m_Series.list)
  221. {
  222. if (serie.titleStyle.componentDirty) m_ReinitTitle = true;
  223. if (serie.nameDirty)
  224. {
  225. foreach (var legend in m_Legends) legend.SetAllDirty();
  226. RefreshChart();
  227. serie.ClearNameDirty();
  228. }
  229. if (serie.vertsDirty)
  230. {
  231. RefreshPainter(serie);
  232. }
  233. }
  234. m_Series.ClearDirty();
  235. }
  236. if (m_Theme.anyDirty)
  237. {
  238. if (m_Theme.componentDirty)
  239. {
  240. foreach (var title in m_Titles) title.SetAllDirty();
  241. foreach (var legend in m_Legends) legend.SetAllDirty();
  242. tooltip.SetAllDirty();
  243. }
  244. if (m_Theme.vertsDirty) RefreshChart();
  245. m_Theme.ClearDirty();
  246. }
  247. CheckComponentDirty(tooltip);
  248. foreach (var component in m_Titles) CheckComponentDirty(component);
  249. foreach (var component in m_Legends) CheckComponentDirty(component);
  250. foreach (var component in m_Tooltips) CheckComponentDirty(component);
  251. foreach (var component in m_DataZooms) CheckComponentDirty(component);
  252. foreach (var component in m_VisualMaps) CheckComponentDirty(component);
  253. foreach (var component in m_Grids) CheckComponentDirty(component);
  254. foreach (var component in m_XAxes) CheckComponentDirty(component);
  255. foreach (var component in m_YAxes) CheckComponentDirty(component);
  256. foreach (var component in m_Vessels) CheckComponentDirty(component);
  257. foreach (var component in m_Polars) CheckComponentDirty(component);
  258. foreach (var component in m_AngleAxes) CheckComponentDirty(component);
  259. foreach (var component in m_RadiusAxes) CheckComponentDirty(component);
  260. foreach (var component in m_Radars) CheckComponentDirty(component);
  261. foreach (var drawSerie in m_DrawSeries) drawSerie.CheckComponent();
  262. }
  263. protected override void SetAllComponentDirty()
  264. {
  265. base.SetAllComponentDirty();
  266. m_Theme.SetAllDirty();
  267. foreach (var component in m_Titles) component.SetAllDirty();
  268. foreach (var component in m_Legends) component.SetAllDirty();
  269. foreach (var component in m_Tooltips) component.SetAllDirty();
  270. foreach (var component in m_Grids) component.SetAllDirty();
  271. foreach (var component in m_XAxes) component.SetAllDirty();
  272. foreach (var component in m_YAxes) component.SetAllDirty();
  273. foreach (var component in m_DataZooms) component.SetAllDirty();
  274. foreach (var component in m_VisualMaps) component.SetAllDirty();
  275. foreach (var component in m_Vessels) component.SetAllDirty();
  276. foreach (var component in m_Polars) component.SetAllDirty();
  277. foreach (var component in m_RadiusAxes) component.SetAllDirty();
  278. foreach (var component in m_AngleAxes) component.SetAllDirty();
  279. foreach (var component in m_Radars) component.SetAllDirty();
  280. m_ReinitLabel = true;
  281. m_ReinitTitle = true;
  282. m_RefreshChart = true;
  283. }
  284. protected override void OnDestroy()
  285. {
  286. for (int i = transform.childCount - 1; i >= 0; i--)
  287. {
  288. DestroyImmediate(transform.GetChild(i).gameObject);
  289. }
  290. }
  291. protected virtual void CheckPainter()
  292. {
  293. for (int i = 0; i < m_Series.Count; i++)
  294. {
  295. var serie = m_Series.GetSerie(i);
  296. serie.index = i;
  297. SetPainterActive(i, true);
  298. }
  299. }
  300. protected override void InitPainter()
  301. {
  302. base.InitPainter();
  303. m_Painter.material = settings.basePainterMaterial;
  304. m_PainterList.Clear();
  305. if (settings == null) return;
  306. var sizeDelta = new Vector2(m_GraphWidth, m_GraphHeight);
  307. for (int i = 0; i < settings.maxPainter; i++)
  308. {
  309. var index = settings.reversePainter ? settings.maxPainter - 1 - i : i;
  310. var painter = ChartHelper.AddPainterObject("painter_" + index, transform, m_GraphMinAnchor,
  311. m_GraphMaxAnchor, m_GraphPivot, sizeDelta, chartHideFlags, 2 + index);
  312. painter.index = m_PainterList.Count;
  313. painter.type = Painter.Type.Serie;
  314. painter.onPopulateMesh = OnDrawPainterSerie;
  315. painter.SetActive(false, m_DebugMode);
  316. painter.material = settings.seriePainterMaterial;
  317. m_PainterList.Add(painter);
  318. }
  319. m_PainterTop = ChartHelper.AddPainterObject("painter_t", transform, m_GraphMinAnchor,
  320. m_GraphMaxAnchor, m_GraphPivot, sizeDelta, chartHideFlags, 2 + settings.maxPainter);
  321. m_PainterTop.type = Painter.Type.Top;
  322. m_PainterTop.onPopulateMesh = OnDrawPainterTop;
  323. m_PainterTop.SetActive(true, m_DebugMode);
  324. m_PainterTop.material = settings.topPainterMaterial;
  325. }
  326. private void InitTitles()
  327. {
  328. for (int i = 0; i < m_Titles.Count; i++)
  329. {
  330. var title = m_Titles[i];
  331. title.index = i;
  332. InitTitle(title);
  333. }
  334. }
  335. private void InitTitle(Title title)
  336. {
  337. title.painter = null;
  338. title.refreshComponent = delegate ()
  339. {
  340. title.OnChanged();
  341. var anchorMin = title.location.runtimeAnchorMin;
  342. var anchorMax = title.location.runtimeAnchorMax;
  343. var pivot = title.location.runtimePivot;
  344. var titleObject = ChartHelper.AddObject(s_TitleObjectName + title.index, transform, anchorMin, anchorMax,
  345. pivot, m_ChartSizeDelta);
  346. title.gameObject = titleObject;
  347. anchorMin = title.location.runtimeAnchorMin;
  348. anchorMax = title.location.runtimeAnchorMax;
  349. pivot = title.location.runtimePivot;
  350. title.textStyle.UpdateAlignmentByLocation(title.location);
  351. title.subTextStyle.UpdateAlignmentByLocation(title.location);
  352. var fontSize = title.textStyle.GetFontSize(theme.title);
  353. ChartHelper.UpdateRectTransform(titleObject, anchorMin, anchorMax, pivot, new Vector2(chartWidth, chartHeight));
  354. var titlePosition = GetTitlePosition(title);
  355. var subTitlePosition = -new Vector3(0, fontSize + title.itemGap, 0);
  356. var titleWid = chartWidth;
  357. titleObject.transform.localPosition = titlePosition;
  358. titleObject.hideFlags = chartHideFlags;
  359. ChartHelper.HideAllObject(titleObject);
  360. var titleText = ChartHelper.AddTextObject(s_TitleObjectName, titleObject.transform, anchorMin, anchorMax,
  361. pivot, new Vector2(titleWid, fontSize), title.textStyle, theme.title);
  362. titleText.SetActive(title.show);
  363. titleText.SetLocalPosition(Vector3.zero + title.textStyle.offsetv3);
  364. titleText.SetText(title.text);
  365. var subText = ChartHelper.AddTextObject(s_SubTitleObjectName, titleObject.transform, anchorMin, anchorMax,
  366. pivot, new Vector2(titleWid, title.subTextStyle.GetFontSize(theme.subTitle)), title.subTextStyle,
  367. theme.subTitle);
  368. subText.SetActive(title.show && !string.IsNullOrEmpty(title.subText));
  369. subText.SetLocalPosition(subTitlePosition + title.subTextStyle.offsetv3);
  370. subText.SetText(title.subText);
  371. };
  372. title.refreshComponent();
  373. }
  374. private void InitLegends()
  375. {
  376. for (int i = 0; i < m_Legends.Count; i++)
  377. {
  378. var legend = m_Legends[i];
  379. legend.index = i;
  380. InitLegend(legend);
  381. }
  382. }
  383. private void InitLegend(Legend legend)
  384. {
  385. legend.painter = null; // legend component does not need to paint
  386. legend.refreshComponent = delegate ()
  387. {
  388. legend.OnChanged();
  389. var legendObject = ChartHelper.AddObject(s_LegendObjectName + legend.index, transform, m_ChartMinAnchor,
  390. m_ChartMaxAnchor, m_ChartPivot, m_ChartSizeDelta);
  391. legend.gameObject = legendObject;
  392. legendObject.hideFlags = chartHideFlags;
  393. SeriesHelper.UpdateSerieNameList(this, ref m_LegendRealShowName);
  394. List<string> datas;
  395. if (legend.show && legend.data.Count > 0)
  396. {
  397. datas = new List<string>();
  398. for (int i = 0; i < m_LegendRealShowName.Count; i++)
  399. {
  400. if (legend.data.Contains(m_LegendRealShowName[i])) datas.Add(m_LegendRealShowName[i]);
  401. }
  402. }
  403. else
  404. {
  405. datas = m_LegendRealShowName;
  406. }
  407. int totalLegend = 0;
  408. for (int i = 0; i < datas.Count; i++)
  409. {
  410. if (!SeriesHelper.IsLegalLegendName(datas[i])) continue;
  411. totalLegend++;
  412. }
  413. legend.RemoveButton();
  414. ChartHelper.HideAllObject(legendObject);
  415. if (!legend.show) return;
  416. for (int i = 0; i < datas.Count; i++)
  417. {
  418. if (!SeriesHelper.IsLegalLegendName(datas[i])) continue;
  419. string legendName = legend.GetFormatterContent(datas[i]);
  420. var readIndex = m_LegendRealShowName.IndexOf(datas[i]);
  421. var active = IsActiveByLegend(datas[i]);
  422. var bgColor = LegendHelper.GetIconColor(this, readIndex, datas[i], active);
  423. var item = LegendHelper.AddLegendItem(legend, i, datas[i], legendObject.transform, m_Theme,
  424. legendName, bgColor, active, readIndex);
  425. legend.SetButton(legendName, item, totalLegend);
  426. ChartHelper.ClearEventListener(item.button.gameObject);
  427. ChartHelper.AddEventListener(item.button.gameObject, EventTriggerType.PointerDown, (data) =>
  428. {
  429. if (data.selectedObject == null || legend.selectedMode == Legend.SelectedMode.None) return;
  430. var temp = data.selectedObject.name.Split('_');
  431. string selectedName = temp[1];
  432. int clickedIndex = int.Parse(temp[0]);
  433. if (legend.selectedMode == Legend.SelectedMode.Multiple)
  434. {
  435. OnLegendButtonClick(clickedIndex, selectedName, !IsActiveByLegend(selectedName));
  436. }
  437. else
  438. {
  439. var btnList = legend.buttonList.Values.ToArray();
  440. if (btnList.Length == 1)
  441. {
  442. OnLegendButtonClick(0, selectedName, !IsActiveByLegend(selectedName));
  443. }
  444. else
  445. {
  446. for (int n = 0; n < btnList.Length; n++)
  447. {
  448. temp = btnList[n].name.Split('_');
  449. selectedName = btnList[n].legendName;
  450. var index = btnList[n].index;
  451. OnLegendButtonClick(n, selectedName, index == clickedIndex ? true : false);
  452. }
  453. }
  454. }
  455. });
  456. ChartHelper.AddEventListener(item.button.gameObject, EventTriggerType.PointerEnter, (data) =>
  457. {
  458. if (item.button == null) return;
  459. var temp = item.button.name.Split('_');
  460. string selectedName = temp[1];
  461. int index = int.Parse(temp[0]);
  462. OnLegendButtonEnter(index, selectedName);
  463. });
  464. ChartHelper.AddEventListener(item.button.gameObject, EventTriggerType.PointerExit, (data) =>
  465. {
  466. if (item.button == null) return;
  467. var temp = item.button.name.Split('_');
  468. string selectedName = temp[1];
  469. int index = int.Parse(temp[0]);
  470. OnLegendButtonExit(index, selectedName);
  471. });
  472. }
  473. if (legend.selectedMode == Legend.SelectedMode.Single)
  474. {
  475. for (int n = 0; n < m_LegendRealShowName.Count; n++)
  476. {
  477. OnLegendButtonClick(n, m_LegendRealShowName[n], n == 0 ? true : false);
  478. }
  479. }
  480. LegendHelper.ResetItemPosition(legend, m_ChartPosition, m_ChartWidth, m_ChartHeight);
  481. };
  482. legend.refreshComponent();
  483. }
  484. private void InitSerieLabel()
  485. {
  486. m_SerieLabelRoot = ChartHelper.AddObject(s_SerieLabelObjectName, transform, m_ChartMinAnchor,
  487. m_ChartMaxAnchor, m_ChartPivot, m_ChartSizeDelta);
  488. m_SerieLabelRoot.hideFlags = chartHideFlags;
  489. SerieLabelPool.ReleaseAll(m_SerieLabelRoot.transform);
  490. int count = 0;
  491. for (int i = 0; i < m_Series.Count; i++)
  492. {
  493. var serie = m_Series.list[i];
  494. serie.index = i;
  495. SerieHelper.UpdateCenter(serie, chartPosition, chartWidth, chartHeight);
  496. for (int j = 0; j < serie.data.Count; j++)
  497. {
  498. var serieData = serie.data[j];
  499. serieData.index = count;
  500. serieData.labelObject = null;
  501. AddSerieLabel(serie, serieData, ref count);
  502. count++;
  503. }
  504. }
  505. SerieLabelHelper.UpdateLabelText(m_Series, m_Theme, m_LegendRealShowName);
  506. }
  507. protected void AddSerieLabel(Serie serie, SerieData serieData, ref int count)
  508. {
  509. if (m_SerieLabelRoot == null) return;
  510. if (count == -1) count = serie.dataCount;
  511. var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
  512. var iconStyle = SerieHelper.GetIconStyle(serie, serieData);
  513. if (serie.IsPerformanceMode()) return;
  514. if (!serieLabel.show && !iconStyle.show) return;
  515. if (serie.animation.enable && serie.animation.HasFadeOut()) return;
  516. var textName = ChartCached.GetSerieLabelName(s_SerieLabelObjectName, serie.index, serieData.index);
  517. var color = Color.grey;
  518. if (serie.type == SerieType.Pie)
  519. {
  520. color = (serieLabel.position == SerieLabel.Position.Inside) ? Color.white :
  521. (Color)m_Theme.GetColor(count);
  522. }
  523. else
  524. {
  525. color = !ChartHelper.IsClearColor(serieLabel.textStyle.color) ? serieLabel.textStyle.color :
  526. (Color)m_Theme.GetColor(serie.index);
  527. }
  528. var labelObj = SerieLabelPool.Get(textName, m_SerieLabelRoot.transform, serieLabel, color,
  529. iconStyle.width, iconStyle.height, theme);
  530. var iconImage = labelObj.transform.Find("Icon").GetComponent<Image>();
  531. var isAutoSize = serieLabel.backgroundWidth == 0 || serieLabel.backgroundHeight == 0;
  532. var item = new ChartLabel();
  533. item.SetLabel(labelObj, isAutoSize, serieLabel.paddingLeftRight, serieLabel.paddingTopBottom);
  534. item.SetIcon(iconImage);
  535. item.SetIconActive(iconStyle.show);
  536. serieData.labelObject = item;
  537. foreach (var dataIndex in serieData.children)
  538. {
  539. AddSerieLabel(serie, serie.GetSerieData(dataIndex), ref count);
  540. count++;
  541. }
  542. }
  543. private void InitSerieTitle()
  544. {
  545. var titleObject = ChartHelper.AddObject(s_SerieTitleObjectName, transform, m_ChartMinAnchor,
  546. m_ChartMaxAnchor, m_ChartPivot, new Vector2(chartWidth, chartHeight));
  547. titleObject.hideFlags = chartHideFlags;
  548. ChartHelper.HideAllObject(titleObject);
  549. for (int i = 0; i < m_Series.Count; i++)
  550. {
  551. var serie = m_Series.list[i];
  552. var textStyle = serie.titleStyle.textStyle;
  553. var titleColor = ChartHelper.IsClearColor(textStyle.color) ? m_Theme.GetColor(i) : (Color32)textStyle.color;
  554. var anchorMin = new Vector2(0.5f, 0.5f);
  555. var anchorMax = new Vector2(0.5f, 0.5f);
  556. var pivot = new Vector2(0.5f, 0.5f);
  557. var fontSize = 10;
  558. var sizeDelta = new Vector2(50, fontSize + 2);
  559. var txt = ChartHelper.AddTextObject("title_" + i, titleObject.transform, anchorMin, anchorMax,
  560. pivot, sizeDelta, textStyle, theme.common);
  561. txt.SetText("");
  562. txt.SetColor(titleColor);
  563. txt.SetLocalPosition(Vector2.zero);
  564. txt.SetLocalEulerAngles(Vector2.zero);
  565. txt.SetActive(serie.titleStyle.show);
  566. serie.titleStyle.runtimeText = txt;
  567. serie.titleStyle.UpdatePosition(serie.runtimeCenterPos);
  568. var serieData = serie.GetSerieData(0);
  569. if (serieData != null)
  570. {
  571. txt.SetText(serieData.name);
  572. }
  573. }
  574. }
  575. private void InitTooltip()
  576. {
  577. tooltip.painter = m_PainterTop;
  578. tooltip.refreshComponent = delegate ()
  579. {
  580. tooltip.gameObject = ChartHelper.AddObject("tooltip", transform, m_ChartMinAnchor,
  581. m_ChartMaxAnchor, m_ChartPivot, m_ChartSizeDelta);
  582. var tooltipObject = tooltip.gameObject;
  583. tooltipObject.transform.localPosition = Vector3.zero;
  584. tooltipObject.hideFlags = chartHideFlags;
  585. DestroyImmediate(tooltipObject.GetComponent<Image>());
  586. var parent = tooltipObject.transform;
  587. var textStyle = tooltip.textStyle;
  588. ChartHelper.HideAllObject(tooltipObject.transform);
  589. GameObject content = ChartHelper.AddTooltipContent("content", parent, textStyle, m_Theme);
  590. tooltip.SetObj(tooltipObject);
  591. tooltip.SetContentObj(content);
  592. tooltip.SetContentBackgroundColor(TooltipHelper.GetTexBackgroundColor(tooltip, m_Theme.tooltip));
  593. tooltip.SetContentTextColor(TooltipHelper.GetTexColor(tooltip, m_Theme.tooltip));
  594. tooltip.SetActive(false);
  595. };
  596. tooltip.refreshComponent();
  597. }
  598. private Vector3 GetLegendPosition(Legend legend, int i)
  599. {
  600. return legend.location.GetPosition(chartWidth, chartHeight);
  601. }
  602. protected override bool IsNeedCheckPointerPos()
  603. {
  604. return (tooltip.show && tooltip.runtimeInited)
  605. || raycastTarget;
  606. }
  607. private void CheckTooltip()
  608. {
  609. if (!isPointerInChart || !tooltip.show || !tooltip.runtimeInited)
  610. {
  611. if (tooltip.IsActive())
  612. {
  613. tooltip.ClearValue();
  614. tooltip.SetActive(false);
  615. m_PainterTop.Refresh();
  616. }
  617. return;
  618. }
  619. for (int i = 0; i < tooltip.runtimeDataIndex.Count; i++)
  620. {
  621. tooltip.runtimeDataIndex[i] = -1;
  622. }
  623. Vector2 local = pointerPos;
  624. if (canvas == null) return;
  625. if (local == Vector2.zero)
  626. {
  627. if (tooltip.IsActive())
  628. {
  629. tooltip.SetActive(false);
  630. m_PainterTop.Refresh();
  631. }
  632. return;
  633. }
  634. if (!IsInChart(local))
  635. {
  636. if (tooltip.IsActive())
  637. {
  638. tooltip.SetActive(false);
  639. m_PainterTop.Refresh();
  640. }
  641. return;
  642. }
  643. tooltip.runtimePointerPos = local;
  644. CheckAllTooptip(local);
  645. }
  646. private void CheckAllTooptip(Vector2 localPostion)
  647. {
  648. tooltip.runtimeGridIndex = -1;
  649. var actived = false;
  650. foreach (var draw in m_DrawSeries)
  651. actived = actived || draw.CheckTootipArea(localPostion);
  652. CheckTootipArea(localPostion, actived);
  653. }
  654. protected virtual void CheckTootipArea(Vector2 localPostion, bool isActivedOther)
  655. {
  656. }
  657. protected override void CheckRefreshChart()
  658. {
  659. if (m_Painter == null) return;
  660. if (m_RefreshChart)
  661. {
  662. m_Painter.Refresh();
  663. foreach (var painter in m_PainterList) painter.Refresh();
  664. if (m_PainterTop != null) m_PainterTop.Refresh();
  665. m_RefreshChart = false;
  666. }
  667. }
  668. protected override void CheckRefreshPainter()
  669. {
  670. if (m_Painter == null) return;
  671. m_Painter.CheckRefresh();
  672. foreach (var painter in m_PainterList) painter.CheckRefresh();
  673. if (m_PainterTop != null) m_PainterTop.CheckRefresh();
  674. }
  675. protected void CheckRefreshLabel()
  676. {
  677. if (m_ReinitLabel)
  678. {
  679. m_ReinitLabel = false;
  680. SeriesHelper.UpdateSerieNameList(this, ref m_LegendRealShowName);
  681. InitSerieLabel();
  682. }
  683. if (m_ReinitTitle)
  684. {
  685. m_ReinitTitle = false;
  686. InitSerieTitle();
  687. }
  688. if (m_RefreshLabel)
  689. {
  690. m_RefreshLabel = false;
  691. OnRefreshLabel();
  692. }
  693. }
  694. public void Internal_CheckAnimation()
  695. {
  696. if (!m_CheckAnimation)
  697. {
  698. m_CheckAnimation = true;
  699. AnimationFadeIn();
  700. }
  701. }
  702. protected virtual void OnRefreshLabel()
  703. {
  704. foreach (var drawSerie in m_DrawSeries) drawSerie.RefreshLabel();
  705. }
  706. protected override void OnSizeChanged()
  707. {
  708. base.OnSizeChanged();
  709. m_ChartWidth = m_GraphWidth;
  710. m_ChartHeight = m_GraphHeight;
  711. m_ChartX = m_GraphX;
  712. m_ChartY = m_GraphY;
  713. m_ChartPosition = m_GraphPosition;
  714. m_ChartMinAnchor = m_GraphMinAnchor;
  715. m_ChartMaxAnchor = m_GraphMaxAnchor;
  716. m_ChartPivot = m_GraphPivot;
  717. m_ChartSizeDelta = m_GraphSizeDelta;
  718. m_ChartRect = m_GraphRect;
  719. SetAllComponentDirty();
  720. m_Series.SetLabelDirty();
  721. m_ReinitLabel = true;
  722. RefreshChart();
  723. }
  724. protected override void OnLocalPositionChanged()
  725. {
  726. m_Background.SetAllDirty();
  727. }
  728. protected virtual void OnThemeChanged()
  729. {
  730. }
  731. protected virtual void OnYMaxValueChanged()
  732. {
  733. }
  734. public virtual void OnDataZoomRangeChanged(DataZoom dataZoom)
  735. {
  736. }
  737. public override void OnPointerDown(PointerEventData eventData)
  738. {
  739. base.OnPointerDown(eventData);
  740. foreach (var drawSerie in m_DrawSeries) drawSerie.OnPointerDown(eventData);
  741. foreach (var handler in m_ComponentHandlers) handler.OnPointerDown(eventData);
  742. }
  743. public override void OnBeginDrag(PointerEventData eventData)
  744. {
  745. base.OnBeginDrag(eventData);
  746. foreach (var handler in m_ComponentHandlers) handler.OnBeginDrag(eventData);
  747. }
  748. public override void OnDrag(PointerEventData eventData)
  749. {
  750. base.OnDrag(eventData);
  751. foreach (var handler in m_ComponentHandlers) handler.OnDrag(eventData);
  752. }
  753. public override void OnEndDrag(PointerEventData eventData)
  754. {
  755. base.OnEndDrag(eventData);
  756. foreach (var handler in m_ComponentHandlers) handler.OnEndDrag(eventData);
  757. }
  758. public override void OnScroll(PointerEventData eventData)
  759. {
  760. base.OnScroll(eventData);
  761. foreach (var handler in m_ComponentHandlers) handler.OnScroll(eventData);
  762. }
  763. protected virtual void OnLegendButtonClick(int index, string legendName, bool show)
  764. {
  765. var clicked = false;
  766. foreach (var drawSerie in m_DrawSeries)
  767. clicked = clicked || drawSerie.OnLegendButtonClick(index, legendName, show);
  768. if (!clicked)
  769. {
  770. foreach (var serie in m_Series.GetSeries(legendName))
  771. {
  772. SetActive(serie.index, show);
  773. RefreshPainter(serie);
  774. }
  775. OnYMaxValueChanged();
  776. }
  777. }
  778. protected virtual void OnLegendButtonEnter(int index, string legendName)
  779. {
  780. var enter = false;
  781. foreach (var drawSerie in m_DrawSeries)
  782. enter = enter || drawSerie.OnLegendButtonEnter(index, legendName);
  783. if (!enter)
  784. {
  785. foreach (var serie in m_Series.GetSeries(legendName))
  786. {
  787. serie.highlighted = true;
  788. RefreshPainter(serie);
  789. }
  790. }
  791. }
  792. protected virtual void OnLegendButtonExit(int index, string legendName)
  793. {
  794. var exit = false;
  795. foreach (var drawSerie in m_DrawSeries)
  796. exit = exit || drawSerie.OnLegendButtonExit(index, legendName);
  797. if (!exit)
  798. {
  799. foreach (var serie in m_Series.GetSeries(legendName))
  800. {
  801. serie.highlighted = false;
  802. RefreshPainter(serie);
  803. }
  804. }
  805. }
  806. protected virtual void UpdateTooltip()
  807. {
  808. }
  809. protected override void OnDrawPainterBase(VertexHelper vh, Painter painter)
  810. {
  811. vh.Clear();
  812. DrawBackground(vh);
  813. DrawPainterBase(vh);
  814. foreach (var draw in m_ComponentHandlers) draw.DrawBase(vh);
  815. foreach (var draw in m_DrawSeries) draw.DrawBase(vh);
  816. if (m_OnCustomDrawBaseCallback != null)
  817. {
  818. m_OnCustomDrawBaseCallback(vh);
  819. }
  820. }
  821. protected virtual void OnDrawPainterSerie(VertexHelper vh, Painter painter)
  822. {
  823. vh.Clear();
  824. var maxPainter = settings.maxPainter;
  825. var maxSeries = m_Series.Count;
  826. var rate = Mathf.CeilToInt(maxSeries * 1.0f / maxPainter);
  827. m_PainterTop.Refresh();
  828. for (int i = painter.index * rate; i < (painter.index + 1) * rate && i < maxSeries; i++)
  829. {
  830. var serie = m_Series.GetSerie(i);
  831. if (m_OnCustomDrawSerieBeforeCallback != null)
  832. {
  833. m_OnCustomDrawSerieBeforeCallback.Invoke(vh, serie);
  834. }
  835. DrawPainterSerie(vh, serie);
  836. if (m_OnCustomDrawSerieAfterCallback != null)
  837. {
  838. m_OnCustomDrawSerieAfterCallback(vh, serie);
  839. }
  840. }
  841. m_RefreshLabel = true;
  842. }
  843. protected virtual void OnDrawPainterTop(VertexHelper vh, Painter painter)
  844. {
  845. vh.Clear();
  846. DrawLegend(vh);
  847. DrawPainterTop(vh);
  848. foreach (var draw in m_ComponentHandlers) draw.DrawTop(vh);
  849. if (m_OnCustomDrawTopCallback != null)
  850. {
  851. m_OnCustomDrawTopCallback(vh);
  852. }
  853. DrawTooltip(vh);
  854. }
  855. protected virtual void DrawPainterSerie(VertexHelper vh, Serie serie)
  856. {
  857. foreach (var drawSerie in m_DrawSeries)
  858. {
  859. drawSerie.DrawSerie(vh, serie);
  860. }
  861. }
  862. protected virtual void DrawPainterTop(VertexHelper vh)
  863. {
  864. }
  865. protected virtual void DrawTooltip(VertexHelper vh)
  866. {
  867. }
  868. protected override void DrawBackground(VertexHelper vh)
  869. {
  870. Vector3 p1 = new Vector3(chartX, chartY + chartHeight);
  871. Vector3 p2 = new Vector3(chartX + chartWidth, chartY + chartHeight);
  872. Vector3 p3 = new Vector3(chartX + chartWidth, chartY);
  873. Vector3 p4 = new Vector3(chartX, chartY);
  874. var backgroundColor = ThemeHelper.GetBackgroundColor(m_Theme, m_Background);
  875. UGL.DrawQuadrilateral(vh, p1, p2, p3, p4, backgroundColor);
  876. }
  877. protected virtual void DrawLegend(VertexHelper vh)
  878. {
  879. if (m_Series.Count == 0) return;
  880. foreach (var legend in m_Legends)
  881. {
  882. if (!legend.show) continue;
  883. if (legend.iconType == Legend.Type.Custom) continue;
  884. foreach (var kv in legend.buttonList)
  885. {
  886. var item = kv.Value;
  887. var rect = item.GetIconRect();
  888. var radius = Mathf.Min(rect.width, rect.height) / 2;
  889. var color = item.GetIconColor();
  890. var iconType = legend.iconType;
  891. if (legend.iconType == Legend.Type.Auto)
  892. {
  893. var serie = m_Series.GetSerie(item.legendName);
  894. if (serie != null && serie.type == SerieType.Line)
  895. {
  896. var sp = new Vector3(rect.center.x - rect.width / 2, rect.center.y);
  897. var ep = new Vector3(rect.center.x + rect.width / 2, rect.center.y);
  898. UGL.DrawLine(vh, sp, ep, m_Settings.legendIconLineWidth, color);
  899. if (!serie.symbol.show) continue;
  900. switch (serie.symbol.type)
  901. {
  902. case SerieSymbolType.None:
  903. continue;
  904. case SerieSymbolType.Circle:
  905. iconType = Legend.Type.Circle;
  906. break;
  907. case SerieSymbolType.Diamond:
  908. iconType = Legend.Type.Diamond;
  909. break;
  910. case SerieSymbolType.EmptyCircle:
  911. iconType = Legend.Type.EmptyCircle;
  912. break;
  913. case SerieSymbolType.Rect:
  914. iconType = Legend.Type.Rect;
  915. break;
  916. case SerieSymbolType.Triangle:
  917. iconType = Legend.Type.Triangle;
  918. break;
  919. }
  920. }
  921. else
  922. {
  923. iconType = Legend.Type.Rect;
  924. }
  925. }
  926. switch (iconType)
  927. {
  928. case Legend.Type.Rect:
  929. var cornerRadius = m_Settings.legendIconCornerRadius;
  930. UGL.DrawRoundRectangle(vh, rect.center, rect.width, rect.height, color, color,
  931. 0, cornerRadius, false, 0.5f);
  932. break;
  933. case Legend.Type.Circle:
  934. UGL.DrawCricle(vh, rect.center, radius, color);
  935. break;
  936. case Legend.Type.Diamond:
  937. UGL.DrawDiamond(vh, rect.center, radius, color);
  938. break;
  939. case Legend.Type.EmptyCircle:
  940. var backgroundColor = ThemeHelper.GetBackgroundColor(m_Theme, m_Background);
  941. UGL.DrawEmptyCricle(vh, rect.center, radius, 2 * m_Settings.legendIconLineWidth,
  942. color, color, backgroundColor, 1f);
  943. break;
  944. case Legend.Type.Triangle:
  945. UGL.DrawTriangle(vh, rect.center, 1.2f * radius, color);
  946. break;
  947. }
  948. }
  949. }
  950. }
  951. public void DrawSymbol(VertexHelper vh, SerieSymbolType type, float symbolSize,
  952. float tickness, Vector3 pos, Color32 color, Color32 toColor, Color32 fillColor, float gap, float[] cornerRadius)
  953. {
  954. DrawSymbol(vh, type, symbolSize, tickness, pos, color, toColor, fillColor, gap, cornerRadius, Vector3.zero);
  955. }
  956. public void DrawSymbol(VertexHelper vh, SerieSymbolType type, float symbolSize,
  957. float tickness, Vector3 pos, Color32 color, Color32 toColor, Color32 fillColor, float gap, float[] cornerRadius, Vector3 startPos)
  958. {
  959. var backgroundColor = ThemeHelper.GetBackgroundColor(m_Theme, m_Background);
  960. if (ChartHelper.IsClearColor(fillColor))
  961. fillColor = backgroundColor;
  962. var smoothness = settings.cicleSmoothness;
  963. ChartDrawer.DrawSymbol(vh, type, symbolSize, tickness, pos, color, toColor, gap,
  964. cornerRadius, fillColor, backgroundColor, smoothness, startPos);
  965. }
  966. public void DrawLabelBackground(VertexHelper vh, Serie serie, SerieData serieData)
  967. {
  968. if (serieData == null || serieData.labelObject == null) return;
  969. var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
  970. if (!serieLabel.show) return;
  971. var invert = serieLabel.autoOffset
  972. && serie.type == SerieType.Line
  973. && SerieHelper.IsDownPoint(serie, serieData.index)
  974. && !serie.areaStyle.show;
  975. var centerPos = Vector3.zero;
  976. if (serie.type == SerieType.Pie)
  977. centerPos = SerieLabelHelper.GetRealLabelPosition(serieData, serieLabel);
  978. else
  979. centerPos = serieData.labelPosition + serieLabel.offset * (invert ? -1 : 1);
  980. var labelHalfWid = serieData.labelObject.GetLabelWidth() / 2;
  981. var labelHalfHig = serieData.GetLabelHeight() / 2;
  982. var p1 = new Vector3(centerPos.x - labelHalfWid, centerPos.y + labelHalfHig);
  983. var p2 = new Vector3(centerPos.x + labelHalfWid, centerPos.y + labelHalfHig);
  984. var p3 = new Vector3(centerPos.x + labelHalfWid, centerPos.y - labelHalfHig);
  985. var p4 = new Vector3(centerPos.x - labelHalfWid, centerPos.y - labelHalfHig);
  986. if (serieLabel.textStyle.rotate > 0)
  987. {
  988. p1 = ChartHelper.RotateRound(p1, centerPos, Vector3.forward, serieLabel.textStyle.rotate);
  989. p2 = ChartHelper.RotateRound(p2, centerPos, Vector3.forward, serieLabel.textStyle.rotate);
  990. p3 = ChartHelper.RotateRound(p3, centerPos, Vector3.forward, serieLabel.textStyle.rotate);
  991. p4 = ChartHelper.RotateRound(p4, centerPos, Vector3.forward, serieLabel.textStyle.rotate);
  992. }
  993. UGL.DrawQuadrilateral(vh, p1, p2, p3, p4, serieLabel.textStyle.backgroundColor);
  994. if (serieLabel.border)
  995. {
  996. UGL.DrawBorder(vh, centerPos, serieData.GetLabelWidth(), serieData.GetLabelHeight(),
  997. serieLabel.borderWidth, serieLabel.borderColor, serieLabel.textStyle.rotate);
  998. }
  999. }
  1000. protected int GetPainterIndexBySerie(Serie serie)
  1001. {
  1002. var maxPainter = settings.maxPainter;
  1003. var maxSeries = m_Series.Count;
  1004. if (maxPainter >= maxSeries) return serie.index;
  1005. else
  1006. {
  1007. var rate = Mathf.CeilToInt(maxSeries * 1.0f / maxPainter);
  1008. return serie.index / rate;
  1009. }
  1010. }
  1011. }
  1012. }