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