mirror of
https://github.com/XCharts-Team/XCharts.git
synced 2026-05-14 20:00:09 +00:00
1117 lines
46 KiB
C#
1117 lines
46 KiB
C#
/************************************************/
|
|
/* */
|
|
/* Copyright (c) 2018 - 2021 monitor1394 */
|
|
/* https://github.com/monitor1394 */
|
|
/* */
|
|
/************************************************/
|
|
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using System.Collections.Generic;
|
|
using System;
|
|
using UnityEngine.EventSystems;
|
|
using XUGL;
|
|
|
|
namespace XCharts
|
|
{
|
|
/// <summary>
|
|
/// the layout is horizontal or vertical.
|
|
/// 垂直还是水平布局方式。
|
|
/// </summary>
|
|
public enum Orient
|
|
{
|
|
/// <summary>
|
|
/// 水平
|
|
/// </summary>
|
|
Horizonal,
|
|
/// <summary>
|
|
/// 垂直
|
|
/// </summary>
|
|
Vertical
|
|
}
|
|
|
|
public partial class BaseChart : BaseGraph
|
|
{
|
|
protected static readonly string s_TitleObjectName = "title";
|
|
protected static readonly string s_SubTitleObjectName = "title_sub";
|
|
protected static readonly string s_LegendObjectName = "legend";
|
|
protected static readonly string s_SerieLabelObjectName = "label";
|
|
protected static readonly string s_SerieTitleObjectName = "serie";
|
|
|
|
[SerializeField] protected string m_ChartName;
|
|
[SerializeField] protected ChartTheme m_Theme;
|
|
[SerializeField] protected Settings m_Settings;
|
|
[SerializeField] protected List<Title> m_Titles = new List<Title>() { Title.defaultTitle };
|
|
[SerializeField] protected List<Legend> m_Legends = new List<Legend>() { Legend.defaultLegend };
|
|
[SerializeField] protected List<Tooltip> m_Tooltips = new List<Tooltip>() { Tooltip.defaultTooltip };
|
|
|
|
[SerializeField] protected List<Grid> m_Grids = new List<Grid>();
|
|
[SerializeField] protected List<XAxis> m_XAxes = new List<XAxis>();
|
|
[SerializeField] protected List<YAxis> m_YAxes = new List<YAxis>();
|
|
[SerializeField] protected List<DataZoom> m_DataZooms = new List<DataZoom>();
|
|
[SerializeField] protected List<VisualMap> m_VisualMaps = new List<VisualMap>();
|
|
[SerializeField] protected List<Vessel> m_Vessels = new List<Vessel>();
|
|
[SerializeField] protected List<Polar> m_Polars = new List<Polar>();
|
|
[SerializeField] protected List<RadiusAxis> m_RadiusAxes = new List<RadiusAxis>();
|
|
[SerializeField] protected List<AngleAxis> m_AngleAxes = new List<AngleAxis>();
|
|
[SerializeField] protected List<Radar> m_Radars = new List<Radar>();
|
|
|
|
[SerializeField] protected Series m_Series = Series.defaultSeries;
|
|
|
|
protected float m_ChartWidth;
|
|
protected float m_ChartHeight;
|
|
protected float m_ChartX;
|
|
protected float m_ChartY;
|
|
protected Vector3 m_ChartPosition = Vector3.zero;
|
|
protected Vector2 m_ChartMinAnchor;
|
|
protected Vector2 m_ChartMaxAnchor;
|
|
protected Vector2 m_ChartPivot;
|
|
protected Vector2 m_ChartSizeDelta;
|
|
protected Rect m_ChartRect = new Rect(0, 0, 0, 0);
|
|
protected Action<VertexHelper> m_OnCustomDrawBaseCallback;
|
|
protected Action<VertexHelper> m_OnCustomDrawTopCallback;
|
|
protected Action<VertexHelper, Serie> m_OnCustomDrawSerieBeforeCallback;
|
|
protected Action<VertexHelper, Serie> m_OnCustomDrawSerieAfterCallback;
|
|
protected Action<PointerEventData, int, int> m_OnPointerClickPie;
|
|
protected Action<int, string, bool> m_OnLegendClick;
|
|
protected Action<int, string> m_OnLegendEnter;
|
|
protected Action<int, string> m_OnLegendExit;
|
|
|
|
protected bool m_RefreshLabel = false;
|
|
internal bool m_ReinitLabel = false;
|
|
internal bool m_ReinitTitle = false;
|
|
internal bool m_CheckAnimation = false;
|
|
internal bool m_IsPlayingAnimation = false;
|
|
internal int m_BasePainterVertCount;
|
|
internal int m_TopPainterVertCount;
|
|
internal protected List<string> m_LegendRealShowName = new List<string>();
|
|
protected List<Painter> m_PainterList = new List<Painter>();
|
|
internal Painter m_PainterTop;
|
|
protected GameObject m_SerieLabelRoot;
|
|
private Theme m_CheckTheme = 0;
|
|
|
|
protected List<IDrawSerie> m_DrawSeries = new List<IDrawSerie>();
|
|
protected List<IComponentHandler> m_ComponentHandlers = new List<IComponentHandler>();
|
|
|
|
protected override void InitComponent()
|
|
{
|
|
base.InitComponent();
|
|
InitTitles();
|
|
InitLegends();
|
|
InitSerieLabel();
|
|
InitSerieTitle();
|
|
InitTooltip();
|
|
m_DrawSeries.Clear();
|
|
m_DrawSeries.Add(new DrawSeriePie(this));
|
|
m_DrawSeries.Add(new DrawSerieRing(this));
|
|
m_DrawSeries.Add(new DrawSerieGauge(this));
|
|
m_DrawSeries.Add(new DrawSerieLiquid(this));
|
|
m_DrawSeries.Add(new DrawSerieRadar(this));
|
|
foreach (var draw in m_DrawSeries) draw.InitComponent();
|
|
|
|
m_ComponentHandlers.Clear();
|
|
m_ComponentHandlers.Add(new VisualMapHandler(this));
|
|
m_ComponentHandlers.Add(new DataZoomHandler(this));
|
|
foreach (var draw in m_ComponentHandlers) draw.Init();
|
|
|
|
m_DebugInfo.Init(this);
|
|
}
|
|
|
|
protected override void Awake()
|
|
{
|
|
if (m_Settings == null) m_Settings = Settings.DefaultSettings;
|
|
if (m_Series == null) m_Series = Series.defaultSeries; ;
|
|
if (m_Titles.Count == 0) m_Titles = new List<Title>() { Title.defaultTitle };
|
|
if (m_Legends.Count == 0) m_Legends = new List<Legend>() { Legend.defaultLegend };
|
|
if (m_Tooltips.Count == 0) m_Tooltips = new List<Tooltip>() { Tooltip.defaultTooltip };
|
|
CheckTheme();
|
|
base.Awake();
|
|
AnimationReset();
|
|
AnimationFadeIn();
|
|
XChartsMgr.Instance.AddChart(this);
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
protected override void Reset()
|
|
{
|
|
base.Reset();
|
|
m_Theme = null;
|
|
m_Settings = null;
|
|
m_Series = null;
|
|
m_Titles.Clear();
|
|
m_Legends.Clear();
|
|
m_Tooltips.Clear();
|
|
var sizeDelta = rectTransform.sizeDelta;
|
|
if (sizeDelta.x < 580 && sizeDelta.y < 300)
|
|
{
|
|
rectTransform.sizeDelta = new Vector2(580, 300);
|
|
}
|
|
ChartHelper.HideAllObject(transform);
|
|
Awake();
|
|
}
|
|
#endif
|
|
|
|
protected override void Start()
|
|
{
|
|
RefreshChart();
|
|
}
|
|
|
|
protected override void Update()
|
|
{
|
|
CheckTheme();
|
|
base.Update();
|
|
CheckPainter();
|
|
CheckTooltip();
|
|
CheckRefreshChart();
|
|
CheckRefreshLabel();
|
|
Internal_CheckAnimation();
|
|
foreach (var draw in m_DrawSeries) draw.Update();
|
|
foreach (var draw in m_ComponentHandlers) draw.Update();
|
|
m_DebugInfo.Update();
|
|
}
|
|
|
|
public Painter GetPainter(int index)
|
|
{
|
|
if (index >= 0 && index < m_PainterList.Count)
|
|
{
|
|
return m_PainterList[index];
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public void RefreshBasePainter()
|
|
{
|
|
m_Painter.Refresh();
|
|
}
|
|
public void RefreshTopPainter()
|
|
{
|
|
m_PainterTop.Refresh();
|
|
}
|
|
|
|
public void RefreshPainter(int index)
|
|
{
|
|
var painter = GetPainter(index);
|
|
RefreshPainter(painter);
|
|
}
|
|
|
|
public void RefreshPainter(Serie serie)
|
|
{
|
|
RefreshPainter(GetPainterIndexBySerie(serie));
|
|
}
|
|
|
|
internal override void RefreshPainter(Painter painter)
|
|
{
|
|
base.RefreshPainter(painter);
|
|
if (painter != null && painter.type == Painter.Type.Serie)
|
|
{
|
|
m_PainterTop.Refresh();
|
|
}
|
|
}
|
|
|
|
public void SetPainterActive(int index, bool flag)
|
|
{
|
|
var painter = GetPainter(index);
|
|
if (painter == null) return;
|
|
painter.SetActive(flag, m_DebugMode);
|
|
}
|
|
|
|
protected virtual void CheckTheme()
|
|
{
|
|
if (m_Theme == null)
|
|
{
|
|
m_Theme = ChartTheme.Default;
|
|
}
|
|
else
|
|
{
|
|
if (m_Theme.colorPalette.Count == 0)
|
|
{
|
|
m_Theme.ResetTheme();
|
|
}
|
|
if (m_CheckTheme != m_Theme.theme)
|
|
{
|
|
m_CheckTheme = m_Theme.theme;
|
|
m_Theme.CopyTheme(m_CheckTheme);
|
|
#if UNITY_EDITOR
|
|
UnityEditor.EditorUtility.SetDirty(this);
|
|
#endif
|
|
SetAllComponentDirty();
|
|
OnThemeChanged();
|
|
}
|
|
}
|
|
}
|
|
protected override void CheckComponent()
|
|
{
|
|
base.CheckComponent();
|
|
if (m_Series.anyDirty)
|
|
{
|
|
if (SeriesHelper.IsLabelDirty(m_Series)) m_ReinitLabel = true;
|
|
if (SeriesHelper.IsNeedLabelUpdate(m_Series) && !m_RefreshChart) m_RefreshLabel = true;
|
|
foreach (var serie in m_Series.list)
|
|
{
|
|
if (serie.titleStyle.componentDirty) m_ReinitTitle = true;
|
|
if (serie.nameDirty)
|
|
{
|
|
foreach (var legend in m_Legends) legend.SetAllDirty();
|
|
RefreshChart();
|
|
serie.ClearNameDirty();
|
|
}
|
|
if (serie.vertsDirty)
|
|
{
|
|
RefreshPainter(serie);
|
|
}
|
|
}
|
|
m_Series.ClearDirty();
|
|
}
|
|
if (m_Theme.anyDirty)
|
|
{
|
|
if (m_Theme.componentDirty)
|
|
{
|
|
foreach (var title in m_Titles) title.SetAllDirty();
|
|
foreach (var legend in m_Legends) legend.SetAllDirty();
|
|
tooltip.SetAllDirty();
|
|
}
|
|
if (m_Theme.vertsDirty) RefreshChart();
|
|
m_Theme.ClearDirty();
|
|
}
|
|
CheckComponentDirty(tooltip);
|
|
foreach (var component in m_Titles) CheckComponentDirty(component);
|
|
foreach (var component in m_Legends) CheckComponentDirty(component);
|
|
foreach (var component in m_Tooltips) CheckComponentDirty(component);
|
|
foreach (var component in m_DataZooms) CheckComponentDirty(component);
|
|
foreach (var component in m_VisualMaps) CheckComponentDirty(component);
|
|
foreach (var component in m_Grids) CheckComponentDirty(component);
|
|
foreach (var component in m_XAxes) CheckComponentDirty(component);
|
|
foreach (var component in m_YAxes) CheckComponentDirty(component);
|
|
foreach (var component in m_Vessels) CheckComponentDirty(component);
|
|
foreach (var component in m_Polars) CheckComponentDirty(component);
|
|
foreach (var component in m_AngleAxes) CheckComponentDirty(component);
|
|
foreach (var component in m_RadiusAxes) CheckComponentDirty(component);
|
|
foreach (var component in m_Radars) CheckComponentDirty(component);
|
|
foreach (var drawSerie in m_DrawSeries) drawSerie.CheckComponent();
|
|
}
|
|
|
|
protected override void SetAllComponentDirty()
|
|
{
|
|
base.SetAllComponentDirty();
|
|
m_Theme.SetAllDirty();
|
|
foreach (var component in m_Titles) component.SetAllDirty();
|
|
foreach (var component in m_Legends) component.SetAllDirty();
|
|
foreach (var component in m_Tooltips) component.SetAllDirty();
|
|
foreach (var component in m_Grids) component.SetAllDirty();
|
|
foreach (var component in m_XAxes) component.SetAllDirty();
|
|
foreach (var component in m_YAxes) component.SetAllDirty();
|
|
foreach (var component in m_DataZooms) component.SetAllDirty();
|
|
foreach (var component in m_VisualMaps) component.SetAllDirty();
|
|
foreach (var component in m_Vessels) component.SetAllDirty();
|
|
foreach (var component in m_Polars) component.SetAllDirty();
|
|
foreach (var component in m_RadiusAxes) component.SetAllDirty();
|
|
foreach (var component in m_AngleAxes) component.SetAllDirty();
|
|
foreach (var component in m_Radars) component.SetAllDirty();
|
|
m_ReinitLabel = true;
|
|
m_ReinitTitle = true;
|
|
m_RefreshChart = true;
|
|
}
|
|
|
|
protected override void OnDestroy()
|
|
{
|
|
for (int i = transform.childCount - 1; i >= 0; i--)
|
|
{
|
|
DestroyImmediate(transform.GetChild(i).gameObject);
|
|
}
|
|
}
|
|
|
|
protected virtual void CheckPainter()
|
|
{
|
|
for (int i = 0; i < m_Series.Count; i++)
|
|
{
|
|
var serie = m_Series.GetSerie(i);
|
|
serie.index = i;
|
|
SetPainterActive(i, true);
|
|
}
|
|
}
|
|
|
|
protected override void InitPainter()
|
|
{
|
|
base.InitPainter();
|
|
m_Painter.material = settings.basePainterMaterial;
|
|
m_PainterList.Clear();
|
|
if (settings == null) return;
|
|
var sizeDelta = new Vector2(m_GraphWidth, m_GraphHeight);
|
|
for (int i = 0; i < settings.maxPainter; i++)
|
|
{
|
|
var index = settings.reversePainter ? settings.maxPainter - 1 - i : i;
|
|
var painter = ChartHelper.AddPainterObject("painter_" + index, transform, m_GraphMinAnchor,
|
|
m_GraphMaxAnchor, m_GraphPivot, sizeDelta, chartHideFlags, 2 + index);
|
|
painter.index = m_PainterList.Count;
|
|
painter.type = Painter.Type.Serie;
|
|
painter.onPopulateMesh = OnDrawPainterSerie;
|
|
painter.SetActive(false, m_DebugMode);
|
|
painter.material = settings.seriePainterMaterial;
|
|
m_PainterList.Add(painter);
|
|
}
|
|
m_PainterTop = ChartHelper.AddPainterObject("painter_t", transform, m_GraphMinAnchor,
|
|
m_GraphMaxAnchor, m_GraphPivot, sizeDelta, chartHideFlags, 2 + settings.maxPainter);
|
|
m_PainterTop.type = Painter.Type.Top;
|
|
m_PainterTop.onPopulateMesh = OnDrawPainterTop;
|
|
m_PainterTop.SetActive(true, m_DebugMode);
|
|
m_PainterTop.material = settings.topPainterMaterial;
|
|
}
|
|
|
|
private void InitTitles()
|
|
{
|
|
for (int i = 0; i < m_Titles.Count; i++)
|
|
{
|
|
var title = m_Titles[i];
|
|
title.index = i;
|
|
InitTitle(title);
|
|
}
|
|
}
|
|
private void InitTitle(Title title)
|
|
{
|
|
title.painter = null;
|
|
title.refreshComponent = delegate ()
|
|
{
|
|
title.OnChanged();
|
|
var anchorMin = title.location.runtimeAnchorMin;
|
|
var anchorMax = title.location.runtimeAnchorMax;
|
|
var pivot = title.location.runtimePivot;
|
|
var titleObject = ChartHelper.AddObject(s_TitleObjectName + title.index, transform, anchorMin, anchorMax,
|
|
pivot, m_ChartSizeDelta);
|
|
title.gameObject = titleObject;
|
|
anchorMin = title.location.runtimeAnchorMin;
|
|
anchorMax = title.location.runtimeAnchorMax;
|
|
pivot = title.location.runtimePivot;
|
|
title.textStyle.UpdateAlignmentByLocation(title.location);
|
|
title.subTextStyle.UpdateAlignmentByLocation(title.location);
|
|
var fontSize = title.textStyle.GetFontSize(theme.title);
|
|
ChartHelper.UpdateRectTransform(titleObject, anchorMin, anchorMax, pivot, new Vector2(chartWidth, chartHeight));
|
|
var titlePosition = GetTitlePosition(title);
|
|
var subTitlePosition = -new Vector3(0, fontSize + title.itemGap, 0);
|
|
var titleWid = chartWidth;
|
|
|
|
titleObject.transform.localPosition = titlePosition;
|
|
titleObject.hideFlags = chartHideFlags;
|
|
ChartHelper.HideAllObject(titleObject);
|
|
|
|
var titleText = ChartHelper.AddTextObject(s_TitleObjectName, titleObject.transform, anchorMin, anchorMax,
|
|
pivot, new Vector2(titleWid, fontSize), title.textStyle, theme.title);
|
|
titleText.SetActive(title.show);
|
|
titleText.SetLocalPosition(Vector3.zero + title.textStyle.offsetv3);
|
|
titleText.SetText(title.text);
|
|
|
|
var subText = ChartHelper.AddTextObject(s_SubTitleObjectName, titleObject.transform, anchorMin, anchorMax,
|
|
pivot, new Vector2(titleWid, title.subTextStyle.GetFontSize(theme.subTitle)), title.subTextStyle,
|
|
theme.subTitle);
|
|
subText.SetActive(title.show && !string.IsNullOrEmpty(title.subText));
|
|
subText.SetLocalPosition(subTitlePosition + title.subTextStyle.offsetv3);
|
|
subText.SetText(title.subText);
|
|
};
|
|
title.refreshComponent();
|
|
}
|
|
|
|
private void InitLegends()
|
|
{
|
|
for (int i = 0; i < m_Legends.Count; i++)
|
|
{
|
|
var legend = m_Legends[i];
|
|
legend.index = i;
|
|
InitLegend(legend);
|
|
}
|
|
}
|
|
|
|
private void InitLegend(Legend legend)
|
|
{
|
|
legend.painter = null; // legend component does not need to paint
|
|
legend.refreshComponent = delegate ()
|
|
{
|
|
legend.OnChanged();
|
|
var legendObject = ChartHelper.AddObject(s_LegendObjectName + legend.index, transform, m_ChartMinAnchor,
|
|
m_ChartMaxAnchor, m_ChartPivot, m_ChartSizeDelta);
|
|
legend.gameObject = legendObject;
|
|
legendObject.hideFlags = chartHideFlags;
|
|
SeriesHelper.UpdateSerieNameList(this, ref m_LegendRealShowName);
|
|
List<string> datas;
|
|
if (legend.show && legend.data.Count > 0)
|
|
{
|
|
datas = new List<string>();
|
|
for (int i = 0; i < m_LegendRealShowName.Count; i++)
|
|
{
|
|
if (legend.data.Contains(m_LegendRealShowName[i])) datas.Add(m_LegendRealShowName[i]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
datas = m_LegendRealShowName;
|
|
}
|
|
int totalLegend = 0;
|
|
for (int i = 0; i < datas.Count; i++)
|
|
{
|
|
if (!SeriesHelper.IsLegalLegendName(datas[i])) continue;
|
|
totalLegend++;
|
|
}
|
|
legend.RemoveButton();
|
|
ChartHelper.HideAllObject(legendObject);
|
|
if (!legend.show) return;
|
|
for (int i = 0; i < datas.Count; i++)
|
|
{
|
|
if (!SeriesHelper.IsLegalLegendName(datas[i])) continue;
|
|
string legendName = legend.GetFormatterContent(datas[i]);
|
|
var readIndex = m_LegendRealShowName.IndexOf(datas[i]);
|
|
var active = IsActiveByLegend(datas[i]);
|
|
var bgColor = LegendHelper.GetIconColor(this, readIndex, datas[i], active);
|
|
var item = LegendHelper.AddLegendItem(legend, i, datas[i], legendObject.transform, m_Theme,
|
|
legendName, bgColor, active, readIndex);
|
|
legend.SetButton(legendName, item, totalLegend);
|
|
ChartHelper.ClearEventListener(item.button.gameObject);
|
|
ChartHelper.AddEventListener(item.button.gameObject, EventTriggerType.PointerDown, (data) =>
|
|
{
|
|
if (data.selectedObject == null || legend.selectedMode == Legend.SelectedMode.None) return;
|
|
var temp = data.selectedObject.name.Split('_');
|
|
string selectedName = temp[1];
|
|
int clickedIndex = int.Parse(temp[0]);
|
|
if (legend.selectedMode == Legend.SelectedMode.Multiple)
|
|
{
|
|
OnLegendButtonClick(clickedIndex, selectedName, !IsActiveByLegend(selectedName));
|
|
}
|
|
else
|
|
{
|
|
var btnList = legend.buttonList.Values.ToArray();
|
|
if (btnList.Length == 1)
|
|
{
|
|
OnLegendButtonClick(0, selectedName, !IsActiveByLegend(selectedName));
|
|
}
|
|
else
|
|
{
|
|
for (int n = 0; n < btnList.Length; n++)
|
|
{
|
|
temp = btnList[n].name.Split('_');
|
|
selectedName = btnList[n].legendName;
|
|
var index = btnList[n].index;
|
|
OnLegendButtonClick(n, selectedName, index == clickedIndex ? true : false);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
ChartHelper.AddEventListener(item.button.gameObject, EventTriggerType.PointerEnter, (data) =>
|
|
{
|
|
if (item.button == null) return;
|
|
var temp = item.button.name.Split('_');
|
|
string selectedName = temp[1];
|
|
int index = int.Parse(temp[0]);
|
|
OnLegendButtonEnter(index, selectedName);
|
|
});
|
|
ChartHelper.AddEventListener(item.button.gameObject, EventTriggerType.PointerExit, (data) =>
|
|
{
|
|
if (item.button == null) return;
|
|
var temp = item.button.name.Split('_');
|
|
string selectedName = temp[1];
|
|
int index = int.Parse(temp[0]);
|
|
OnLegendButtonExit(index, selectedName);
|
|
});
|
|
}
|
|
if (legend.selectedMode == Legend.SelectedMode.Single)
|
|
{
|
|
for (int n = 0; n < m_LegendRealShowName.Count; n++)
|
|
{
|
|
OnLegendButtonClick(n, m_LegendRealShowName[n], n == 0 ? true : false);
|
|
}
|
|
}
|
|
LegendHelper.ResetItemPosition(legend, m_ChartPosition, m_ChartWidth, m_ChartHeight);
|
|
};
|
|
legend.refreshComponent();
|
|
}
|
|
|
|
private void InitSerieLabel()
|
|
{
|
|
m_SerieLabelRoot = ChartHelper.AddObject(s_SerieLabelObjectName, transform, m_ChartMinAnchor,
|
|
m_ChartMaxAnchor, m_ChartPivot, m_ChartSizeDelta);
|
|
m_SerieLabelRoot.hideFlags = chartHideFlags;
|
|
SerieLabelPool.ReleaseAll(m_SerieLabelRoot.transform);
|
|
int count = 0;
|
|
for (int i = 0; i < m_Series.Count; i++)
|
|
{
|
|
var serie = m_Series.list[i];
|
|
serie.index = i;
|
|
SerieHelper.UpdateCenter(serie, chartPosition, chartWidth, chartHeight);
|
|
for (int j = 0; j < serie.data.Count; j++)
|
|
{
|
|
var serieData = serie.data[j];
|
|
serieData.index = count;
|
|
serieData.labelObject = null;
|
|
AddSerieLabel(serie, serieData, ref count);
|
|
count++;
|
|
}
|
|
}
|
|
SerieLabelHelper.UpdateLabelText(m_Series, m_Theme, m_LegendRealShowName);
|
|
}
|
|
|
|
|
|
protected void AddSerieLabel(Serie serie, SerieData serieData, ref int count)
|
|
{
|
|
if (m_SerieLabelRoot == null) return;
|
|
if (count == -1) count = serie.dataCount;
|
|
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
|
var serieEmphasisLable = SerieHelper.GetSerieEmphasisLabel(serie, serieData);
|
|
var iconStyle = SerieHelper.GetIconStyle(serie, serieData);
|
|
if (serie.IsPerformanceMode()) return;
|
|
if (!serieLabel.show && (serieEmphasisLable == null || !serieEmphasisLable.show) && !iconStyle.show) return;
|
|
if (serie.animation.enable && serie.animation.HasFadeOut()) return;
|
|
var textName = ChartCached.GetSerieLabelName(s_SerieLabelObjectName, serie.index, serieData.index);
|
|
var color = Color.grey;
|
|
if (serie.type == SerieType.Pie)
|
|
{
|
|
color = (serieLabel.position == SerieLabel.Position.Inside) ? Color.white :
|
|
(Color)m_Theme.GetColor(count);
|
|
}
|
|
else
|
|
{
|
|
color = !ChartHelper.IsClearColor(serieLabel.textStyle.color) ? serieLabel.textStyle.color :
|
|
(Color)m_Theme.GetColor(serie.index);
|
|
}
|
|
var labelObj = SerieLabelPool.Get(textName, m_SerieLabelRoot.transform, serieLabel, color,
|
|
iconStyle.width, iconStyle.height, theme);
|
|
var iconImage = labelObj.transform.Find("Icon").GetComponent<Image>();
|
|
var isAutoSize = serieLabel.backgroundWidth == 0 || serieLabel.backgroundHeight == 0;
|
|
var item = new ChartLabel();
|
|
item.SetLabel(labelObj, isAutoSize, serieLabel.paddingLeftRight, serieLabel.paddingTopBottom);
|
|
item.SetIcon(iconImage);
|
|
item.SetIconActive(iconStyle.show);
|
|
serieData.labelObject = item;
|
|
|
|
foreach (var dataIndex in serieData.children)
|
|
{
|
|
AddSerieLabel(serie, serie.GetSerieData(dataIndex), ref count);
|
|
count++;
|
|
}
|
|
}
|
|
|
|
private void InitSerieTitle()
|
|
{
|
|
var titleObject = ChartHelper.AddObject(s_SerieTitleObjectName, transform, m_ChartMinAnchor,
|
|
m_ChartMaxAnchor, m_ChartPivot, new Vector2(chartWidth, chartHeight));
|
|
titleObject.hideFlags = chartHideFlags;
|
|
ChartHelper.HideAllObject(titleObject);
|
|
for (int i = 0; i < m_Series.Count; i++)
|
|
{
|
|
var serie = m_Series.list[i];
|
|
var textStyle = serie.titleStyle.textStyle;
|
|
var titleColor = ChartHelper.IsClearColor(textStyle.color) ? m_Theme.GetColor(i) : (Color32)textStyle.color;
|
|
var anchorMin = new Vector2(0.5f, 0.5f);
|
|
var anchorMax = new Vector2(0.5f, 0.5f);
|
|
var pivot = new Vector2(0.5f, 0.5f);
|
|
var fontSize = 10;
|
|
var sizeDelta = new Vector2(50, fontSize + 2);
|
|
var txt = ChartHelper.AddTextObject("title_" + i, titleObject.transform, anchorMin, anchorMax,
|
|
pivot, sizeDelta, textStyle, theme.common);
|
|
txt.SetText("");
|
|
txt.SetColor(titleColor);
|
|
txt.SetLocalPosition(Vector2.zero);
|
|
txt.SetLocalEulerAngles(Vector2.zero);
|
|
txt.SetActive(serie.titleStyle.show);
|
|
serie.titleStyle.runtimeText = txt;
|
|
serie.titleStyle.UpdatePosition(serie.runtimeCenterPos);
|
|
var serieData = serie.GetSerieData(0);
|
|
if (serieData != null)
|
|
{
|
|
txt.SetText(serieData.name);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void InitTooltip()
|
|
{
|
|
tooltip.painter = m_PainterTop;
|
|
tooltip.refreshComponent = delegate ()
|
|
{
|
|
tooltip.gameObject = ChartHelper.AddObject("tooltip", transform, m_ChartMinAnchor,
|
|
m_ChartMaxAnchor, m_ChartPivot, m_ChartSizeDelta);
|
|
var tooltipObject = tooltip.gameObject;
|
|
tooltipObject.transform.localPosition = Vector3.zero;
|
|
tooltipObject.hideFlags = chartHideFlags;
|
|
DestroyImmediate(tooltipObject.GetComponent<Image>());
|
|
var parent = tooltipObject.transform;
|
|
var textStyle = tooltip.textStyle;
|
|
ChartHelper.HideAllObject(tooltipObject.transform);
|
|
GameObject content = ChartHelper.AddTooltipContent("content", parent, textStyle, m_Theme);
|
|
tooltip.SetObj(tooltipObject);
|
|
tooltip.SetContentObj(content);
|
|
tooltip.SetContentBackgroundColor(TooltipHelper.GetTexBackgroundColor(tooltip, m_Theme.tooltip));
|
|
tooltip.SetContentTextColor(TooltipHelper.GetTexColor(tooltip, m_Theme.tooltip));
|
|
tooltip.SetActive(false);
|
|
};
|
|
tooltip.refreshComponent();
|
|
}
|
|
|
|
private Vector3 GetLegendPosition(Legend legend, int i)
|
|
{
|
|
return legend.location.GetPosition(chartWidth, chartHeight);
|
|
}
|
|
|
|
protected override bool IsNeedCheckPointerPos()
|
|
{
|
|
return (tooltip.show && tooltip.runtimeInited)
|
|
|| raycastTarget;
|
|
}
|
|
|
|
private void CheckTooltip()
|
|
{
|
|
if (!isPointerInChart || !tooltip.show || !tooltip.runtimeInited)
|
|
{
|
|
if (tooltip.IsActive())
|
|
{
|
|
tooltip.ClearValue();
|
|
tooltip.SetActive(false);
|
|
m_PainterTop.Refresh();
|
|
}
|
|
return;
|
|
}
|
|
for (int i = 0; i < tooltip.runtimeDataIndex.Count; i++)
|
|
{
|
|
tooltip.runtimeDataIndex[i] = -1;
|
|
}
|
|
Vector2 local = pointerPos;
|
|
if (canvas == null) return;
|
|
|
|
if (local == Vector2.zero)
|
|
{
|
|
if (tooltip.IsActive())
|
|
{
|
|
tooltip.SetActive(false);
|
|
m_PainterTop.Refresh();
|
|
}
|
|
return;
|
|
}
|
|
if (!IsInChart(local))
|
|
{
|
|
if (tooltip.IsActive())
|
|
{
|
|
tooltip.SetActive(false);
|
|
m_PainterTop.Refresh();
|
|
}
|
|
return;
|
|
}
|
|
tooltip.runtimePointerPos = local;
|
|
CheckAllTooptip(local);
|
|
}
|
|
|
|
private void CheckAllTooptip(Vector2 localPostion)
|
|
{
|
|
tooltip.runtimeGridIndex = -1;
|
|
var actived = false;
|
|
foreach (var draw in m_DrawSeries)
|
|
actived = actived || draw.CheckTootipArea(localPostion);
|
|
CheckTootipArea(localPostion, actived);
|
|
}
|
|
|
|
protected virtual void CheckTootipArea(Vector2 localPostion, bool isActivedOther)
|
|
{
|
|
}
|
|
|
|
protected override void CheckRefreshChart()
|
|
{
|
|
if (m_Painter == null) return;
|
|
if (m_RefreshChart)
|
|
{
|
|
m_Painter.Refresh();
|
|
foreach (var painter in m_PainterList) painter.Refresh();
|
|
if (m_PainterTop != null) m_PainterTop.Refresh();
|
|
m_RefreshChart = false;
|
|
}
|
|
}
|
|
|
|
protected override void CheckRefreshPainter()
|
|
{
|
|
if (m_Painter == null) return;
|
|
m_Painter.CheckRefresh();
|
|
foreach (var painter in m_PainterList) painter.CheckRefresh();
|
|
if (m_PainterTop != null) m_PainterTop.CheckRefresh();
|
|
}
|
|
|
|
protected void CheckRefreshLabel()
|
|
{
|
|
if (m_ReinitLabel)
|
|
{
|
|
m_ReinitLabel = false;
|
|
SeriesHelper.UpdateSerieNameList(this, ref m_LegendRealShowName);
|
|
InitSerieLabel();
|
|
}
|
|
if (m_ReinitTitle)
|
|
{
|
|
m_ReinitTitle = false;
|
|
InitSerieTitle();
|
|
}
|
|
if (m_RefreshLabel)
|
|
{
|
|
m_RefreshLabel = false;
|
|
OnRefreshLabel();
|
|
}
|
|
}
|
|
|
|
public void Internal_CheckAnimation()
|
|
{
|
|
if (!m_CheckAnimation)
|
|
{
|
|
m_CheckAnimation = true;
|
|
AnimationFadeIn();
|
|
}
|
|
}
|
|
|
|
protected virtual void OnRefreshLabel()
|
|
{
|
|
foreach (var drawSerie in m_DrawSeries) drawSerie.RefreshLabel();
|
|
}
|
|
|
|
protected override void OnSizeChanged()
|
|
{
|
|
base.OnSizeChanged();
|
|
m_ChartWidth = m_GraphWidth;
|
|
m_ChartHeight = m_GraphHeight;
|
|
m_ChartX = m_GraphX;
|
|
m_ChartY = m_GraphY;
|
|
m_ChartPosition = m_GraphPosition;
|
|
m_ChartMinAnchor = m_GraphMinAnchor;
|
|
m_ChartMaxAnchor = m_GraphMaxAnchor;
|
|
m_ChartPivot = m_GraphPivot;
|
|
m_ChartSizeDelta = m_GraphSizeDelta;
|
|
m_ChartRect = m_GraphRect;
|
|
|
|
SetAllComponentDirty();
|
|
m_Series.SetLabelDirty();
|
|
m_ReinitLabel = true;
|
|
RefreshChart();
|
|
}
|
|
|
|
protected override void OnLocalPositionChanged()
|
|
{
|
|
m_Background.SetAllDirty();
|
|
}
|
|
|
|
protected virtual void OnThemeChanged()
|
|
{
|
|
}
|
|
|
|
protected virtual void OnYMaxValueChanged()
|
|
{
|
|
}
|
|
|
|
public virtual void OnDataZoomRangeChanged(DataZoom dataZoom)
|
|
{
|
|
}
|
|
|
|
public override void OnPointerClick(PointerEventData eventData)
|
|
{
|
|
m_DebugInfo.clickChartCount++;
|
|
base.OnPointerClick(eventData);
|
|
}
|
|
|
|
public override void OnPointerDown(PointerEventData eventData)
|
|
{
|
|
base.OnPointerDown(eventData);
|
|
foreach (var drawSerie in m_DrawSeries) drawSerie.OnPointerDown(eventData);
|
|
foreach (var handler in m_ComponentHandlers) handler.OnPointerDown(eventData);
|
|
}
|
|
|
|
public override void OnBeginDrag(PointerEventData eventData)
|
|
{
|
|
base.OnBeginDrag(eventData);
|
|
foreach (var handler in m_ComponentHandlers) handler.OnBeginDrag(eventData);
|
|
}
|
|
|
|
public override void OnDrag(PointerEventData eventData)
|
|
{
|
|
base.OnDrag(eventData);
|
|
foreach (var handler in m_ComponentHandlers) handler.OnDrag(eventData);
|
|
}
|
|
|
|
public override void OnEndDrag(PointerEventData eventData)
|
|
{
|
|
base.OnEndDrag(eventData);
|
|
foreach (var handler in m_ComponentHandlers) handler.OnEndDrag(eventData);
|
|
}
|
|
|
|
public override void OnScroll(PointerEventData eventData)
|
|
{
|
|
base.OnScroll(eventData);
|
|
foreach (var handler in m_ComponentHandlers) handler.OnScroll(eventData);
|
|
}
|
|
|
|
protected virtual void OnLegendButtonClick(int index, string legendName, bool show)
|
|
{
|
|
var clicked = false;
|
|
foreach (var drawSerie in m_DrawSeries)
|
|
clicked = clicked || drawSerie.OnLegendButtonClick(index, legendName, show);
|
|
if (!clicked)
|
|
{
|
|
foreach (var serie in m_Series.GetSeries(legendName))
|
|
{
|
|
SetActive(serie.index, show);
|
|
RefreshPainter(serie);
|
|
}
|
|
OnYMaxValueChanged();
|
|
}
|
|
if(m_OnLegendClick != null)
|
|
m_OnLegendClick(index, legendName, show);
|
|
}
|
|
|
|
protected virtual void OnLegendButtonEnter(int index, string legendName)
|
|
{
|
|
var enter = false;
|
|
foreach (var drawSerie in m_DrawSeries)
|
|
enter = enter || drawSerie.OnLegendButtonEnter(index, legendName);
|
|
if (!enter)
|
|
{
|
|
foreach (var serie in m_Series.GetSeries(legendName))
|
|
{
|
|
serie.highlighted = true;
|
|
RefreshPainter(serie);
|
|
}
|
|
}
|
|
if(m_OnLegendEnter != null)
|
|
m_OnLegendEnter(index, legendName);
|
|
}
|
|
|
|
protected virtual void OnLegendButtonExit(int index, string legendName)
|
|
{
|
|
var exit = false;
|
|
foreach (var drawSerie in m_DrawSeries)
|
|
exit = exit || drawSerie.OnLegendButtonExit(index, legendName);
|
|
if (!exit)
|
|
{
|
|
foreach (var serie in m_Series.GetSeries(legendName))
|
|
{
|
|
serie.highlighted = false;
|
|
RefreshPainter(serie);
|
|
}
|
|
}
|
|
if(m_OnLegendExit != null)
|
|
m_OnLegendExit(index, legendName);
|
|
}
|
|
|
|
protected virtual void UpdateTooltip()
|
|
{
|
|
}
|
|
|
|
protected override void OnDrawPainterBase(VertexHelper vh, Painter painter)
|
|
{
|
|
vh.Clear();
|
|
DrawBackground(vh);
|
|
DrawPainterBase(vh);
|
|
foreach (var draw in m_ComponentHandlers) draw.DrawBase(vh);
|
|
foreach (var draw in m_DrawSeries) draw.DrawBase(vh);
|
|
if (m_OnCustomDrawBaseCallback != null)
|
|
{
|
|
m_OnCustomDrawBaseCallback(vh);
|
|
}
|
|
m_BasePainterVertCount = vh.currentVertCount;
|
|
}
|
|
|
|
protected virtual void OnDrawPainterSerie(VertexHelper vh, Painter painter)
|
|
{
|
|
vh.Clear();
|
|
var maxPainter = settings.maxPainter;
|
|
var maxSeries = m_Series.Count;
|
|
var rate = Mathf.CeilToInt(maxSeries * 1.0f / maxPainter);
|
|
m_PainterTop.Refresh();
|
|
m_DebugInfo.refreshCount++;
|
|
for (int i = painter.index * rate; i < (painter.index + 1) * rate && i < maxSeries; i++)
|
|
{
|
|
var serie = m_Series.GetSerie(i);
|
|
if (m_OnCustomDrawSerieBeforeCallback != null)
|
|
{
|
|
m_OnCustomDrawSerieBeforeCallback.Invoke(vh, serie);
|
|
}
|
|
DrawPainterSerie(vh, serie);
|
|
if (m_OnCustomDrawSerieAfterCallback != null)
|
|
{
|
|
m_OnCustomDrawSerieAfterCallback(vh, serie);
|
|
}
|
|
serie.runtimeVertCount = vh.currentVertCount;
|
|
}
|
|
m_RefreshLabel = true;
|
|
}
|
|
|
|
protected virtual void OnDrawPainterTop(VertexHelper vh, Painter painter)
|
|
{
|
|
vh.Clear();
|
|
DrawLegend(vh);
|
|
DrawPainterTop(vh);
|
|
foreach (var draw in m_ComponentHandlers) draw.DrawTop(vh);
|
|
if (m_OnCustomDrawTopCallback != null)
|
|
{
|
|
m_OnCustomDrawTopCallback(vh);
|
|
}
|
|
DrawTooltip(vh);
|
|
m_TopPainterVertCount = vh.currentVertCount;
|
|
}
|
|
|
|
protected virtual void DrawPainterSerie(VertexHelper vh, Serie serie)
|
|
{
|
|
foreach (var drawSerie in m_DrawSeries)
|
|
{
|
|
drawSerie.DrawSerie(vh, serie);
|
|
}
|
|
}
|
|
|
|
protected virtual void DrawPainterTop(VertexHelper vh)
|
|
{
|
|
}
|
|
|
|
protected virtual void DrawTooltip(VertexHelper vh)
|
|
{
|
|
}
|
|
|
|
protected override void DrawBackground(VertexHelper vh)
|
|
{
|
|
Vector3 p1 = new Vector3(chartX, chartY + chartHeight);
|
|
Vector3 p2 = new Vector3(chartX + chartWidth, chartY + chartHeight);
|
|
Vector3 p3 = new Vector3(chartX + chartWidth, chartY);
|
|
Vector3 p4 = new Vector3(chartX, chartY);
|
|
var backgroundColor = ThemeHelper.GetBackgroundColor(m_Theme, m_Background);
|
|
UGL.DrawQuadrilateral(vh, p1, p2, p3, p4, backgroundColor);
|
|
}
|
|
|
|
protected virtual void DrawLegend(VertexHelper vh)
|
|
{
|
|
if (m_Series.Count == 0) return;
|
|
foreach (var legend in m_Legends)
|
|
{
|
|
if (!legend.show) continue;
|
|
if (legend.iconType == Legend.Type.Custom) continue;
|
|
foreach (var kv in legend.buttonList)
|
|
{
|
|
var item = kv.Value;
|
|
var rect = item.GetIconRect();
|
|
var radius = Mathf.Min(rect.width, rect.height) / 2;
|
|
var color = item.GetIconColor();
|
|
var iconType = legend.iconType;
|
|
if (legend.iconType == Legend.Type.Auto)
|
|
{
|
|
var serie = m_Series.GetSerie(item.legendName);
|
|
if (serie != null && serie.type == SerieType.Line)
|
|
{
|
|
var sp = new Vector3(rect.center.x - rect.width / 2, rect.center.y);
|
|
var ep = new Vector3(rect.center.x + rect.width / 2, rect.center.y);
|
|
UGL.DrawLine(vh, sp, ep, m_Settings.legendIconLineWidth, color);
|
|
if (!serie.symbol.show) continue;
|
|
switch (serie.symbol.type)
|
|
{
|
|
case SerieSymbolType.None:
|
|
continue;
|
|
case SerieSymbolType.Circle:
|
|
iconType = Legend.Type.Circle;
|
|
break;
|
|
case SerieSymbolType.Diamond:
|
|
iconType = Legend.Type.Diamond;
|
|
break;
|
|
case SerieSymbolType.EmptyCircle:
|
|
iconType = Legend.Type.EmptyCircle;
|
|
break;
|
|
case SerieSymbolType.Rect:
|
|
iconType = Legend.Type.Rect;
|
|
break;
|
|
case SerieSymbolType.Triangle:
|
|
iconType = Legend.Type.Triangle;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
iconType = Legend.Type.Rect;
|
|
}
|
|
}
|
|
switch (iconType)
|
|
{
|
|
case Legend.Type.Rect:
|
|
var cornerRadius = m_Settings.legendIconCornerRadius;
|
|
UGL.DrawRoundRectangle(vh, rect.center, rect.width, rect.height, color, color,
|
|
0, cornerRadius, false, 0.5f);
|
|
break;
|
|
case Legend.Type.Circle:
|
|
UGL.DrawCricle(vh, rect.center, radius, color);
|
|
break;
|
|
case Legend.Type.Diamond:
|
|
UGL.DrawDiamond(vh, rect.center, radius, color);
|
|
break;
|
|
case Legend.Type.EmptyCircle:
|
|
var backgroundColor = ThemeHelper.GetBackgroundColor(m_Theme, m_Background);
|
|
UGL.DrawEmptyCricle(vh, rect.center, radius, 2 * m_Settings.legendIconLineWidth,
|
|
color, color, backgroundColor, 1f);
|
|
break;
|
|
case Legend.Type.Triangle:
|
|
UGL.DrawTriangle(vh, rect.center, 1.2f * radius, color);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void DrawSymbol(VertexHelper vh, SerieSymbolType type, float symbolSize,
|
|
float tickness, Vector3 pos, Color32 color, Color32 toColor, Color32 fillColor, float gap, float[] cornerRadius)
|
|
{
|
|
DrawSymbol(vh, type, symbolSize, tickness, pos, color, toColor, fillColor, gap, cornerRadius, Vector3.zero);
|
|
}
|
|
|
|
public void DrawSymbol(VertexHelper vh, SerieSymbolType type, float symbolSize,
|
|
float tickness, Vector3 pos, Color32 color, Color32 toColor, Color32 fillColor, float gap, float[] cornerRadius, Vector3 startPos)
|
|
{
|
|
var backgroundColor = ThemeHelper.GetBackgroundColor(m_Theme, m_Background);
|
|
if (ChartHelper.IsClearColor(fillColor))
|
|
fillColor = backgroundColor;
|
|
var smoothness = settings.cicleSmoothness;
|
|
ChartDrawer.DrawSymbol(vh, type, symbolSize, tickness, pos, color, toColor, gap,
|
|
cornerRadius, fillColor, backgroundColor, smoothness, startPos);
|
|
}
|
|
|
|
public void DrawLabelBackground(VertexHelper vh, Serie serie, SerieData serieData)
|
|
{
|
|
if (serieData == null || serieData.labelObject == null) return;
|
|
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
|
if (!serieLabel.show) return;
|
|
var invert = serieLabel.autoOffset
|
|
&& serie.type == SerieType.Line
|
|
&& SerieHelper.IsDownPoint(serie, serieData.index)
|
|
&& !serie.areaStyle.show;
|
|
var centerPos = Vector3.zero;
|
|
if (serie.type == SerieType.Pie)
|
|
centerPos = SerieLabelHelper.GetRealLabelPosition(serieData, serieLabel);
|
|
else
|
|
centerPos = serieData.labelPosition + serieLabel.offset * (invert ? -1 : 1);
|
|
var labelHalfWid = serieData.labelObject.GetLabelWidth() / 2;
|
|
var labelHalfHig = serieData.GetLabelHeight() / 2;
|
|
var p1 = new Vector3(centerPos.x - labelHalfWid, centerPos.y + labelHalfHig);
|
|
var p2 = new Vector3(centerPos.x + labelHalfWid, centerPos.y + labelHalfHig);
|
|
var p3 = new Vector3(centerPos.x + labelHalfWid, centerPos.y - labelHalfHig);
|
|
var p4 = new Vector3(centerPos.x - labelHalfWid, centerPos.y - labelHalfHig);
|
|
|
|
if (serieLabel.textStyle.rotate > 0)
|
|
{
|
|
p1 = ChartHelper.RotateRound(p1, centerPos, Vector3.forward, serieLabel.textStyle.rotate);
|
|
p2 = ChartHelper.RotateRound(p2, centerPos, Vector3.forward, serieLabel.textStyle.rotate);
|
|
p3 = ChartHelper.RotateRound(p3, centerPos, Vector3.forward, serieLabel.textStyle.rotate);
|
|
p4 = ChartHelper.RotateRound(p4, centerPos, Vector3.forward, serieLabel.textStyle.rotate);
|
|
}
|
|
|
|
UGL.DrawQuadrilateral(vh, p1, p2, p3, p4, serieLabel.textStyle.backgroundColor);
|
|
|
|
if (serieLabel.border)
|
|
{
|
|
UGL.DrawBorder(vh, centerPos, serieData.GetLabelWidth(), serieData.GetLabelHeight(),
|
|
serieLabel.borderWidth, serieLabel.borderColor, serieLabel.textStyle.rotate);
|
|
}
|
|
}
|
|
|
|
protected int GetPainterIndexBySerie(Serie serie)
|
|
{
|
|
var maxPainter = settings.maxPainter;
|
|
var maxSeries = m_Series.Count;
|
|
if (maxPainter >= maxSeries) return serie.index;
|
|
else
|
|
{
|
|
var rate = Mathf.CeilToInt(maxSeries * 1.0f / maxPainter);
|
|
return serie.index / rate;
|
|
}
|
|
}
|
|
}
|
|
}
|