Aimbot Enviroment very first

Basic environment include Multi scene, Reward Change, Visible chart, etc....
This commit is contained in:
2022-09-05 20:46:08 +09:00
parent aa337c5fc2
commit 2d404cfdf2
1552 changed files with 162551 additions and 0 deletions
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: db4db63725f6848e785146f5cf4bb657
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,32 @@
namespace XCharts.Runtime
{
[System.Serializable]
[SerieHandler(typeof(BarHandler), true)]
[SerieConvert(typeof(Line), typeof(Pie))]
[RequireChartComponent(typeof(GridCoord))]
[DefaultAnimation(AnimationType.BottomToTop)]
[SerieExtraComponent(typeof(LabelStyle), typeof(EmphasisItemStyle), typeof(EmphasisLabelStyle))]
[SerieDataExtraComponent(typeof(ItemStyle), typeof(LabelStyle), typeof(EmphasisItemStyle), typeof(EmphasisLabelStyle))]
[SerieDataExtraField("m_Ignore")]
public class Bar : Serie, INeedSerieContainer
{
public int containerIndex { get; internal set; }
public int containterInstanceId { get; internal set; }
public static Serie AddDefaultSerie(BaseChart chart, string serieName)
{
var serie = chart.AddSerie<Bar>(serieName);
for (int i = 0; i < 5; i++)
{
chart.AddData(serie.index, UnityEngine.Random.Range(10, 90));
}
return serie;
}
public static Bar CovertSerie(Serie serie)
{
var newSerie = SerieHelper.CloneSerie<Bar>(serie);
return newSerie;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cfb8051cfc49e4afabd94a11c5912c3e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,436 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using XUGL;
namespace XCharts.Runtime
{
[UnityEngine.Scripting.Preserve]
internal sealed class BarHandler : SerieHandler<Bar>
{
List<List<SerieData>> m_StackSerieData = new List<List<SerieData>>();
private GridCoord m_SerieGrid;
private float[] m_CapusleDefaultCornerRadius = new float[] { 1, 1, 1, 1 };
public override void Update()
{
base.Update();
UpdateSerieContext();
}
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
string marker, string itemFormatter, string numericFormatter,
ref List<SerieParams> paramList, ref string title)
{
UpdateCoordSerieParams(ref paramList, ref title, dataIndex, showCategory, category,
marker, itemFormatter, numericFormatter);
}
public override void DrawSerie(VertexHelper vh)
{
DrawBarSerie(vh, serie, serie.context.colorIndex);
}
public override Vector3 GetSerieDataLabelPosition(SerieData serieData, LabelStyle label)
{
switch (label.position)
{
case LabelStyle.Position.Bottom:
var center = serieData.context.rect.center;
return new Vector3(center.x, center.y - serieData.context.rect.height / 2);
case LabelStyle.Position.Center:
case LabelStyle.Position.Inside:
return serieData.context.rect.center;
default:
return serieData.context.position;
}
}
public override void OnPointerDown(PointerEventData eventData)
{
if (!serie.context.pointerEnter) return;
if (serie.context.pointerItemDataIndex < 0) return;
if (chart.onPointerClickBar != null)
{
chart.onPointerClickBar(eventData, serie.context.pointerItemDataIndex);
}
}
private void UpdateSerieContext()
{
if (m_SerieGrid == null)
return;
var needCheck = (chart.isPointerInChart && m_SerieGrid.IsPointerEnter()) || m_LegendEnter;
var needInteract = false;
if (!needCheck)
{
if (m_LastCheckContextFlag != needCheck)
{
m_LastCheckContextFlag = needCheck;
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
foreach (var serieData in serie.data)
{
serieData.context.highlight = false;
serieData.interact.Reset();
}
chart.RefreshPainter(serie);
}
return;
}
m_LastCheckContextFlag = needCheck;
if (m_LegendEnter)
{
serie.context.pointerEnter = true;
foreach (var serieData in serie.data)
{
var barColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serie.context.colorIndex, true);
var barToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serie.context.colorIndex, true);
serieData.interact.SetColor(ref needInteract, barColor, barToColor);
}
}
else
{
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
foreach (var serieData in serie.data)
{
if (serie.context.pointerAxisDataIndexs.Contains(serieData.index) ||
serieData.context.rect.Contains(chart.pointerPos))
{
serie.context.pointerItemDataIndex = serieData.index;
serie.context.pointerEnter = true;
serieData.context.highlight = true;
var barColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serie.context.colorIndex, true);
var barToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serie.context.colorIndex, true);
serieData.interact.SetColor(ref needInteract, barColor, barToColor);
}
else
{
serieData.context.highlight = false;
var barColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serie.context.colorIndex, false);
var barToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serie.context.colorIndex, false);
serieData.interact.SetColor(ref needInteract, barColor, barToColor);
}
}
}
if (needInteract)
{
chart.RefreshPainter(serie);
}
}
private void DrawBarSerie(VertexHelper vh, Bar serie, int colorIndex)
{
if (!serie.show || serie.animation.HasFadeOut())
return;
var isY = ComponentHelper.IsAnyCategoryOfYAxis(chart.components);
Axis axis;
Axis relativedAxis;
if (isY)
{
axis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
relativedAxis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
}
else
{
axis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
relativedAxis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
}
m_SerieGrid = chart.GetChartComponent<GridCoord>(axis.gridIndex);
if (axis == null)
return;
if (relativedAxis == null)
return;
if (m_SerieGrid == null)
return;
var dataZoom = chart.GetDataZoomOfAxis(axis);
var showData = serie.GetDataList(dataZoom);
if (showData.Count <= 0)
return;
var axisLength = isY ? m_SerieGrid.context.height : m_SerieGrid.context.width;
var relativedAxisLength = isY ? m_SerieGrid.context.width : m_SerieGrid.context.height;
var axisXY = isY ? m_SerieGrid.context.y : m_SerieGrid.context.x;
var isStack = SeriesHelper.IsStack<Bar>(chart.series, serie.stack);
if (isStack)
SeriesHelper.UpdateStackDataList(chart.series, serie, dataZoom, m_StackSerieData);
var barCount = chart.GetSerieBarRealCount<Bar>();
float categoryWidth = AxisHelper.GetDataWidth(axis, axisLength, showData.Count, dataZoom);
float barGap = chart.GetSerieBarGap<Bar>();
float totalBarWidth = chart.GetSerieTotalWidth<Bar>(categoryWidth, barGap, barCount);
float barWidth = serie.GetBarWidth(categoryWidth, barCount);
float offset = (categoryWidth - totalBarWidth) * 0.5f;
var serieReadIndex = chart.GetSerieIndexIfStack<Bar>(serie);
float gap = serie.barGap == -1 ? offset : offset + chart.GetSerieTotalGap<Bar>(categoryWidth, barGap, serieReadIndex);
int maxCount = serie.maxShow > 0 ?
(serie.maxShow > showData.Count ? showData.Count : serie.maxShow) :
showData.Count;
var isPercentStack = SeriesHelper.IsPercentStack<Bar>(chart.series, serie.stack);
bool dataChanging = false;
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
double yMinValue = relativedAxis.context.minValue;
double yMaxValue = relativedAxis.context.maxValue;
var areaColor = ColorUtil.clearColor32;
var areaToColor = ColorUtil.clearColor32;
var interacting = false;
serie.containerIndex = m_SerieGrid.index;
serie.containterInstanceId = m_SerieGrid.instanceId;
serie.animation.InitProgress(axisXY, axisXY + axisLength);
for (int i = serie.minShow; i < maxCount; i++)
{
var serieData = showData[i];
serieData.index = i;
if (!serieData.show || serie.IsIgnoreValue(serieData))
{
serie.context.dataPoints.Add(Vector3.zero);
continue;
}
if (serieData.IsDataChanged())
dataChanging = true;
var highlight = serieData.context.highlight || serie.highlight;
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, highlight);
var value = axis.IsCategory() ? i : serieData.GetData(0, axis.inverse);
var relativedValue = serieData.GetCurrData(1, dataChangeDuration, relativedAxis.inverse, yMinValue, yMaxValue);
var borderWidth = relativedValue == 0 ? 0 : itemStyle.runtimeBorderWidth;
var borderGap = relativedValue == 0 ? 0 : itemStyle.borderGap;
var borderGapAndWidth = borderWidth + borderGap;
if (!serieData.interact.TryGetColor(ref areaColor, ref areaToColor, ref interacting))
{
areaColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, highlight);
areaToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, colorIndex, highlight);
serieData.interact.SetColor(ref interacting, areaColor, areaToColor);
}
var pX = 0f;
var pY = 0f;
UpdateXYPosition(m_SerieGrid, isY, axis, relativedAxis, i, categoryWidth, barWidth, isStack, value, ref pX, ref pY);
var barHig = 0f;
if (isPercentStack)
{
var valueTotal = chart.GetSerieSameStackTotalValue<Bar>(serie.stack, i);
barHig = valueTotal != 0 ? (float) (relativedValue / valueTotal * relativedAxisLength) : 0;
}
else
{
barHig = AxisHelper.GetAxisValueLength(m_SerieGrid, relativedAxis, categoryWidth, relativedValue);
}
float currHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, barHig);
Vector3 plb, plt, prt, prb, top;
UpdateRectPosition(m_SerieGrid, isY, relativedValue, pX, pY, gap, borderWidth, barWidth, currHig,
out plb, out plt, out prt, out prb, out top);
serieData.context.stackHeight = barHig;
serieData.context.position = top;
serieData.context.rect = Rect.MinMaxRect(plb.x + borderGapAndWidth, plb.y + borderGapAndWidth,
prt.x - borderGapAndWidth, prt.y - borderGapAndWidth);
serieData.context.backgroundRect = isY ?
Rect.MinMaxRect(m_SerieGrid.context.x, plb.y, m_SerieGrid.context.x + relativedAxisLength, prt.y) :
Rect.MinMaxRect(plb.x, m_SerieGrid.context.y, prb.x, m_SerieGrid.context.y + relativedAxisLength);
if (!serie.clip || (serie.clip && m_SerieGrid.Contains(top)))
serie.context.dataPoints.Add(top);
else
continue;
if (serie.show && currHig != 0 && !serie.placeHolder)
{
switch (serie.barType)
{
case BarType.Normal:
case BarType.Capsule:
DrawNormalBar(vh, serie, serieData, itemStyle, colorIndex, highlight, gap, barWidth,
pX, pY, plb, plt, prt, prb, isY, m_SerieGrid, axis, areaColor, areaToColor, relativedValue);
break;
case BarType.Zebra:
DrawZebraBar(vh, serie, serieData, itemStyle, colorIndex, highlight, gap, barWidth,
pX, pY, plb, plt, prt, prb, isY, m_SerieGrid, axis, areaColor, areaToColor);
break;
}
}
if (serie.animation.CheckDetailBreak(top, isY))
{
break;
}
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress();
chart.RefreshPainter(serie);
}
if (dataChanging || interacting)
{
chart.RefreshPainter(serie);
}
}
private void UpdateXYPosition(GridCoord grid, bool isY, Axis axis, Axis relativedAxis, int i, float categoryWidth, float barWidth, bool isStack,
double value, ref float pX, ref float pY)
{
if (isY)
{
if (axis.IsCategory())
{
pY = grid.context.y + i * categoryWidth + (axis.boundaryGap ? 0 : -categoryWidth * 0.5f);
}
else
{
if (axis.context.minMaxRange <= 0) pY = grid.context.y;
else
{
var valueLen = (float) ((value - axis.context.minValue) / axis.context.minMaxRange) * grid.context.height;
pY = grid.context.y + valueLen - categoryWidth * 0.5f;
}
}
pX = AxisHelper.GetAxisValuePosition(grid, relativedAxis, categoryWidth, 0);
if (isStack)
{
for (int n = 0; n < m_StackSerieData.Count - 1; n++)
pX += m_StackSerieData[n][i].context.stackHeight;
}
}
else
{
if (axis.IsCategory())
{
pX = grid.context.x + i * categoryWidth + (axis.boundaryGap ? 0 : -categoryWidth * 0.5f);
}
else
{
if (axis.context.minMaxRange <= 0) pX = grid.context.x;
else
{
var valueLen = (float) ((value - axis.context.minValue) / axis.context.minMaxRange) * grid.context.width;
pX = grid.context.x + valueLen - categoryWidth * 0.5f;
}
}
pY = AxisHelper.GetAxisValuePosition(grid, relativedAxis, categoryWidth, 0);
if (isStack)
{
for (int n = 0; n < m_StackSerieData.Count - 1; n++)
pY += m_StackSerieData[n][i].context.stackHeight;
}
}
}
private void UpdateRectPosition(GridCoord grid, bool isY, double yValue, float pX, float pY, float gap, float borderWidth,
float barWidth, float currHig,
out Vector3 plb, out Vector3 plt, out Vector3 prt, out Vector3 prb, out Vector3 top)
{
if (isY)
{
if (yValue < 0)
{
plt = new Vector3(pX + currHig, pY + gap + barWidth);
prt = new Vector3(pX, pY + gap + barWidth);
prb = new Vector3(pX, pY + gap);
plb = new Vector3(pX + currHig, pY + gap);
}
else
{
plt = new Vector3(pX, pY + gap + barWidth);
prt = new Vector3(pX + currHig, pY + gap + barWidth);
prb = new Vector3(pX + currHig, pY + gap);
plb = new Vector3(pX, pY + gap);
}
top = new Vector3(pX + currHig, pY + gap + barWidth / 2);
}
else
{
if (yValue < 0)
{
plb = new Vector3(pX + gap, pY + currHig);
plt = new Vector3(pX + gap, pY);
prt = new Vector3(pX + gap + barWidth, pY);
prb = new Vector3(pX + gap + barWidth, pY + currHig);
}
else
{
plb = new Vector3(pX + gap, pY);
plt = new Vector3(pX + gap, pY + currHig);
prt = new Vector3(pX + gap + barWidth, pY + currHig);
prb = new Vector3(pX + gap + barWidth, pY);
}
top = new Vector3(pX + gap + barWidth / 2, pY + currHig);
}
if (serie.clip)
{
plb = chart.ClampInGrid(grid, plb);
plt = chart.ClampInGrid(grid, plt);
prt = chart.ClampInGrid(grid, prt);
prb = chart.ClampInGrid(grid, prb);
top = chart.ClampInGrid(grid, top);
}
}
private void DrawNormalBar(VertexHelper vh, Serie serie, SerieData serieData, ItemStyle itemStyle, int colorIndex,
bool highlight, float gap, float barWidth, float pX, float pY, Vector3 plb, Vector3 plt, Vector3 prt,
Vector3 prb, bool isYAxis, GridCoord grid, Axis axis, Color32 areaColor, Color32 areaToColor, double value)
{
var borderWidth = itemStyle.runtimeBorderWidth;
var backgroundColor = SerieHelper.GetItemBackgroundColor(serie, serieData, chart.theme, colorIndex, highlight, false);
var cornerRadius = serie.barType == BarType.Capsule && !itemStyle.IsNeedCorner() ?
m_CapusleDefaultCornerRadius :
itemStyle.cornerRadius;
var invert = value < 0;
if (!ChartHelper.IsClearColor(backgroundColor))
{
UGL.DrawRoundRectangle(vh, serieData.context.backgroundRect, backgroundColor, backgroundColor, 0,
cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert);
}
UGL.DrawRoundRectangle(vh, serieData.context.rect, areaColor, areaToColor, 0,
cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert);
if (serie.barType == BarType.Capsule)
{
UGL.DrawBorder(vh, serieData.context.backgroundRect, borderWidth, itemStyle.borderColor,
0, cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert, -borderWidth);
}
else
{
UGL.DrawBorder(vh, serieData.context.rect, borderWidth, itemStyle.borderColor,
0, cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert, itemStyle.borderGap);
}
}
private void DrawZebraBar(VertexHelper vh, Serie serie, SerieData serieData, ItemStyle itemStyle, int colorIndex,
bool highlight, float gap, float barWidth, float pX, float pY, Vector3 plb, Vector3 plt, Vector3 prt,
Vector3 prb, bool isYAxis, GridCoord grid, Axis axis, Color32 barColor, Color32 barToColor)
{
var backgroundColor = SerieHelper.GetItemBackgroundColor(serie, serieData, chart.theme, colorIndex, highlight, false);
if (!ChartHelper.IsClearColor(backgroundColor))
{
UGL.DrawRoundRectangle(vh, serieData.context.backgroundRect, backgroundColor, backgroundColor, 0,
null, isYAxis, chart.settings.cicleSmoothness, false);
}
if (isYAxis)
{
plt = (plb + plt) / 2;
prt = (prt + prb) / 2;
chart.DrawClipZebraLine(vh, plt, prt, barWidth / 2, serie.barZebraWidth, serie.barZebraGap,
barColor, barToColor, serie.clip, grid, grid.context.width);
}
else
{
plb = (prb + plb) / 2;
plt = (plt + prt) / 2;
chart.DrawClipZebraLine(vh, plb, plt, barWidth / 2, serie.barZebraWidth, serie.barZebraGap,
barColor, barToColor, serie.clip, grid, grid.context.height);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5bd8425bf4c1b4bf2adf8940be58ddec
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,41 @@
using System;
using UnityEngine;
namespace XCharts.Runtime
{
[Serializable]
[SerieHandler(typeof(SimplifiedBarHandler), true)]
[SerieConvert(typeof(SimplifiedLine), typeof(Bar))]
[CoordOptions(typeof(GridCoord))]
[DefaultAnimation(AnimationType.LeftToRight)]
[SerieExtraComponent()]
[SerieDataExtraComponent()]
[SerieDataExtraField()]
public class SimplifiedBar : Serie, INeedSerieContainer, ISimplifiedSerie
{
public int containerIndex { get; internal set; }
public int containterInstanceId { get; internal set; }
public static Serie AddDefaultSerie(BaseChart chart, string serieName)
{
var serie = chart.AddSerie<SimplifiedBar>(serieName);
serie.symbol.show = false;
var lastValue = 0d;
for (int i = 0; i < 50; i++)
{
if (i < 20)
lastValue += UnityEngine.Random.Range(0, 5);
else
lastValue += UnityEngine.Random.Range(-3, 5);
chart.AddData(serie.index, lastValue);
}
return serie;
}
public static SimplifiedBar CovertSerie(Serie serie)
{
var newSerie = serie.Clone<SimplifiedBar>();
return newSerie;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7fc754e0afd4d4f138389c19611aaedb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,368 @@
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using XUGL;
namespace XCharts.Runtime
{
[UnityEngine.Scripting.Preserve]
internal sealed class SimplifiedBarHandler : SerieHandler<SimplifiedBar>
{
private GridCoord m_SerieGrid;
public override void Update()
{
base.Update();
UpdateSerieContext();
}
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
string marker, string itemFormatter, string numericFormatter,
ref List<SerieParams> paramList, ref string title)
{
UpdateCoordSerieParams(ref paramList, ref title, dataIndex, showCategory, category,
marker, itemFormatter, numericFormatter);
}
public override void DrawSerie(VertexHelper vh)
{
DrawBarSerie(vh, serie, serie.context.colorIndex);
}
private void UpdateSerieContext()
{
if (m_SerieGrid == null)
return;
var needCheck = (chart.isPointerInChart && m_SerieGrid.IsPointerEnter()) || m_LegendEnter;
var needInteract = false;
if (!needCheck)
{
if (m_LastCheckContextFlag != needCheck)
{
m_LastCheckContextFlag = needCheck;
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
foreach (var serieData in serie.data)
{
var barColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serie.context.colorIndex, false);
var barToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serie.context.colorIndex, false);
serieData.interact.SetColor(ref needInteract, barColor, barToColor);
}
if (needInteract)
{
chart.RefreshPainter(serie);
}
}
return;
}
m_LastCheckContextFlag = needCheck;
if (m_LegendEnter)
{
serie.context.pointerEnter = true;
foreach (var serieData in serie.data)
{
var barColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serie.context.colorIndex, true);
var barToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serie.context.colorIndex, true);
serieData.interact.SetColor(ref needInteract, barColor, barToColor);
}
}
else
{
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
foreach (var serieData in serie.data)
{
if (serieData.context.rect.Contains(chart.pointerPos))
{
serie.context.pointerItemDataIndex = serieData.index;
serie.context.pointerEnter = true;
serieData.context.highlight = true;
var barColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serie.context.colorIndex, true);
var barToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serie.context.colorIndex, true);
serieData.interact.SetColor(ref needInteract, barColor, barToColor);
}
else
{
serieData.context.highlight = false;
var barColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serie.context.colorIndex, false);
var barToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serie.context.colorIndex, false);
serieData.interact.SetColor(ref needInteract, barColor, barToColor);
}
}
}
if (needInteract)
{
chart.RefreshPainter(serie);
}
}
private void DrawBarSerie(VertexHelper vh, SimplifiedBar serie, int colorIndex)
{
if (!serie.show || serie.animation.HasFadeOut())
return;
var isY = ComponentHelper.IsAnyCategoryOfYAxis(chart.components);
Axis axis;
Axis relativedAxis;
if (isY)
{
axis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
relativedAxis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
}
else
{
axis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
relativedAxis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
}
m_SerieGrid = chart.GetChartComponent<GridCoord>(axis.gridIndex);
if (axis == null)
return;
if (relativedAxis == null)
return;
if (m_SerieGrid == null)
return;
var dataZoom = chart.GetDataZoomOfAxis(axis);
var showData = serie.GetDataList(dataZoom);
if (showData.Count <= 0)
return;
var axisLength = isY ? m_SerieGrid.context.height : m_SerieGrid.context.width;
var axisXY = isY ? m_SerieGrid.context.y : m_SerieGrid.context.x;
var barCount = chart.GetSerieBarRealCount<SimplifiedBar>();
float categoryWidth = AxisHelper.GetDataWidth(axis, axisLength, showData.Count, dataZoom);
float barGap = chart.GetSerieBarGap<SimplifiedBar>();
float totalBarWidth = chart.GetSerieTotalWidth<SimplifiedBar>(categoryWidth, barGap, barCount);
float barWidth = serie.GetBarWidth(categoryWidth, barCount);
float offset = (categoryWidth - totalBarWidth) * 0.5f;
float barGapWidth = barWidth + barWidth * barGap;
float gap = serie.barGap == -1 ? offset : offset + serie.index * barGapWidth;
int maxCount = serie.maxShow > 0 ?
(serie.maxShow > showData.Count ? showData.Count : serie.maxShow) :
showData.Count;
bool dataChanging = false;
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
double yMinValue = relativedAxis.context.minValue;
double yMaxValue = relativedAxis.context.maxValue;
var areaColor = ColorUtil.clearColor32;
var areaToColor = ColorUtil.clearColor32;
var interacting = false;
serie.containerIndex = m_SerieGrid.index;
serie.containterInstanceId = m_SerieGrid.instanceId;
serie.animation.InitProgress(axisXY, axisXY + axisLength);
for (int i = serie.minShow; i < maxCount; i++)
{
var serieData = showData[i];
if (!serieData.show || serie.IsIgnoreValue(serieData))
{
serie.context.dataPoints.Add(Vector3.zero);
continue;
}
if (serieData.IsDataChanged())
dataChanging = true;
var highlight = serieData.context.highlight || serie.highlight;
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, highlight);
var value = axis.IsCategory() ? i : serieData.GetData(0, axis.inverse);
var relativedValue = serieData.GetCurrData(1, dataChangeDuration, relativedAxis.inverse, yMinValue, yMaxValue);
var borderWidth = relativedValue == 0 ? 0 : itemStyle.runtimeBorderWidth;
if (!serieData.interact.TryGetColor(ref areaColor, ref areaToColor, ref interacting))
{
areaColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, highlight);
areaToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, colorIndex, highlight);
serieData.interact.SetColor(ref interacting, areaColor, areaToColor);
}
var pX = 0f;
var pY = 0f;
UpdateXYPosition(m_SerieGrid, isY, axis, relativedAxis, i, categoryWidth, barWidth, value, ref pX, ref pY);
var barHig = AxisHelper.GetAxisValueLength(m_SerieGrid, relativedAxis, categoryWidth, relativedValue);
var currHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, barHig);
Vector3 plb, plt, prt, prb, top;
UpdateRectPosition(m_SerieGrid, isY, relativedValue, pX, pY, gap, borderWidth, barWidth, currHig,
out plb, out plt, out prt, out prb, out top);
serieData.context.stackHeight = barHig;
serieData.context.position = top;
serieData.context.rect = Rect.MinMaxRect(plb.x, plb.y, prb.x, prt.y);
serie.context.dataPoints.Add(top);
DrawNormalBar(vh, serie, serieData, itemStyle, colorIndex, highlight, gap, barWidth,
pX, pY, plb, plt, prt, prb, false, m_SerieGrid, areaColor, areaToColor);
if (serie.animation.CheckDetailBreak(top, isY))
{
break;
}
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress();
chart.RefreshPainter(serie);
}
if (dataChanging || interacting)
{
chart.RefreshPainter(serie);
}
}
private void UpdateXYPosition(GridCoord grid, bool isY, Axis axis, Axis relativedAxis, int i, float categoryWidth, float barWidth,
double value, ref float pX, ref float pY)
{
if (isY)
{
if (axis.IsCategory())
{
pY = grid.context.y + i * categoryWidth + (axis.boundaryGap ? 0 : -categoryWidth * 0.5f);
}
else
{
if (axis.context.minMaxRange <= 0) pY = grid.context.y;
else pY = grid.context.y + (float) ((value - axis.context.minValue) / axis.context.minMaxRange) * (grid.context.height - barWidth);
}
pX = AxisHelper.GetAxisValuePosition(grid, relativedAxis, categoryWidth, 0);
}
else
{
if (axis.IsCategory())
{
pX = grid.context.x + i * categoryWidth + (axis.boundaryGap ? 0 : -categoryWidth * 0.5f);
}
else
{
if (axis.context.minMaxRange <= 0) pX = grid.context.x;
else pX = grid.context.x + (float) ((value - axis.context.minValue) / axis.context.minMaxRange) * (grid.context.width - barWidth);
}
pY = AxisHelper.GetAxisValuePosition(grid, relativedAxis, categoryWidth, 0);
}
}
private void UpdateRectPosition(GridCoord grid, bool isY, double yValue, float pX, float pY, float gap, float borderWidth,
float barWidth, float currHig,
out Vector3 plb, out Vector3 plt, out Vector3 prt, out Vector3 prb, out Vector3 top)
{
if (isY)
{
if (yValue < 0)
{
plt = new Vector3(pX - borderWidth, pY + gap + barWidth - borderWidth);
prt = new Vector3(pX + currHig + borderWidth, pY + gap + barWidth - borderWidth);
prb = new Vector3(pX + currHig + borderWidth, pY + gap + borderWidth);
plb = new Vector3(pX - borderWidth, pY + gap + borderWidth);
}
else
{
plt = new Vector3(pX + borderWidth, pY + gap + barWidth - borderWidth);
prt = new Vector3(pX + currHig - borderWidth, pY + gap + barWidth - borderWidth);
prb = new Vector3(pX + currHig - borderWidth, pY + gap + borderWidth);
plb = new Vector3(pX + borderWidth, pY + gap + borderWidth);
}
top = new Vector3(pX + currHig - borderWidth, pY + gap + barWidth / 2);
}
else
{
if (yValue < 0)
{
plb = new Vector3(pX + gap + borderWidth, pY - borderWidth);
plt = new Vector3(pX + gap + borderWidth, pY + currHig + borderWidth);
prt = new Vector3(pX + gap + barWidth - borderWidth, pY + currHig + borderWidth);
prb = new Vector3(pX + gap + barWidth - borderWidth, pY - borderWidth);
}
else
{
plb = new Vector3(pX + gap + borderWidth, pY + borderWidth);
plt = new Vector3(pX + gap + borderWidth, pY + currHig - borderWidth);
prt = new Vector3(pX + gap + barWidth - borderWidth, pY + currHig - borderWidth);
prb = new Vector3(pX + gap + barWidth - borderWidth, pY + borderWidth);
}
top = new Vector3(pX + gap + barWidth / 2, pY + currHig - borderWidth);
}
if (serie.clip)
{
plb = chart.ClampInGrid(grid, plb);
plt = chart.ClampInGrid(grid, plt);
prt = chart.ClampInGrid(grid, prt);
prb = chart.ClampInGrid(grid, prb);
top = chart.ClampInGrid(grid, top);
}
}
private void DrawNormalBar(VertexHelper vh, Serie serie, SerieData serieData, ItemStyle itemStyle, int colorIndex,
bool highlight, float gap, float barWidth, float pX, float pY, Vector3 plb, Vector3 plt, Vector3 prt,
Vector3 prb, bool isYAxis, GridCoord grid, Color32 areaColor, Color32 areaToColor)
{
var borderWidth = itemStyle.runtimeBorderWidth;
if (isYAxis)
{
if (serie.clip)
{
prb = chart.ClampInGrid(grid, prb);
plb = chart.ClampInGrid(grid, plb);
plt = chart.ClampInGrid(grid, plt);
prt = chart.ClampInGrid(grid, prt);
}
var itemWidth = Mathf.Abs(prb.x - plt.x);
var itemHeight = Mathf.Abs(prt.y - plb.y);
var center = new Vector3((plt.x + prb.x) / 2, (prt.y + plb.y) / 2);
if (itemWidth > 0 && itemHeight > 0)
{
var invert = center.x < plb.x;
if (itemStyle.IsNeedCorner())
{
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, areaColor, areaToColor, 0,
itemStyle.cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert);
}
else
{
chart.DrawClipPolygon(vh, plb, plt, prt, prb, areaColor, areaToColor, serie.clip, grid);
}
UGL.DrawBorder(vh, center, itemWidth, itemHeight, borderWidth, itemStyle.borderColor,
itemStyle.borderToColor, 0, itemStyle.cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert);
}
}
else
{
if (serie.clip)
{
prb = chart.ClampInGrid(grid, prb);
plb = chart.ClampInGrid(grid, plb);
plt = chart.ClampInGrid(grid, plt);
prt = chart.ClampInGrid(grid, prt);
}
var itemWidth = Mathf.Abs(prt.x - plb.x);
var itemHeight = Mathf.Abs(plt.y - prb.y);
var center = new Vector3((plb.x + prt.x) / 2, (plt.y + prb.y) / 2);
if (itemWidth > 0 && itemHeight > 0)
{
var invert = center.y < plb.y;
if (itemStyle.IsNeedCorner())
{
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, areaColor, areaToColor, 0,
itemStyle.cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert);
}
else
{
chart.DrawClipPolygon(vh, ref prb, ref plb, ref plt, ref prt, areaColor, areaToColor,
serie.clip, grid);
}
UGL.DrawBorder(vh, center, itemWidth, itemHeight, borderWidth, itemStyle.borderColor,
itemStyle.borderToColor, 0, itemStyle.cornerRadius, isYAxis, chart.settings.cicleSmoothness, invert);
}
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: afd7226ecff7f4b9fad297101bc33b8c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 641a5dafd45e6455ca9ef9558efe1083
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,30 @@
using UnityEngine;
namespace XCharts.Runtime
{
[System.Serializable]
[SerieHandler(typeof(CandlestickHandler), true)]
[DefaultAnimation(AnimationType.LeftToRight)]
[SerieExtraComponent()]
[SerieDataExtraComponent(typeof(ItemStyle), typeof(EmphasisItemStyle))]
[SerieDataExtraField()]
public class Candlestick : Serie, INeedSerieContainer
{
public int containerIndex { get; internal set; }
public int containterInstanceId { get; internal set; }
public static Serie AddDefaultSerie(BaseChart chart, string serieName)
{
var serie = chart.AddSerie<Candlestick>(serieName);
var defaultDataCount = 5;
for (int i = 0; i < defaultDataCount; i++)
{
var open = Random.Range(20, 60);
var close = Random.Range(40, 90);
var lowest = Random.Range(0, 50);
var heighest = Random.Range(50, 100);
chart.AddData(serie.index, open, close, lowest, heighest);
}
return serie;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c1fbb6247f54f4dd2a1f3e7f6bafb8c7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,213 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using XUGL;
namespace XCharts.Runtime
{
[UnityEngine.Scripting.Preserve]
internal sealed class CandlestickHandler : SerieHandler<Candlestick>
{
public override void DrawSerie(VertexHelper vh)
{
DrawCandlestickSerie(vh, serie);
}
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
string marker, string itemFormatter, string numericFormatter,
ref List<SerieParams> paramList, ref string title)
{
if (dataIndex < 0)
dataIndex = serie.context.pointerItemDataIndex;
if (dataIndex < 0)
return;
var serieData = serie.GetSerieData(dataIndex);
if (serieData == null)
return;
title = category;
var color = SerieHelper.GetItemColor(serie, serieData, chart.theme, serie.context.colorIndex, false);
var newMarker = SerieHelper.GetItemMarker(serie, serieData, marker);
var newItemFormatter = SerieHelper.GetItemFormatter(serie, serieData, itemFormatter);
var newNumericFormatter = SerieHelper.GetNumericFormatter(serie, serieData, numericFormatter);
var param = serie.context.param;
param.serieName = serie.serieName;
param.serieIndex = serie.index;
param.category = category;
param.dimension = 1;
param.serieData = serieData;
param.dataCount = serie.dataCount;
param.value = 0;
param.total = 0;
param.color = color;
param.marker = newMarker;
param.itemFormatter = newItemFormatter;
param.numericFormatter = newNumericFormatter;
param.columns.Clear();
param.columns.Add(param.marker);
param.columns.Add(serie.serieName);
param.columns.Add(string.Empty);
paramList.Add(param);
for (int i = 0; i < 4; i++)
{
param = new SerieParams();
param.serieName = serie.serieName;
param.serieIndex = serie.index;
param.dimension = i;
param.serieData = serieData;
param.dataCount = serie.dataCount;
param.value = serieData.GetData(i);
param.total = SerieHelper.GetMaxData(serie, i);
param.color = color;
param.marker = newMarker;
param.itemFormatter = newItemFormatter;
param.numericFormatter = newNumericFormatter;
param.columns.Clear();
param.columns.Add(param.marker);
param.columns.Add(XCSettings.lang.GetCandlestickDimensionName(i));
param.columns.Add(ChartCached.NumberToStr(param.value, param.numericFormatter));
paramList.Add(param);
}
}
private void DrawCandlestickSerie(VertexHelper vh, Candlestick serie)
{
if (!serie.show) return;
if (serie.animation.HasFadeOut()) return;
XAxis xAxis;
YAxis yAxis;
GridCoord grid;
if (!chart.TryGetChartComponent<XAxis>(out xAxis, serie.xAxisIndex)) return;
if (!chart.TryGetChartComponent<YAxis>(out yAxis, serie.yAxisIndex)) return;
if (!chart.TryGetChartComponent<GridCoord>(out grid, xAxis.gridIndex)) return;
var theme = chart.theme;
var dataZoom = chart.GetDataZoomOfAxis(xAxis);
var showData = serie.GetDataList(dataZoom);
float categoryWidth = AxisHelper.GetDataWidth(xAxis, grid.context.width, showData.Count, dataZoom);
float barWidth = serie.GetBarWidth(categoryWidth);
float gap = (categoryWidth - barWidth) / 2;
int maxCount = serie.maxShow > 0 ?
(serie.maxShow > showData.Count ? showData.Count : serie.maxShow) :
showData.Count;
bool dataChanging = false;
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
double yMinValue = yAxis.context.minValue;
double yMaxValue = yAxis.context.maxValue;
var isYAxis = false;
serie.containerIndex = grid.index;
serie.containterInstanceId = grid.instanceId;
for (int i = serie.minShow; i < maxCount; i++)
{
var serieData = showData[i];
if (serie.IsIgnoreValue(serieData))
{
serie.context.dataPoints.Add(Vector3.zero);
continue;
}
var highlight = serie.data[i].context.highlight || serie.highlight;
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, highlight);
var open = serieData.GetCurrData(0, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
var close = serieData.GetCurrData(1, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
var lowest = serieData.GetCurrData(2, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
var heighest = serieData.GetCurrData(3, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
var isRise = yAxis.inverse ? close<open : close> open;
var borderWidth = open == 0 ? 0f :
(itemStyle.runtimeBorderWidth == 0 ? theme.serie.candlestickBorderWidth :
itemStyle.runtimeBorderWidth);
if (serieData.IsDataChanged()) dataChanging = true;
float pX = grid.context.x + i * categoryWidth;
float zeroY = grid.context.y + yAxis.context.offset;
if (!xAxis.boundaryGap) pX -= categoryWidth / 2;
float pY = zeroY;
var barHig = 0f;
double valueTotal = yMaxValue - yMinValue;
var minCut = (yMinValue > 0 ? yMinValue : 0);
if (valueTotal != 0)
{
barHig = (float) ((close - open) / valueTotal * grid.context.height);
pY += (float) ((open - minCut) / valueTotal * grid.context.height);
}
serieData.context.stackHeight = barHig;
float currHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, barHig);
Vector3 plb, plt, prt, prb, top;
plb = new Vector3(pX + gap + borderWidth, pY + borderWidth);
plt = new Vector3(pX + gap + borderWidth, pY + currHig - borderWidth);
prt = new Vector3(pX + gap + barWidth - borderWidth, pY + currHig - borderWidth);
prb = new Vector3(pX + gap + barWidth - borderWidth, pY + borderWidth);
top = new Vector3(pX + gap + barWidth / 2, pY + currHig - borderWidth);
if (serie.clip)
{
plb = chart.ClampInGrid(grid, plb);
plt = chart.ClampInGrid(grid, plt);
prt = chart.ClampInGrid(grid, prt);
prb = chart.ClampInGrid(grid, prb);
top = chart.ClampInGrid(grid, top);
}
serie.context.dataPoints.Add(top);
var areaColor = isRise ?
itemStyle.GetColor(theme.serie.candlestickColor) :
itemStyle.GetColor0(theme.serie.candlestickColor0);
var borderColor = isRise ?
itemStyle.GetBorderColor(theme.serie.candlestickBorderColor) :
itemStyle.GetBorderColor0(theme.serie.candlestickBorderColor0);
var itemWidth = Mathf.Abs(prt.x - plb.x);
var itemHeight = Mathf.Abs(plt.y - prb.y);
var center = new Vector3((plb.x + prt.x) / 2, (plt.y + prb.y) / 2);
var lowPos = new Vector3(center.x, zeroY + (float) ((lowest - minCut) / valueTotal * grid.context.height));
var heighPos = new Vector3(center.x, zeroY + (float) ((heighest - minCut) / valueTotal * grid.context.height));
var openCenterPos = new Vector3(center.x, prb.y);
var closeCenterPos = new Vector3(center.x, prt.y);
if (barWidth > 2f * borderWidth)
{
if (itemWidth > 0 && itemHeight > 0)
{
if (itemStyle.IsNeedCorner())
{
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, areaColor, areaColor, 0,
itemStyle.cornerRadius, isYAxis, 0.5f);
}
else
{
chart.DrawClipPolygon(vh, ref prb, ref plb, ref plt, ref prt, areaColor, areaColor,
serie.clip, grid);
}
UGL.DrawBorder(vh, center, itemWidth, itemHeight, 2 * borderWidth, borderColor, 0,
itemStyle.cornerRadius, isYAxis, 0.5f);
}
}
else
{
UGL.DrawLine(vh, openCenterPos, closeCenterPos, Mathf.Max(borderWidth, barWidth / 2), borderColor);
}
if (isRise)
{
UGL.DrawLine(vh, openCenterPos, lowPos, borderWidth, borderColor);
UGL.DrawLine(vh, closeCenterPos, heighPos, borderWidth, borderColor);
}
else
{
UGL.DrawLine(vh, closeCenterPos, lowPos, borderWidth, borderColor);
UGL.DrawLine(vh, openCenterPos, heighPos, borderWidth, borderColor);
}
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress();
}
if (dataChanging)
{
chart.RefreshPainter(serie);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6d530c536c5784f2593e9a7c5a57df16
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,39 @@
using UnityEngine;
namespace XCharts.Runtime
{
[System.Serializable]
[SerieHandler(typeof(SimplifiedCandlestickHandler), true)]
[DefaultAnimation(AnimationType.LeftToRight)]
[SerieExtraComponent()]
[SerieDataExtraComponent()]
[SerieDataExtraField()]
public class SimplifiedCandlestick : Serie, INeedSerieContainer, ISimplifiedSerie
{
public int containerIndex { get; internal set; }
public int containterInstanceId { get; internal set; }
public static Serie AddDefaultSerie(BaseChart chart, string serieName)
{
var serie = chart.AddSerie<SimplifiedCandlestick>(serieName);
var lastValue = 50d;
for (int i = 0; i < 50; i++)
{
lastValue += UnityEngine.Random.Range(-10, 20);
var open = lastValue + Random.Range(-10, 5);
var close = lastValue + Random.Range(-5, 10);
var lowest = lastValue + Random.Range(-15, -10);
var heighest = lastValue + Random.Range(10, 20);
chart.AddData(serie.index, open, close, lowest, heighest);
}
return serie;
}
public static SimplifiedCandlestick CovertSerie(Serie serie)
{
var newSerie = serie.Clone<SimplifiedCandlestick>();
return newSerie;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1202f0da64c484488bb69b8382af9918
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,214 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using XUGL;
namespace XCharts.Runtime
{
[UnityEngine.Scripting.Preserve]
internal sealed class SimplifiedCandlestickHandler : SerieHandler<SimplifiedCandlestick>
{
public override void DrawSerie(VertexHelper vh)
{
DrawCandlestickSerie(vh, serie);
}
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
string marker, string itemFormatter, string numericFormatter,
ref List<SerieParams> paramList, ref string title)
{
if (dataIndex < 0)
dataIndex = serie.context.pointerItemDataIndex;
if (dataIndex < 0)
return;
var serieData = serie.GetSerieData(dataIndex);
if (serieData == null)
return;
title = category;
var color = SerieHelper.GetItemColor(serie, serieData, chart.theme, serie.context.colorIndex, false);
var newMarker = SerieHelper.GetItemMarker(serie, serieData, marker);
var newItemFormatter = SerieHelper.GetItemFormatter(serie, serieData, itemFormatter);
var newNumericFormatter = SerieHelper.GetNumericFormatter(serie, serieData, numericFormatter);
var param = serie.context.param;
param.serieName = serie.serieName;
param.serieIndex = serie.index;
param.category = category;
param.dimension = 1;
param.serieData = serieData;
param.dataCount = serie.dataCount;
param.value = 0;
param.total = 0;
param.color = color;
param.marker = newMarker;
param.itemFormatter = newItemFormatter;
param.numericFormatter = newNumericFormatter;
param.columns.Clear();
param.columns.Add(param.marker);
param.columns.Add(serie.serieName);
param.columns.Add(string.Empty);
paramList.Add(param);
for (int i = 0; i < 4; i++)
{
param = new SerieParams();
param.serieName = serie.serieName;
param.serieIndex = serie.index;
param.dimension = i;
param.serieData = serieData;
param.dataCount = serie.dataCount;
param.value = serieData.GetData(i);
param.total = SerieHelper.GetMaxData(serie, i);
param.color = color;
param.marker = newMarker;
param.itemFormatter = newItemFormatter;
param.numericFormatter = newNumericFormatter;
param.columns.Clear();
param.columns.Add(param.marker);
param.columns.Add(XCSettings.lang.GetCandlestickDimensionName(i));
param.columns.Add(ChartCached.NumberToStr(param.value, param.numericFormatter));
paramList.Add(param);
}
}
private void DrawCandlestickSerie(VertexHelper vh, SimplifiedCandlestick serie)
{
if (!serie.show) return;
if (serie.animation.HasFadeOut()) return;
XAxis xAxis;
YAxis yAxis;
GridCoord grid;
if (!chart.TryGetChartComponent<XAxis>(out xAxis, serie.xAxisIndex)) return;
if (!chart.TryGetChartComponent<YAxis>(out yAxis, serie.yAxisIndex)) return;
if (!chart.TryGetChartComponent<GridCoord>(out grid, xAxis.gridIndex)) return;
var theme = chart.theme;
var dataZoom = chart.GetDataZoomOfAxis(xAxis);
var showData = serie.GetDataList(dataZoom);
float categoryWidth = AxisHelper.GetDataWidth(xAxis, grid.context.width, showData.Count, dataZoom);
float barWidth = serie.GetBarWidth(categoryWidth);
float gap = (categoryWidth - barWidth) / 2;
int maxCount = serie.maxShow > 0 ?
(serie.maxShow > showData.Count ? showData.Count : serie.maxShow) :
showData.Count;
bool dataChanging = false;
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
double yMinValue = yAxis.context.minValue;
double yMaxValue = yAxis.context.maxValue;
var isYAxis = false;
var itemStyle = serie.itemStyle;
serie.containerIndex = grid.index;
serie.containterInstanceId = grid.instanceId;
for (int i = serie.minShow; i < maxCount; i++)
{
var serieData = showData[i];
if (serie.IsIgnoreValue(serieData))
{
serie.context.dataPoints.Add(Vector3.zero);
continue;
}
var open = serieData.GetCurrData(0, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
var close = serieData.GetCurrData(1, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
var lowest = serieData.GetCurrData(2, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
var heighest = serieData.GetCurrData(3, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
var isRise = yAxis.inverse ? close<open : close> open;
var borderWidth = open == 0 ? 0f :
(itemStyle.runtimeBorderWidth == 0 ? theme.serie.candlestickBorderWidth :
itemStyle.runtimeBorderWidth);
if (serieData.IsDataChanged()) dataChanging = true;
float pX = grid.context.x + i * categoryWidth;
float zeroY = grid.context.y + yAxis.context.offset;
if (!xAxis.boundaryGap) pX -= categoryWidth / 2;
float pY = zeroY;
var barHig = 0f;
double valueTotal = yMaxValue - yMinValue;
var minCut = (yMinValue > 0 ? yMinValue : 0);
if (valueTotal != 0)
{
barHig = (float) ((close - open) / valueTotal * grid.context.height);
pY += (float) ((open - minCut) / valueTotal * grid.context.height);
}
serieData.context.stackHeight = barHig;
float currHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, barHig);
Vector3 plb, plt, prt, prb, top;
plb = new Vector3(pX + gap + borderWidth, pY + borderWidth);
plt = new Vector3(pX + gap + borderWidth, pY + currHig - borderWidth);
prt = new Vector3(pX + gap + barWidth - borderWidth, pY + currHig - borderWidth);
prb = new Vector3(pX + gap + barWidth - borderWidth, pY + borderWidth);
top = new Vector3(pX + gap + barWidth / 2, pY + currHig - borderWidth);
// if (serie.clip)
// {
// plb = chart.ClampInGrid(grid, plb);
// plt = chart.ClampInGrid(grid, plt);
// prt = chart.ClampInGrid(grid, prt);
// prb = chart.ClampInGrid(grid, prb);
// top = chart.ClampInGrid(grid, top);
// }
serie.context.dataPoints.Add(top);
var areaColor = isRise ?
itemStyle.GetColor(theme.serie.candlestickColor) :
itemStyle.GetColor0(theme.serie.candlestickColor0);
var borderColor = isRise ?
itemStyle.GetBorderColor(theme.serie.candlestickBorderColor) :
itemStyle.GetBorderColor0(theme.serie.candlestickBorderColor0);
var itemWidth = Mathf.Abs(prt.x - plb.x);
var itemHeight = Mathf.Abs(plt.y - prb.y);
var center = new Vector3((plb.x + prt.x) / 2, (plt.y + prb.y) / 2);
var lowPos = new Vector3(center.x, zeroY + (float) ((lowest - minCut) / valueTotal * grid.context.height));
var heighPos = new Vector3(center.x, zeroY + (float) ((heighest - minCut) / valueTotal * grid.context.height));
var openCenterPos = new Vector3(center.x, prb.y);
var closeCenterPos = new Vector3(center.x, prt.y);
if (barWidth > 2f * borderWidth)
{
if (itemWidth > 0 && itemHeight > 0)
{
if (itemStyle.IsNeedCorner())
{
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, areaColor, areaColor, 0,
itemStyle.cornerRadius, isYAxis, 0.5f);
}
else
{
chart.DrawClipPolygon(vh, ref prb, ref plb, ref plt, ref prt, areaColor, areaColor,
serie.clip, grid);
}
UGL.DrawBorder(vh, center, itemWidth, itemHeight, 2 * borderWidth, borderColor, 0,
itemStyle.cornerRadius, isYAxis, 0.5f);
}
if (isRise)
{
UGL.DrawLine(vh, openCenterPos, lowPos, borderWidth, borderColor);
UGL.DrawLine(vh, closeCenterPos, heighPos, borderWidth, borderColor);
}
else
{
UGL.DrawLine(vh, closeCenterPos, lowPos, borderWidth, borderColor);
UGL.DrawLine(vh, openCenterPos, heighPos, borderWidth, borderColor);
}
}
else
{
UGL.DrawLine(vh, openCenterPos, closeCenterPos, Mathf.Max(borderWidth, barWidth / 2), borderColor);
}
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress();
}
if (dataChanging)
{
chart.RefreshPainter(serie);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 42727a035319b4eab92ddf0742630115
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 70535a50c140c47cc8cac1820dc03170
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,30 @@
using UnityEngine;
namespace XCharts.Runtime
{
[System.Serializable]
[SerieHandler(typeof(HeatmapHandler), true)]
[DefaultAnimation(AnimationType.LeftToRight)]
[RequireChartComponent(typeof(VisualMap))]
[SerieExtraComponent(typeof(LabelStyle), typeof(EmphasisItemStyle), typeof(EmphasisLabelStyle))]
[SerieDataExtraComponent(typeof(ItemStyle), typeof(LabelStyle), typeof(EmphasisItemStyle), typeof(EmphasisLabelStyle))]
[SerieDataExtraField()]
public class Heatmap : Serie, INeedSerieContainer
{
public int containerIndex { get; internal set; }
public int containterInstanceId { get; internal set; }
public static Serie AddDefaultSerie(BaseChart chart, string serieName)
{
var serie = chart.AddSerie<Heatmap>(serieName);
serie.itemStyle.show = true;
serie.itemStyle.borderWidth = 1;
serie.itemStyle.borderColor = Color.clear;
var emphasis = serie.AddExtraComponent<EmphasisItemStyle>();
emphasis.show = true;
emphasis.borderWidth = 1;
emphasis.borderColor = Color.black;
return serie;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2a9984972d3c74a01945c4064739a826
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,236 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using XUGL;
namespace XCharts.Runtime
{
[UnityEngine.Scripting.Preserve]
internal sealed class HeatmapHandler : SerieHandler<Heatmap>
{
private GridCoord m_SerieGrid;
public override int defaultDimension { get { return 2; } }
public override void Update()
{
base.Update();
UpdateSerieContext();
}
public override void DrawSerie(VertexHelper vh)
{
DrawHeatmapSerie(vh, serie);
}
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
string marker, string itemFormatter, string numericFormatter,
ref List<SerieParams> paramList, ref string title)
{
dataIndex = serie.context.pointerItemDataIndex;
if (dataIndex < 0)
return;
var serieData = serie.GetSerieData(dataIndex);
if (serieData == null)
return;
if (string.IsNullOrEmpty(category))
{
var xAxis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
if (xAxis != null)
category = xAxis.GetData((int) serieData.GetData(0));
}
title = serie.serieName;
var param = serie.context.param;
param.serieName = serie.serieName;
param.serieIndex = serie.index;
param.dimension = defaultDimension;
param.dataCount = serie.dataCount;
param.serieData = serieData;
param.color = serieData.context.color;
param.marker = SerieHelper.GetItemMarker(serie, serieData, marker);
param.itemFormatter = SerieHelper.GetItemFormatter(serie, serieData, itemFormatter);
param.numericFormatter = SerieHelper.GetNumericFormatter(serie, serieData, numericFormatter);
param.columns.Clear();
param.columns.Add(param.marker);
param.columns.Add(category);
param.columns.Add(ChartCached.NumberToStr(serieData.GetData(defaultDimension), param.numericFormatter));
paramList.Add(param);
}
private void UpdateSerieContext()
{
if (m_SerieGrid == null)
return;
var needCheck = (chart.isPointerInChart && m_SerieGrid.IsPointerEnter()) || m_LegendEnter;
var needInteract = false;
if (!needCheck)
{
if (m_LastCheckContextFlag != needCheck)
{
m_LastCheckContextFlag = needCheck;
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
foreach (var serieData in serie.data)
{
serieData.context.highlight = false;
}
chart.RefreshPainter(serie);
}
return;
}
m_LastCheckContextFlag = needCheck;
if (m_LegendEnter)
{
serie.context.pointerEnter = true;
foreach (var serieData in serie.data)
{
serieData.context.highlight = true;
}
}
else
{
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
foreach (var serieData in serie.data)
{
if (!needInteract && serieData.context.rect.Contains(chart.pointerPos))
{
serie.context.pointerItemDataIndex = serieData.index;
serie.context.pointerEnter = true;
serieData.context.highlight = true;
needInteract = true;
}
else
{
serieData.context.highlight = false;
}
}
}
if (needInteract)
{
chart.RefreshPainter(serie);
}
}
private void DrawHeatmapSerie(VertexHelper vh, Heatmap serie)
{
if (serie.animation.HasFadeOut()) return;
XAxis xAxis;
YAxis yAxis;
if (!chart.TryGetChartComponent<XAxis>(out xAxis, serie.xAxisIndex)) return;
if (!chart.TryGetChartComponent<YAxis>(out yAxis, serie.yAxisIndex)) return;
m_SerieGrid = chart.GetChartComponent<GridCoord>(xAxis.gridIndex);
xAxis.boundaryGap = true;
yAxis.boundaryGap = true;
var visualMap = chart.GetVisualMapOfSerie(serie);
var emphasisItemStyle = serie.emphasisItemStyle;
var xCount = xAxis.data.Count;
var yCount = yAxis.data.Count;
var xWidth = m_SerieGrid.context.width / xCount;
var yWidth = m_SerieGrid.context.height / yCount;
var zeroX = m_SerieGrid.context.x;
var zeroY = m_SerieGrid.context.y;
var rangeMin = visualMap.rangeMin;
var rangeMax = visualMap.rangeMax;
var color = chart.theme.GetColor(serie.index);
var borderWidth = serie.itemStyle.show ? serie.itemStyle.borderWidth : 0;
var rectWid = xWidth - 2 * borderWidth;
var rectHig = yWidth - 2 * borderWidth;
var borderColor = serie.itemStyle.opacity > 0 ?
serie.itemStyle.borderColor :
ChartConst.clearColor32;
borderColor.a = (byte) (borderColor.a * serie.itemStyle.opacity);
var borderToColor = serie.itemStyle.opacity > 0 ?
serie.itemStyle.borderToColor :
ChartConst.clearColor32;
borderToColor.a = (byte) (borderToColor.a * serie.itemStyle.opacity);
serie.context.dataPoints.Clear();
serie.animation.InitProgress(0, xCount);
var animationIndex = serie.animation.GetCurrIndex();
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
var dataChanging = false;
serie.containerIndex = m_SerieGrid.index;
serie.containterInstanceId = m_SerieGrid.instanceId;
for (int n = 0; n < serie.dataCount; n++)
{
var serieData = serie.data[n];
serieData.index = n;
var i = (int) serieData.GetData(0);
var j = (int) serieData.GetData(1);
var dimension = VisualMapHelper.GetDimension(visualMap, serieData.data.Count);
if (serie.IsIgnoreValue(serieData, dimension))
{
serie.context.dataPoints.Add(Vector3.zero);
continue;
}
var value = serieData.GetCurrData(dimension, dataChangeDuration, yAxis.inverse,
yAxis.context.minValue, yAxis.context.maxValue);
if (serieData.IsDataChanged()) dataChanging = true;
var pos = new Vector3(zeroX + (i + (xAxis.boundaryGap ? 0.5f : 0)) * xWidth,
zeroY + (j + (yAxis.boundaryGap ? 0.5f : 0)) * yWidth);
serie.context.dataPoints.Add(pos);
serieData.context.position = pos;
serieData.context.canShowLabel = false;
serieData.context.rect = new Rect(pos.x - rectWid / 2, pos.y - rectHig / 2, rectWid, rectHig);
if (value == 0) continue;
if ((value < rangeMin && rangeMin != visualMap.min) ||
(value > rangeMax && rangeMax != visualMap.max))
{
continue;
}
if (!visualMap.IsInSelectedValue(value)) continue;
if (animationIndex >= 0 && i > animationIndex) continue;
color = visualMap.GetColor(value);
if (serieData.context.highlight)
color = ChartHelper.GetHighlightColor(color);
serieData.context.canShowLabel = true;
serieData.context.color = color;
var highlight = (serieData.context.highlight) ||
visualMap.context.pointerIndex > 0;
//UGL.DrawRectangle(vh, pos, rectWid / 2, rectHig / 2, color);
UGL.DrawRectangle(vh, serieData.context.rect, color);
if (borderWidth > 0 && !ChartHelper.IsClearColor(borderColor))
{
UGL.DrawBorder(vh, pos, rectWid, rectHig, borderWidth, borderColor, borderToColor);
}
if (visualMap.hoverLink && highlight && emphasisItemStyle != null &&
emphasisItemStyle.borderWidth > 0)
{
var emphasisBorderWidth = emphasisItemStyle.borderWidth;
var emphasisBorderColor = emphasisItemStyle.opacity > 0 ?
emphasisItemStyle.borderColor : ChartConst.clearColor32;
var emphasisBorderToColor = emphasisItemStyle.opacity > 0 ?
emphasisItemStyle.borderToColor : ChartConst.clearColor32;
UGL.DrawBorder(vh, pos, rectWid, rectHig, emphasisBorderWidth, emphasisBorderColor,
emphasisBorderToColor);
}
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress(xCount);
chart.RefreshPainter(serie);
}
if (dataChanging)
{
chart.RefreshPainter(serie);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3a5cd70274da44d50b48fc04d8b52e21
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 61f1a04d9920849e7861bebdfd070384
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,45 @@
using System;
namespace XCharts.Runtime
{
[Serializable]
[SerieHandler(typeof(LineHandler), true)]
[SerieConvert(typeof(Bar), typeof(Pie))]
[CoordOptions(typeof(GridCoord), typeof(PolarCoord))]
[DefaultAnimation(AnimationType.LeftToRight)]
[SerieExtraComponent(
typeof(LabelStyle),
typeof(EndLabelStyle),
typeof(LineArrow),
typeof(AreaStyle),
typeof(EmphasisItemStyle),
typeof(EmphasisLabelStyle))]
[SerieDataExtraComponent(
typeof(ItemStyle),
typeof(LabelStyle),
typeof(SerieSymbol),
typeof(EmphasisItemStyle),
typeof(EmphasisLabelStyle))]
[SerieDataExtraField("m_Ignore")]
public class Line : Serie, INeedSerieContainer
{
public int containerIndex { get; internal set; }
public int containterInstanceId { get; internal set; }
public static Serie AddDefaultSerie(BaseChart chart, string serieName)
{
var serie = chart.AddSerie<Line>(serieName);
serie.symbol.show = true;
for (int i = 0; i < 5; i++)
{
chart.AddData(serie.index, UnityEngine.Random.Range(10, 90));
}
return serie;
}
public static Line CovertSerie(Serie serie)
{
var newSerie = serie.Clone<Line>();
return newSerie;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 883eff3dc77e0439a80d257577790cbc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,436 @@
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using XUGL;
namespace XCharts.Runtime
{
/// <summary>
/// For grid coord
/// </summary>
internal sealed partial class LineHandler : SerieHandler<Line>
{
List<List<SerieData>> m_StackSerieData = new List<List<SerieData>>();
private GridCoord m_SerieGrid;
public override Vector3 GetSerieDataLabelOffset(SerieData serieData, LabelStyle label)
{
var invert = label.autoOffset &&
SerieHelper.IsDownPoint(serie, serieData.index) &&
(serie.areaStyle == null || !serie.areaStyle.show);
if (invert)
{
var offset = label.GetOffset(serie.context.insideRadius);
return new Vector3(offset.x, -offset.y, offset.z);
}
else
{
return label.GetOffset(serie.context.insideRadius);
}
}
private void UpdateSerieGridContext()
{
if (m_SerieGrid == null)
return;
var lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
var needCheck = (chart.isPointerInChart && m_SerieGrid.IsPointerEnter()) || m_LegendEnter;
if (!needCheck)
{
if (m_LastCheckContextFlag != needCheck)
{
m_LastCheckContextFlag = needCheck;
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
serie.highlight = false;
serie.ResetInteract();
foreach (var serieData in serie.data)
serieData.context.highlight = false;
if (SeriesHelper.IsStack(chart.series))
chart.RefreshTopPainter();
else
chart.RefreshPainter(serie);
}
return;
}
m_LastCheckContextFlag = needCheck;
var themeSymbolSize = chart.theme.serie.lineSymbolSize;
var themeSymbolSelectedSize = chart.theme.serie.lineSymbolSelectedSize;
var needInteract = false;
if (m_LegendEnter)
{
serie.interact.SetValue(ref needInteract, lineWidth, true, chart.theme.serie.selectedRate);
for (int i = 0; i < serie.dataCount; i++)
{
var serieData = serie.data[i];
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
var symbolSelectedSize = symbol.GetSelectedSize(serieData.data, themeSymbolSelectedSize);
serieData.context.highlight = true;
serieData.interact.SetValue(ref needInteract, symbolSelectedSize);
}
}
else if (serie.context.isTriggerByAxis)
{
serie.context.pointerEnter = true;
serie.interact.SetValue(ref needInteract, lineWidth, true, chart.theme.serie.selectedRate);
for (int i = 0; i < serie.dataCount; i++)
{
var serieData = serie.data[i];
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
var symbolSize = symbol.GetSize(serieData.data, themeSymbolSize);
var symbolSelectedSize = symbol.GetSelectedSize(serieData.data, themeSymbolSelectedSize);
if (i == serie.context.pointerItemDataIndex)
{
serieData.context.highlight = true;
serieData.interact.SetValue(ref needInteract, symbolSelectedSize);
}
else
{
serieData.context.highlight = false;
serieData.interact.SetValue(ref needInteract, symbolSize);
}
}
}
else
{
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
for (int i = 0; i < serie.dataCount; i++)
{
var serieData = serie.data[i];
serieData.index = i;
var dist = Vector3.Distance(chart.pointerPos, serieData.context.position);
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
var symbolSize = symbol.GetSize(serieData.data, themeSymbolSize);
var symbolSelectedSize = symbol.GetSelectedSize(serieData.data, themeSymbolSelectedSize);
if (dist <= symbolSelectedSize)
{
serie.context.pointerItemDataIndex = serieData.index;
serie.context.pointerEnter = true;
serie.interact.SetValue(ref needInteract, lineWidth, true);
serieData.context.highlight = true;
serieData.interact.SetValue(ref needInteract, symbolSelectedSize);
}
else
{
serieData.context.highlight = false;
serieData.interact.SetValue(ref needInteract, symbolSize);
}
}
}
if (needInteract)
{
if (SeriesHelper.IsStack(chart.series))
chart.RefreshTopPainter();
else
chart.RefreshPainter(serie);
}
}
private void DrawLinePoint(VertexHelper vh, Serie serie)
{
if (!serie.show || serie.IsPerformanceMode())
return;
if (m_SerieGrid == null)
return;
var count = serie.context.dataPoints.Count;
var clip = SeriesHelper.IsAnyClipSerie(chart.series);
var theme = chart.theme;
var interacting = false;
var lineArrow = serie.lineArrow;
var visualMap = chart.GetVisualMapOfSerie(serie);
var isVisualMapGradient = VisualMapHelper.IsNeedLineGradient(visualMap);
var isY = ComponentHelper.IsAnyCategoryOfYAxis(chart.components);
Axis axis;
Axis relativedAxis;
if (isY)
{
axis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
relativedAxis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
}
else
{
axis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
relativedAxis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
}
for (int i = 0; i < count; i++)
{
var serieData = serie.GetSerieData(i);
if (serieData == null)
continue;
if (serieData.context.isClip)
continue;
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
if (!symbol.show || !symbol.ShowSymbol(i, count))
continue;
var pos = serie.context.dataPoints[i];
if (lineArrow != null && lineArrow.show)
{
if (lineArrow.position == LineArrow.Position.Start && i == 0)
continue;
if (lineArrow.position == LineArrow.Position.End && i == count - 1)
continue;
}
if (ChartHelper.IsIngore(pos))
continue;
var highlight = serie.data[i].context.highlight || serie.highlight;
var symbolSize = highlight ?
theme.serie.lineSymbolSelectedSize :
theme.serie.lineSymbolSize;
if (!serieData.interact.TryGetValue(ref symbolSize, ref interacting))
{
symbolSize = highlight ?
symbol.GetSelectedSize(serieData.data, symbolSize) :
symbol.GetSize(serieData.data, symbolSize);
serieData.interact.SetValue(ref interacting, symbolSize);
symbolSize = serie.animation.GetSysmbolSize(symbolSize);
}
var symbolColor = SerieHelper.GetItemColor(serie, serieData, theme, serie.index, highlight);
var symbolToColor = SerieHelper.GetItemToColor(serie, serieData, theme, serie.index, highlight);
var symbolEmptyColor = SerieHelper.GetItemBackgroundColor(serie, serieData, theme, serie.index, highlight, false);
if (isVisualMapGradient)
{
symbolColor = VisualMapHelper.GetLineGradientColor(visualMap, pos, m_SerieGrid, axis, relativedAxis, symbolColor);
symbolToColor = symbolColor;
}
var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, theme, highlight);
var borderColor = SerieHelper.GetSymbolBorderColor(serie, serieData, theme, highlight);
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, highlight);
chart.DrawClipSymbol(vh, symbol.type, symbolSize, symbolBorder, pos,
symbolColor, symbolToColor, symbolEmptyColor, borderColor, symbol.gap, clip, cornerRadius, m_SerieGrid,
i > 0 ? serie.context.dataPoints[i - 1] : m_SerieGrid.context.position);
}
if (interacting)
{
if (SeriesHelper.IsStack(chart.series))
chart.RefreshTopPainter();
else
chart.RefreshPainter(serie);
}
}
private void DrawLineArrow(VertexHelper vh, Serie serie)
{
if (!serie.show || serie.lineArrow == null || !serie.lineArrow.show)
return;
if (serie.context.dataPoints.Count < 2)
return;
var lineColor = SerieHelper.GetLineColor(serie, null, chart.theme, serie.index, false);
var startPos = Vector3.zero;
var arrowPos = Vector3.zero;
var lineArrow = serie.lineArrow.arrow;
var dataPoints = serie.context.drawPoints;
switch (serie.lineArrow.position)
{
case LineArrow.Position.End:
if (dataPoints.Count < 3)
{
startPos = dataPoints[dataPoints.Count - 2].position;
arrowPos = dataPoints[dataPoints.Count - 1].position;
}
else
{
startPos = dataPoints[dataPoints.Count - 3].position;
arrowPos = dataPoints[dataPoints.Count - 2].position;
}
UGL.DrawArrow(vh, startPos, arrowPos, lineArrow.width, lineArrow.height,
lineArrow.offset, lineArrow.dent, lineArrow.GetColor(lineColor));
break;
case LineArrow.Position.Start:
startPos = dataPoints[1].position;
arrowPos = dataPoints[0].position;
UGL.DrawArrow(vh, startPos, arrowPos, lineArrow.width, lineArrow.height,
lineArrow.offset, lineArrow.dent, lineArrow.GetColor(lineColor));
break;
}
}
private void DrawLineSerie(VertexHelper vh, Line serie)
{
if (!serie.show)
return;
if (serie.animation.HasFadeOut())
return;
var isY = ComponentHelper.IsAnyCategoryOfYAxis(chart.components);
Axis axis;
Axis relativedAxis;
if (isY)
{
axis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
relativedAxis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
}
else
{
axis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
relativedAxis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
}
if (axis == null)
return;
if (relativedAxis == null)
return;
m_SerieGrid = chart.GetChartComponent<GridCoord>(axis.gridIndex);
if (m_SerieGrid == null)
return;
if (m_EndLabel != null && !m_SerieGrid.context.endLabelList.Contains(m_EndLabel))
{
m_SerieGrid.context.endLabelList.Add(m_EndLabel);
}
var visualMap = chart.GetVisualMapOfSerie(serie);
var dataZoom = chart.GetDataZoomOfAxis(axis);
var showData = serie.GetDataList(dataZoom);
if (showData.Count <= 0)
return;
var axisLength = isY ? m_SerieGrid.context.height : m_SerieGrid.context.width;
var scaleWid = AxisHelper.GetDataWidth(axis, axisLength, showData.Count, dataZoom);
int maxCount = serie.maxShow > 0 ?
(serie.maxShow > showData.Count ? showData.Count : serie.maxShow) :
showData.Count;
int rate = LineHelper.GetDataAverageRate(serie, m_SerieGrid, maxCount, false);
var totalAverage = serie.sampleAverage > 0 ?
serie.sampleAverage :
DataHelper.DataAverage(ref showData, serie.sampleType, serie.minShow, maxCount, rate);
var dataChanging = false;
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
var interacting = false;
var lineWidth = LineHelper.GetLineWidth(ref interacting, serie, chart.theme.serie.lineWidth);
axis.context.scaleWidth = scaleWid;
serie.containerIndex = m_SerieGrid.index;
serie.containterInstanceId = m_SerieGrid.instanceId;
Serie lastSerie = null;
var isStack = SeriesHelper.IsStack<Line>(chart.series, serie.stack);
if (isStack)
{
lastSerie = SeriesHelper.GetLastStackSerie(chart.series, serie);
SeriesHelper.UpdateStackDataList(chart.series, serie, dataZoom, m_StackSerieData);
}
var lp = Vector3.zero;
for (int i = serie.minShow; i < maxCount; i += rate)
{
var serieData = showData[i];
var isIgnore = serie.IsIgnoreValue(serieData);
if (isIgnore)
{
serieData.context.stackHeight = 0;
serieData.context.position = Vector3.zero;
if (serie.ignoreLineBreak && serie.context.dataIgnores.Count > 0)
{
serie.context.dataIgnores[serie.context.dataIgnores.Count - 1] = true;
}
}
else
{
var np = Vector3.zero;
var xValue = axis.IsCategory() ? i : serieData.GetData(0, axis.inverse);
var relativedValue = DataHelper.SampleValue(ref showData, serie.sampleType, rate, serie.minShow,
maxCount, totalAverage, i, dataChangeDuration, ref dataChanging, relativedAxis);
serieData.context.stackHeight = GetDataPoint(isY, axis, relativedAxis, m_SerieGrid, xValue, relativedValue,
i, scaleWid, isStack, ref np);
serieData.context.isClip = false;
if (serie.clip && !m_SerieGrid.Contains(np))
{
if (m_SerieGrid.BoundaryPoint(lp, np, ref np))
{
serieData.context.isClip = true;
}
}
serie.context.dataIgnores.Add(false);
serieData.context.position = np;
serie.context.dataPoints.Add(np);
lp = np;
}
}
if (dataChanging || interacting)
chart.RefreshPainter(serie);
if (serie.context.dataPoints.Count <= 0)
return;
serie.animation.InitProgress(serie.context.dataPoints, isY);
VisualMapHelper.AutoSetLineMinMax(visualMap, serie, isY, axis, relativedAxis);
LineHelper.UpdateSerieDrawPoints(serie, chart.settings, chart.theme, visualMap, lineWidth, isY);
LineHelper.DrawSerieLineArea(vh, serie, lastSerie, chart.theme, visualMap, isY, axis, relativedAxis, m_SerieGrid);
LineHelper.DrawSerieLine(vh, chart.theme, serie, visualMap, m_SerieGrid, axis, relativedAxis, lineWidth);
serie.context.vertCount = vh.currentVertCount;
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress();
serie.animation.CheckSymbol(serie.symbol.GetSize(null, chart.theme.serie.lineSymbolSize));
chart.RefreshPainter(serie);
}
}
private float GetDataPoint(bool isY, Axis axis, Axis relativedAxis, GridCoord grid, double xValue,
double yValue, int i, float scaleWid, bool isStack, ref Vector3 np)
{
float xPos, yPos;
var gridXY = isY ? grid.context.x : grid.context.y;
var valueHig = 0f;
if (isY)
{
valueHig = AxisHelper.GetAxisValueDistance(grid, relativedAxis, scaleWid, yValue);
valueHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, valueHig);
xPos = gridXY + valueHig;
yPos = AxisHelper.GetAxisValuePosition(grid, axis, scaleWid, xValue);
if (isStack)
{
for (int n = 0; n < m_StackSerieData.Count - 1; n++)
xPos += m_StackSerieData[n][i].context.stackHeight;
}
}
else
{
valueHig = AxisHelper.GetAxisValueDistance(grid, relativedAxis, scaleWid, yValue);
valueHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, valueHig);
yPos = gridXY + valueHig;
xPos = AxisHelper.GetAxisValuePosition(grid, axis, scaleWid, xValue);
if (isStack)
{
for (int n = 0; n < m_StackSerieData.Count - 1; n++)
yPos += m_StackSerieData[n][i].context.stackHeight;
}
}
np = new Vector3(xPos, yPos);
return valueHig;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 34168c2605d4546c291adeb8e857fd62
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,262 @@
using UnityEngine;
using UnityEngine.UI;
using XUGL;
namespace XCharts.Runtime
{
/// <summary>
/// For polar coord
/// </summary>
internal sealed partial class LineHandler
{
private PolarCoord m_SeriePolar;
private void UpdateSeriePolarContext()
{
if (m_SeriePolar == null)
return;
var needCheck = (chart.isPointerInChart && m_SeriePolar.IsPointerEnter()) || m_LegendEnter;
var lineWidth = 0f;
if (!needCheck)
{
if (m_LastCheckContextFlag != needCheck)
{
var needAnimation1 = false;
lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
m_LastCheckContextFlag = needCheck;
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
serie.interact.SetValue(ref needAnimation1, lineWidth, false);
foreach (var serieData in serie.data)
{
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
var symbolSize = symbol.GetSize(serieData.data, chart.theme.serie.lineSymbolSize);
serieData.context.highlight = false;
serieData.interact.SetValue(ref needAnimation1, symbolSize);
}
if (needAnimation1)
{
if (SeriesHelper.IsStack(chart.series))
chart.RefreshTopPainter();
else
chart.RefreshPainter(serie);
}
}
return;
}
m_LastCheckContextFlag = needCheck;
var themeSymbolSize = chart.theme.serie.lineSymbolSize;
var themeSymbolSelectedSize = chart.theme.serie.lineSymbolSelectedSize;
lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
var needInteract = false;
if (m_LegendEnter)
{
serie.interact.SetValue(ref needInteract, lineWidth, true, chart.theme.serie.selectedRate);
for (int i = 0; i < serie.dataCount; i++)
{
var serieData = serie.data[i];
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
var symbolSelectedSize = symbol.GetSelectedSize(serieData.data, themeSymbolSelectedSize);
serieData.context.highlight = true;
serieData.interact.SetValue(ref needInteract, symbolSelectedSize);
}
}
else
{
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
var dir = chart.pointerPos - new Vector2(m_SeriePolar.context.center.x, m_SeriePolar.context.center.y);
var pointerAngle = ChartHelper.GetAngle360(Vector2.up, dir);
for (int i = 0; i < serie.dataCount; i++)
{
var serieData = serie.data[i];
var angle0 = serieData.context.angle;
var angle1 = i >= serie.dataCount - 1 ? angle0 : serie.data[i + 1].context.angle;
if (pointerAngle >= angle0 && pointerAngle < angle1)
{
serie.context.pointerItemDataIndex = i;
serie.context.pointerEnter = true;
serieData.context.highlight = true;
}
else
{
serieData.context.highlight = false;
}
}
}
if (needInteract)
{
if (SeriesHelper.IsStack(chart.series))
chart.RefreshTopPainter();
else
chart.RefreshPainter(serie);
}
}
private void DrawPolarLine(VertexHelper vh, Serie serie)
{
var datas = serie.data;
if (datas.Count <= 0)
return;
m_SeriePolar = chart.GetChartComponent<PolarCoord>(serie.polarIndex);
if (m_SeriePolar == null)
return;
var m_AngleAxis = ComponentHelper.GetAngleAxis(chart.components, m_SeriePolar.index);
var m_RadiusAxis = ComponentHelper.GetRadiusAxis(chart.components, m_SeriePolar.index);
if (m_AngleAxis == null || m_RadiusAxis == null)
return;
var startAngle = m_AngleAxis.startAngle;
var radius = m_SeriePolar.context.radius;
var min = m_RadiusAxis.context.minValue;
var max = m_RadiusAxis.context.maxValue;
var firstSerieData = datas[0];
var lp = GetPolarPos(m_SeriePolar, m_AngleAxis, firstSerieData, min, max, radius);
var cp = Vector3.zero;
var lineColor = SerieHelper.GetLineColor(serie, null, chart.theme, serie.index, serie.highlight);
var lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
var currDetailProgress = 0f;
var totalDetailProgress = datas.Count;
serie.animation.InitProgress(currDetailProgress, totalDetailProgress);
var ltp = Vector3.zero;
var lbp = Vector3.zero;
var ntp = Vector3.zero;
var nbp = Vector3.zero;
var itp = Vector3.zero;
var ibp = Vector3.zero;
var clp = Vector3.zero;
var crp = Vector3.zero;
bool bitp = true, bibp = true;
for (int i = 1; i < datas.Count; i++)
{
if (serie.animation.CheckDetailBreak(i))
break;
var serieData = datas[i];
cp = GetPolarPos(m_SeriePolar, m_AngleAxis, datas[i], min, max, radius);
var np = i == datas.Count - 1 ? cp :
GetPolarPos(m_SeriePolar, m_AngleAxis, datas[i + 1], min, max, radius);
UGLHelper.GetLinePoints(lp, cp, np, lineWidth,
ref ltp, ref lbp,
ref ntp, ref nbp,
ref itp, ref ibp,
ref clp, ref crp,
ref bitp, ref bibp, i);
if (i == 1)
{
UGL.AddVertToVertexHelper(vh, ltp, lbp, lineColor, false);
}
if (bitp == bibp)
{
if (bitp)
UGL.AddVertToVertexHelper(vh, itp, ibp, lineColor, true);
else
{
UGL.AddVertToVertexHelper(vh, ltp, clp, lineColor, true);
UGL.AddVertToVertexHelper(vh, ltp, crp, lineColor, true);
}
}
else
{
if (bitp)
{
UGL.AddVertToVertexHelper(vh, itp, clp, lineColor, true);
UGL.AddVertToVertexHelper(vh, itp, crp, lineColor, true);
}
else if (bibp)
{
UGL.AddVertToVertexHelper(vh, clp, ibp, lineColor, true);
UGL.AddVertToVertexHelper(vh, crp, ibp, lineColor, true);
}
}
lp = cp;
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress(totalDetailProgress);
serie.animation.CheckSymbol(serie.symbol.GetSize(null, chart.theme.serie.lineSymbolSize));
chart.RefreshChart();
}
}
private void DrawPolarLineSymbol(VertexHelper vh)
{
for (int n = 0; n < chart.series.Count; n++)
{
var serie = chart.series[n];
if (!serie.show)
continue;
if (!(serie is Line))
continue;
var count = serie.dataCount;
for (int i = 0; i < count; i++)
{
var serieData = serie.GetSerieData(i);
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
if (ChartHelper.IsIngore(serieData.context.position))
continue;
bool highlight = serieData.context.highlight || serie.highlight;
if ((!symbol.show || !symbol.ShowSymbol(i, count) || serie.IsPerformanceMode()) &&
!serieData.context.highlight)
continue;
var symbolSize = highlight ?
symbol.GetSelectedSize(serieData.data, chart.theme.serie.lineSymbolSize) :
symbol.GetSize(serieData.data, chart.theme.serie.lineSymbolSize);
var symbolColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, n, highlight);
var symbolToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, n, highlight);
var symbolEmptyColor = SerieHelper.GetItemBackgroundColor(serie, serieData, chart.theme, n, highlight, false);
var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, chart.theme, highlight);
var borderColor = SerieHelper.GetSymbolBorderColor(serie, serieData, chart.theme, highlight);
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, highlight);
symbolSize = serie.animation.GetSysmbolSize(symbolSize);
chart.DrawSymbol(vh, symbol.type, symbolSize, symbolBorder, serieData.context.position,
symbolColor, symbolToColor, symbolEmptyColor, borderColor, symbol.gap, cornerRadius);
}
}
}
private Vector3 GetPolarPos(PolarCoord m_Polar, AngleAxis m_AngleAxis, SerieData serieData, double min,
double max, float polarRadius)
{
var angle = 0f;
if (!m_AngleAxis.clockwise)
{
angle = m_AngleAxis.GetValueAngle((float) serieData.GetData(1));
}
else
{
angle = m_AngleAxis.GetValueAngle((float) serieData.GetData(1));
}
var value = serieData.GetData(0);
var radius = (float) ((value - min) / (max - min) * polarRadius);
angle = (angle + 360) % 360;
serieData.context.angle = angle;
serieData.context.position = ChartHelper.GetPos(m_Polar.context.center, radius, angle, true);
return serieData.context.position;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8655c97b8c7e44e44852f8b81a7372b8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,99 @@
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using XUGL;
namespace XCharts.Runtime
{
/// <summary>
/// For grid coord
/// </summary>
[UnityEngine.Scripting.Preserve]
internal sealed partial class LineHandler : SerieHandler<Line>
{
public override void Update()
{
base.Update();
if (serie.IsUseCoord<GridCoord>())
UpdateSerieGridContext();
else if (serie.IsUseCoord<PolarCoord>())
UpdateSeriePolarContext();
}
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
string marker, string itemFormatter, string numericFormatter,
ref List<SerieParams> paramList, ref string title)
{
UpdateCoordSerieParams(ref paramList, ref title, dataIndex, showCategory, category,
marker, itemFormatter, numericFormatter);
}
public override void DrawSerie(VertexHelper vh)
{
if (serie.IsUseCoord<PolarCoord>())
{
DrawPolarLine(vh, serie);
DrawPolarLineSymbol(vh);
}
else if (serie.IsUseCoord<GridCoord>())
{
DrawLineSerie(vh, serie);
if (!SeriesHelper.IsStack(chart.series))
{
DrawLinePoint(vh, serie);
DrawLineArrow(vh, serie);
}
}
}
public override void DrawTop(VertexHelper vh)
{
if (serie.IsUseCoord<GridCoord>())
{
if (SeriesHelper.IsStack(chart.series))
{
DrawLinePoint(vh, serie);
DrawLineArrow(vh, serie);
}
}
}
public override void RefreshEndLabelInternal()
{
base.RefreshEndLabelInternal();
if (m_SerieGrid == null) return;
if (!serie.animation.IsFinish()) return;
var endLabelList = m_SerieGrid.context.endLabelList;
if (endLabelList.Count <= 1) return;
endLabelList.Sort(delegate(ChartLabel a, ChartLabel b)
{
if (a == null || b == null) return 1;
return b.transform.position.y.CompareTo(a.transform.position.y);
});
var lastY = float.NaN;
for (int i = 0; i < endLabelList.Count; i++)
{
var label = endLabelList[i];
if (label == null) continue;
if (!label.isAnimationEnd) continue;
var labelPosition = label.transform.localPosition;
if (float.IsNaN(lastY))
{
lastY = labelPosition.y;
}
else
{
var labelHeight = label.GetTextHeight();
if (labelPosition.y + labelHeight > lastY)
{
label.SetPosition(new Vector3(labelPosition.x, lastY - labelHeight, labelPosition.z));
}
lastY = label.transform.localPosition.y;
}
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6e3a076ca3ee241c3b8b1088d4519dfa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,551 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using XUGL;
namespace XCharts.Runtime
{
internal static class LineHelper
{
private static List<Vector3> s_CurvesPosList = new List<Vector3>();
public static int GetDataAverageRate(Serie serie, GridCoord grid, int maxCount, bool isYAxis)
{
var sampleDist = serie.sampleDist;
var rate = 0;
var width = isYAxis ? grid.context.height : grid.context.width;
if (sampleDist > 0)
rate = (int) ((maxCount - serie.minShow) / (width / sampleDist));
if (rate < 1)
rate = 1;
return rate;
}
public static void DrawSerieLineArea(VertexHelper vh, Serie serie, Serie lastStackSerie,
ThemeStyle theme, VisualMap visualMap, bool isY, Axis axis, Axis relativedAxis, GridCoord grid)
{
if (serie.areaStyle == null || !serie.areaStyle.show)
return;
var srcAreaColor = SerieHelper.GetAreaColor(serie, null, theme, serie.context.colorIndex, false);
var srcAreaToColor = SerieHelper.GetAreaToColor(serie, null, theme, serie.context.colorIndex, false);
var gridXY = (isY ? grid.context.x : grid.context.y);
if (lastStackSerie == null)
{
DrawSerieLineNormalArea(vh, serie, isY,
gridXY + relativedAxis.context.offset,
gridXY,
gridXY + (isY ? grid.context.width : grid.context.height),
srcAreaColor,
srcAreaToColor,
visualMap,
axis,
relativedAxis,
grid);
}
else
{
DrawSerieLineStackArea(vh, serie, lastStackSerie, isY,
gridXY + relativedAxis.context.offset,
gridXY,
gridXY + (isY ? grid.context.width : grid.context.height),
srcAreaColor,
srcAreaToColor,
visualMap);
}
}
private static void DrawSerieLineNormalArea(VertexHelper vh, Serie serie, bool isY,
float zero, float min, float max, Color32 areaColor, Color32 areaToColor,
VisualMap visualMap, Axis axis, Axis relativedAxis, GridCoord grid)
{
var points = serie.context.drawPoints;
var count = points.Count;
if (count < 2)
return;
var isBreak = false;
var lp = Vector3.zero;
var isVisualMapGradient = VisualMapHelper.IsNeedAreaGradient(visualMap);
var areaLerp = !ChartHelper.IsValueEqualsColor(areaColor, areaToColor);
var zsp = isY ?
new Vector3(zero, points[0].position.y) :
new Vector3(points[0].position.x, zero);
var zep = isY ?
new Vector3(zero, points[count - 1].position.y) :
new Vector3(points[count - 1].position.x, zero);
var lastDataIsIgnore = false;
for (int i = 0; i < points.Count; i++)
{
var tp = points[i].position;
var isIgnore = points[i].isIgnoreBreak;
var color = areaColor;
var toColor = areaToColor;
var lerp = areaLerp;
if (serie.animation.CheckDetailBreak(tp, isY))
{
isBreak = true;
var progress = serie.animation.GetCurrDetail();
var ip = Vector3.zero;
var axisStartPos = isY ? new Vector3(-10000, progress) : new Vector3(progress, -10000);
var axisEndPos = isY ? new Vector3(10000, progress) : new Vector3(progress, 10000);
if (UGLHelper.GetIntersection(lp, tp, axisStartPos, axisEndPos, ref ip))
tp = ip;
}
var zp = isY ? new Vector3(zero, tp.y) : new Vector3(tp.x, zero);
if (isVisualMapGradient)
{
color = VisualMapHelper.GetLineGradientColor(visualMap, zp, grid, axis, relativedAxis, areaColor);
toColor = VisualMapHelper.GetLineGradientColor(visualMap, tp, grid, axis, relativedAxis, areaToColor);
lerp = true;
}
if (i > 0)
{
if ((lp.y - zero > 0 && tp.y - zero < 0) || (lp.y - zero < 0 && tp.y - zero > 0))
{
var ip = Vector3.zero;
if (UGLHelper.GetIntersection(lp, tp, zsp, zep, ref ip))
{
if (lerp)
AddVertToVertexHelperWithLerpColor(vh, ip, ip, color, toColor, isY, min, max, i > 0);
else
{
if (lastDataIsIgnore)
UGL.AddVertToVertexHelper(vh, ip, ip, ColorUtil.clearColor32, true);
UGL.AddVertToVertexHelper(vh, ip, ip, toColor, color, i > 0);
if (isIgnore)
UGL.AddVertToVertexHelper(vh, ip, ip, ColorUtil.clearColor32, true);
}
}
}
}
if (lerp)
AddVertToVertexHelperWithLerpColor(vh, tp, zp, color, toColor, isY, min, max, i > 0);
else
{
if (lastDataIsIgnore)
UGL.AddVertToVertexHelper(vh, tp, zp, ColorUtil.clearColor32, true);
UGL.AddVertToVertexHelper(vh, tp, zp, toColor, color, i > 0);
if (isIgnore)
UGL.AddVertToVertexHelper(vh, tp, zp, ColorUtil.clearColor32, true);
}
lp = tp;
lastDataIsIgnore = isIgnore;
if (isBreak)
break;
}
}
private static void DrawSerieLineStackArea(VertexHelper vh, Serie serie, Serie lastStackSerie, bool isY,
float zero, float min, float max, Color32 color, Color32 toColor, VisualMap visualMap)
{
if (lastStackSerie == null)
return;
var upPoints = serie.context.drawPoints;
var downPoints = lastStackSerie.context.drawPoints;
var upCount = upPoints.Count;
var downCount = downPoints.Count;
if (upCount <= 0 || downCount <= 0)
return;
var lerp = !ChartHelper.IsValueEqualsColor(color, toColor);
var ltp = upPoints[0].position;
var lbp = downPoints[0].position;
if (lerp)
AddVertToVertexHelperWithLerpColor(vh, ltp, lbp, color, toColor, isY, min, max, false);
else
UGL.AddVertToVertexHelper(vh, ltp, lbp, color, false);
int u = 1, d = 1;
var isBreakTop = false;
var isBreakBottom = false;
while ((u < upCount || d < downCount))
{
var tp = u < upCount ? upPoints[u].position : upPoints[upCount - 1].position;
var bp = d < downCount ? downPoints[d].position : downPoints[downCount - 1].position;
var tnp = (u + 1) < upCount ? upPoints[u + 1].position : upPoints[upCount - 1].position;
var bnp = (d + 1) < downCount ? downPoints[d + 1].position : downPoints[downCount - 1].position;
if (serie.animation.CheckDetailBreak(tp, isY))
{
isBreakTop = true;
var progress = serie.animation.GetCurrDetail();
var ip = Vector3.zero;
if (UGLHelper.GetIntersection(ltp, tp,
new Vector3(progress, -10000),
new Vector3(progress, 10000), ref ip))
tp = ip;
else
tp = new Vector3(progress, tp.y);
}
if (serie.animation.CheckDetailBreak(bp, isY))
{
isBreakBottom = true;
var progress = serie.animation.GetCurrDetail();
var ip = Vector3.zero;
if (UGLHelper.GetIntersection(lbp, bp,
new Vector3(progress, -10000),
new Vector3(progress, 10000), ref ip))
bp = ip;
else
bp = new Vector3(progress, bp.y);
}
if (lerp)
AddVertToVertexHelperWithLerpColor(vh, tp, bp, color, toColor, isY, min, max, true);
else
UGL.AddVertToVertexHelper(vh, tp, bp, color, true);
u++;
d++;
if (bp.x < tp.x && bnp.x < tp.x)
u--;
if (tp.x < bp.x && tnp.x < bp.x)
d--;
ltp = tp;
lbp = bp;
if (isBreakTop && isBreakBottom)
break;
}
}
private static void AddVertToVertexHelperWithLerpColor(VertexHelper vh, Vector3 tp, Vector3 bp,
Color32 color, Color32 toColor, bool isY, float min, float max, bool needTriangle)
{
var range = max - min;
var color1 = Color32.Lerp(color, toColor, ((isY ? tp.x : tp.y) - min) / range);
var color2 = Color32.Lerp(color, toColor, ((isY ? bp.x : bp.y) - min) / range);
UGL.AddVertToVertexHelper(vh, tp, bp, color1, color2, needTriangle);
}
internal static void DrawSerieLine(VertexHelper vh, ThemeStyle theme, Serie serie, VisualMap visualMap,
GridCoord grid, Axis axis, Axis relativedAxis, float lineWidth)
{
if (!serie.lineStyle.show || serie.lineStyle.type == LineStyle.Type.None)
return;
var datas = serie.context.drawPoints;
var dataCount = datas.Count;
if (dataCount < 2)
return;
var ltp = Vector3.zero;
var lbp = Vector3.zero;
var ntp = Vector3.zero;
var nbp = Vector3.zero;
var itp = Vector3.zero;
var ibp = Vector3.zero;
var clp = Vector3.zero;
var crp = Vector3.zero;
var isBreak = false;
var isY = axis is YAxis;
var isVisualMapGradient = VisualMapHelper.IsNeedLineGradient(visualMap);
var isLineStyleGradient = serie.lineStyle.IsNeedGradient();
//var highlight = serie.highlight || serie.context.pointerEnter;
var lineColor = SerieHelper.GetLineColor(serie, null, theme, serie.context.colorIndex, false);
var lastDataIsIgnore = datas[0].isIgnoreBreak;
var smooth = serie.lineType == LineType.Smooth;
for (int i = 1; i < dataCount; i++)
{
var cdata = datas[i];
var isIgnore = cdata.isIgnoreBreak;
var cp = cdata.position;
var lp = datas[i - 1].position;
var np = i == dataCount - 1 ? cp : datas[i + 1].position;
if (serie.animation.CheckDetailBreak(cp, isY))
{
isBreak = true;
var ip = Vector3.zero;
var progress = serie.animation.GetCurrDetail();
if (AnimationStyleHelper.GetAnimationPosition(serie.animation, isY, lp, cp, progress, ref ip))
cp = np = ip;
}
serie.context.lineEndPostion = cp;
serie.context.lineEndValue = AxisHelper.GetAxisPositionValue(grid, relativedAxis, cp);
lastDataIsIgnore = isIgnore;
var handled = false;
if (!smooth)
{
switch (serie.lineStyle.type)
{
case LineStyle.Type.Dashed:
UGL.DrawDashLine(vh, lp, cp, lineWidth, lineColor, lineColor, 0, 0);
handled = true;
break;
case LineStyle.Type.Dotted:
UGL.DrawDotLine(vh, lp, cp, lineWidth, lineColor, lineColor, 0, 0);
handled = true;
break;
case LineStyle.Type.DashDot:
UGL.DrawDashDotLine(vh, lp, cp, lineWidth, lineColor, 0, 0, 0);
handled = true;
break;
case LineStyle.Type.DashDotDot:
UGL.DrawDashDotDotLine(vh, lp, cp, lineWidth, lineColor, 0, 0, 0);
handled = true;
break;
case LineStyle.Type.None:
handled = true;
break;
}
}
if (handled)
{
if (isBreak)
break;
else
continue;
}
bool bitp = true, bibp = true;
UGLHelper.GetLinePoints(lp, cp, np, lineWidth,
ref ltp, ref lbp,
ref ntp, ref nbp,
ref itp, ref ibp,
ref clp, ref crp,
ref bitp, ref bibp, i);
if (i == 1)
{
AddLineVertToVertexHelper(vh, ltp, lbp, lineColor, isVisualMapGradient, isLineStyleGradient,
visualMap, serie.lineStyle, grid, axis, relativedAxis, false, lastDataIsIgnore, isIgnore);
if (dataCount == 2 || isBreak)
{
AddLineVertToVertexHelper(vh, clp, crp, lineColor, isVisualMapGradient, isLineStyleGradient,
visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
serie.context.lineEndPostion = cp;
serie.context.lineEndValue = AxisHelper.GetAxisPositionValue(grid, relativedAxis, cp);
break;
}
}
if (bitp == bibp)
{
if (bitp)
AddLineVertToVertexHelper(vh, itp, ibp, lineColor, isVisualMapGradient, isLineStyleGradient,
visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
else
{
AddLineVertToVertexHelper(vh, ltp, clp, lineColor, isVisualMapGradient, isLineStyleGradient,
visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
AddLineVertToVertexHelper(vh, ltp, crp, lineColor, isVisualMapGradient, isLineStyleGradient,
visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
}
}
else
{
if (bitp)
{
AddLineVertToVertexHelper(vh, itp, clp, lineColor, isVisualMapGradient, isLineStyleGradient,
visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
AddLineVertToVertexHelper(vh, itp, crp, lineColor, isVisualMapGradient, isLineStyleGradient,
visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
}
else if (bibp)
{
AddLineVertToVertexHelper(vh, clp, ibp, lineColor, isVisualMapGradient, isLineStyleGradient,
visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
AddLineVertToVertexHelper(vh, crp, ibp, lineColor, isVisualMapGradient, isLineStyleGradient,
visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
}
}
if (isBreak)
break;
}
}
public static float GetLineWidth(ref bool interacting, Serie serie, float defaultWidth)
{
var lineWidth = 0f;
if (!serie.interact.TryGetValue(ref lineWidth, ref interacting))
{
lineWidth = serie.lineStyle.GetWidth(defaultWidth);
serie.interact.SetValue(ref interacting, lineWidth);
}
return lineWidth;
}
private static void AddLineVertToVertexHelper(VertexHelper vh, Vector3 tp, Vector3 bp,
Color32 lineColor, bool visualMapGradient, bool lineStyleGradient, VisualMap visualMap,
LineStyle lineStyle, GridCoord grid, Axis axis, Axis relativedAxis, bool needTriangle,
bool lastIgnore, bool ignore)
{
if (lastIgnore && needTriangle)
UGL.AddVertToVertexHelper(vh, tp, bp, ColorUtil.clearColor32, true);
if (visualMapGradient)
{
var color1 = VisualMapHelper.GetLineGradientColor(visualMap, tp, grid, axis, relativedAxis, lineColor);
var color2 = VisualMapHelper.GetLineGradientColor(visualMap, bp, grid, axis, relativedAxis, lineColor);
UGL.AddVertToVertexHelper(vh, tp, bp, color1, color2, needTriangle);
}
else if (lineStyleGradient)
{
var color1 = VisualMapHelper.GetLineStyleGradientColor(lineStyle, tp, grid, axis, lineColor);
var color2 = VisualMapHelper.GetLineStyleGradientColor(lineStyle, bp, grid, axis, lineColor);
UGL.AddVertToVertexHelper(vh, tp, bp, color1, color2, needTriangle);
}
else
{
UGL.AddVertToVertexHelper(vh, tp, bp, lineColor, needTriangle);
}
if (lastIgnore && !needTriangle)
UGL.AddVertToVertexHelper(vh, tp, bp, ColorUtil.clearColor32, false);
if (ignore && needTriangle)
UGL.AddVertToVertexHelper(vh, tp, bp, ColorUtil.clearColor32, false);
}
internal static void UpdateSerieDrawPoints(Serie serie, Settings setting, ThemeStyle theme, VisualMap visualMap,
float lineWidth, bool isY = false)
{
serie.context.drawPoints.Clear();
var last = Vector3.zero;
switch (serie.lineType)
{
case LineType.Smooth:
UpdateSmoothLineDrawPoints(serie, setting, isY);
break;
case LineType.StepStart:
case LineType.StepMiddle:
case LineType.StepEnd:
UpdateStepLineDrawPoints(serie, setting, theme, isY, lineWidth);
break;
default:
UpdateNormalLineDrawPoints(serie, setting, visualMap);
break;
}
}
private static void UpdateNormalLineDrawPoints(Serie serie, Settings setting, VisualMap visualMap)
{
var isVisualMapGradient = VisualMapHelper.IsNeedGradient(visualMap);
if (isVisualMapGradient)
{
var dataPoints = serie.context.dataPoints;
if (dataPoints.Count > 1)
{
var sp = dataPoints[0];
for (int i = 1; i < dataPoints.Count; i++)
{
var ep = dataPoints[i];
var ignore = serie.context.dataIgnores[i];
var dir = (ep - sp).normalized;
var dist = Vector3.Distance(sp, ep);
var segment = (int) (dist / setting.lineSegmentDistance);
serie.context.drawPoints.Add(new PointInfo(sp, ignore));
for (int j = 1; j < segment; j++)
{
var np = sp + dir * dist * j / segment;
serie.context.drawPoints.Add(new PointInfo(np, ignore));
}
sp = ep;
if (i == dataPoints.Count - 1)
{
serie.context.drawPoints.Add(new PointInfo(ep, ignore));
}
}
}
else
{
serie.context.drawPoints.Add(new PointInfo(dataPoints[0], serie.context.dataIgnores[0]));
}
}
else
{
for (int i = 0; i < serie.context.dataPoints.Count; i++)
{
serie.context.drawPoints.Add(new PointInfo(serie.context.dataPoints[i], serie.context.dataIgnores[i]));
}
}
}
private static void UpdateSmoothLineDrawPoints(Serie serie, Settings setting, bool isY)
{
var points = serie.context.dataPoints;
float smoothness = setting.lineSmoothness;
for (int i = 0; i < points.Count - 1; i++)
{
var sp = points[i];
var ep = points[i + 1];
var lsp = i > 0 ? points[i - 1] : sp;
var nep = i < points.Count - 2 ? points[i + 2] : ep;
var ignore = serie.context.dataIgnores[i];
if (isY)
UGLHelper.GetBezierListVertical(ref s_CurvesPosList, sp, ep, smoothness, setting.lineSmoothStyle);
else
UGLHelper.GetBezierList(ref s_CurvesPosList, sp, ep, lsp, nep, smoothness, setting.lineSmoothStyle);
for (int j = 1; j < s_CurvesPosList.Count; j++)
{
serie.context.drawPoints.Add(new PointInfo(s_CurvesPosList[j], ignore));
}
}
}
private static void UpdateStepLineDrawPoints(Serie serie, Settings setting, ThemeStyle theme, bool isY, float lineWidth)
{
var points = serie.context.dataPoints;
var lp = points[0];
serie.context.drawPoints.Clear();
serie.context.drawPoints.Add(new PointInfo(lp, serie.context.dataIgnores[0]));
for (int i = 1; i < points.Count; i++)
{
var cp = points[i];
var ignore = serie.context.dataIgnores[i];
if ((isY && Mathf.Abs(lp.x - cp.x) <= lineWidth) ||
(!isY && Mathf.Abs(lp.y - cp.y) <= lineWidth))
{
serie.context.drawPoints.Add(new PointInfo(cp, ignore));
lp = cp;
continue;
}
switch (serie.lineType)
{
case LineType.StepStart:
serie.context.drawPoints.Add(new PointInfo(isY ?
new Vector3(cp.x, lp.y) :
new Vector3(lp.x, cp.y), ignore));
break;
case LineType.StepMiddle:
serie.context.drawPoints.Add(new PointInfo(isY ?
new Vector3(lp.x, (lp.y + cp.y) / 2) :
new Vector3((lp.x + cp.x) / 2, lp.y), ignore));
serie.context.drawPoints.Add(new PointInfo(isY ?
new Vector3(cp.x, (lp.y + cp.y) / 2) :
new Vector3((lp.x + cp.x) / 2, cp.y), ignore));
break;
case LineType.StepEnd:
serie.context.drawPoints.Add(new PointInfo(isY ?
new Vector3(lp.x, cp.y) :
new Vector3(cp.x, lp.y), ignore));
break;
}
serie.context.drawPoints.Add(new PointInfo(cp, ignore));
lp = cp;
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7292748fb01ef44709a94d08f4907dd5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,41 @@
using System;
using UnityEngine;
namespace XCharts.Runtime
{
[Serializable]
[SerieHandler(typeof(SimplifiedLineHandler), true)]
[SerieConvert(typeof(SimplifiedBar), typeof(Line))]
[CoordOptions(typeof(GridCoord))]
[DefaultAnimation(AnimationType.LeftToRight)]
[SerieExtraComponent(typeof(AreaStyle))]
[SerieDataExtraComponent()]
[SerieDataExtraField()]
public class SimplifiedLine : Serie, INeedSerieContainer, ISimplifiedSerie
{
public int containerIndex { get; internal set; }
public int containterInstanceId { get; internal set; }
public static Serie AddDefaultSerie(BaseChart chart, string serieName)
{
var serie = chart.AddSerie<SimplifiedLine>(serieName);
serie.symbol.show = false;
var lastValue = 0d;
for (int i = 0; i < 50; i++)
{
if (i < 20)
lastValue += UnityEngine.Random.Range(0, 5);
else
lastValue += UnityEngine.Random.Range(-3, 5);
chart.AddData(serie.index, lastValue);
}
return serie;
}
public static SimplifiedLine CovertSerie(Serie serie)
{
var newSerie = serie.Clone<SimplifiedLine>();
return newSerie;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a5740626e12a84a0ca3a984935f61720
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,280 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace XCharts.Runtime
{
/// <summary>
/// For grid coord
/// </summary>
[UnityEngine.Scripting.Preserve]
internal sealed class SimplifiedLineHandler : SerieHandler<SimplifiedLine>
{
private GridCoord m_SerieGrid;
public override void Update()
{
base.Update();
UpdateSerieContext();
}
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
string marker, string itemFormatter, string numericFormatter,
ref List<SerieParams> paramList, ref string title)
{
UpdateCoordSerieParams(ref paramList, ref title, dataIndex, showCategory, category,
marker, itemFormatter, numericFormatter);
}
public override void DrawSerie(VertexHelper vh)
{
DrawLineSerie(vh, serie);
}
private void UpdateSerieContext()
{
if (m_SerieGrid == null)
return;
var needCheck = (chart.isPointerInChart && m_SerieGrid.IsPointerEnter()) || m_LegendEnter;
var lineWidth = 0f;
if (!needCheck)
{
if (m_LastCheckContextFlag != needCheck)
{
var needAnimation1 = false;
lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
m_LastCheckContextFlag = needCheck;
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
serie.interact.SetValue(ref needAnimation1, lineWidth, false);
foreach (var serieData in serie.data)
{
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
var symbolSize = symbol.GetSize(serieData.data, chart.theme.serie.lineSymbolSize);
serieData.context.highlight = false;
serieData.interact.SetValue(ref needAnimation1, symbolSize);
}
if (needAnimation1)
{
if (SeriesHelper.IsStack(chart.series))
chart.RefreshTopPainter();
else
chart.RefreshPainter(serie);
}
}
return;
}
m_LastCheckContextFlag = needCheck;
var themeSymbolSize = chart.theme.serie.lineSymbolSize;
var themeSymbolSelectedSize = chart.theme.serie.lineSymbolSelectedSize;
lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
var needInteract = false;
if (m_LegendEnter)
{
serie.interact.SetValue(ref needInteract, lineWidth, true, chart.theme.serie.selectedRate);
for (int i = 0; i < serie.dataCount; i++)
{
var serieData = serie.data[i];
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
var symbolSelectedSize = symbol.GetSelectedSize(serieData.data, themeSymbolSelectedSize);
serieData.context.highlight = true;
serieData.interact.SetValue(ref needInteract, symbolSelectedSize);
}
}
else if (serie.context.isTriggerByAxis)
{
serie.context.pointerEnter = true;
serie.interact.SetValue(ref needInteract, lineWidth, true, chart.theme.serie.selectedRate);
for (int i = 0; i < serie.dataCount; i++)
{
var serieData = serie.data[i];
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
var symbolSize = symbol.GetSize(serieData.data, themeSymbolSize);
var symbolSelectedSize = symbol.GetSelectedSize(serieData.data, themeSymbolSelectedSize);
if (i == serie.context.pointerItemDataIndex)
{
serieData.context.highlight = true;
serieData.interact.SetValue(ref needInteract, symbolSelectedSize);
}
else
{
serieData.context.highlight = false;
serieData.interact.SetValue(ref needInteract, symbolSize);
}
}
}
else
{
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
foreach (var serieData in serie.data)
{
var dist = Vector3.Distance(chart.pointerPos, serieData.context.position);
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
var symbolSize = symbol.GetSize(serieData.data, themeSymbolSize);
var symbolSelectedSize = symbol.GetSelectedSize(serieData.data, themeSymbolSelectedSize);
if (dist <= symbolSelectedSize)
{
serie.context.pointerItemDataIndex = serieData.index;
serie.context.pointerEnter = true;
serie.interact.SetValue(ref needInteract, lineWidth, true);
serieData.context.highlight = true;
serieData.interact.SetValue(ref needInteract, symbolSelectedSize);
}
else
{
serieData.context.highlight = false;
serieData.interact.SetValue(ref needInteract, symbolSize);
}
}
}
if (needInteract)
{
if (SeriesHelper.IsStack(chart.series))
chart.RefreshTopPainter();
else
chart.RefreshPainter(serie);
}
}
private void DrawLineSerie(VertexHelper vh, SimplifiedLine serie)
{
if (!serie.show)
return;
if (serie.animation.HasFadeOut())
return;
var isY = ComponentHelper.IsAnyCategoryOfYAxis(chart.components);
Axis axis;
Axis relativedAxis;
if (isY)
{
axis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
relativedAxis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
}
else
{
axis = chart.GetChartComponent<XAxis>(serie.xAxisIndex);
relativedAxis = chart.GetChartComponent<YAxis>(serie.yAxisIndex);
}
m_SerieGrid = chart.GetChartComponent<GridCoord>(axis.gridIndex);
if (axis == null)
return;
if (relativedAxis == null)
return;
if (m_SerieGrid == null)
return;
var dataZoom = chart.GetDataZoomOfAxis(axis);
var showData = serie.GetDataList(dataZoom);
if (showData.Count <= 0)
return;
var axisLength = isY ? m_SerieGrid.context.height : m_SerieGrid.context.width;
var scaleWid = AxisHelper.GetDataWidth(axis, axisLength, showData.Count, dataZoom);
int maxCount = serie.maxShow > 0 ?
(serie.maxShow > showData.Count ? showData.Count : serie.maxShow) :
showData.Count;
int rate = LineHelper.GetDataAverageRate(serie, m_SerieGrid, maxCount, false);
var totalAverage = serie.sampleAverage > 0 ?
serie.sampleAverage :
DataHelper.DataAverage(ref showData, serie.sampleType, serie.minShow, maxCount, rate);
var dataChanging = false;
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
var interacting = false;
var lineWidth = LineHelper.GetLineWidth(ref interacting, serie, chart.theme.serie.lineWidth);
axis.context.scaleWidth = scaleWid;
serie.containerIndex = m_SerieGrid.index;
serie.containterInstanceId = m_SerieGrid.instanceId;
for (int i = serie.minShow; i < maxCount; i += rate)
{
var serieData = showData[i];
var isIgnore = serie.IsIgnoreValue(serieData);
if (isIgnore)
{
serieData.context.stackHeight = 0;
serieData.context.position = Vector3.zero;
if (serie.ignoreLineBreak && serie.context.dataIgnores.Count > 0)
{
serie.context.dataIgnores[serie.context.dataIgnores.Count - 1] = true;
}
}
else
{
var np = Vector3.zero;
var xValue = axis.IsCategory() ? i : serieData.GetData(0, axis.inverse);
var relativedValue = DataHelper.SampleValue(ref showData, serie.sampleType, rate, serie.minShow,
maxCount, totalAverage, i, dataChangeDuration, ref dataChanging, relativedAxis);
serieData.context.stackHeight = GetDataPoint(isY, axis, relativedAxis, m_SerieGrid, xValue, relativedValue,
i, scaleWid, false, ref np);
serieData.context.position = np;
serie.context.dataPoints.Add(np);
serie.context.dataIgnores.Add(false);
}
}
if (dataChanging || interacting)
chart.RefreshPainter(serie);
if (serie.context.dataPoints.Count <= 0)
return;
serie.animation.InitProgress(serie.context.dataPoints, isY);
LineHelper.UpdateSerieDrawPoints(serie, chart.settings, chart.theme, null, lineWidth, isY);
LineHelper.DrawSerieLineArea(vh, serie, null, chart.theme, null, isY, axis, relativedAxis, m_SerieGrid);
LineHelper.DrawSerieLine(vh, chart.theme, serie, null, m_SerieGrid, axis, relativedAxis, lineWidth);
serie.context.vertCount = vh.currentVertCount;
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress();
chart.RefreshPainter(serie);
}
}
private float GetDataPoint(bool isY, Axis axis, Axis relativedAxis, GridCoord grid, double xValue,
double yValue, int i, float scaleWid, bool isStack, ref Vector3 np)
{
float xPos, yPos;
var gridXY = isY ? grid.context.x : grid.context.y;
if (isY)
{
var valueHig = AxisHelper.GetAxisValueDistance(grid, relativedAxis, scaleWid, yValue);
valueHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, valueHig);
xPos = gridXY + valueHig;
yPos = AxisHelper.GetAxisValuePosition(grid, axis, scaleWid, xValue);
}
else
{
var valueHig = AxisHelper.GetAxisValueDistance(grid, relativedAxis, scaleWid, yValue);
valueHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, valueHig);
yPos = gridXY + valueHig;
xPos = AxisHelper.GetAxisValuePosition(grid, axis, scaleWid, xValue);
}
np = new Vector3(xPos, yPos);
return yPos;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3c4714bd08de34548ac7be3ec6523ee1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c2ba7099a74f54617b446aeaf3d95672
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,36 @@
using System.Collections.Generic;
using UnityEngine;
namespace XCharts.Runtime
{
[System.Serializable]
[SerieHandler(typeof(ParallelHandler), true)]
[RequireChartComponent(typeof(ParallelCoord))]
[SerieDataExtraComponent(typeof(ItemStyle), typeof(LabelStyle), typeof(EmphasisItemStyle), typeof(EmphasisLabelStyle))]
[SerieDataExtraField()]
public class Parallel : Serie, INeedSerieContainer
{
public int containerIndex { get; internal set; }
public int containterInstanceId { get; internal set; }
public static Serie AddDefaultSerie(BaseChart chart, string serieName)
{
var serie = chart.AddSerie<Parallel>(serieName);
serie.lineStyle.width = 0.8f;
serie.lineStyle.opacity = 0.6f;
for (int i = 0; i < 100; i++)
{
var data = new List<double>()
{
Random.Range(0f, 50f),
Random.Range(0f, 100f),
Random.Range(0f, 1000f),
Random.Range(0, 5),
};
serie.AddData(data, "data" + i);
}
chart.RefreshChart();
return serie;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 283df79138f274a6ba975ff8f30c6d30
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,150 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using XUGL;
namespace XCharts.Runtime
{
[UnityEngine.Scripting.Preserve]
internal sealed class ParallelHandler : SerieHandler<Parallel>
{
private List<Vector3> m_Points = new List<Vector3>();
public override void Update()
{
base.Update();
UpdateSerieContext();
}
public override void DrawSerie(VertexHelper vh)
{
DrawParallelSerie(vh, serie);
}
private void UpdateSerieContext()
{ }
private void DrawParallelSerie(VertexHelper vh, Parallel serie)
{
if (!serie.show) return;
if (serie.animation.HasFadeOut()) return;
var parallel = chart.GetChartComponent<ParallelCoord>(serie.parallelIndex);
if (parallel == null)
return;
var axisCount = parallel.context.parallelAxes.Count;
if (axisCount <= 0)
return;
var animationIndex = serie.animation.GetCurrIndex();
var isHorizonal = parallel.orient == Orient.Horizonal;
var lineColor = SerieHelper.GetLineColor(serie, null, chart.theme, serie.context.colorIndex, false);
var lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
float currDetailProgress = !isHorizonal ?
parallel.context.x :
parallel.context.y;
float totalDetailProgress = !isHorizonal ?
parallel.context.x + parallel.context.width :
parallel.context.y + parallel.context.height;
serie.animation.InitProgress(currDetailProgress, totalDetailProgress);
serie.context.dataPoints.Clear();
serie.containerIndex = parallel.index;
serie.containterInstanceId = parallel.instanceId;
var currProgress = serie.animation.GetCurrDetail();
var isSmooth = serie.lineType == LineType.Smooth;
foreach (var serieData in serie.data)
{
m_Points.Clear();
var count = Mathf.Min(axisCount, serieData.data.Count);
var lp = Vector3.zero;
for (int i = 0; i < count; i++)
{
if (animationIndex >= 0 && i > animationIndex) continue;
var pos = GetPos(parallel, i, serieData.data[i], isHorizonal);
if (!isHorizonal)
{
if (isSmooth)
{
m_Points.Add(pos);
}
else if (pos.x <= currProgress)
{
m_Points.Add(pos);
}
else
{
var currProgressStart = new Vector3(currProgress, parallel.context.y - 50);
var currProgressEnd = new Vector3(currProgress, parallel.context.y + parallel.context.height + 50);
var intersectionPos = Vector3.zero;
if (UGLHelper.GetIntersection(lp, pos, currProgressStart, currProgressEnd, ref intersectionPos))
m_Points.Add(intersectionPos);
else
m_Points.Add(pos);
break;
}
}
else
{
if (isSmooth)
{
m_Points.Add(pos);
}
else if (pos.y <= currProgress)
{
m_Points.Add(pos);
}
else
{
var currProgressStart = new Vector3(parallel.context.x - 50, currProgress);
var currProgressEnd = new Vector3(parallel.context.x + parallel.context.width + 50, currProgress);
var intersectionPos = Vector3.zero;
if (UGLHelper.GetIntersection(lp, pos, currProgressStart, currProgressEnd, ref intersectionPos))
m_Points.Add(intersectionPos);
else
m_Points.Add(pos);
break;
}
}
lp = pos;
}
if (isSmooth)
UGL.DrawCurves(vh, m_Points, lineWidth, lineColor, chart.settings.lineSmoothness, currProgress, isHorizonal);
else
UGL.DrawLine(vh, m_Points, lineWidth, lineColor, isSmooth);
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress(totalDetailProgress - currDetailProgress);
chart.RefreshPainter(serie);
}
}
private static ParallelAxis GetAxis(ParallelCoord parallel, int index)
{
if (index >= 0 && index < parallel.context.parallelAxes.Count)
return parallel.context.parallelAxes[index];
else
return null;
}
private static Vector3 GetPos(ParallelCoord parallel, int axisIndex, double dataValue, bool isHorizonal)
{
var axis = GetAxis(parallel, axisIndex);
if (axis == null)
return Vector3.zero;
var sValueDist = axis.GetDistance(dataValue, axis.context.width);
return new Vector3(
isHorizonal ? axis.context.x + sValueDist : axis.context.x,
isHorizonal ? axis.context.y : axis.context.y + sValueDist);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 482b461d91f8c4013bf291153d5810e6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a5dfd0cb375a24f659bf56e113aa6fc8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,30 @@
namespace XCharts.Runtime
{
[System.Serializable]
[SerieConvert(typeof(Line), typeof(Bar))]
[SerieHandler(typeof(PieHandler), true)]
[DefaultAnimation(AnimationType.Clockwise)]
[SerieExtraComponent(typeof(LabelStyle), typeof(LabelLine), typeof(TitleStyle), typeof(EmphasisItemStyle), typeof(EmphasisLabelStyle), typeof(EmphasisLabelLine))]
[SerieDataExtraComponent(typeof(ItemStyle), typeof(LabelStyle), typeof(LabelLine), typeof(EmphasisItemStyle), typeof(EmphasisLabelStyle), typeof(EmphasisLabelLine))]
[SerieDataExtraField("m_Ignore", "m_Selected", "m_Radius")]
public class Pie : Serie
{
public override bool useDataNameForColor { get { return true; } }
public override bool titleJustForSerie { get { return true; } }
public static Serie AddDefaultSerie(BaseChart chart, string serieName)
{
var serie = chart.AddSerie<Pie>(serieName);
chart.AddData(serie.index, 70, "pie1");
chart.AddData(serie.index, 20, "pie2");
chart.AddData(serie.index, 10, "pie3");
return serie;
}
public static Pie CovertSerie(Serie serie)
{
var newSerie = SerieHelper.CloneSerie<Pie>(serie);
return newSerie;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 53f0d225949a3450e9e90687759f1714
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,564 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using XUGL;
namespace XCharts.Runtime
{
[UnityEngine.Scripting.Preserve]
internal sealed class PieHandler : SerieHandler<Pie>
{
public override void Update()
{
base.Update();
UpdateSerieContext();
}
public override void DrawSerie(VertexHelper vh)
{
UpdateRuntimeData(serie);
DrawPieLabelLine(vh, serie);
DrawPie(vh, serie);
}
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
string marker, string itemFormatter, string numericFormatter,
ref List<SerieParams> paramList, ref string title)
{
UpdateItemSerieParams(ref paramList, ref title, dataIndex, category,
marker, itemFormatter, numericFormatter);
}
public override Vector3 GetSerieDataLabelPosition(SerieData serieData, LabelStyle label)
{
var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);
return SerieLabelHelper.GetRealLabelPosition(serie, serieData, label, labelLine);
}
public override Vector3 GetSerieDataTitlePosition(SerieData serieData, TitleStyle titleStyle)
{
return serie.context.center;
}
public override void OnLegendButtonClick(int index, string legendName, bool show)
{
if (!serie.IsLegendName(legendName))
return;
LegendHelper.CheckDataShow(serie, legendName, show);
chart.UpdateLegendColor(legendName, show);
chart.RefreshPainter(serie);
}
public override void OnLegendButtonEnter(int index, string legendName)
{
if (!serie.IsLegendName(legendName))
return;
LegendHelper.CheckDataHighlighted(serie, legendName, true);
chart.RefreshPainter(serie);
}
public override void OnLegendButtonExit(int index, string legendName)
{
if (!serie.IsLegendName(legendName))
return;
LegendHelper.CheckDataHighlighted(serie, legendName, false);
chart.RefreshPainter(serie);
}
public override void OnPointerDown(PointerEventData eventData)
{
if (!chart.HasSerie<Pie>()) return;
if (chart.pointerPos == Vector2.zero) return;
var refresh = false;
for (int i = 0; i < chart.series.Count; i++)
{
var serie = chart.GetSerie(i);
if (!(serie is Pie)) continue;
var index = GetPiePosIndex(serie, chart.pointerPos);
if (index >= 0)
{
refresh = true;
for (int j = 0; j < serie.data.Count; j++)
{
if (j == index) serie.data[j].context.selected = !serie.data[j].context.selected;
else serie.data[j].context.selected = false;
}
if (chart.onPointerClickPie != null)
{
chart.onPointerClickPie(eventData, i, index);
}
}
}
if (refresh) chart.RefreshChart();
}
private void UpdateSerieContext()
{
var needCheck = m_LegendEnter || (chart.isPointerInChart && PointerIsInPieSerie(serie, chart.pointerPos));
var needInteract = false;
if (!needCheck)
{
if (m_LastCheckContextFlag != needCheck)
{
m_LastCheckContextFlag = needCheck;
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
foreach (var serieData in serie.data)
{
var colorIndex = chart.GetLegendRealShowNameIndex(serieData.legendName);
var color = SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, false);
var toColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, colorIndex, false);
serieData.context.highlight = false;
serieData.interact.SetValueAndColor(ref needInteract, serieData.context.outsideRadius, color, toColor);
}
if (needInteract)
{
chart.RefreshPainter(serie);
}
}
return;
}
m_LastCheckContextFlag = needCheck;
serie.context.pointerItemDataIndex = -1;
var dataIndex = GetPiePosIndex(serie, chart.pointerPos);
for (int i = 0; i < serie.dataCount; i++)
{
var serieData = serie.data[i];
if (dataIndex == i || (m_LegendEnter && m_LegendEnterIndex == i))
{
serie.context.pointerItemDataIndex = i;
serieData.context.highlight = true;
var colorIndex = chart.GetLegendRealShowNameIndex(serieData.legendName);
var color = SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, true);
var toColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, colorIndex, true);
var value = serieData.context.outsideRadius + chart.theme.serie.pieTooltipExtraRadius;
serieData.interact.SetValueAndColor(ref needInteract, value, color, toColor);
}
else
{
serieData.context.highlight = false;
var colorIndex = chart.GetLegendRealShowNameIndex(serieData.legendName);
var color = SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, false);
var toColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, colorIndex, false);
serieData.interact.SetValueAndColor(ref needInteract, serieData.context.outsideRadius, color, toColor);
}
}
if (needInteract)
{
chart.RefreshPainter(serie);
}
}
private void UpdateRuntimeData(Serie serie)
{
var data = serie.data;
serie.context.dataMax = serie.yMax;
serie.context.startAngle = GetStartAngle(serie);
var runtimePieDataTotal = serie.yTotal;
SerieHelper.UpdateCenter(serie, chart.chartPosition, chart.chartWidth, chart.chartHeight);
float startDegree = serie.context.startAngle;
float totalDegree = 0;
float zeroReplaceValue = 0;
int showdataCount = 0;
foreach (var sd in serie.data)
{
if (sd.show && serie.pieRoseType == RoseType.Area) showdataCount++;
sd.context.canShowLabel = false;
}
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
bool isAllZeroValue = SerieHelper.IsAllZeroValue(serie, 1);
var dataTotalFilterMinAngle = runtimePieDataTotal;
if (isAllZeroValue)
{
totalDegree = 360;
zeroReplaceValue = totalDegree / data.Count;
serie.context.dataMax = zeroReplaceValue;
runtimePieDataTotal = 360;
dataTotalFilterMinAngle = 360;
}
else
{
dataTotalFilterMinAngle = GetTotalAngle(serie, runtimePieDataTotal, ref totalDegree);
}
for (int n = 0; n < data.Count; n++)
{
var serieData = data[n];
serieData.index = n;
var value = isAllZeroValue ? zeroReplaceValue : serieData.GetCurrData(1, dataChangeDuration);
serieData.context.startAngle = startDegree;
serieData.context.toAngle = startDegree;
serieData.context.halfAngle = startDegree;
serieData.context.currentAngle = startDegree;
if (!serieData.show)
{
continue;
}
float degree = serie.pieRoseType == RoseType.Area ?
(totalDegree / showdataCount) :
(float) (totalDegree * value / dataTotalFilterMinAngle);
if (serie.minAngle > 0 && degree < serie.minAngle) degree = serie.minAngle;
serieData.context.toAngle = startDegree + degree;
if (serieData.radius > 0)
serieData.context.outsideRadius = ChartHelper.GetActualValue(serieData.radius, Mathf.Min(chart.chartWidth, chart.chartHeight));
else
serieData.context.outsideRadius = serie.pieRoseType > 0 ?
serie.context.insideRadius + (float) ((serie.context.outsideRadius - serie.context.insideRadius) * value / serie.context.dataMax) :
serie.context.outsideRadius;
if (serieData.context.highlight)
{
serieData.context.outsideRadius += chart.theme.serie.pieTooltipExtraRadius;
}
var offset = 0f;
if (serie.pieClickOffset && serieData.selected)
{
offset += chart.theme.serie.pieSelectedOffset;
}
if (serie.animation.CheckDetailBreak(serieData.context.toAngle))
{
serieData.context.currentAngle = serie.animation.GetCurrDetail();
}
else
{
serieData.context.currentAngle = serieData.context.toAngle;
}
var halfDegree = (serieData.context.toAngle - startDegree) / 2;
serieData.context.halfAngle = startDegree + halfDegree;
serieData.context.offsetCenter = serie.context.center;
serieData.context.insideRadius = serie.context.insideRadius;
if (offset > 0)
{
var currRad = serieData.context.halfAngle * Mathf.Deg2Rad;
var currSin = Mathf.Sin(currRad);
var currCos = Mathf.Cos(currRad);
serieData.context.offsetRadius = 0;
serieData.context.insideRadius -= serieData.context.offsetRadius;
serieData.context.outsideRadius -= serieData.context.offsetRadius;
if (serie.pieClickOffset && serieData.selected)
{
serieData.context.offsetRadius += chart.theme.serie.pieSelectedOffset;
if (serieData.context.insideRadius > 0)
{
serieData.context.insideRadius += chart.theme.serie.pieSelectedOffset;
}
serieData.context.outsideRadius += chart.theme.serie.pieSelectedOffset;
}
serieData.context.offsetCenter = new Vector3(
serie.context.center.x + serieData.context.offsetRadius * currSin,
serie.context.center.y + serieData.context.offsetRadius * currCos);
}
serieData.context.canShowLabel = serieData.context.currentAngle >= serieData.context.halfAngle;
startDegree = serieData.context.toAngle;
SerieLabelHelper.UpdatePieLabelPosition(serie, serieData);
}
SerieLabelHelper.AvoidLabelOverlap(serie, chart.theme.common);
}
private double GetTotalAngle(Serie serie, double dataTotal, ref float totalAngle)
{
totalAngle = serie.context.startAngle + 360f;
if (serie.minAngle > 0)
{
var rate = serie.minAngle / 360;
var minAngleValue = dataTotal * rate;
foreach (var serieData in serie.data)
{
var value = serieData.GetData(1);
if (value < minAngleValue)
{
totalAngle -= serie.minAngle;
dataTotal -= value;
}
}
return dataTotal;
}
else
{
return dataTotal;
}
}
private void DrawPieCenter(VertexHelper vh, Serie serie, ItemStyle itemStyle, float insideRadius)
{
if (!ChartHelper.IsClearColor(itemStyle.centerColor))
{
var radius = insideRadius - itemStyle.centerGap;
UGL.DrawCricle(vh, serie.context.center, radius, itemStyle.centerColor, chart.settings.cicleSmoothness);
}
}
private void DrawPie(VertexHelper vh, Serie serie)
{
if (!serie.show || serie.animation.HasFadeOut())
{
return;
}
var dataChanging = false;
var interacting = false;
var color = ColorUtil.clearColor32;
var toColor = ColorUtil.clearColor32;
var data = serie.data;
serie.animation.InitProgress(0, 360);
for (int n = 0; n < data.Count; n++)
{
var serieData = data[n];
if (!serieData.show)
{
continue;
}
if (serieData.IsDataChanged())
dataChanging = true;
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, serieData.context.highlight);
var colorIndex = chart.GetLegendRealShowNameIndex(serieData.legendName);
var outsideRadius = 0f;
var borderWidth = itemStyle.borderWidth;
var borderColor = itemStyle.borderColor;
var progress = AnimationStyleHelper.CheckDataAnimation(chart, serie, n, 1);
var insideRadius = serieData.context.insideRadius * progress;
//if (!serieData.interact.TryGetValueAndColor(ref outsideRadius, ref color, ref toColor, ref interacting))
{
color = SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, serieData.context.highlight);
toColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, colorIndex, serieData.context.highlight);
outsideRadius = serieData.context.outsideRadius * progress;
serieData.interact.SetValueAndColor(ref interacting, outsideRadius, color, toColor);
}
if (serie.pieClickOffset && serieData.selected)
{
var drawEndDegree = serieData.context.currentAngle;
var needRoundCap = serie.roundCap && insideRadius > 0;
UGL.DrawDoughnut(vh, serieData.context.offsetCenter, insideRadius,
outsideRadius, color, toColor, Color.clear, serieData.context.startAngle,
drawEndDegree, borderWidth, borderColor, serie.gap / 2, chart.settings.cicleSmoothness,
needRoundCap, true);
}
else
{
var drawEndDegree = serieData.context.currentAngle;
var needRoundCap = serie.roundCap && insideRadius > 0;
UGL.DrawDoughnut(vh, serie.context.center, insideRadius,
outsideRadius, color, toColor, Color.clear, serieData.context.startAngle,
drawEndDegree, borderWidth, borderColor, serie.gap / 2, chart.settings.cicleSmoothness,
needRoundCap, true);
DrawPieCenter(vh, serie, itemStyle, insideRadius);
}
if (serie.animation.CheckDetailBreak(serieData.context.toAngle))
break;
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress();
serie.animation.CheckSymbol(serie.symbol.GetSize(null, chart.theme.serie.lineSymbolSize));
chart.RefreshPainter(serie);
}
if (dataChanging)
{
chart.RefreshPainter(serie);
}
}
private bool IsAnyPieClickOffset()
{
foreach (var serie in chart.series)
{
if (serie is Pie && serie.pieClickOffset)
return true;
}
return false;
}
private bool IsAnyPieDataHighlight()
{
foreach (var serie in chart.series)
{
if (serie is Pie)
{
foreach (var serieData in serie.data)
{
if (serieData.context.highlight)
return true;
}
}
}
return false;
}
private void DrawPieLabelLine(VertexHelper vh, Serie serie)
{
foreach (var serieData in serie.data)
{
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
if (SerieLabelHelper.CanShowLabel(serie, serieData, serieLabel, 1))
{
int colorIndex = chart.m_LegendRealShowName.IndexOf(serieData.name);
Color color = chart.theme.GetColor(colorIndex);
DrawPieLabelLine(vh, serie, serieData, color);
}
}
}
private void DrawPieLabelLine(VertexHelper vh, Serie serie, SerieData serieData, Color color)
{
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);
if (serieLabel != null && serieLabel.show &&
labelLine != null && labelLine.show &&
(serieLabel.IsDefaultPosition(LabelStyle.Position.Outside)))
{
var insideRadius = serieData.context.insideRadius;
var outSideRadius = serieData.context.outsideRadius;
var center = serie.context.center;
var currAngle = serieData.context.halfAngle;
if (!ChartHelper.IsClearColor(labelLine.lineColor))
color = labelLine.lineColor;
else if (labelLine.lineType == LabelLine.LineType.HorizontalLine)
color *= color;
float currSin = Mathf.Sin(currAngle * Mathf.Deg2Rad);
float currCos = Mathf.Cos(currAngle * Mathf.Deg2Rad);
var radius1 = labelLine.lineType == LabelLine.LineType.HorizontalLine ?
serie.context.outsideRadius : outSideRadius;
var radius2 = serie.context.outsideRadius + labelLine.lineLength1;
var radius3 = insideRadius + (outSideRadius - insideRadius) / 2;
if (radius1 < serie.context.insideRadius) radius1 = serie.context.insideRadius;
radius1 -= 0.1f;
var pos0 = new Vector3(center.x + radius3 * currSin, center.y + radius3 * currCos);
var pos1 = new Vector3(center.x + radius1 * currSin, center.y + radius1 * currCos);
var pos2 = serieData.context.labelPosition;
if (pos2.x == 0)
{
pos2 = new Vector3(center.x + radius2 * currSin, center.y + radius2 * currCos);
}
Vector3 pos4, pos6;
var horizontalLineCircleRadius = labelLine.lineWidth * 4f;
var lineCircleDiff = horizontalLineCircleRadius - 0.3f;
var startAngle = serie.context.startAngle;
if (currAngle < 90)
{
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos * radius3, 2)) - currSin * radius3;
r4 += labelLine.lineLength1 - lineCircleDiff;
pos6 = pos0 + Vector3.right * lineCircleDiff;
pos4 = pos6 + Vector3.right * r4;
}
else if (currAngle < 180)
{
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos * radius3, 2)) - currSin * radius3;
r4 += labelLine.lineLength1 - lineCircleDiff;
pos6 = pos0 + Vector3.right * lineCircleDiff;
pos4 = pos6 + Vector3.right * r4;
}
else if (currAngle < 270)
{
var currSin1 = Mathf.Sin((360 - currAngle) * Mathf.Deg2Rad);
var currCos1 = Mathf.Cos((360 - currAngle) * Mathf.Deg2Rad);
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos1 * radius3, 2)) - currSin1 * radius3;
r4 += labelLine.lineLength1 - lineCircleDiff;
pos6 = pos0 + Vector3.left * lineCircleDiff;
pos4 = pos6 + Vector3.left * r4;
}
else
{
var currSin1 = Mathf.Sin((360 - currAngle) * Mathf.Deg2Rad);
var currCos1 = Mathf.Cos((360 - currAngle) * Mathf.Deg2Rad);
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos1 * radius3, 2)) - currSin1 * radius3;
r4 += labelLine.lineLength1 - lineCircleDiff;
pos6 = pos0 + Vector3.left * lineCircleDiff;
pos4 = pos6 + Vector3.left * r4;
}
var pos5X = (currAngle - startAngle) % 360 > 180 ?
pos2.x - labelLine.lineLength2 : pos2.x + labelLine.lineLength2;
var pos5 = new Vector3(pos5X, pos2.y);
switch (labelLine.lineType)
{
case LabelLine.LineType.BrokenLine:
UGL.DrawLine(vh, pos1, pos2, pos5, labelLine.lineWidth, color);
break;
case LabelLine.LineType.Curves:
UGL.DrawCurves(vh, pos1, pos5, pos1, pos2, labelLine.lineWidth, color,
chart.settings.lineSmoothness);
break;
case LabelLine.LineType.HorizontalLine:
UGL.DrawCricle(vh, pos0, horizontalLineCircleRadius, color);
UGL.DrawLine(vh, pos6, pos4, labelLine.lineWidth, color);
break;
}
}
}
private int GetPiePosIndex(Serie serie, Vector2 local)
{
if (!(serie is Pie))
return -1;
var dist = Vector2.Distance(local, serie.context.center);
var maxRadius = serie.context.outsideRadius + 3 * chart.theme.serie.pieSelectedOffset;
if (dist < serie.context.insideRadius || dist > maxRadius)
return -1;
var dir = local - new Vector2(serie.context.center.x, serie.context.center.y);
var angle = ChartHelper.GetAngle360(Vector2.up, dir);
for (int i = 0; i < serie.data.Count; i++)
{
var serieData = serie.data[i];
if (angle >= serieData.context.startAngle && angle <= serieData.context.toAngle)
{
var ndist = serieData.selected ?
Vector2.Distance(local, serieData.context.offsetCenter) :
dist;
if (ndist >= serieData.context.insideRadius && ndist <= serieData.context.outsideRadius)
{
return i;
}
}
}
return -1;
}
private bool PointerIsInPieSerie(Serie serie, Vector2 local)
{
if (!(serie is Pie))
return false;
var dist = Vector2.Distance(local, serie.context.center);
if (dist >= serie.context.insideRadius && dist <= serie.context.outsideRadius)
return true;
return false;
}
private float GetStartAngle(Serie serie)
{
return serie.clockwise ? (serie.startAngle + 360) % 360 : 360 - serie.startAngle;
}
private float GetToAngle(Serie serie, float angle)
{
var toAngle = angle + serie.startAngle;
if (!serie.clockwise)
{
toAngle = 360 - angle - serie.startAngle;
}
if (!serie.animation.IsFinish())
{
var currAngle = serie.animation.GetCurrDetail();
if (serie.clockwise)
{
toAngle = toAngle > currAngle ? currAngle : toAngle;
}
else
{
toAngle = toAngle < 360 - currAngle ? 360 - currAngle : toAngle;
}
}
return toAngle;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 13b8c981e5910447fbe769d539b77f96
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 375cebcd4f8c54025ab608f35b1fa8c6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,35 @@
using System.Collections.Generic;
using UnityEngine;
namespace XCharts.Runtime
{
[System.Serializable]
[SerieHandler(typeof(RadarHandler), true)]
[RequireChartComponent(typeof(RadarCoord))]
[SerieExtraComponent(typeof(LabelStyle), typeof(AreaStyle), typeof(EmphasisItemStyle), typeof(EmphasisLabelStyle))]
[SerieDataExtraComponent(typeof(ItemStyle), typeof(LabelStyle), typeof(AreaStyle), typeof(EmphasisItemStyle), typeof(EmphasisLabelStyle))]
[SerieDataExtraField()]
public class Radar : Serie, INeedSerieContainer
{
public int containerIndex { get; internal set; }
public int containterInstanceId { get; internal set; }
public override bool useDataNameForColor { get { return true; } }
public override bool multiDimensionLabel { get { return radarType == RadarType.Multiple; } }
public static Serie AddDefaultSerie(BaseChart chart, string serieName)
{
chart.AddChartComponentWhenNoExist<RadarCoord>();
var serie = chart.AddSerie<Radar>(serieName);
serie.symbol.show = true;
serie.symbol.type = SymbolType.Circle;
serie.showDataName = true;
List<double> data = new List<double>();
for (int i = 0; i < 5; i++)
{
data.Add(Random.Range(20, 90));
}
chart.AddData(serie.index, data, "legendName");
return serie;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0bda9968e18724e389ff1cbde57baeee
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,504 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using XUGL;
namespace XCharts.Runtime
{
[UnityEngine.Scripting.Preserve]
internal sealed class RadarHandler : SerieHandler<Radar>
{
private RadarCoord m_RadarCoord;
public override void Update()
{
base.Update();
UpdateSerieContext();
}
public override void DrawSerie(VertexHelper vh)
{
if (!serie.show) return;
switch (serie.radarType)
{
case RadarType.Multiple:
DrawMutipleRadar(vh);
break;
case RadarType.Single:
DrawSingleRadar(vh);
break;
}
}
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
string marker, string itemFormatter, string numericFormatter,
ref List<SerieParams> paramList, ref string title)
{
if (!serie.context.pointerEnter)
return;
dataIndex = serie.context.pointerItemDataIndex;
if (dataIndex < 0)
return;
if (serie.radarType == RadarType.Single)
{
UpdateItemSerieParams(ref paramList, ref title, dataIndex, category,
marker, itemFormatter, numericFormatter);
return;
}
var radar = chart.GetChartComponent<RadarCoord>(serie.radarIndex);
if (radar == null)
return;
var serieData = serie.GetSerieData(dataIndex);
if (serieData == null)
return;
var color = SerieHelper.GetItemColor(serie, serieData, chart.theme, dataIndex, false);;
title = serieData.name;
for (int i = 0; i < serieData.data.Count; i++)
{
var indicator = radar.GetIndicator(i);
if (indicator == null) continue;
var param = new SerieParams();
param.serieName = serie.serieName;
param.serieIndex = serie.index;
param.dimension = i;
param.serieData = serieData;
param.dataCount = serie.dataCount;
param.value = serieData.GetData(i);
param.total = indicator.max;
param.color = color;
param.marker = SerieHelper.GetItemMarker(serie, serieData, marker);
param.itemFormatter = SerieHelper.GetItemFormatter(serie, serieData, itemFormatter);
param.numericFormatter = SerieHelper.GetNumericFormatter(serie, serieData, numericFormatter);
param.columns.Clear();
param.columns.Add(param.marker);
param.columns.Add(indicator.name);
param.columns.Add(ChartCached.NumberToStr(serieData.GetData(i), param.numericFormatter));
paramList.Add(param);
}
}
private void UpdateSerieContext()
{
var needCheck = m_LegendEnter ||
(chart.isPointerInChart && (m_RadarCoord != null && m_RadarCoord.IsPointerEnter()));
var needInteract = false;
var needHideAll = false;
if (!needCheck)
{
if (m_LastCheckContextFlag == needCheck)
return;
needHideAll = true;
}
m_LastCheckContextFlag = needCheck;
serie.context.pointerEnter = false;
serie.context.pointerItemDataIndex = -1;
var areaStyle = serie.areaStyle;
switch (serie.radarType)
{
case RadarType.Multiple:
for (int i = 0; i < serie.data.Count; i++)
{
var serieData = serie.data[i];
serieData.index = i;
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
var symbolSize = symbol.GetSize(serieData.data, chart.theme.serie.lineSymbolSize);
if (needHideAll || m_LegendEnter)
{
serieData.context.highlight = needHideAll ? false : true;
serieData.interact.SetValue(ref needInteract, symbolSize, serieData.context.highlight);
}
else
{
serieData.context.highlight = false;
foreach (var pos in serieData.context.dataPoints)
{
if (Vector3.Distance(chart.pointerPos, pos) < symbolSize * 2)
{
serie.context.pointerEnter = true;
serie.context.pointerItemDataIndex = i;
serieData.context.highlight = true;
break;
}
}
if (!serieData.context.highlight && areaStyle != null)
{
var center = m_RadarCoord.context.center;
var dataPoints = serieData.context.dataPoints;
for (int n = 0; n < dataPoints.Count; n++)
{
var p1 = dataPoints[n];
var p2 = n >= dataPoints.Count - 1 ? dataPoints[0] : dataPoints[n + 1];
if (UGLHelper.IsPointInTriangle(p1, center, p2, chart.pointerPos))
{
serie.context.pointerEnter = true;
serie.context.pointerItemDataIndex = i;
serieData.context.highlight = true;
break;
}
}
}
serieData.interact.SetValue(ref needInteract, symbolSize, serieData.context.highlight);
}
}
break;
case RadarType.Single:
for (int i = 0; i < serie.data.Count; i++)
{
var serieData = serie.data[i];
serieData.index = i;
if (Vector3.Distance(chart.pointerPos, serieData.context.position) < serie.symbol.size * 2)
{
serie.context.pointerEnter = true;
serie.context.pointerItemDataIndex = i;
return;
}
}
if (!serie.context.pointerEnter && areaStyle != null)
{
var center = m_RadarCoord.context.center;
var dataPoints = serie.data;
for (int n = 0; n < dataPoints.Count; n++)
{
var p1 = dataPoints[n];
var p2 = n >= dataPoints.Count - 1 ? dataPoints[0] : dataPoints[n + 1];
if (UGLHelper.IsPointInTriangle(p1.context.position, center, p2.context.position, chart.pointerPos))
{
serie.context.pointerEnter = true;
serie.context.pointerItemDataIndex = n;
p1.context.highlight = true;
break;
}
}
}
break;
}
if (needInteract)
{
chart.RefreshPainter(serie);
}
}
private void DrawMutipleRadar(VertexHelper vh)
{
if (!serie.show) return;
m_RadarCoord = chart.GetChartComponent<RadarCoord>(serie.radarIndex);
if (m_RadarCoord == null) return;
serie.containerIndex = m_RadarCoord.index;
serie.containterInstanceId = m_RadarCoord.instanceId;
var startPoint = Vector3.zero;
var toPoint = Vector3.zero;
var firstPoint = Vector3.zero;
var indicatorNum = m_RadarCoord.indicatorList.Count;
var angle = 2 * Mathf.PI / indicatorNum;
var centerPos = m_RadarCoord.context.center;
serie.animation.InitProgress(0, 1);
if (!serie.show || serie.animation.HasFadeOut())
{
return;
}
var rate = serie.animation.GetCurrRate();
var dataChanging = false;
var interacting = false;
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
SerieHelper.GetAllMinMaxData(serie, m_RadarCoord.ceilRate);
for (int j = 0; j < serie.data.Count; j++)
{
var serieData = serie.data[j];
string dataName = serieData.name;
if (!serieData.show)
{
continue;
}
var lineStyle = SerieHelper.GetLineStyle(serie, serieData);
var areaStyle = SerieHelper.GetAreaStyle(serie, serieData);
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
var isHighlight = serieData.context.highlight;
var colorIndex = chart.GetLegendRealShowNameIndex(serieData.legendName);
var areaColor = SerieHelper.GetAreaColor(serie, serieData, chart.theme, colorIndex, isHighlight);
var areaToColor = SerieHelper.GetAreaToColor(serie, serieData, chart.theme, colorIndex, isHighlight);
var lineColor = SerieHelper.GetLineColor(serie, serieData, chart.theme, colorIndex, isHighlight);
var lineWidth = lineStyle.GetWidth(chart.theme.serie.lineWidth);
int dataCount = m_RadarCoord.indicatorList.Count;
serieData.context.dataPoints.Clear();
for (int n = 0; n < dataCount; n++)
{
if (n >= serieData.data.Count) break;
var min = m_RadarCoord.GetIndicatorMin(n);
var max = m_RadarCoord.GetIndicatorMax(n);
var value = serieData.GetCurrData(n, dataChangeDuration);
if (serieData.IsDataChanged()) dataChanging = true;
if (max == 0)
{
if (serie.data.Count > 1)
{
SerieHelper.GetMinMaxData(serie, n, out min, out max);
min = ChartHelper.GetMinDivisibleValue(min, 0);
max = ChartHelper.GetMaxDivisibleValue(max, 0);
if (min > 0) min = 0;
}
else
{
max = serie.context.dataMax;
}
}
var radius = (float) (m_RadarCoord.context.dataRadius * (value - min) / (max - min));
var currAngle = (n + (m_RadarCoord.positionType == RadarCoord.PositionType.Between ? 0.5f : 0)) * angle;
radius *= rate;
if (n == 0)
{
startPoint = new Vector3(centerPos.x + radius * Mathf.Sin(currAngle),
centerPos.y + radius * Mathf.Cos(currAngle));
firstPoint = startPoint;
}
else
{
toPoint = new Vector3(centerPos.x + radius * Mathf.Sin(currAngle),
centerPos.y + radius * Mathf.Cos(currAngle));
if (areaStyle != null && areaStyle.show)
{
UGL.DrawTriangle(vh, startPoint, toPoint, centerPos, areaColor, areaColor, areaToColor);
}
if (lineStyle.show)
{
ChartDrawer.DrawLineStyle(vh, lineStyle.type, lineWidth, startPoint, toPoint, lineColor);
}
startPoint = toPoint;
}
serieData.context.dataPoints.Add(startPoint);
}
if (areaStyle != null && areaStyle.show)
{
UGL.DrawTriangle(vh, startPoint, firstPoint, centerPos, areaColor, areaColor, areaToColor);
}
if (lineStyle.show)
{
ChartDrawer.DrawLineStyle(vh, lineStyle.type, lineWidth, startPoint, firstPoint, lineColor);
}
if (symbol.show && symbol.type != SymbolType.None)
{
for (int m = 0; m < serieData.context.dataPoints.Count; m++)
{
var point = serieData.context.dataPoints[m];
var symbolSize = isHighlight ?
symbol.GetSelectedSize(null, chart.theme.serie.lineSymbolSelectedSize) :
symbol.GetSize(null, chart.theme.serie.lineSymbolSize);
if (!serieData.interact.TryGetValue(ref symbolSize, ref interacting))
{
symbolSize = isHighlight ?
symbol.GetSelectedSize(serieData.data, symbolSize) :
symbol.GetSize(serieData.data, symbolSize);
serieData.interact.SetValue(ref interacting, symbolSize);
symbolSize = serie.animation.GetSysmbolSize(symbolSize);
}
var symbolColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, j, isHighlight);
var symbolToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, j, isHighlight);
var symbolEmptyColor = SerieHelper.GetItemBackgroundColor(serie, serieData, chart.theme, j, isHighlight, false);
var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, chart.theme, isHighlight);
var borderColor = SerieHelper.GetSymbolBorderColor(serie, serieData, chart.theme, isHighlight);
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, isHighlight);
chart.DrawSymbol(vh, symbol.type, symbolSize, symbolBorder, point, symbolColor,
symbolToColor, symbolEmptyColor, borderColor, symbol.gap, cornerRadius);
}
}
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress(1);
chart.RefreshPainter(serie);
}
if (dataChanging || interacting)
{
chart.RefreshPainter(serie);
}
}
private void DrawSingleRadar(VertexHelper vh)
{
var radar = chart.GetChartComponent<RadarCoord>(serie.radarIndex);
if (radar == null)
return;
var indicatorNum = radar.indicatorList.Count;
var angle = 2 * Mathf.PI / indicatorNum;
var centerPos = radar.context.center;
serie.animation.InitProgress(0, 1);
serie.context.dataPoints.Clear();
if (!serie.show || serie.animation.HasFadeOut())
{
return;
}
var startPoint = Vector3.zero;
var toPoint = Vector3.zero;
var firstPoint = Vector3.zero;
var lastColor = ColorUtil.clearColor32;
var firstColor = ColorUtil.clearColor32;
var rate = serie.animation.GetCurrRate();
var dataChanging = false;
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
var startIndex = GetStartShowIndex(serie);
var endIndex = GetEndShowIndex(serie);
SerieHelper.UpdateMinMaxData(serie, 1, radar.ceilRate);
for (int j = 0; j < serie.data.Count; j++)
{
var serieData = serie.data[j];
serieData.index = j;
string dataName = serieData.name;
if (!serieData.show)
{
serieData.context.labelPosition = Vector3.zero;
continue;
}
var lineStyle = SerieHelper.GetLineStyle(serie, serieData);
var areaStyle = SerieHelper.GetAreaStyle(serie, serieData);
var isHighlight = serie.context.pointerEnter;
var areaColor = SerieHelper.GetAreaColor(serie, serieData, chart.theme, j, isHighlight);
var areaToColor = SerieHelper.GetAreaToColor(serie, serieData, chart.theme, j, isHighlight);
var lineColor = SerieHelper.GetLineColor(serie, serieData, chart.theme, j, isHighlight);
int dataCount = radar.indicatorList.Count;
var index = serieData.index;
var p = radar.context.center;
var max = radar.GetIndicatorMax(index);
var value = serieData.GetCurrData(1, dataChangeDuration);
if (serieData.IsDataChanged()) dataChanging = true;
if (max == 0)
{
max = serie.context.dataMax;
}
if (!radar.IsInIndicatorRange(j, serieData.GetData(1)))
{
lineColor = radar.outRangeColor;
}
var radius = (float) (max < 0 ? radar.context.dataRadius - radar.context.dataRadius * value / max :
radar.context.dataRadius * value / max);
var currAngle = (index + (radar.positionType == RadarCoord.PositionType.Between ? 0.5f : 0)) * angle;
radius *= rate;
if (index == startIndex)
{
startPoint = new Vector3(p.x + radius * Mathf.Sin(currAngle),
p.y + radius * Mathf.Cos(currAngle));
firstPoint = startPoint;
lastColor = lineColor;
firstColor = lineColor;
}
else
{
toPoint = new Vector3(p.x + radius * Mathf.Sin(currAngle),
p.y + radius * Mathf.Cos(currAngle));
if (areaStyle != null && areaStyle.show)
{
UGL.DrawTriangle(vh, startPoint, toPoint, p, areaColor, areaColor, areaToColor);
}
if (lineStyle.show)
{
if (radar.connectCenter)
ChartDrawer.DrawLineStyle(vh, lineStyle, startPoint, centerPos,
chart.theme.serie.lineWidth, LineStyle.Type.Solid, lastColor, lastColor);
ChartDrawer.DrawLineStyle(vh, lineStyle, startPoint, toPoint, chart.theme.serie.lineWidth,
LineStyle.Type.Solid, radar.lineGradient ? lastColor : lineColor, lineColor);
}
startPoint = toPoint;
lastColor = lineColor;
}
serieData.context.position = startPoint;
serieData.context.labelPosition = startPoint;
if (areaStyle != null && areaStyle.show && j == endIndex)
{
UGL.DrawTriangle(vh, startPoint, firstPoint, centerPos, areaColor, areaColor, areaToColor);
}
if (lineStyle.show && j == endIndex)
{
if (radar.connectCenter)
ChartDrawer.DrawLineStyle(vh, lineStyle, startPoint, centerPos,
chart.theme.serie.lineWidth, LineStyle.Type.Solid, lastColor, lastColor);
ChartDrawer.DrawLineStyle(vh, lineStyle, startPoint, firstPoint, chart.theme.serie.lineWidth,
LineStyle.Type.Solid, lineColor, radar.lineGradient ? firstColor : lineColor);
}
}
if (serie.symbol.show && serie.symbol.type != SymbolType.None)
{
for (int j = 0; j < serie.data.Count; j++)
{
var serieData = serie.data[j];
if (!serieData.show) continue;
var isHighlight = serie.highlight || serieData.context.highlight || serie.context.pointerEnter;
var serieIndex = serieData.index;
var symbolSize = isHighlight ?
serie.symbol.GetSelectedSize(serieData.data, chart.theme.serie.lineSymbolSelectedSize) :
serie.symbol.GetSize(serieData.data, chart.theme.serie.lineSymbolSize);
var symbolColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serieIndex, isHighlight);
var symbolToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serieIndex, isHighlight);
var symbolEmptyColor = SerieHelper.GetItemBackgroundColor(serie, serieData, chart.theme, serieIndex, isHighlight, false);
var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, chart.theme, isHighlight);
var borderColor = SerieHelper.GetSymbolBorderColor(serie, serieData, chart.theme, isHighlight);
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, isHighlight);
if (!radar.IsInIndicatorRange(j, serieData.GetData(1)))
{
symbolColor = radar.outRangeColor;
symbolToColor = radar.outRangeColor;
}
chart.DrawSymbol(vh, serie.symbol.type, symbolSize, symbolBorder, serieData.context.labelPosition, symbolColor,
symbolToColor, symbolEmptyColor, borderColor, serie.symbol.gap, cornerRadius);
}
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress(1);
chart.RefreshPainter(serie);
}
if (dataChanging)
{
chart.RefreshPainter(serie);
}
}
private int GetStartShowIndex(Serie serie)
{
for (int i = 0; i < serie.dataCount; i++)
{
if (serie.data[i].show) return i;
}
return 0;
}
private int GetEndShowIndex(Serie serie)
{
for (int i = serie.dataCount - 1; i >= 0; i--)
{
if (serie.data[i].show) return i;
}
return 0;
}
private void DrawRadarSymbol(VertexHelper vh, Serie serie, SerieData serieData, int serieIndex, bool isHighlight,
List<Vector3> pointList)
{
if (serie.symbol.show && serie.symbol.type != SymbolType.None)
{
var symbolSize = isHighlight ?
serie.symbol.GetSelectedSize(serieData.data, chart.theme.serie.lineSymbolSelectedSize) :
serie.symbol.GetSize(serieData.data, chart.theme.serie.lineSymbolSize);
var symbolColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serieIndex, isHighlight);
var symbolToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serieIndex, isHighlight);
var symbolEmptyColor = SerieHelper.GetItemBackgroundColor(serie, serieData, chart.theme, serieIndex, isHighlight, false);
var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, chart.theme, isHighlight);
var borderColor = SerieHelper.GetSymbolBorderColor(serie, serieData, chart.theme, isHighlight);
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, isHighlight);
foreach (var point in pointList)
{
chart.DrawSymbol(vh, serie.symbol.type, symbolSize, symbolBorder, point, symbolColor,
symbolToColor, symbolEmptyColor, borderColor, serie.symbol.gap, cornerRadius);
}
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c8dd73709db7a4451b2fe6f03476cb7f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c15a1b60f1d3c4daca1fcd88d96ae7e7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,44 @@
using UnityEngine;
namespace XCharts.Runtime
{
[System.Serializable]
[SerieHandler(typeof(RingHandler), true)]
[SerieExtraComponent(typeof(LabelStyle), typeof(TitleStyle), typeof(EmphasisItemStyle), typeof(EmphasisLabelStyle))]
[SerieDataExtraComponent(typeof(ItemStyle), typeof(LabelStyle), typeof(TitleStyle), typeof(EmphasisItemStyle), typeof(EmphasisLabelStyle))]
[SerieDataExtraField()]
public class Ring : Serie
{
public override bool useDataNameForColor { get { return true; } }
public static Serie AddDefaultSerie(BaseChart chart, string serieName)
{
var serie = chart.AddSerie<Ring>(serieName);
serie.roundCap = true;
serie.gap = 10;
serie.radius = new float[] { 0.3f, 0.35f };
var label = serie.AddExtraComponent<LabelStyle>();
label.show = true;
label.position = LabelStyle.Position.Center;
label.formatter = "{d:f0}%";
label.textStyle.autoColor = true;
label.textStyle.fontSize = 28;
var titleStyle = serie.AddExtraComponent<TitleStyle>();
titleStyle.show = false;
titleStyle.offset = new Vector2(0, 30);
var value = Random.Range(30, 90);
var max = 100;
chart.AddData(serie.index, value, max, "data1");
return serie;
}
public override double GetDataTotal(int dimension, SerieData serieData = null)
{
if (serieData == null || serieData.data.Count <= 1)
return base.GetDataTotal(dimension, serieData);
return serieData.GetData(1);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0c7fe8316f26241d8a9f4b3ce94d61bc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,323 @@
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using XUGL;
namespace XCharts.Runtime
{
[UnityEngine.Scripting.Preserve]
internal sealed class RingHandler : SerieHandler<Ring>
{
public override int defaultDimension { get { return 0; } }
public override void Update()
{
base.Update();
UpdateSerieContext();
}
private void UpdateSerieContext()
{
var needCheck = chart.isPointerInChart || m_LegendEnter;
var needInteract = false;
if (!needCheck)
{
if (m_LastCheckContextFlag != needCheck)
{
m_LastCheckContextFlag = needCheck;
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
foreach (var serieData in serie.data)
{
serieData.context.highlight = false;
}
chart.RefreshPainter(serie);
}
return;
}
m_LastCheckContextFlag = needCheck;
if (m_LegendEnter)
{
serie.context.pointerEnter = true;
foreach (var serieData in serie.data)
{
serieData.context.highlight = true;
}
}
else
{
serie.context.pointerEnter = false;
serie.context.pointerItemDataIndex = -1;
var ringIndex = GetRingIndex(chart.pointerPos);
foreach (var serieData in serie.data)
{
if (!needInteract && ringIndex == serieData.index)
{
serie.context.pointerEnter = true;
serie.context.pointerItemDataIndex = ringIndex;
serieData.context.highlight = true;
needInteract = true;
}
else
{
serieData.context.highlight = false;
}
}
}
if (needInteract)
{
chart.RefreshPainter(serie);
}
}
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
string marker, string itemFormatter, string numericFormatter,
ref List<SerieParams> paramList, ref string title)
{
if (dataIndex < 0)
dataIndex = serie.context.pointerItemDataIndex;
if (dataIndex < 0)
return;
var serieData = serie.GetSerieData(dataIndex);
if (serieData == null)
return;
var param = serie.context.param;
param.serieName = serie.serieName;
param.serieIndex = serie.index;
param.category = category;
param.dimension = defaultDimension;
param.serieData = serieData;
param.dataCount = serie.dataCount;
param.value = serieData.GetData(0);
param.total = serieData.GetData(1);
param.color = SerieHelper.GetItemColor(serie, serieData, chart.theme, dataIndex, false);
param.marker = SerieHelper.GetItemMarker(serie, serieData, marker);
param.itemFormatter = SerieHelper.GetItemFormatter(serie, serieData, itemFormatter);
param.numericFormatter = SerieHelper.GetNumericFormatter(serie, serieData, numericFormatter);;
param.columns.Clear();
param.columns.Add(param.marker);
param.columns.Add(serieData.name);
param.columns.Add(ChartCached.NumberToStr(param.value, param.numericFormatter));
paramList.Add(param);
}
public override Vector3 GetSerieDataLabelPosition(SerieData serieData, LabelStyle label)
{
var centerRadius = (serieData.context.outsideRadius + serieData.context.insideRadius) / 2;
var startAngle = serieData.context.startAngle;
var toAngle = serieData.context.toAngle;
switch (label.position)
{
case LabelStyle.Position.Bottom:
case LabelStyle.Position.Start:
var px1 = Mathf.Sin(startAngle * Mathf.Deg2Rad) * centerRadius;
var py1 = Mathf.Cos(startAngle * Mathf.Deg2Rad) * centerRadius;
var xDiff = serie.clockwise ? -label.distance : label.distance;
serieData.context.labelPosition = serie.context.center + new Vector3(px1 + xDiff, py1);
break;
case LabelStyle.Position.Top:
case LabelStyle.Position.End:
startAngle += serie.clockwise ? -label.distance : label.distance;
toAngle += serie.clockwise ? label.distance : -label.distance;
var px2 = Mathf.Sin(toAngle * Mathf.Deg2Rad) * centerRadius;
var py2 = Mathf.Cos(toAngle * Mathf.Deg2Rad) * centerRadius;
serieData.context.labelPosition = serie.context.center + new Vector3(px2, py2);
break;
default: //LabelStyle.Position.Center
serieData.context.labelPosition = serie.context.center + label.offset;
break;
}
return serieData.context.labelPosition;
}
public override void DrawSerie(VertexHelper vh)
{
if (!serie.show || serie.animation.HasFadeOut()) return;
var data = serie.data;
serie.animation.InitProgress(serie.startAngle, serie.startAngle + 360);
SerieHelper.UpdateCenter(serie, chart.chartPosition, chart.chartWidth, chart.chartHeight);
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
var ringWidth = serie.context.outsideRadius - serie.context.insideRadius;
var dataChanging = false;
for (int j = 0; j < data.Count; j++)
{
var serieData = data[j];
serieData.index = j;
if (!serieData.show) continue;
if (serieData.IsDataChanged()) dataChanging = true;
var value = serieData.GetFirstData(dataChangeDuration);
var max = serieData.GetLastData();
var degree = (float) (360 * value / max);
var startDegree = GetStartAngle(serie);
var toDegree = GetToAngle(serie, degree);
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, serieData.context.highlight);
var colorIndex = chart.GetLegendRealShowNameIndex(serieData.legendName);
var itemColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, serieData.context.highlight);
var itemToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, colorIndex, serieData.context.highlight);
var outsideRadius = serie.context.outsideRadius - j * (ringWidth + serie.gap);
var insideRadius = outsideRadius - ringWidth;
var borderWidth = itemStyle.borderWidth;
var borderColor = itemStyle.borderColor;
var roundCap = serie.roundCap && insideRadius > 0;
serieData.context.startAngle = serie.clockwise ? startDegree : toDegree;
serieData.context.toAngle = serie.clockwise ? toDegree : startDegree;
serieData.context.insideRadius = insideRadius;
serieData.context.outsideRadius = serieData.radius > 0 ? serieData.radius : outsideRadius;
DrawBackground(vh, serie, serieData, j, insideRadius, outsideRadius);
UGL.DrawDoughnut(vh, serie.context.center, insideRadius, outsideRadius, itemColor, itemToColor,
Color.clear, startDegree, toDegree, borderWidth, borderColor, 0, chart.settings.cicleSmoothness,
roundCap, serie.clockwise);
DrawCenter(vh, serie, serieData, insideRadius, j == data.Count - 1);
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress(360);
chart.RefreshChart();
}
if (dataChanging)
{
chart.RefreshChart();
}
}
public override void OnLegendButtonClick(int index, string legendName, bool show)
{
if (!serie.IsLegendName(legendName))
return;
LegendHelper.CheckDataShow(serie, legendName, show);
chart.UpdateLegendColor(legendName, show);
chart.RefreshPainter(serie);
}
public override void OnLegendButtonEnter(int index, string legendName)
{
if (!serie.IsLegendName(legendName))
return;
LegendHelper.CheckDataHighlighted(serie, legendName, true);
chart.RefreshPainter(serie);
}
public override void OnLegendButtonExit(int index, string legendName)
{
if (!serie.IsLegendName(legendName))
return;
LegendHelper.CheckDataHighlighted(serie, legendName, false);
chart.RefreshPainter(serie);
}
public override void OnPointerDown(PointerEventData eventData)
{ }
private float GetStartAngle(Serie serie)
{
return serie.clockwise ? serie.startAngle : 360 - serie.startAngle;
}
private float GetToAngle(Serie serie, float angle)
{
var toAngle = angle + serie.startAngle;
if (!serie.clockwise)
{
toAngle = 360 - angle - serie.startAngle;
}
if (!serie.animation.IsFinish())
{
var currAngle = serie.animation.GetCurrDetail();
if (serie.clockwise)
{
toAngle = toAngle > currAngle ? currAngle : toAngle;
}
else
{
toAngle = toAngle < 360 - currAngle ? 360 - currAngle : toAngle;
}
}
return toAngle;
}
private void DrawCenter(VertexHelper vh, Serie serie, SerieData serieData, float insideRadius, bool last)
{
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
if (!ChartHelper.IsClearColor(itemStyle.centerColor) && last)
{
var radius = insideRadius - itemStyle.centerGap;
var smoothness = chart.settings.cicleSmoothness;
UGL.DrawCricle(vh, serie.context.center, radius, itemStyle.centerColor, smoothness);
}
}
private void DrawBackground(VertexHelper vh, Serie serie, SerieData serieData, int index, float insideRadius, float outsideRadius)
{
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
var backgroundColor = SerieHelper.GetItemBackgroundColor(serie, serieData, chart.theme, index, false);
if (itemStyle.backgroundWidth != 0)
{
var centerRadius = (outsideRadius + insideRadius) / 2;
var inradius = centerRadius - itemStyle.backgroundWidth / 2;
var outradius = centerRadius + itemStyle.backgroundWidth / 2;
UGL.DrawDoughnut(vh, serie.context.center, inradius,
outradius, backgroundColor, Color.clear, chart.settings.cicleSmoothness);
}
else
{
UGL.DrawDoughnut(vh, serie.context.center, insideRadius,
outsideRadius, backgroundColor, Color.clear, chart.settings.cicleSmoothness);
}
}
private void DrawBorder(VertexHelper vh, Serie serie, SerieData serieData, float insideRadius, float outsideRadius)
{
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
if (itemStyle.show && itemStyle.borderWidth > 0 && !ChartHelper.IsClearColor(itemStyle.borderColor))
{
UGL.DrawDoughnut(vh, serie.context.center, outsideRadius,
outsideRadius + itemStyle.borderWidth, itemStyle.borderColor,
Color.clear, chart.settings.cicleSmoothness);
UGL.DrawDoughnut(vh, serie.context.center, insideRadius,
insideRadius + itemStyle.borderWidth, itemStyle.borderColor,
Color.clear, chart.settings.cicleSmoothness);
}
}
private int GetRingIndex(Vector2 local)
{
var dist = Vector2.Distance(local, serie.context.center);
if (dist > serie.context.outsideRadius) return -1;
Vector2 dir = local - new Vector2(serie.context.center.x, serie.context.center.y);
float angle = VectorAngle(Vector2.up, dir);
for (int i = 0; i < serie.data.Count; i++)
{
var serieData = serie.data[i];
serieData.index = i;
if (dist >= serieData.context.insideRadius &&
dist <= serieData.context.outsideRadius &&
angle >= serieData.context.startAngle &&
angle <= serieData.context.toAngle)
{
return i;
}
}
return -1;
}
private float VectorAngle(Vector2 from, Vector2 to)
{
float angle;
Vector3 cross = Vector3.Cross(from, to);
angle = Vector2.Angle(from, to);
angle = cross.z > 0 ? -angle : angle;
angle = (angle + 360) % 360;
return angle;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8c3c486efd6d8464a88d8f4b572b7bc4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 97fc5bddab1db4321aa7377ab8b8b8bc
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,9 @@
namespace XCharts.Runtime
{
[System.Serializable]
public class BaseScatter : Serie, INeedSerieContainer
{
public int containerIndex { get; internal set; }
public int containterInstanceId { get; internal set; }
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dba0ca827ad4d4b9989def35aba66665
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,350 @@
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
namespace XCharts.Runtime
{
[UnityEngine.Scripting.Preserve]
internal class BaseScatterHandler<T> : SerieHandler<T> where T : BaseScatter
{
private GridCoord m_Grid;
public override void Update()
{
UpdateSerieContext();
}
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
string marker, string itemFormatter, string numericFormatter,
ref List<SerieParams> paramList, ref string title)
{
dataIndex = serie.context.pointerItemDataIndex;
if (dataIndex < 0)
return;
var serieData = serie.GetSerieData(dataIndex);
if (serieData == null)
return;
title = serie.serieName;
var param = serie.context.param;
param.serieName = serie.serieName;
param.serieIndex = serie.index;
param.category = category;
param.dimension = 1;
param.dataCount = serie.dataCount;
param.serieData = serieData;
param.color = SerieHelper.GetItemColor(serie, serieData, chart.theme, serie.context.colorIndex, false);
param.marker = SerieHelper.GetItemMarker(serie, serieData, marker);
param.itemFormatter = SerieHelper.GetItemFormatter(serie, serieData, itemFormatter);
param.numericFormatter = SerieHelper.GetNumericFormatter(serie, serieData, numericFormatter);
param.columns.Clear();
param.columns.Add(param.marker);
if (!string.IsNullOrEmpty(serieData.name))
param.columns.Add(serieData.name);
param.columns.Add(ChartCached.NumberToStr(serieData.GetData(1), param.numericFormatter));
paramList.Add(param);
}
public override void DrawSerie(VertexHelper vh)
{
if (serie.IsUseCoord<SingleAxisCoord>())
{
DrawSingAxisScatterSerie(vh, serie);
}
else if (serie.IsUseCoord<GridCoord>())
{
DrawScatterSerie(vh, serie);
}
}
private void UpdateSerieContext()
{
var needCheck = m_LegendEnter || (chart.isPointerInChart && (m_Grid == null || m_Grid.IsPointerEnter()));
var needHideAll = false;
if (!needCheck)
{
if (m_LastCheckContextFlag == needCheck)
return;
needHideAll = true;
}
m_LastCheckContextFlag = needCheck;
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
var themeSymbolSize = chart.theme.serie.scatterSymbolSize;
var themeSymbolSelectedSize = chart.theme.serie.scatterSymbolSelectedSize;
var needInteract = false;
for (int i = serie.dataCount - 1; i >= 0; i--)
{
var serieData = serie.data[i];
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
var symbolSize = symbol.GetSize(serieData.data, themeSymbolSize);
var symbolSelectedSize = symbol.GetSelectedSize(serieData.data, themeSymbolSelectedSize);
if (m_LegendEnter ||
(!needHideAll && Vector3.Distance(serieData.context.position, chart.pointerPos) <= symbolSize))
{
serie.context.pointerItemDataIndex = i;
serie.context.pointerEnter = true;
serieData.context.highlight = true;
serieData.interact.SetValue(ref needInteract, symbolSelectedSize);
}
else
{
serieData.context.highlight = false;
serieData.interact.SetValue(ref needInteract, symbolSize);
}
}
if (needInteract)
{
chart.RefreshPainter(serie);
}
}
protected virtual void DrawScatterSerie(VertexHelper vh, BaseScatter serie)
{
if (serie.animation.HasFadeOut())
return;
if (!serie.show)
return;
XAxis xAxis;
if (!chart.TryGetChartComponent<XAxis>(out xAxis, serie.xAxisIndex))
return;
YAxis yAxis;
if (!chart.TryGetChartComponent<YAxis>(out yAxis, serie.yAxisIndex))
return;
if (!chart.TryGetChartComponent<GridCoord>(out m_Grid, xAxis.gridIndex))
return;
DataZoom xDataZoom;
DataZoom yDataZoom;
chart.GetDataZoomOfSerie(serie, out xDataZoom, out yDataZoom);
var theme = chart.theme;
int maxCount = serie.maxShow > 0 ?
(serie.maxShow > serie.dataCount ? serie.dataCount : serie.maxShow) :
serie.dataCount;
serie.animation.InitProgress(0, 1);
var rate = serie.animation.GetCurrRate();
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
var dataChanging = false;
var interacting = false;
var dataList = serie.GetDataList(xDataZoom);
var isEffectScatter = serie is EffectScatter;
var colorIndex = serie.context.colorIndex;
serie.containerIndex = m_Grid.index;
serie.containterInstanceId = m_Grid.instanceId;
foreach (var serieData in dataList)
{
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
if (!symbol.ShowSymbol(serieData.index, maxCount))
continue;
var highlight = serie.highlight || serieData.context.highlight;
var color = SerieHelper.GetItemColor(serie, serieData, theme, colorIndex, highlight);
var toColor = SerieHelper.GetItemToColor(serie, serieData, theme, colorIndex, highlight);
var emptyColor = SerieHelper.GetItemBackgroundColor(serie, serieData, theme, colorIndex, highlight, false);
var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, theme, highlight);
var borderColor = SerieHelper.GetSymbolBorderColor(serie, serieData, theme, highlight);
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, highlight);
double xValue = serieData.GetCurrData(0, dataChangeDuration, xAxis.inverse);
double yValue = serieData.GetCurrData(1, dataChangeDuration, yAxis.inverse);
if (serieData.IsDataChanged())
dataChanging = true;
float pX = m_Grid.context.x + xAxis.axisLine.GetWidth(theme.axis.lineWidth);
float pY = m_Grid.context.y + yAxis.axisLine.GetWidth(theme.axis.lineWidth);
float xDataHig = GetDataHig(xAxis, xValue, m_Grid.context.width);
float yDataHig = GetDataHig(yAxis, yValue, m_Grid.context.height);
var pos = new Vector3(pX + xDataHig, pY + yDataHig);
if (!m_Grid.Contains(pos))
continue;
serie.context.dataPoints.Add(pos);
serieData.context.position = pos;
var datas = serieData.data;
var symbolSize = serie.highlight || serieData.context.highlight ?
theme.serie.scatterSymbolSelectedSize :
theme.serie.scatterSymbolSize;
if (!serieData.interact.TryGetValue(ref symbolSize, ref interacting))
{
symbolSize = highlight ?
symbol.GetSelectedSize(serieData.data, symbolSize) :
symbol.GetSize(serieData.data, symbolSize);
serieData.interact.SetValue(ref interacting, symbolSize);
}
symbolSize *= rate;
if (isEffectScatter)
{
for (int count = 0; count < symbol.animationSize.Count; count++)
{
var nowSize = symbol.animationSize[count];
color.a = (byte) (255 * (symbolSize - nowSize) / symbolSize);
chart.DrawSymbol(vh, symbol.type, nowSize, symbolBorder, pos,
color, toColor, emptyColor, borderColor, symbol.gap, cornerRadius);
}
chart.RefreshPainter(serie);
}
else
{
if (symbolSize > 100) symbolSize = 100;
chart.DrawSymbol(vh, symbol.type, symbolSize, symbolBorder, pos,
color, toColor, emptyColor, borderColor, symbol.gap, cornerRadius);
}
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress(1);
chart.RefreshPainter(serie);
}
if (dataChanging || interacting)
{
chart.RefreshPainter(serie);
}
}
protected virtual void DrawSingAxisScatterSerie(VertexHelper vh, BaseScatter serie)
{
if (serie.animation.HasFadeOut())
return;
if (!serie.show)
return;
var axis = chart.GetChartComponent<SingleAxis>(serie.singleAxisIndex);
if (axis == null)
return;
DataZoom xDataZoom;
DataZoom yDataZoom;
chart.GetDataZoomOfSerie(serie, out xDataZoom, out yDataZoom);
var theme = chart.theme;
int maxCount = serie.maxShow > 0 ?
(serie.maxShow > serie.dataCount ? serie.dataCount : serie.maxShow) :
serie.dataCount;
serie.animation.InitProgress(0, 1);
var rate = serie.animation.GetCurrRate();
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
var dataChanging = false;
var dataList = serie.GetDataList(xDataZoom);
var isEffectScatter = serie is EffectScatter;
var colorIndex = serie.context.colorIndex;
serie.containerIndex = axis.index;
serie.containterInstanceId = axis.instanceId;
foreach (var serieData in dataList)
{
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
if (!symbol.ShowSymbol(serieData.index, maxCount))
continue;
var highlight = serie.highlight || serieData.context.highlight;
var color = SerieHelper.GetItemColor(serie, serieData, theme, colorIndex, highlight);
var toColor = SerieHelper.GetItemToColor(serie, serieData, theme, colorIndex, highlight);
var emptyColor = SerieHelper.GetItemBackgroundColor(serie, serieData, theme, colorIndex, highlight, false);
var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, theme, highlight);
var borderColor = SerieHelper.GetSymbolBorderColor(serie, serieData, theme, highlight);
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, highlight);
var xValue = serieData.GetCurrData(0, dataChangeDuration, axis.inverse);
if (serieData.IsDataChanged())
dataChanging = true;
var pos = Vector3.zero;
if (axis.orient == Orient.Horizonal)
{
var xDataHig = GetDataHig(axis, xValue, axis.context.width);
var yDataHig = axis.context.height / 2;
pos = new Vector3(axis.context.x + xDataHig, axis.context.y + yDataHig);
}
else
{
var yDataHig = GetDataHig(axis, xValue, axis.context.width);
var xDataHig = axis.context.height / 2;
pos = new Vector3(axis.context.x + xDataHig, axis.context.y + yDataHig);
}
serie.context.dataPoints.Add(pos);
serieData.context.position = pos;
var datas = serieData.data;
var symbolSize = 0f;
if (serie.highlight || serieData.context.highlight)
symbolSize = symbol.GetSelectedSize(datas, theme.serie.scatterSymbolSelectedSize);
else
symbolSize = symbol.GetSize(datas, theme.serie.scatterSymbolSize);
symbolSize *= rate;
if (isEffectScatter)
{
if (symbolSize > 100) symbolSize = 100;
for (int count = 0; count < symbol.animationSize.Count; count++)
{
var nowSize = symbol.animationSize[count];
color.a = (byte) (255 * (symbolSize - nowSize) / symbolSize);
chart.DrawSymbol(vh, symbol.type, nowSize, symbolBorder, pos,
color, toColor, emptyColor, borderColor, symbol.gap, cornerRadius);
}
chart.RefreshPainter(serie);
}
else
{
if (symbolSize > 100) symbolSize = 100;
chart.DrawSymbol(vh, symbol.type, symbolSize, symbolBorder, pos,
color, toColor, emptyColor, borderColor, symbol.gap, cornerRadius);
}
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress(1);
chart.RefreshPainter(serie);
}
if (dataChanging)
{
chart.RefreshPainter(serie);
}
}
private static float GetDataHig(Axis axis, double value, float totalWidth)
{
if (axis.IsLog())
{
int minIndex = axis.GetLogMinIndex();
float nowIndex = axis.GetLogValue(value);
return (nowIndex - minIndex) / axis.splitNumber * totalWidth;
}
else if (axis.IsCategory())
{
if (axis.boundaryGap)
{
float tick = (float) (totalWidth / (axis.context.minMaxRange + 1));
return tick / 2 + (float) (value - axis.context.minValue) * tick;
}
else
{
return (float) ((value - axis.context.minValue) / axis.context.minMaxRange * totalWidth);
}
}
else
{
return (float) ((value - axis.context.minValue) / axis.context.minMaxRange * totalWidth);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 31373c1595ff249188e33330f2eff1ed
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,27 @@
using UnityEngine;
namespace XCharts.Runtime
{
[System.Serializable]
[SerieHandler(typeof(EffectScatterHandler), true)]
[CoordOptions(typeof(GridCoord), typeof(SingleAxisCoord))]
[SerieExtraComponent(typeof(LabelStyle), typeof(EmphasisItemStyle), typeof(EmphasisLabelStyle))]
[SerieDataExtraComponent(typeof(ItemStyle), typeof(LabelStyle), typeof(EmphasisItemStyle), typeof(EmphasisLabelStyle))]
[SerieDataExtraField("m_Radius")]
public class EffectScatter : BaseScatter
{
public static Serie AddDefaultSerie(BaseChart chart, string serieName)
{
var serie = chart.AddSerie<EffectScatter>(serieName);
serie.symbol.show = true;
serie.symbol.type = SymbolType.Circle;
serie.itemStyle.opacity = 0.8f;
serie.clip = false;
for (int i = 0; i < 10; i++)
{
chart.AddData(serie.index, Random.Range(10, 100), Random.Range(10, 100));
}
return serie;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c34d4976ef53c48a4b091d52694d8a7f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,25 @@
using UnityEngine;
namespace XCharts.Runtime
{
[UnityEngine.Scripting.Preserve]
internal sealed class EffectScatterHandler : BaseScatterHandler<EffectScatter>
{
private float m_EffectScatterSpeed = 15;
public override void Update()
{
base.Update();
var symbolSize = serie.symbol.GetSize(null, chart.theme.serie.scatterSymbolSize);
for (int i = 0; i < serie.symbol.animationSize.Count; ++i)
{
serie.symbol.animationSize[i] += m_EffectScatterSpeed * Time.deltaTime;
if (serie.symbol.animationSize[i] > symbolSize)
{
serie.symbol.animationSize[i] = i * 5;
}
chart.RefreshPainter(serie);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bb7c24770dff64d7b857f459de7b2333
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,27 @@
using UnityEngine;
namespace XCharts.Runtime
{
[System.Serializable]
[SerieHandler(typeof(ScatterHandler), true)]
[CoordOptions(typeof(GridCoord), typeof(SingleAxisCoord))]
[SerieExtraComponent(typeof(LabelStyle), typeof(EmphasisItemStyle), typeof(EmphasisLabelStyle))]
[SerieDataExtraComponent(typeof(ItemStyle), typeof(LabelStyle), typeof(EmphasisItemStyle), typeof(EmphasisLabelStyle))]
[SerieDataExtraField("m_Radius")]
public class Scatter : BaseScatter
{
public static Serie AddDefaultSerie(BaseChart chart, string serieName)
{
var serie = chart.AddSerie<Scatter>(serieName);
serie.symbol.show = true;
serie.symbol.type = SymbolType.Circle;
serie.itemStyle.opacity = 0.8f;
serie.clip = false;
for (int i = 0; i < 10; i++)
{
chart.AddData(serie.index, Random.Range(10, 100), Random.Range(10, 100));
}
return serie;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 75a031f5547984317b5659a03d7f5e32
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,6 @@
namespace XCharts.Runtime
{
[UnityEngine.Scripting.Preserve]
internal sealed class ScatterHandler : BaseScatterHandler<Scatter>
{ }
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7ee7d7a8f04034cd38fd9d43f1a41825
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,150 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
namespace XCharts.Runtime
{
public partial class Serie
{
public static Dictionary<Type, string> extraComponentMap = new Dictionary<Type, string>
{ { typeof(LabelStyle), "m_Labels" },
{ typeof(LabelLine), "m_LabelLines" },
{ typeof(EndLabelStyle), "m_EndLabels" },
{ typeof(LineArrow), "m_LineArrows" },
{ typeof(AreaStyle), "m_AreaStyles" },
{ typeof(TitleStyle), "m_TitleStyles" },
{ typeof(EmphasisItemStyle), "m_EmphasisItemStyles" },
{ typeof(EmphasisLabelStyle), "m_EmphasisLabels" },
{ typeof(EmphasisLabelLine), "m_EmphasisLabelLines" },
};
[SerializeField][IgnoreDoc] private List<LabelStyle> m_Labels = new List<LabelStyle>();
[SerializeField][IgnoreDoc] private List<LabelLine> m_LabelLines = new List<LabelLine>();
[SerializeField][IgnoreDoc] private List<EndLabelStyle> m_EndLabels = new List<EndLabelStyle>();
[SerializeField][IgnoreDoc] private List<LineArrow> m_LineArrows = new List<LineArrow>();
[SerializeField][IgnoreDoc] private List<AreaStyle> m_AreaStyles = new List<AreaStyle>();
[SerializeField][IgnoreDoc] private List<TitleStyle> m_TitleStyles = new List<TitleStyle>();
[SerializeField][IgnoreDoc] private List<EmphasisItemStyle> m_EmphasisItemStyles = new List<EmphasisItemStyle>();
[SerializeField][IgnoreDoc] private List<EmphasisLabelStyle> m_EmphasisLabels = new List<EmphasisLabelStyle>();
[SerializeField][IgnoreDoc] private List<EmphasisLabelLine> m_EmphasisLabelLines = new List<EmphasisLabelLine>();
/// <summary>
/// The style of area.
/// |区域填充样式。
/// </summary>
public AreaStyle areaStyle { get { return m_AreaStyles.Count > 0 ? m_AreaStyles[0] : null; } }
/// <summary>
/// Text label of graphic element,to explain some data information about graphic item like value, name and so on.
/// |图形上的文本标签,可用于说明图形的一些数据信息,比如值,名称等。
/// </summary>
public LabelStyle label { get { return m_Labels.Count > 0 ? m_Labels[0] : null; } }
public LabelStyle endLabel { get { return m_EndLabels.Count > 0 ? m_EndLabels[0] : null; } }
/// <summary>
/// The line of label.
/// |标签上的视觉引导线。
/// </summary>
public LabelLine labelLine { get { return m_LabelLines.Count > 0 ? m_LabelLines[0] : null; } }
/// <summary>
/// The arrow of line.
/// |折线图的箭头。
/// </summary>
public LineArrow lineArrow { get { return m_LineArrows.Count > 0 ? m_LineArrows[0] : null; } }
/// <summary>
/// 高亮的图形样式
/// </summary>
public EmphasisItemStyle emphasisItemStyle { get { return m_EmphasisItemStyles.Count > 0 ? m_EmphasisItemStyles[0] : null; } }
/// <summary>
/// 高亮时的标签样式
/// </summary>
public EmphasisLabelStyle emphasisLabel { get { return m_EmphasisLabels.Count > 0 ? m_EmphasisLabels[0] : null; } }
/// <summary>
/// 高亮时的标签引导线样式
/// </summary>
public EmphasisLabelLine emphasisLabelLine { get { return m_EmphasisLabelLines.Count > 0 ? m_EmphasisLabelLines[0] : null; } }
/// <summary>
/// the icon of data.
/// |数据项标题样式。
/// </summary>
public TitleStyle titleStyle { get { return m_TitleStyles.Count > 0 ? m_TitleStyles[0] : null; } }
public void RemoveAllExtraComponent()
{
var serieType = GetType();
foreach (var kv in extraComponentMap)
{
ReflectionUtil.InvokeListClear(this, serieType.GetField(kv.Value));
}
SetAllDirty();
}
public T AddExtraComponent<T>() where T : ChildComponent, ISerieExtraComponent
{
return AddExtraComponent(typeof(T)) as T;
}
public ISerieExtraComponent AddExtraComponent(Type type)
{
if (GetType().IsDefined(typeof(SerieExtraComponentAttribute), false))
{
var attr = GetType().GetAttribute<SerieExtraComponentAttribute>();
if (attr.Contains(type))
{
var fieldName = string.Empty;
if (extraComponentMap.TryGetValue(type, out fieldName))
{
var field = typeof(Serie).GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
if (ReflectionUtil.InvokeListCount(this, field) <= 0)
{
var extraComponent = Activator.CreateInstance(type) as ISerieExtraComponent;
ReflectionUtil.InvokeListAdd(this, field, extraComponent);
SetAllDirty();
return extraComponent;
}
else
{
return ReflectionUtil.InvokeListGet<ISerieExtraComponent>(this, field, 0);
}
}
}
}
throw new System.Exception(string.Format("Serie {0} not support extra component: {1}",
GetType().Name, type.Name));
}
public void RemoveExtraComponent<T>() where T : ISerieExtraComponent
{
RemoveExtraComponent(typeof(T));
}
public void RemoveExtraComponent(Type type)
{
if (GetType().IsDefined(typeof(SerieExtraComponentAttribute), false))
{
var attr = GetType().GetAttribute<SerieExtraComponentAttribute>();
if (attr.Contains(type))
{
var fieldName = string.Empty;
if (extraComponentMap.TryGetValue(type, out fieldName))
{
var field = typeof(Serie).GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
ReflectionUtil.InvokeListClear(this, field);
SetAllDirty();
return;
}
}
}
throw new System.Exception(string.Format("Serie {0} not support extra component: {1}",
GetType().Name, type.Name));
}
private void RemoveExtraComponentList<T>(List<T> list) where T : ISerieExtraComponent
{
if (list.Count > 0)
{
list.Clear();
SetAllDirty();
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9c4f3a01039fd4e7fbf771a65ede0069
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aa9c09045961a4ea9a34a098f099f2a1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,109 @@
using System.Collections.Generic;
using UnityEngine;
namespace XCharts.Runtime
{
public struct PointInfo
{
public Vector3 position;
public bool isIgnoreBreak;
public PointInfo(Vector3 pos, bool ignore)
{
this.position = pos;
this.isIgnoreBreak = ignore;
}
}
public class SerieContext
{
/// <summary>
/// 鼠标是否进入serie
/// </summary>
public bool pointerEnter;
/// <summary>
/// 鼠标当前指示的数据项索引(单个)
/// </summary>
public int pointerItemDataIndex = -1;
/// <summary>
/// 鼠标所在轴线上的数据项索引(可能有多个)
/// </summary>
public List<int> pointerAxisDataIndexs = new List<int>();
public bool isTriggerByAxis = false;
/// <summary>
/// 中心点
/// </summary>
public Vector3 center;
/// <summary>
/// 线段终点
/// </summary>
public Vector3 lineEndPostion;
public double lineEndValue;
/// <summary>
/// 内半径
/// </summary>
public float insideRadius;
/// <summary>
/// 外半径
/// </summary>
public float outsideRadius;
public float startAngle;
/// <summary>
/// 最大值
/// </summary>
public double dataMax;
/// <summary>
/// 最小值
/// </summary>
public double dataMin;
public double checkValue;
/// <summary>
/// 左下角坐标X
/// </summary>
public float x;
/// <summary>
/// 左下角坐标Y
/// </summary>
public float y;
/// <summary>
/// 宽
/// </summary>
public float width;
/// <summary>
/// 高
/// </summary>
public float height;
/// <summary>
/// 矩形区域
/// </summary>
public Rect rect;
/// <summary>
/// 绘制顶点数
/// </summary>
public int vertCount;
/// <summary>
/// 数据对应的位置坐标。
/// </summary>
public List<Vector3> dataPoints = new List<Vector3>();
/// <summary>
/// 数据对应的位置坐标是否忽略(忽略时连线是透明的),dataIgnore 和 dataPoints 一一对应。
/// </summary>
public List<bool> dataIgnores = new List<bool>();
/// <summary>
/// 排序后的数据
/// </summary>
public List<SerieData> sortedData = new List<SerieData>();
public List<SerieData> rootData = new List<SerieData>();
/// <summary>
/// theme的颜色索引
/// </summary>
public int colorIndex;
/// <summary>
/// 绘制点
/// </summary>
public List<PointInfo> drawPoints = new List<PointInfo>();
public SerieParams param = new SerieParams();
public ChartLabel titleObject { get; set; }
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 87f333572a32a4cb39aa0a05ed97983a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,565 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using XUGL;
namespace XCharts.Runtime
{
/// <summary>
/// A data item of serie.
/// |系列中的一个数据项。可存储数据名和1-n维个数据。
/// </summary>
[System.Serializable]
public class SerieData : ChildComponent
{
public static List<string> extraFieldList = new List<string>()
{
"m_Id",
"m_ParentId",
"m_Ignore",
"m_Selected",
"m_Radius"
};
public static Dictionary<Type, string> extraComponentMap = new Dictionary<Type, string>
{ { typeof(ItemStyle), "m_ItemStyles" },
{ typeof(LabelStyle), "m_Labels" },
{ typeof(LabelLine), "m_LabelLines" },
{ typeof(SerieSymbol), "m_Symbols" },
{ typeof(LineStyle), "m_LineStyles" },
{ typeof(AreaStyle), "m_AreaStyles" },
{ typeof(TitleStyle), "m_TitleStyles" },
{ typeof(EmphasisItemStyle), "m_EmphasisItemStyles" },
{ typeof(EmphasisLabelStyle), "m_EmphasisLabels" },
{ typeof(EmphasisLabelLine), "m_EmphasisLabelLines" },
};
[SerializeField] private int m_Index;
[SerializeField] private string m_Name;
[SerializeField] private string m_Id;
[SerializeField] private string m_ParentId;
[SerializeField] private bool m_Ignore;
[SerializeField] private bool m_Selected;
[SerializeField] private float m_Radius;
[SerializeField][IgnoreDoc] private List<ItemStyle> m_ItemStyles = new List<ItemStyle>();
[SerializeField][IgnoreDoc] private List<LabelStyle> m_Labels = new List<LabelStyle>();
[SerializeField][IgnoreDoc] private List<LabelLine> m_LabelLines = new List<LabelLine>();
[SerializeField][IgnoreDoc] private List<SerieSymbol> m_Symbols = new List<SerieSymbol>();
[SerializeField][IgnoreDoc] private List<LineStyle> m_LineStyles = new List<LineStyle>();
[SerializeField][IgnoreDoc] private List<AreaStyle> m_AreaStyles = new List<AreaStyle>();
[SerializeField][IgnoreDoc] private List<TitleStyle> m_TitleStyles = new List<TitleStyle>();
[SerializeField][IgnoreDoc] private List<EmphasisItemStyle> m_EmphasisItemStyles = new List<EmphasisItemStyle>();
[SerializeField][IgnoreDoc] private List<EmphasisLabelStyle> m_EmphasisLabels = new List<EmphasisLabelStyle>();
[SerializeField][IgnoreDoc] private List<EmphasisLabelLine> m_EmphasisLabelLines = new List<EmphasisLabelLine>();
[SerializeField] private List<double> m_Data = new List<double>();
[NonSerialized] public SerieDataContext context = new SerieDataContext();
[NonSerialized] public InteractData interact = new InteractData();
public ChartLabel labelObject { get; set; }
public ChartLabel titleObject { get; set; }
private bool m_Show = true;
/// <summary>
/// the index of SerieData.
/// |数据项索引。
/// </summary>
public override int index { get { return m_Index; } set { m_Index = value; } }
/// <summary>
/// the name of data item.
/// |数据项名称。
/// </summary>
public string name { get { return m_Name; } set { m_Name = value; } }
/// <summary>
/// the id of data.
/// |数据项的唯一id。唯一id不是必须设置的。
/// </summary>
public string id { get { return m_Id; } set { m_Id = value; } }
/// <summary>
/// the id of parent SerieData.
/// |父节点id。父节点id不是必须设置的。
/// </summary>
public string parentId { get { return m_ParentId; } set { m_ParentId = value; } }
/// <summary>
/// 是否忽略数据。当为 true 时,数据不进行绘制。
/// </summary>
public bool ignore
{
get { return m_Ignore; }
set { if (PropertyUtil.SetStruct(ref m_Ignore, value)) SetVerticesDirty(); }
}
/// <summary>
/// 自定义半径。可用在饼图中自定义某个数据项的半径。
/// </summary>
public float radius { get { return m_Radius; } set { m_Radius = value; } }
/// <summary>
/// Whether the data item is selected.
/// |该数据项是否被选中。
/// </summary>
public bool selected { get { return m_Selected; } set { m_Selected = value; } }
/// <summary>
/// 数据项图例名称。当数据项名称不为空时,图例名称即为系列名称;反之则为索引index。
/// </summary>
/// <value></value>
public string legendName { get { return string.IsNullOrEmpty(name) ? ChartCached.IntToStr(index) : name; } }
/// <summary>
/// 单个数据项的标签设置。
/// </summary>
public LabelStyle labelStyle { get { return m_Labels.Count > 0 ? m_Labels[0] : null; } }
public LabelLine labelLine { get { return m_LabelLines.Count > 0 ? m_LabelLines[0] : null; } }
/// <summary>
/// 单个数据项的样式设置。
/// </summary>
public ItemStyle itemStyle { get { return m_ItemStyles.Count > 0 ? m_ItemStyles[0] : null; } }
/// <summary>
/// 单个数据项的标记设置。
/// </summary>
public SerieSymbol symbol { get { return m_Symbols.Count > 0 ? m_Symbols[0] : null; } }
public LineStyle lineStyle { get { return m_LineStyles.Count > 0 ? m_LineStyles[0] : null; } }
public AreaStyle areaStyle { get { return m_AreaStyles.Count > 0 ? m_AreaStyles[0] : null; } }
public TitleStyle titleStyle { get { return m_TitleStyles.Count > 0 ? m_TitleStyles[0] : null; } }
/// <summary>
/// 高亮的图形样式
/// </summary>
public EmphasisItemStyle emphasisItemStyle { get { return m_EmphasisItemStyles.Count > 0 ? m_EmphasisItemStyles[0] : null; } }
/// <summary>
/// 高亮时的标签样式
/// </summary>
public EmphasisLabelStyle emphasisLabel { get { return m_EmphasisLabels.Count > 0 ? m_EmphasisLabels[0] : null; } }
/// <summary>
/// 高亮时的标签引导线样式
/// </summary>
public EmphasisLabelLine emphasisLabelLine { get { return m_EmphasisLabelLines.Count > 0 ? m_EmphasisLabelLines[0] : null; } }
/// <summary>
/// An arbitrary dimension data list of data item.
/// |可指定任意维数的数值列表。
/// </summary>
public List<double> data { get { return m_Data; } set { m_Data = value; } }
/// <summary>
/// [default:true] Whether the data item is showed.
/// |该数据项是否要显示。
/// </summary>
public bool show { get { return m_Show; } set { m_Show = value; } }
private List<double> m_PreviousData = new List<double>();
private List<float> m_DataUpdateTime = new List<float>();
private List<bool> m_DataUpdateFlag = new List<bool>();
private List<Vector2> m_PolygonPoints = new List<Vector2>();
public override bool vertsDirty
{
get
{
return m_VertsDirty ||
(labelLine != null && labelLine.vertsDirty) ||
(itemStyle != null && itemStyle.vertsDirty) ||
(symbol != null && symbol.vertsDirty) ||
(lineStyle != null && lineStyle.vertsDirty) ||
(areaStyle != null && areaStyle.vertsDirty) ||
(emphasisItemStyle != null && emphasisItemStyle.vertsDirty);
}
}
public override bool componentDirty
{
get
{
return m_ComponentDirty ||
(labelStyle != null && labelStyle.componentDirty) ||
(labelLine != null && labelLine.componentDirty) ||
(titleStyle != null && titleStyle.componentDirty) ||
(emphasisLabel != null && emphasisLabel.componentDirty) ||
(emphasisLabelLine != null && emphasisLabelLine.componentDirty);
}
}
public override void ClearVerticesDirty()
{
base.ClearVerticesDirty();
if (labelLine != null) labelLine.ClearVerticesDirty();
if (itemStyle != null) itemStyle.ClearVerticesDirty();
if (lineStyle != null) lineStyle.ClearVerticesDirty();
if (areaStyle != null) areaStyle.ClearVerticesDirty();
if (symbol != null) symbol.ClearVerticesDirty();
if (emphasisItemStyle != null) emphasisItemStyle.ClearVerticesDirty();
}
public override void ClearComponentDirty()
{
base.ClearComponentDirty();
if (labelLine != null) labelLine.ClearComponentDirty();
if (itemStyle != null) itemStyle.ClearComponentDirty();
if (lineStyle != null) lineStyle.ClearComponentDirty();
if (areaStyle != null) areaStyle.ClearComponentDirty();
if (symbol != null) symbol.ClearComponentDirty();
if (emphasisLabel != null) emphasisLabel.ClearComponentDirty();
if (emphasisLabelLine != null) emphasisLabelLine.ClearComponentDirty();
}
public void Reset()
{
index = 0;
m_Id = null;
m_ParentId = null;
labelObject = null;
m_Name = string.Empty;
m_Show = true;
context.Reset();
interact.Reset();
m_Data.Clear();
m_PreviousData.Clear();
m_DataUpdateTime.Clear();
m_DataUpdateFlag.Clear();
m_Labels.Clear();
m_LabelLines.Clear();
m_ItemStyles.Clear();
m_Symbols.Clear();
m_LineStyles.Clear();
m_AreaStyles.Clear();
m_TitleStyles.Clear();
m_EmphasisItemStyles.Clear();
m_EmphasisLabels.Clear();
m_EmphasisLabelLines.Clear();
}
public T GetOrAddComponent<T>() where T : ChildComponent, ISerieDataComponent
{
return GetOrAddComponent(typeof(T)) as T;
}
public ISerieDataComponent GetOrAddComponent(Type type)
{
if (type == typeof(ItemStyle))
{
if (m_ItemStyles.Count == 0)
m_ItemStyles.Add(new ItemStyle() { show = true });
return m_ItemStyles[0];
}
else if (type == typeof(LabelStyle))
{
if (m_Labels.Count == 0)
m_Labels.Add(new LabelStyle() { show = true });
return m_Labels[0];
}
else if (type == typeof(LabelLine))
{
if (m_LabelLines.Count == 0)
m_LabelLines.Add(new LabelLine() { show = true });
return m_LabelLines[0];
}
else if (type == typeof(EmphasisItemStyle))
{
if (m_EmphasisItemStyles.Count == 0)
m_EmphasisItemStyles.Add(new EmphasisItemStyle() { show = true });
return m_EmphasisItemStyles[0];
}
else if (type == typeof(EmphasisLabelStyle))
{
if (m_EmphasisLabels.Count == 0)
m_EmphasisLabels.Add(new EmphasisLabelStyle() { show = true });
return m_EmphasisLabels[0];
}
else if (type == typeof(EmphasisLabelLine))
{
if (m_EmphasisLabelLines.Count == 0)
m_EmphasisLabelLines.Add(new EmphasisLabelLine() { show = true });
return m_EmphasisLabelLines[0];
}
else if (type == typeof(SerieSymbol))
{
if (m_Symbols.Count == 0)
m_Symbols.Add(new SerieSymbol() { show = true });
return m_Symbols[0];
}
else if (type == typeof(LineStyle))
{
if (m_LineStyles.Count == 0)
m_LineStyles.Add(new LineStyle() { show = true });
return m_LineStyles[0];
}
else if (type == typeof(AreaStyle))
{
if (m_AreaStyles.Count == 0)
m_AreaStyles.Add(new AreaStyle() { show = true });
return m_AreaStyles[0];
}
else if (type == typeof(TitleStyle))
{
if (m_TitleStyles.Count == 0)
m_TitleStyles.Add(new TitleStyle() { show = true });
return m_TitleStyles[0];
}
else
{
throw new System.Exception("SerieData not support component:" + type);
}
}
public void RemoveAllComponent()
{
m_ItemStyles.Clear();
m_Labels.Clear();
m_LabelLines.Clear();
m_Symbols.Clear();
m_EmphasisItemStyles.Clear();
m_EmphasisLabels.Clear();
m_EmphasisLabelLines.Clear();
m_LineStyles.Clear();
m_AreaStyles.Clear();
m_TitleStyles.Clear();
}
public void RemoveComponent<T>() where T : ISerieDataComponent
{
RemoveComponent(typeof(T));
}
public void RemoveComponent(Type type)
{
if (type == typeof(ItemStyle))
m_ItemStyles.Clear();
else if (type == typeof(LabelStyle))
m_Labels.Clear();
else if (type == typeof(LabelLine))
m_LabelLines.Clear();
else if (type == typeof(EmphasisItemStyle))
m_EmphasisItemStyles.Clear();
else if (type == typeof(EmphasisLabelStyle))
m_EmphasisLabels.Clear();
else if (type == typeof(EmphasisLabelLine))
m_EmphasisLabelLines.Clear();
else if (type == typeof(SerieSymbol))
m_Symbols.Clear();
else if (type == typeof(LineStyle))
m_LineStyles.Clear();
else if (type == typeof(AreaStyle))
m_AreaStyles.Clear();
else if (type == typeof(TitleStyle))
m_TitleStyles.Clear();
else
throw new System.Exception("SerieData not support component:" + type);
}
public double GetData(int index, bool inverse = false)
{
if (index >= 0 && index < m_Data.Count)
{
return inverse ? -m_Data[index] : m_Data[index];
}
else return 0;
}
public double GetData(int index, double min, double max)
{
if (index >= 0 && index < m_Data.Count)
{
var value = m_Data[index];
if (value < min) return min;
else if (value > max) return max;
else return value;
}
else return 0;
}
public double GetPreviousData(int index, bool inverse = false)
{
if (index >= 0 && index < m_PreviousData.Count)
{
return inverse ? -m_PreviousData[index] : m_PreviousData[index];
}
else return 0;
}
public double GetFirstData(float animationDuration = 500f)
{
if (m_Data.Count > 0) return GetCurrData(0, animationDuration);
return 0;
}
public double GetLastData()
{
if (m_Data.Count > 0) return m_Data[m_Data.Count - 1];
return 0;
}
public double GetCurrData(int index, float animationDuration = 500f, bool inverse = false)
{
return GetCurrData(index, animationDuration, inverse, 0, 0);
}
public double GetCurrData(int index, float animationDuration, bool inverse, double min, double max)
{
if (index < m_DataUpdateFlag.Count && m_DataUpdateFlag[index] && animationDuration > 0)
{
var time = Time.time - m_DataUpdateTime[index];
var total = animationDuration / 1000;
var rate = time / total;
if (rate > 1) rate = 1;
if (rate < 1)
{
CheckLastData();
var curr = MathUtil.Lerp(GetPreviousData(index), GetData(index), rate);
if (min != 0 || max != 0)
{
if (inverse)
{
var temp = min;
min = -max;
max = -temp;
}
var pre = m_PreviousData[index];
if (pre < min)
{
m_PreviousData[index] = min;
curr = min;
}
else if (pre > max)
{
m_PreviousData[index] = max;
curr = max;
}
}
curr = inverse ? -curr : curr;
return curr;
}
else
{
m_DataUpdateFlag[index] = false;
return GetData(index, inverse);
}
}
else
{
return GetData(index, inverse);
}
}
/// <summary>
/// the maxinum value.
/// |最大值。
/// </summary>
public double GetMaxData(bool inverse = false)
{
if (m_Data.Count == 0) return 0;
var temp = double.MinValue;
for (int i = 0; i < m_Data.Count; i++)
{
var value = GetData(i, inverse);
if (value > temp) temp = value;
}
return temp;
}
/// <summary>
/// the mininum value.
/// |最小值。
/// </summary>
public double GetMinData(bool inverse = false)
{
if (m_Data.Count == 0) return 0;
var temp = double.MaxValue;
for (int i = 0; i < m_Data.Count; i++)
{
var value = GetData(i, inverse);
if (value < temp) temp = value;
}
return temp;
}
public double GetTotalData()
{
var total = 0d;
foreach (var value in m_Data)
total += value;
return total;
}
public bool UpdateData(int dimension, double value, bool updateAnimation, float animationDuration = 500f)
{
if (dimension >= 0 && dimension < data.Count)
{
CheckLastData();
m_PreviousData[dimension] = GetCurrData(dimension, animationDuration);
//m_PreviousData[dimension] = data[dimension];;
m_DataUpdateTime[dimension] = Time.time;
m_DataUpdateFlag[dimension] = updateAnimation;
data[dimension] = value;
return true;
}
return false;
}
public bool UpdateData(int dimension, double value)
{
if (dimension >= 0 && dimension < data.Count)
{
data[dimension] = value;
return true;
}
return false;
}
private void CheckLastData()
{
if (m_PreviousData.Count != m_Data.Count)
{
m_PreviousData.Clear();
m_DataUpdateTime.Clear();
m_DataUpdateFlag.Clear();
for (int i = 0; i < m_Data.Count; i++)
{
m_PreviousData.Add(m_Data[i]);
m_DataUpdateTime.Add(Time.time);
m_DataUpdateFlag.Add(false);
}
}
}
public bool IsDataChanged()
{
for (int i = 0; i < m_DataUpdateFlag.Count; i++)
if (m_DataUpdateFlag[i]) return true;
return false;
}
public float GetLabelWidth()
{
if (labelObject != null) return labelObject.GetTextWidth();
else return 0;
}
public float GetLabelHeight()
{
if (labelObject != null) return labelObject.GetTextHeight();
return 0;
}
public void SetLabelActive(bool flag)
{
if (labelObject != null) labelObject.SetActive(flag);
}
public void SetIconActive(bool flag)
{
if (labelObject != null) labelObject.SetActive(flag);
}
public void SetPolygon(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4)
{
m_PolygonPoints.Clear();
m_PolygonPoints.Add(p1);
m_PolygonPoints.Add(p2);
m_PolygonPoints.Add(p3);
m_PolygonPoints.Add(p4);
}
public void SetPolygon(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, Vector2 p5)
{
SetPolygon(p1, p2, p3, p4);
m_PolygonPoints.Add(p5);
}
public bool IsInPolygon(Vector2 p)
{
return UGLHelper.IsPointInPolygon(p, m_PolygonPoints);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dbf44007311214228976678a623479b9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,84 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace XCharts.Runtime
{
public class SerieDataContext
{
public Vector3 labelPosition;
/// <summary>
/// 开始角度
/// </summary>
public float startAngle;
/// <summary>
/// 结束角度
/// </summary>
public float toAngle;
/// <summary>
/// 一半时的角度
/// </summary>
public float halfAngle;
/// <summary>
/// 当前角度
/// </summary>
public float currentAngle;
/// <summary>
/// 饼图数据项的内半径
/// </summary>
public float insideRadius;
/// <summary>
/// 饼图数据项的偏移半径
/// </summary>
public float offsetRadius;
public float outsideRadius;
public Vector3 position;
public List<Vector3> dataPoints = new List<Vector3>();
public List<ChartLabel> dataLabels = new List<ChartLabel>();
public List<SerieData> children = new List<SerieData>();
/// <summary>
/// 绘制区域。
/// </summary>
public Rect rect;
public Rect backgroundRect;
public Rect subRect;
public int level;
public SerieData parent;
public Color32 color;
public double area;
public float angle;
public Vector3 offsetCenter;
public Vector3 areaCenter;
public float stackHeight;
public bool isClip;
public bool canShowLabel = true;
public Image symbol;
/// <summary>
/// Whether the data item is highlighted.
/// |该数据项是否被高亮,一般由鼠标悬停或图例悬停触发高亮。
/// </summary>
public bool highlight
{
get { return m_Highligth; }
set
{
m_Highligth = value;
}
}
private bool m_Highligth;
public bool selected;
public void Reset()
{
canShowLabel = true;
highlight = false;
parent = null;
symbol = null;
rect = Rect.zero;
subRect = Rect.zero;
children.Clear();
dataPoints.Clear();
dataLabels.Clear();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6fa67a86e80b4456cbe76ef4b330f3fb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,579 @@
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace XCharts.Runtime
{
public abstract class SerieHandler
{
public BaseChart chart { get; internal set; }
public SerieHandlerAttribute attribute { get; internal set; }
public virtual int defaultDimension { get; internal set; }
public virtual void InitComponent() { }
public virtual void RemoveComponent() { }
public virtual void CheckComponent(StringBuilder sb) { }
public virtual void Update() { }
public virtual void DrawBase(VertexHelper vh) { }
public virtual void DrawSerie(VertexHelper vh) { }
public virtual void DrawTop(VertexHelper vh) { }
public virtual void OnPointerClick(PointerEventData eventData) { }
public virtual void OnPointerDown(PointerEventData eventData) { }
public virtual void OnPointerUp(PointerEventData eventData) { }
public virtual void OnPointerEnter(PointerEventData eventData) { }
public virtual void OnPointerExit(PointerEventData eventData) { }
public virtual void OnDrag(PointerEventData eventData) { }
public virtual void OnBeginDrag(PointerEventData eventData) { }
public virtual void OnEndDrag(PointerEventData eventData) { }
public virtual void OnScroll(PointerEventData eventData) { }
public virtual void RefreshLabelNextFrame() { }
public virtual void RefreshLabelInternal() { }
public virtual void UpdateTooltipSerieParams(int dataIndex, bool showCategory,
string category, string marker,
string itemFormatter, string numericFormatter,
ref List<SerieParams> paramList, ref string title) { }
public virtual void OnLegendButtonClick(int index, string legendName, bool show) { }
public virtual void OnLegendButtonEnter(int index, string legendName) { }
public virtual void OnLegendButtonExit(int index, string legendName) { }
internal abstract void SetSerie(Serie serie);
}
public abstract class SerieHandler<T> : SerieHandler where T : Serie
{
private static readonly string s_SerieLabelObjectName = "label";
private static readonly string s_SerieTitleObjectName = "title";
private static readonly string s_SerieRootObjectName = "serie";
private static readonly string s_SerieEndLabelObjectName = "end_label";
protected GameObject m_SerieRoot;
protected GameObject m_SerieLabelRoot;
protected bool m_InitedLabel;
protected bool m_NeedInitComponent;
protected bool m_RefreshLabel;
protected bool m_LastCheckContextFlag = false;
protected bool m_LegendEnter = false;
protected int m_LegendEnterIndex;
protected ChartLabel m_EndLabel;
public T serie { get; internal set; }
public GameObject labelObject { get { return m_SerieLabelRoot; } }
internal override void SetSerie(Serie serie)
{
this.serie = (T) serie;
this.serie.context.param.serieType = typeof(T);
m_NeedInitComponent = true;
AnimationStyleHelper.UpdateSerieAnimation(serie);
}
public override void Update()
{
if (m_NeedInitComponent)
{
m_NeedInitComponent = false;
InitComponent();
}
if (m_RefreshLabel)
{
m_RefreshLabel = false;
RefreshLabelInternal();
RefreshEndLabelInternal();
}
if (serie.dataDirty)
{
SeriesHelper.UpdateSerieNameList(chart, ref chart.m_LegendRealShowName);
serie.OnDataUpdate();
serie.dataDirty = false;
}
if (serie.label != null && (serie.labelDirty || serie.label.componentDirty))
{
serie.labelDirty = false;
serie.label.ClearComponentDirty();
InitSerieLabel();
InitSerieEndLabel();
}
if (serie.endLabel != null && serie.endLabel.componentDirty)
{
serie.endLabel.ClearComponentDirty();
InitSerieEndLabel();
}
if (serie.titleStyle != null && (serie.titleDirty || serie.titleStyle.componentDirty))
{
serie.titleDirty = false;
serie.titleStyle.ClearComponentDirty();
InitSerieTitle();
}
if (serie.nameDirty)
{
foreach (var component in chart.components)
{
if (component is Legend)
component.SetAllDirty();
}
chart.RefreshChart();
serie.ClearSerieNameDirty();
}
if (serie.vertsDirty)
{
chart.RefreshPainter(serie);
serie.ResetInteract();
serie.ClearVerticesDirty();
}
}
public override void RefreshLabelNextFrame()
{
m_RefreshLabel = true;
}
public override void InitComponent()
{
m_InitedLabel = false;
InitRoot();
InitSerieLabel();
InitSerieTitle();
InitSerieEndLabel();
}
public override void RemoveComponent()
{
ChartHelper.SetActive(m_SerieRoot, false);
}
public override void OnLegendButtonClick(int index, string legendName, bool show)
{
if (serie.useDataNameForColor && serie.IsSerieDataLegendName(legendName))
{
LegendHelper.CheckDataShow(serie, legendName, show);
chart.UpdateLegendColor(legendName, show);
chart.RefreshPainter(serie);
}
else if (serie.IsLegendName(legendName))
{
chart.SetSerieActive(serie, show);
chart.RefreshPainter(serie);
}
}
public override void OnLegendButtonEnter(int index, string legendName)
{
if (serie.useDataNameForColor && serie.IsSerieDataLegendName(legendName))
{
LegendHelper.CheckDataHighlighted(serie, legendName, true);
chart.RefreshPainter(serie);
}
else if (serie.IsLegendName(legendName))
{
m_LegendEnter = true;
chart.RefreshPainter(serie);
}
}
public override void OnLegendButtonExit(int index, string legendName)
{
if (serie.useDataNameForColor && serie.IsSerieDataLegendName(legendName))
{
LegendHelper.CheckDataHighlighted(serie, legendName, false);
chart.RefreshPainter(serie);
}
else if (serie.IsLegendName(legendName))
{
m_LegendEnter = false;
chart.RefreshPainter(serie);
}
}
private void InitRoot()
{
if (m_SerieRoot != null)
{
var rect = ChartHelper.GetOrAddComponent<RectTransform>(m_SerieRoot);
rect.localPosition = Vector3.zero;
rect.sizeDelta = chart.chartSizeDelta;
rect.anchorMin = chart.chartMinAnchor;
rect.anchorMax = chart.chartMaxAnchor;
rect.pivot = chart.chartPivot;
return;
}
var objName = s_SerieRootObjectName + "_" + serie.index;
m_SerieRoot = ChartHelper.AddObject(objName, chart.transform, chart.chartMinAnchor,
chart.chartMaxAnchor, chart.chartPivot, chart.chartSizeDelta);
m_SerieRoot.hideFlags = chart.chartHideFlags;
ChartHelper.SetActive(m_SerieRoot, true);
ChartHelper.HideAllObject(m_SerieRoot);
}
private void InitSerieLabel()
{
InitRoot();
m_SerieLabelRoot = ChartHelper.AddObject(s_SerieLabelObjectName, m_SerieRoot.transform,
chart.chartMinAnchor, chart.chartMaxAnchor, chart.chartPivot, chart.chartSizeDelta);
m_SerieLabelRoot.hideFlags = chart.chartHideFlags;
SerieLabelPool.ReleaseAll(m_SerieLabelRoot.transform);
//ChartHelper.DestroyAllChildren(m_SerieLabelRoot.transform);
int count = 0;
SerieHelper.UpdateCenter(serie, chart.chartPosition, chart.chartWidth, chart.chartHeight);
for (int j = 0; j < serie.data.Count; j++)
{
var serieData = serie.data[j];
serieData.index = count;
serieData.labelObject = null;
if (AddSerieLabel(m_SerieLabelRoot, serieData, ref count))
{
m_InitedLabel = true;
count++;
}
}
RefreshLabelInternal();
}
protected bool AddSerieLabel(GameObject serieLabelRoot, SerieData serieData, ref int count)
{
if (serieData == null)
return false;
if (serieLabelRoot == null)
return false;
if (serie.IsPerformanceMode())
return false;
if (count == -1) count = serie.dataCount;
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
if (serieLabel == null)
{
serieLabel = SerieHelper.GetSerieEmphasisLabel(serie, serieData);
if (serieLabel == null || !serieLabel.show)
return false;
}
var dataAutoColor = GetSerieDataAutoColor(serieData);
serieData.context.dataLabels.Clear();
if (serie.multiDimensionLabel)
{
for (int i = 0; i < serieData.data.Count; i++)
{
var textName = string.Format("{0}_{1}_{2}_{3}", s_SerieLabelObjectName, serie.index, serieData.index, i);
var label = ChartHelper.AddChartLabel(textName, serieLabelRoot.transform, serieLabel, chart.theme.common,
"", dataAutoColor, TextAnchor.MiddleCenter);
label.SetActive(serieLabel.show);
serieData.context.dataLabels.Add(label);
}
}
else
{
var textName = ChartCached.GetSerieLabelName(s_SerieLabelObjectName, serie.index, serieData.index);
var label = ChartHelper.AddChartLabel(textName, serieLabelRoot.transform, serieLabel, chart.theme.common,
"", dataAutoColor, TextAnchor.MiddleCenter);
label.SetActive(serieLabel.show);
serieData.labelObject = label;
}
if (serieData.context.children.Count > 0)
{
foreach (var childSerieData in serieData.context.children)
{
AddSerieLabel(serieLabelRoot, childSerieData, ref count);
count++;
}
}
return true;
}
private void InitSerieEndLabel()
{
if (serie.endLabel == null)
{
if (m_EndLabel != null)
{
m_EndLabel.SetActive(false);
m_EndLabel = null;
}
return;
}
InitRoot();
var dataAutoColor = (Color) chart.GetLegendRealShowNameColor(serie.legendName);
m_EndLabel = ChartHelper.AddChartLabel(s_SerieEndLabelObjectName, m_SerieRoot.transform, serie.endLabel,
chart.theme.common, "", dataAutoColor, TextAnchor.MiddleLeft);
m_EndLabel.SetActive(serie.endLabel.show);
RefreshEndLabelInternal();
}
private void InitSerieTitle()
{
InitRoot();
var serieTitleRoot = ChartHelper.AddObject(s_SerieTitleObjectName, m_SerieRoot.transform,
chart.chartMinAnchor, chart.chartMaxAnchor, chart.chartPivot, chart.chartSizeDelta);
serieTitleRoot.hideFlags = chart.chartHideFlags;
SerieLabelPool.ReleaseAll(serieTitleRoot.transform);
ChartHelper.RemoveComponent<Text>(serieTitleRoot);
SerieHelper.UpdateCenter(serie, chart.chartPosition, chart.chartWidth, chart.chartHeight);
if (serie.titleJustForSerie)
{
var titleStyle = SerieHelper.GetTitleStyle(serie, null);
if (titleStyle != null)
{
var color = chart.GetItemColor(serie, null);
var content = string.Empty;
if (string.IsNullOrEmpty(titleStyle.formatter))
{
content = serie.serieName;
}
else
{
content = titleStyle.formatter;
FormatterHelper.ReplaceContent(ref content, 0, titleStyle.numericFormatter, serie, chart);
}
var label = ChartHelper.AddChartLabel("title_" + 0, serieTitleRoot.transform, titleStyle, chart.theme.common,
content, color, TextAnchor.MiddleCenter);
serie.context.titleObject = label;
label.SetActive(titleStyle.show);
var labelPosition = GetSerieDataTitlePosition(null, titleStyle);
var offset = titleStyle.GetOffset(serie.context.insideRadius);
label.SetPosition(labelPosition + offset);
}
}
else
{
for (int i = 0; i < serie.dataCount; i++)
{
var serieData = serie.data[i];
var titleStyle = SerieHelper.GetTitleStyle(serie, serieData);
if (titleStyle == null) continue;
var color = chart.GetItemColor(serie, serieData);
var content = string.Empty;
if (string.IsNullOrEmpty(titleStyle.formatter))
{
content = serieData.name;
}
else
{
content = titleStyle.formatter;
FormatterHelper.ReplaceContent(ref content, 0, titleStyle.numericFormatter, serie, chart);
}
FormatterHelper.ReplaceContent(ref content, i, titleStyle.numericFormatter, serie, chart);
var label = ChartHelper.AddChartLabel("title_" + i, serieTitleRoot.transform, titleStyle, chart.theme.common,
content, color, TextAnchor.MiddleCenter);
serieData.titleObject = label;
label.SetActive(titleStyle.show);
var labelPosition = GetSerieDataTitlePosition(serieData, titleStyle);
var offset = titleStyle.GetOffset(serie.context.insideRadius);
label.SetPosition(labelPosition + offset);
}
}
}
public override void RefreshLabelInternal()
{
if (!m_InitedLabel)
return;
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
foreach (var serieData in serie.data)
{
if (serieData.labelObject == null && serieData.context.dataLabels.Count <= 0)
continue;
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
var emphasisLabel = SerieHelper.GetSerieEmphasisLabel(serie, serieData);
var isHighlight = (serieData.context.highlight && emphasisLabel != null && emphasisLabel.show);
var isIgnore = serie.IsIgnoreIndex(serieData.index, defaultDimension);
var currLabel = isHighlight && emphasisLabel != null ? emphasisLabel : serieLabel;
if (serie.show &&
currLabel != null &&
(currLabel.show || isHighlight) &&
serieData.context.canShowLabel &&
!isIgnore)
{
if (serie.multiDimensionLabel)
{
var total = serieData.GetTotalData();
var color = chart.GetItemColor(serie, serieData);
for (int i = 0; i < serieData.context.dataLabels.Count; i++)
{
if (i >= serieData.context.dataPoints.Count) continue;
var labelObject = serieData.context.dataLabels[i];
var value = serieData.GetCurrData(i, dataChangeDuration);
var content = string.IsNullOrEmpty(currLabel.formatter) ?
ChartCached.NumberToStr(value, serieLabel.numericFormatter) :
SerieLabelHelper.GetFormatterContent(serie, serieData, value, total,
currLabel, color);
var offset = GetSerieDataLabelOffset(serieData, currLabel);
labelObject.SetActive(!isIgnore);
labelObject.SetText(content);
labelObject.SetPosition(serieData.context.dataPoints[i] + offset);
labelObject.UpdateIcon(currLabel.icon);
if (currLabel.textStyle.autoColor)
{
var dataAutoColor = GetSerieDataAutoColor(serieData);
if (!ChartHelper.IsClearColor(dataAutoColor))
labelObject.SetTextColor(dataAutoColor);
}
}
}
else
{
var value = serieData.GetCurrData(defaultDimension, dataChangeDuration);
var total = serie.GetDataTotal(defaultDimension, serieData);
var color = chart.GetItemColor(serie, serieData);
var content = string.IsNullOrEmpty(currLabel.formatter) ?
ChartCached.NumberToStr(value, serieLabel.numericFormatter) :
SerieLabelHelper.GetFormatterContent(serie, serieData, value, total,
currLabel, color);
serieData.SetLabelActive(!isIgnore);
serieData.labelObject.UpdateIcon(currLabel.icon);
serieData.labelObject.SetText(content);
UpdateLabelPosition(serieData, currLabel);
if (currLabel.textStyle.autoColor)
{
var dataAutoColor = GetSerieDataAutoColor(serieData);
if (!ChartHelper.IsClearColor(dataAutoColor))
serieData.labelObject.SetTextColor(dataAutoColor);
}
}
}
else
{
serieData.SetLabelActive(false);
foreach (var labelObject in serieData.context.dataLabels)
{
labelObject.SetActive(false);
}
}
}
}
public virtual void RefreshEndLabelInternal()
{
if (m_EndLabel == null)
return;
var endLabelStyle = serie.endLabel;
if (endLabelStyle == null)
return;
var dataCount = serie.context.drawPoints.Count;
var active = endLabelStyle.show && dataCount > 0;
m_EndLabel.SetActive(active);
if (active)
{
var value = serie.context.lineEndValue;
var content = SerieLabelHelper.GetFormatterContent(serie, null, value, 0,
endLabelStyle, Color.clear);
m_EndLabel.SetText(content);
m_EndLabel.SetPosition(serie.context.lineEndPostion + endLabelStyle.offset);
}
m_EndLabel.isAnimationEnd = serie.animation.IsFinish();
}
private void UpdateLabelPosition(SerieData serieData, LabelStyle currLabel)
{
var labelPosition = GetSerieDataLabelPosition(serieData, currLabel);
var offset = GetSerieDataLabelOffset(serieData, currLabel);
serieData.labelObject.SetPosition(labelPosition + offset);
}
public virtual Vector3 GetSerieDataLabelPosition(SerieData serieData, LabelStyle label)
{
return ChartHelper.IsZeroVector(serieData.context.labelPosition) ?
serieData.context.position :
serieData.context.labelPosition;
}
public virtual Vector3 GetSerieDataLabelOffset(SerieData serieData, LabelStyle label)
{
return label.GetOffset(serie.context.insideRadius);
}
public virtual Vector3 GetSerieDataTitlePosition(SerieData serieData, TitleStyle titleStyle)
{
return serieData.context.position;
}
public virtual Color GetSerieDataAutoColor(SerieData serieData)
{
var colorIndex = serie.useDataNameForColor ? serieData.index : serie.index;
return (Color) SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, false, false);
}
protected void UpdateCoordSerieParams(ref List<SerieParams> paramList, ref string title,
int dataIndex, bool showCategory, string category, string marker,
string itemFormatter, string numericFormatter)
{
if (dataIndex < 0)
dataIndex = serie.context.pointerItemDataIndex;
if (dataIndex < 0)
return;
var serieData = serie.GetSerieData(dataIndex);
if (serieData == null)
return;
itemFormatter = SerieHelper.GetItemFormatter(serie, serieData, itemFormatter);
if (TooltipHelper.IsIgnoreItemFormatter(itemFormatter))
return;
var param = serie.context.param;
param.serieName = serie.serieName;
param.serieIndex = serie.index;
param.category = category;
param.dimension = 1;
param.serieData = serieData;
param.dataCount = serie.dataCount;
param.value = serieData.GetData(1);
param.total = serie.yTotal;
param.color = SerieHelper.GetItemColor(serie, serieData, chart.theme, serie.context.colorIndex, false);
param.marker = SerieHelper.GetItemMarker(serie, serieData, marker);
param.itemFormatter = itemFormatter;
param.numericFormatter = SerieHelper.GetNumericFormatter(serie, serieData, numericFormatter);
param.columns.Clear();
param.columns.Add(param.marker);
param.columns.Add(showCategory ? category : serie.serieName);
param.columns.Add(ChartCached.NumberToStr(param.value, param.numericFormatter));
paramList.Add(param);
}
protected void UpdateItemSerieParams(ref List<SerieParams> paramList, ref string title,
int dataIndex, string category, string marker,
string itemFormatter, string numericFormatter, int dimension = 1)
{
if (dataIndex < 0)
dataIndex = serie.context.pointerItemDataIndex;
if (dataIndex < 0)
return;
var serieData = serie.GetSerieData(dataIndex);
if (serieData == null)
return;
itemFormatter = SerieHelper.GetItemFormatter(serie, serieData, itemFormatter);
if (TooltipHelper.IsIgnoreItemFormatter(itemFormatter))
return;
var colorIndex = chart.GetLegendRealShowNameIndex(serieData.name);
var param = serie.context.param;
param.serieName = serie.serieName;
param.serieIndex = serie.index;
param.category = category;
param.dimension = dimension;
param.serieData = serieData;
param.dataCount = serie.dataCount;
param.value = serieData.GetData(param.dimension);
param.total = SerieHelper.GetMaxData(serie, dimension);
param.color = SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, false);
param.marker = SerieHelper.GetItemMarker(serie, serieData, marker);
param.itemFormatter = itemFormatter;
param.numericFormatter = SerieHelper.GetNumericFormatter(serie, serieData, numericFormatter);
param.columns.Clear();
param.columns.Add(param.marker);
param.columns.Add(serieData.name);
param.columns.Add(ChartCached.NumberToStr(param.value, param.numericFormatter));
paramList.Add(param);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7f2bc0a6a80a84eae9c87842c954bc32
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace XCharts.Runtime
{
public class SerieParams
{
public Type serieType;
public int serieIndex;
public string serieName;
public string marker = "●";
public string category;
public int dimension;
public SerieData serieData;
public int dataCount;
public double value;
public double total;
public Color32 color;
public string itemFormatter;
public string numericFormatter;
public List<string> columns = new List<string>();
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c46808eb5842743c5b02d03c4c503228
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: