海拔图和小地图

This commit is contained in:
lishuo committed 2021-03-28 18:17:15 +08:00
1 parent 45801dff22
commit c5bd9daba2
521 files changed
+1985033 -439

No files matched your search

File diff suppressed because it is too large. Load diff
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d5053a63a1ebdfe4f8972f194156c3d3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,396 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
using UnityEngine.UI;
using System;
using UnityEngine.EventSystems;
namespace XCharts
{
[RequireComponent(typeof(CanvasRenderer))]
public partial class BaseGraph : MaskableGraphic, IPointerDownHandler, IPointerUpHandler,
IPointerEnterHandler, IPointerExitHandler, IBeginDragHandler, IPointerClickHandler,
IDragHandler, IEndDragHandler, IScrollHandler
{
protected static readonly string s_BackgroundObjectName = "background";
[SerializeField] protected bool m_MultiComponentMode = false;
[SerializeField] protected bool m_DebugMode = false;
[SerializeField] protected bool m_EnableTextMeshPro = false;
[SerializeField] protected Background m_Background = Background.defaultBackground;
protected Painter m_Painter;
protected int m_SiblingIndex;
protected float m_GraphWidth;
protected float m_GraphHeight;
protected float m_GraphX;
protected float m_GraphY;
protected Vector3 m_GraphPosition = Vector3.zero;
protected Vector2 m_GraphMinAnchor;
protected Vector2 m_GraphMaxAnchor;
protected Vector2 m_GraphPivot;
protected Vector2 m_GraphSizeDelta;
protected Vector2 m_GraphAnchoredPosition;
protected Rect m_GraphRect = new Rect(0, 0, 0, 0);
protected bool m_RefreshChart = false;
protected bool m_ForceOpenRaycastTarget;
protected bool m_IsControlledByLayout = false;
protected bool m_PainerDirty = false;
protected bool m_IsOnValidate = false;
protected Vector3 m_LastLocalPosition;
protected Action<PointerEventData, BaseGraph> m_OnPointerClick;
protected Action<PointerEventData, BaseGraph> m_OnPointerDown;
protected Action<PointerEventData, BaseGraph> m_OnPointerUp;
protected Action<PointerEventData, BaseGraph> m_OnPointerEnter;
protected Action<PointerEventData, BaseGraph> m_OnPointerExit;
protected Action<PointerEventData, BaseGraph> m_OnBeginDrag;
protected Action<PointerEventData, BaseGraph> m_OnDrag;
protected Action<PointerEventData, BaseGraph> m_OnEndDrag;
protected Action<PointerEventData, BaseGraph> m_OnScroll;
protected Vector2 graphAnchorMax { get { return m_GraphMinAnchor; } }
protected Vector2 graphAnchorMin { get { return m_GraphMaxAnchor; } }
protected Vector2 graphPivot { get { return m_GraphPivot; } }
internal HideFlags chartHideFlags { get { return m_DebugMode ? HideFlags.None : HideFlags.HideInHierarchy; } }
private ScrollRect m_ScrollRect;
protected virtual void InitComponent()
{
InitPainter();
InitBackground();
}
protected override void Awake()
{
CheckTextMeshPro();
m_SiblingIndex = 0;
if (transform.parent != null)
{
m_IsControlledByLayout = transform.parent.GetComponent<LayoutGroup>() != null;
}
raycastTarget = false;
m_LastLocalPosition = transform.localPosition;
UpdateSize();
InitComponent();
CheckIsInScrollRect();
}
protected override void Start()
{
m_RefreshChart = true;
}
protected virtual void Update()
{
CheckSize();
if (m_IsOnValidate)
{
m_IsOnValidate = false;
m_RefreshChart = true;
CheckTextMeshPro();
InitComponent();
}
else
{
CheckComponent();
}
CheckPointerPos();
CheckRefreshChart();
CheckRefreshPainter();
}
protected virtual void SetAllComponentDirty()
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
m_IsOnValidate = true;
Update();
}
#endif
m_PainerDirty = true;
m_Background.SetAllDirty();
}
protected virtual void CheckComponent()
{
CheckComponentDirty(m_Background);
if (m_PainerDirty)
{
InitPainter();
m_PainerDirty = false;
}
}
private void CheckTextMeshPro()
{
#if dUI_TextMeshPro
var enableTextMeshPro = true;
#else
var enableTextMeshPro = false;
#endif
if (m_EnableTextMeshPro != enableTextMeshPro)
{
m_EnableTextMeshPro = enableTextMeshPro;
RemoveChartObject();
}
}
protected void CheckComponentDirty(ChartComponent component)
{
if (component.anyDirty)
{
if (component.componentDirty)
{
component.refreshComponent?.Invoke();
}
if (component.vertsDirty)
{
if (component.painter != null)
{
RefreshPainter(component.painter);
}
}
component.ClearDirty();
}
}
#if UNITY_EDITOR
protected override void Reset()
{
}
protected override void OnValidate()
{
m_IsOnValidate = true;
}
#endif
protected override void OnDestroy()
{
for (int i = transform.childCount - 1; i >= 0; i--)
{
DestroyImmediate(transform.GetChild(i).gameObject);
}
}
protected override void OnPopulateMesh(VertexHelper vh)
{
vh.Clear();
}
private void InitBackground()
{
m_Background.painter = m_Painter;
m_Background.refreshComponent = delegate ()
{
var backgroundObj = ChartHelper.AddObject(s_BackgroundObjectName, transform, m_GraphMinAnchor,
m_GraphMaxAnchor, m_GraphPivot, m_GraphSizeDelta);
m_Background.gameObject = backgroundObj;
backgroundObj.hideFlags = chartHideFlags;
var backgroundImage = ChartHelper.GetOrAddComponent<Image>(backgroundObj);
ChartHelper.UpdateRectTransform(backgroundObj, m_GraphMinAnchor,
m_GraphMaxAnchor, m_GraphPivot, m_GraphSizeDelta);
backgroundImage.sprite = m_Background.image;
backgroundImage.type = m_Background.imageType;
backgroundImage.color = m_Background.imageColor;
backgroundObj.transform.SetSiblingIndex(0);
backgroundObj.SetActive(m_Background.show);
};
m_Background.refreshComponent();
}
protected virtual void InitPainter()
{
m_Painter = ChartHelper.AddPainterObject("painter_b", transform, m_GraphMinAnchor,
m_GraphMaxAnchor, m_GraphPivot, new Vector2(m_GraphWidth, m_GraphHeight), chartHideFlags, 1);
m_Painter.type = Painter.Type.Base;
m_Painter.onPopulateMesh = OnDrawPainterBase;
}
private void CheckSize()
{
var currWidth = rectTransform.rect.width;
var currHeight = rectTransform.rect.height;
if (m_GraphWidth == 0 && m_GraphHeight == 0 && (currWidth != 0 || currHeight != 0))
{
Awake();
}
if (m_GraphWidth != currWidth
|| m_GraphHeight != currHeight
|| m_GraphMinAnchor != rectTransform.anchorMin
|| m_GraphMaxAnchor != rectTransform.anchorMax
|| m_GraphAnchoredPosition != rectTransform.anchoredPosition)
{
UpdateSize();
}
if (!ChartHelper.IsValueEqualsVector3(m_LastLocalPosition, transform.localPosition))
{
m_LastLocalPosition = transform.localPosition;
OnLocalPositionChanged();
}
}
protected void UpdateSize()
{
m_GraphWidth = rectTransform.rect.width;
m_GraphHeight = rectTransform.rect.height;
m_GraphMaxAnchor = rectTransform.anchorMax;
m_GraphMinAnchor = rectTransform.anchorMin;
m_GraphSizeDelta = rectTransform.sizeDelta;
m_GraphAnchoredPosition = rectTransform.anchoredPosition;
rectTransform.pivot = LayerHelper.ResetChartPositionAndPivot(m_GraphMinAnchor, m_GraphMaxAnchor,
m_GraphWidth, m_GraphHeight, ref m_GraphX, ref m_GraphY);
m_GraphPivot = rectTransform.pivot;
m_GraphRect.x = m_GraphX;
m_GraphRect.y = m_GraphY;
m_GraphRect.width = m_GraphWidth;
m_GraphRect.height = m_GraphHeight;
m_GraphPosition.x = m_GraphX;
m_GraphPosition.y = m_GraphY;
OnSizeChanged();
}
private void CheckPointerPos()
{
if (m_ForceOpenRaycastTarget) raycastTarget = true;
if (IsNeedCheckPointerPos())
{
raycastTarget = true;
if (canvas == null) return;
Vector2 local;
var cam = canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : canvas.worldCamera;
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform,
Input.mousePosition, cam, out local))
{
pointerPos = Vector2.zero;
}
else
{
pointerPos = local;
}
}
else
{
raycastTarget = false;
}
}
protected virtual void CheckIsInScrollRect()
{
m_ScrollRect = GetComponentInParent<ScrollRect>();
}
protected virtual bool IsNeedCheckPointerPos()
{
return raycastTarget;
}
protected virtual void CheckRefreshChart()
{
if (m_RefreshChart)
{
m_Painter.Refresh();
m_RefreshChart = false;
}
}
protected virtual void CheckRefreshPainter()
{
m_Painter.CheckRefresh();
}
internal virtual void RefreshPainter(Painter painter)
{
if (painter == null) return;
painter.Refresh();
}
protected virtual void OnSizeChanged()
{
m_RefreshChart = true;
}
protected virtual void OnLocalPositionChanged()
{
}
protected virtual void OnDrawPainterBase(VertexHelper vh, Painter painter)
{
DrawBackground(vh);
DrawPainterBase(vh);
}
protected virtual void DrawPainterBase(VertexHelper vh)
{
}
protected virtual void DrawBackground(VertexHelper vh)
{
}
public virtual void OnPointerClick(PointerEventData eventData)
{
if (m_OnPointerClick != null) m_OnPointerClick(eventData, this);
}
public virtual void OnPointerDown(PointerEventData eventData)
{
if (m_OnPointerDown != null) m_OnPointerDown(eventData, this);
}
public virtual void OnPointerUp(PointerEventData eventData)
{
if (m_OnPointerUp != null) m_OnPointerUp(eventData, this);
}
public virtual void OnPointerEnter(PointerEventData eventData)
{
isPointerInChart = true;
if (m_OnPointerEnter != null) m_OnPointerEnter(eventData, this);
}
public virtual void OnPointerExit(PointerEventData eventData)
{
isPointerInChart = false;
if (m_OnPointerExit != null) m_OnPointerExit(eventData, this);
}
public virtual void OnBeginDrag(PointerEventData eventData)
{
if (m_ScrollRect != null) m_ScrollRect.OnBeginDrag(eventData);
if (m_OnBeginDrag != null) m_OnBeginDrag(eventData, this);
}
public virtual void OnEndDrag(PointerEventData eventData)
{
if (m_ScrollRect != null) m_ScrollRect.OnEndDrag(eventData);
if (m_OnEndDrag != null) m_OnEndDrag(eventData, this);
}
public virtual void OnDrag(PointerEventData eventData)
{
if (m_ScrollRect != null) m_ScrollRect.OnDrag(eventData);
if (m_OnDrag != null) m_OnDrag(eventData, this);
}
public virtual void OnScroll(PointerEventData eventData)
{
if (m_ScrollRect != null) m_ScrollRect.OnScroll(eventData);
if (m_OnScroll != null) m_OnScroll(eventData, this);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4f059825ead3b4a7da7f1fbcebbf545e
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: c20b1e83703d1084c899f1f1b605c278
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,704 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using XUGL;
namespace XCharts
{
public partial class CoordinateChart
{
protected Action<PointerEventData, int> m_OnPointerClickBar;
protected void DrawYBarSerie(VertexHelper vh, Serie serie, int colorIndex)
{
if (!IsActive(serie.name)) return;
if (serie.animation.HasFadeOut()) return;
var xAxis = m_XAxes[serie.xAxisIndex];
var yAxis = m_YAxes[serie.yAxisIndex];
var grid = GetSerieGridOrDefault(serie);
var showData = serie.GetDataList(dataZoom);
float categoryWidth = AxisHelper.GetDataWidth(yAxis, grid.runtimeHeight, showData.Count, dataZoom);
float barGap = GetBarGap();
float totalBarWidth = GetBarTotalWidth(categoryWidth, barGap);
float barWidth = serie.GetBarWidth(categoryWidth);
float offset = (categoryWidth - totalBarWidth) / 2;
float barGapWidth = barWidth + barWidth * barGap;
float space = serie.barGap == -1 ? offset : offset + GetBarIndex(serie) * barGapWidth;
var isStack = SeriesHelper.IsStack(m_Series, serie.stack, SerieType.Bar);
m_StackSerieData.Clear();
if (isStack) SeriesHelper.UpdateStackDataList(m_Series, serie, dataZoom, m_StackSerieData);
int maxCount = serie.maxShow > 0 ?
(serie.maxShow > showData.Count ? showData.Count : serie.maxShow)
: showData.Count;
var isPercentStack = SeriesHelper.IsPercentStack(m_Series, serie.stack, SerieType.Bar);
bool dataChanging = false;
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
float xMinValue = xAxis.GetCurrMinValue(dataChangeDuration);
float xMaxValue = xAxis.GetCurrMaxValue(dataChangeDuration);
var isAllBarEnd = true;
for (int i = serie.minShow; i < maxCount; i++)
{
var serieData = showData[i];
if (serie.IsIgnoreValue(serieData.GetData(1)))
{
serie.dataPoints.Add(Vector3.zero);
continue;
}
var highlight = (tooltip.show && tooltip.IsSelected(i))
|| serie.data[i].highlighted
|| serie.highlighted;
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, highlight);
serieData.canShowLabel = true;
float value = showData[i].GetCurrData(1, dataChangeDuration, xAxis.inverse, xMinValue, xMaxValue);
float borderWidth = value == 0 ? 0 : itemStyle.runtimeBorderWidth;
if (showData[i].IsDataChanged()) dataChanging = true;
float axisLineWidth = value == 0 ? 0
: ((value < 0 ? -1 : 1) * yAxis.axisLine.GetWidth(m_Theme.axis.lineWidth));
float pY = grid.runtimeY + i * categoryWidth;
if (!yAxis.boundaryGap) pY -= categoryWidth / 2;
float pX = grid.runtimeX + xAxis.runtimeZeroXOffset + axisLineWidth;
if (isStack)
{
for (int n = 0; n < m_StackSerieData.Count - 1; n++)
{
pX += m_StackSerieData[n][i].runtimeStackHig;
}
}
var barHig = 0f;
var valueTotal = 0f;
if (isPercentStack)
{
valueTotal = GetSameStackTotalValue(serie.stack, i);
barHig = valueTotal != 0 ? (value / valueTotal * grid.runtimeWidth) : 0;
}
else
{
valueTotal = xMaxValue - xMinValue;
if (valueTotal != 0)
barHig = (xMinValue > 0 ? value - xMinValue : value)
/ valueTotal * grid.runtimeWidth;
}
serieData.runtimeStackHig = barHig;
var isBarEnd = false;
float currHig = CheckAnimation(serie, i, barHig, out isBarEnd);
if (!isBarEnd) isAllBarEnd = false;
Vector3 plt, prt, prb, plb, top;
if (value < 0)
{
plt = new Vector3(pX - borderWidth, pY + space + barWidth - borderWidth);
prt = new Vector3(pX + currHig + borderWidth, pY + space + barWidth - borderWidth);
prb = new Vector3(pX + currHig + borderWidth, pY + space + borderWidth);
plb = new Vector3(pX - borderWidth, pY + space + borderWidth);
}
else
{
plt = new Vector3(pX + borderWidth, pY + space + barWidth - borderWidth);
prt = new Vector3(pX + currHig - borderWidth , pY + space + barWidth - borderWidth);
prb = new Vector3(pX + currHig - borderWidth , pY + space + borderWidth);
plb = new Vector3(pX + borderWidth, pY + space + borderWidth);
}
top = new Vector3(pX + currHig - borderWidth, pY + space + barWidth / 2);
plt = ClampInGrid(grid, plt);
prt = ClampInGrid(grid, prt);
prb = ClampInGrid(grid, prb);
plb = ClampInGrid(grid, plb);
top = ClampInGrid(grid, top);
serie.dataPoints.Add(top);
if (serie.show)
{
switch (serie.barType)
{
case BarType.Normal:
DrawNormalBar(vh, serie, serieData, itemStyle, colorIndex, highlight, space, barWidth,
pX, pY, plb, plt, prt, prb, true, grid);
break;
case BarType.Zebra:
DrawZebraBar(vh, serie, serieData, itemStyle, colorIndex, highlight, space, barWidth,
pX, pY, plb, plt, prt, prb, true, grid);
break;
case BarType.Capsule:
DrawCapsuleBar(vh, serie, serieData, itemStyle, colorIndex, highlight, space, barWidth,
pX, pY, plb, plt, prt, prb, true, grid);
break;
}
}
}
if (isAllBarEnd) serie.animation.AllBarEnd();
if (dataChanging)
{
RefreshPainter(serie);
}
}
private float CheckAnimation(Serie serie, int dataIndex, float barHig, out bool isBarEnd)
{
float currHig = serie.animation.CheckBarProgress(dataIndex, barHig, serie.dataCount, out isBarEnd);
if (!serie.animation.IsFinish())
{
RefreshPainter(serie);
m_IsPlayingAnimation = true;
}
return currHig;
}
protected void DrawXBarSerie(VertexHelper vh, Serie serie, int colorIndex)
{
if (!IsActive(serie.index)) return;
if (serie.animation.HasFadeOut()) return;
var showData = serie.GetDataList(dataZoom);
var yAxis = m_YAxes[serie.yAxisIndex];
var xAxis = m_XAxes[serie.xAxisIndex];
var grid = GetSerieGridOrDefault(serie);
var isStack = SeriesHelper.IsStack(m_Series, serie.stack, SerieType.Bar);
m_StackSerieData.Clear();
if (isStack) SeriesHelper.UpdateStackDataList(m_Series, serie, dataZoom, m_StackSerieData);
float categoryWidth = AxisHelper.GetDataWidth(xAxis, grid.runtimeWidth, showData.Count, dataZoom);
float barGap = GetBarGap();
float totalBarWidth = GetBarTotalWidth(categoryWidth, barGap);
float barWidth = serie.GetBarWidth(categoryWidth);
float offset = (categoryWidth - totalBarWidth) / 2;
float barGapWidth = barWidth + barWidth * barGap;
float space = serie.barGap == -1 ? offset : offset + GetBarIndex(serie) * barGapWidth;
int maxCount = serie.maxShow > 0
? (serie.maxShow > showData.Count ? showData.Count : serie.maxShow)
: showData.Count;
var isPercentStack = SeriesHelper.IsPercentStack(m_Series, serie.stack, SerieType.Bar);
bool dataChanging = false;
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
float yMinValue = yAxis.GetCurrMinValue(dataChangeDuration);
float yMaxValue = yAxis.GetCurrMaxValue(dataChangeDuration);
var isAllBarEnd = true;
for (int i = serie.minShow; i < maxCount; i++)
{
var serieData = showData[i];
if (serie.IsIgnoreValue(serieData.GetData(1)))
{
serie.dataPoints.Add(Vector3.zero);
continue;
}
var highlight = (tooltip.show && tooltip.IsSelected(i))
|| serie.data[i].highlighted
|| serie.highlighted;
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, highlight);
float value = serieData.GetCurrData(1, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
float borderWidth = value == 0 ? 0 : itemStyle.runtimeBorderWidth;
if (serieData.IsDataChanged()) dataChanging = true;
float pX = grid.runtimeX + i * categoryWidth;
float zeroY = grid.runtimeY + yAxis.runtimeZeroYOffset;
if (!xAxis.boundaryGap) pX -= categoryWidth / 2;
float axisLineWidth = value == 0 ? 0 :
((value < 0 ? -1 : 1) * xAxis.axisLine.GetWidth(m_Theme.axis.lineWidth));
float pY = zeroY + axisLineWidth;
if (isStack)
{
for (int n = 0; n < m_StackSerieData.Count - 1; n++)
{
pY += m_StackSerieData[n][i].runtimeStackHig;
}
}
var barHig = 0f;
var valueTotal = 0f;
if (isPercentStack)
{
valueTotal = GetSameStackTotalValue(serie.stack, i);
barHig = valueTotal != 0 ? (value / valueTotal * grid.runtimeHeight) : 0;
}
else
{
valueTotal = yMaxValue - yMinValue;
if (valueTotal != 0)
{
barHig = (yMinValue > 0 ? value - yMinValue : value) / valueTotal * grid.runtimeHeight;
}
}
serieData.runtimeStackHig = barHig;
var isBarEnd = false;
float currHig = CheckAnimation(serie, i, barHig, out isBarEnd);
if (!isBarEnd) isAllBarEnd = false;
Vector3 plb, plt, prt, prb, top;
if (value < 0)
{
plb = new Vector3(pX + space + borderWidth, pY - borderWidth);
plt = new Vector3(pX + space + borderWidth, pY + currHig + borderWidth);
prt = new Vector3(pX + space + barWidth - borderWidth, pY + currHig + borderWidth);
prb = new Vector3(pX + space + barWidth - borderWidth, pY - borderWidth);
}
else
{
plb = new Vector3(pX + space + borderWidth, pY + borderWidth);
plt = new Vector3(pX + space + borderWidth, pY + currHig - borderWidth);
prt = new Vector3(pX + space + barWidth - borderWidth, pY + currHig - borderWidth);
prb = new Vector3(pX + space + barWidth - borderWidth, pY + borderWidth);
}
top = new Vector3(pX + space + barWidth / 2, pY + currHig - borderWidth);
if (serie.clip)
{
plb = ClampInGrid(grid, plb);
plt = ClampInGrid(grid, plt);
prt = ClampInGrid(grid, prt);
prb = ClampInGrid(grid, prb);
top = ClampInGrid(grid, top);
}
serie.dataPoints.Add(top);
if (serie.show && currHig != 0)
{
switch (serie.barType)
{
case BarType.Normal:
DrawNormalBar(vh, serie, serieData, itemStyle, colorIndex, highlight, space, barWidth,
pX, pY, plb, plt, prt, prb, false, grid);
break;
case BarType.Zebra:
DrawZebraBar(vh, serie, serieData, itemStyle, colorIndex, highlight, space, barWidth,
pX, pY, plb, plt, prt, prb, false, grid);
break;
case BarType.Capsule:
DrawCapsuleBar(vh, serie, serieData, itemStyle, colorIndex, highlight, space, barWidth,
pX, pY, plb, plt, prt, prb, false, grid);
break;
}
}
}
if (isAllBarEnd)
{
serie.animation.AllBarEnd();
}
if (dataChanging)
{
RefreshPainter(serie);
}
}
private void DrawNormalBar(VertexHelper vh, Serie serie, SerieData serieData, ItemStyle itemStyle, int colorIndex,
bool highlight, float space, float barWidth, float pX, float pY, Vector3 plb, Vector3 plt, Vector3 prt,
Vector3 prb, bool isYAxis, Grid grid)
{
var areaColor = SerieHelper.GetItemColor(serie, serieData, m_Theme, colorIndex, highlight);
var areaToColor = SerieHelper.GetItemToColor(serie, serieData, m_Theme, colorIndex, highlight);
DrawBarBackground(vh, serie, serieData, itemStyle, colorIndex, highlight, pX, pY, space, barWidth, isYAxis, grid);
var borderWidth = itemStyle.runtimeBorderWidth;
if (isYAxis)
{
if (serie.clip)
{
prb = ClampInGrid(grid, prb);
plb = ClampInGrid(grid, plb);
plt = ClampInGrid(grid, plt);
prt = ClampInGrid(grid, prt);
}
var borderColor = itemStyle.borderColor;
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)
{
if (ItemStyleHelper.IsNeedCorner(itemStyle))
{
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, areaColor, areaToColor, 0,
itemStyle.cornerRadius, isYAxis);
}
else
{
CheckClipAndDrawPolygon(vh, plb, plt, prt, prb, areaColor, areaToColor, serie.clip, grid);
}
UGL.DrawBorder(vh, center, itemWidth, itemHeight, borderWidth, borderColor, 0,
itemStyle.cornerRadius, isYAxis);
}
}
else
{
if (serie.clip)
{
prb = ClampInGrid(grid, prb);
plb = ClampInGrid(grid, plb);
plt = ClampInGrid(grid, plt);
prt = ClampInGrid(grid, prt);
}
var borderColor = itemStyle.borderColor;
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)
{
if (ItemStyleHelper.IsNeedCorner(itemStyle))
{
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, areaColor, areaToColor, 0,
itemStyle.cornerRadius, isYAxis);
}
else
{
CheckClipAndDrawPolygon(vh, ref prb, ref plb, ref plt, ref prt, areaColor, areaToColor,
serie.clip, grid);
}
UGL.DrawBorder(vh, center, itemWidth, itemHeight, borderWidth, borderColor, 0,
itemStyle.cornerRadius, isYAxis);
}
}
}
private void DrawZebraBar(VertexHelper vh, Serie serie, SerieData serieData, ItemStyle itemStyle, int colorIndex,
bool highlight, float space, float barWidth, float pX, float pY, Vector3 plb, Vector3 plt, Vector3 prt,
Vector3 prb, bool isYAxis, Grid grid)
{
var areaColor = SerieHelper.GetItemColor(serie, serieData, m_Theme, colorIndex, highlight);
DrawBarBackground(vh, serie, serieData, itemStyle, colorIndex, highlight, pX, pY, space, barWidth, isYAxis, grid);
if (isYAxis)
{
plt = (plb + plt) / 2;
prt = (prt + prb) / 2;
CheckClipAndDrawZebraLine(vh, plt, prt, barWidth / 2, serie.barZebraWidth, serie.barZebraGap,
areaColor, serie.clip, grid);
}
else
{
plb = (prb + plb) / 2;
plt = (plt + prt) / 2;
CheckClipAndDrawZebraLine(vh, plb, plt, barWidth / 2, serie.barZebraWidth, serie.barZebraGap,
areaColor, serie.clip, grid);
}
}
private void DrawCapsuleBar(VertexHelper vh, Serie serie, SerieData serieData, ItemStyle itemStyle, int colorIndex,
bool highlight, float space, float barWidth, float pX, float pY, Vector3 plb, Vector3 plt, Vector3 prt,
Vector3 prb, bool isYAxis, Grid grid)
{
var areaColor = SerieHelper.GetItemColor(serie, serieData, m_Theme, colorIndex, highlight);
var areaToColor = SerieHelper.GetItemToColor(serie, serieData, m_Theme, colorIndex, highlight);
DrawBarBackground(vh, serie, serieData, itemStyle, colorIndex, highlight, pX, pY, space, barWidth, isYAxis, grid);
var borderWidth = itemStyle.runtimeBorderWidth;
var radius = barWidth / 2 - borderWidth;
var isGradient = !ChartHelper.IsValueEqualsColor(areaColor, areaToColor);
if (isYAxis)
{
var diff = Vector3.right * radius;
if (plt.x < prt.x)
{
var pcl = (plt + plb) / 2 + diff;
var pcr = (prt + prb) / 2 - diff;
if (pcr.x > pcl.x)
{
if (isGradient)
{
var barLen = prt.x - plt.x;
var rectStartColor = Color32.Lerp(areaColor, areaToColor, radius / barLen);
var rectEndColor = Color32.Lerp(areaColor, areaToColor, (barLen - radius) / barLen);
CheckClipAndDrawPolygon(vh, plb + diff, plt + diff, prt - diff, prb - diff, rectStartColor,
rectEndColor, serie.clip, grid);
UGL.DrawSector(vh, pcl, radius, areaColor, rectStartColor, 180, 360, 1, isYAxis);
UGL.DrawSector(vh, pcr, radius, rectEndColor, areaToColor, 0, 180, 1, isYAxis);
}
else
{
CheckClipAndDrawPolygon(vh, plb + diff, plt + diff, prt - diff, prb - diff, areaColor,
areaToColor, serie.clip, grid);
UGL.DrawSector(vh, pcl, radius, areaColor, 180, 360);
UGL.DrawSector(vh, pcr, radius, areaToColor, 0, 180);
}
}
}
else if (plt.x > prt.x)
{
var pcl = (plt + plb) / 2 - diff;
var pcr = (prt + prb) / 2 + diff;
if (pcr.x < pcl.x)
{
if (isGradient)
{
var barLen = plt.x - prt.x;
var rectStartColor = Color32.Lerp(areaColor, areaToColor, radius / barLen);
var rectEndColor = Color32.Lerp(areaColor, areaToColor, (barLen - radius) / barLen);
CheckClipAndDrawPolygon(vh, plb - diff, plt - diff, prt + diff, prb + diff, rectStartColor,
rectEndColor, serie.clip, grid);
UGL.DrawSector(vh, pcl, radius, rectStartColor, areaColor, 0, 180, 1, isYAxis);
UGL.DrawSector(vh, pcr, radius, areaToColor, rectEndColor, 180, 360, 1, isYAxis);
}
else
{
CheckClipAndDrawPolygon(vh, plb - diff, plt - diff, prt + diff, prb + diff, areaColor,
areaToColor, serie.clip, grid);
UGL.DrawSector(vh, pcl, radius, areaColor, 0, 180);
UGL.DrawSector(vh, pcr, radius, areaToColor, 180, 360);
}
}
}
}
else
{
var diff = Vector3.up * radius;
if (plt.y > plb.y)
{
var pct = (plt + prt) / 2 - diff;
var pcb = (plb + prb) / 2 + diff;
if (pct.y > pcb.y)
{
if (isGradient)
{
var barLen = plt.y - plb.y;
var rectStartColor = Color32.Lerp(areaColor, areaToColor, radius / barLen);
var rectEndColor = Color32.Lerp(areaColor, areaToColor, (barLen - radius) / barLen);
CheckClipAndDrawPolygon(vh, prb + diff, plb + diff, plt - diff, prt - diff, rectStartColor,
rectEndColor, serie.clip, grid);
UGL.DrawSector(vh, pct, radius, rectEndColor, areaToColor, 270, 450, 1, isYAxis);
UGL.DrawSector(vh, pcb, radius, rectStartColor, areaColor, 90, 270, 1, isYAxis);
}
else
{
CheckClipAndDrawPolygon(vh, prb + diff, plb + diff, plt - diff, prt - diff, areaColor,
areaToColor, serie.clip, grid);
UGL.DrawSector(vh, pct, radius, areaToColor, 270, 450);
UGL.DrawSector(vh, pcb, radius, areaColor, 90, 270);
}
}
}
else if (plt.y < plb.y)
{
var pct = (plt + prt) / 2 + diff;
var pcb = (plb + prb) / 2 - diff;
if (pct.y < pcb.y)
{
if (isGradient)
{
var barLen = plb.y - plt.y;
var rectStartColor = Color32.Lerp(areaColor, areaToColor, radius / barLen);
var rectEndColor = Color32.Lerp(areaColor, areaToColor, (barLen - radius) / barLen);
CheckClipAndDrawPolygon(vh, prb - diff, plb - diff, plt + diff, prt + diff, rectStartColor,
rectEndColor, serie.clip, grid);
UGL.DrawSector(vh, pct, radius, rectEndColor, areaToColor, 90, 270, 1, isYAxis);
UGL.DrawSector(vh, pcb, radius, rectStartColor, areaColor, 270, 450, 1, isYAxis);
}
else
{
CheckClipAndDrawPolygon(vh, prb - diff, plb - diff, plt + diff, prt + diff, areaColor,
areaToColor, serie.clip, grid);
UGL.DrawSector(vh, pct, radius, areaToColor, 90, 270);
UGL.DrawSector(vh, pcb, radius, areaColor, 270, 450);
}
}
}
}
}
private void DrawBarBackground(VertexHelper vh, Serie serie, SerieData serieData, ItemStyle itemStyle,
int colorIndex, bool highlight, float pX, float pY, float space, float barWidth, bool isYAxis, Grid grid)
{
var color = SerieHelper.GetItemBackgroundColor(serie, serieData, m_Theme, colorIndex, highlight, false);
if (ChartHelper.IsClearColor(color)) return;
if (isYAxis)
{
var axis = m_YAxes[serie.yAxisIndex];
var axisWidth = axis.axisLine.GetWidth(m_Theme.axis.lineWidth);
Vector3 plt = new Vector3(grid.runtimeX + axisWidth, pY + space + barWidth);
Vector3 prt = new Vector3(grid.runtimeX + axisWidth + grid.runtimeWidth, pY + space + barWidth);
Vector3 prb = new Vector3(grid.runtimeX + axisWidth + grid.runtimeWidth, pY + space);
Vector3 plb = new Vector3(grid.runtimeX + axisWidth, pY + space);
if (serie.barType == BarType.Capsule)
{
var radius = barWidth / 2;
var diff = Vector3.right * radius;
var pcl = (plt + plb) / 2 + diff;
var pcr = (prt + prb) / 2 - diff;
CheckClipAndDrawPolygon(vh, plb + diff, plt + diff, prt - diff, prb - diff, color, color, serie.clip, grid);
UGL.DrawSector(vh, pcl, radius, color, 180, 360);
UGL.DrawSector(vh, pcr, radius, color, 0, 180);
if (itemStyle.NeedShowBorder())
{
var borderWidth = itemStyle.borderWidth;
var borderColor = itemStyle.borderColor;
var smoothness = settings.cicleSmoothness;
var inRadius = radius - borderWidth;
var outRadius = radius;
var p1 = plb + diff + Vector3.up * borderWidth / 2;
var p2 = prb - diff + Vector3.up * borderWidth / 2;
var p3 = plt + diff - Vector3.up * borderWidth / 2;
var p4 = prt - diff - Vector3.up * borderWidth / 2;
UGL.DrawLine(vh, p1, p2, borderWidth / 2, borderColor);
UGL.DrawLine(vh, p3, p4, borderWidth / 2, borderColor);
UGL.DrawDoughnut(vh, pcl, inRadius, outRadius, borderColor, ChartConst.clearColor32,
180, 360, smoothness);
UGL.DrawDoughnut(vh, pcr, inRadius, outRadius, borderColor, ChartConst.clearColor32,
0, 180, smoothness);
}
}
else
{
CheckClipAndDrawPolygon(vh, ref plb, ref plt, ref prt, ref prb, color, color, serie.clip, grid);
}
}
else
{
var axis = m_XAxes[serie.xAxisIndex];
var axisWidth = axis.axisLine.GetWidth(m_Theme.axis.lineWidth);
Vector3 plb = new Vector3(pX + space, grid.runtimeY + axisWidth);
Vector3 plt = new Vector3(pX + space, grid.runtimeY + grid.runtimeHeight + axisWidth);
Vector3 prt = new Vector3(pX + space + barWidth, grid.runtimeY + grid.runtimeHeight + axisWidth);
Vector3 prb = new Vector3(pX + space + barWidth, grid.runtimeY + axisWidth);
if (serie.barType == BarType.Capsule)
{
var radius = barWidth / 2;
var diff = Vector3.up * radius;
var pct = (plt + prt) / 2 - diff;
var pcb = (plb + prb) / 2 + diff;
CheckClipAndDrawPolygon(vh, prb + diff, plb + diff, plt - diff, prt - diff, color, color,
serie.clip, grid);
UGL.DrawSector(vh, pct, radius, color, 270, 450);
UGL.DrawSector(vh, pcb, radius, color, 90, 270);
if (itemStyle.NeedShowBorder())
{
var borderWidth = itemStyle.borderWidth;
var borderColor = itemStyle.borderColor;
var smoothness = settings.cicleSmoothness;
var inRadius = radius - borderWidth;
var outRadius = radius;
var p1 = plb + diff + Vector3.right * borderWidth / 2;
var p2 = plt - diff + Vector3.right * borderWidth / 2;
var p3 = prb + diff - Vector3.right * borderWidth / 2;
var p4 = prt - diff - Vector3.right * borderWidth / 2;
UGL.DrawLine(vh, p1, p2, borderWidth / 2, borderColor);
UGL.DrawLine(vh, p3, p4, borderWidth / 2, borderColor);
UGL.DrawDoughnut(vh, pct, inRadius, outRadius, borderColor, ChartConst.clearColor32,
270, 450, smoothness);
UGL.DrawDoughnut(vh, pcb, inRadius, outRadius, borderColor, ChartConst.clearColor32,
90, 270, smoothness);
}
}
else
{
CheckClipAndDrawPolygon(vh, ref prb, ref plb, ref plt, ref prt, color, color, serie.clip, grid);
}
}
}
private float GetBarGap()
{
float gap = 0.3f;
for (int i = 0; i < m_Series.Count; i++)
{
var serie = m_Series.list[i];
if (serie.type == SerieType.Bar || serie.type == SerieType.Candlestick)
{
if (serie.barGap != 0)
{
gap = serie.barGap;
}
}
}
return gap;
}
private float GetSameStackTotalValue(string stack, int dataIndex)
{
if (string.IsNullOrEmpty(stack)) return 0;
float total = 0;
foreach (var serie in m_Series.list)
{
if (serie.type == SerieType.Bar)
{
if (stack.Equals(serie.stack))
{
total += serie.data[dataIndex].data[1];
}
}
}
return total;
}
private HashSet<string> barStackSet = new HashSet<string>();
private float GetBarTotalWidth(float categoryWidth, float gap)
{
float total = 0;
float lastGap = 0;
barStackSet.Clear();
for (int i = 0; i < m_Series.Count; i++)
{
var serie = m_Series.list[i];
if (!serie.show) continue;
if (serie.type == SerieType.Bar || serie.type == SerieType.Candlestick)
{
if (!string.IsNullOrEmpty(serie.stack))
{
if (barStackSet.Contains(serie.stack)) continue;
barStackSet.Add(serie.stack);
}
var width = GetStackBarWidth(categoryWidth, serie);
if (gap == -1)
{
if (width > total) total = width;
}
else
{
lastGap = width * gap;
total += width;
total += lastGap;
}
}
}
if (total > 0 && gap != -1) total -= lastGap;
return total;
}
private float GetStackBarWidth(float categoryWidth, Serie now)
{
if (string.IsNullOrEmpty(now.stack)) return now.GetBarWidth(categoryWidth);
float barWidth = 0;
for (int i = 0; i < m_Series.Count; i++)
{
var serie = m_Series.list[i];
if ((serie.type == SerieType.Bar && serie.type == SerieType.Candlestick)
&& serie.show && now.stack.Equals(serie.stack))
{
if (serie.barWidth > barWidth) barWidth = serie.barWidth;
}
}
if (barWidth > 1) return barWidth;
else return barWidth * categoryWidth;
}
private List<string> tempList = new List<string>();
private int GetBarIndex(Serie currSerie)
{
tempList.Clear();
int index = 0;
for (int i = 0; i < m_Series.Count; i++)
{
var serie = m_Series.GetSerie(i);
if (serie.type != SerieType.Bar) continue;
if (string.IsNullOrEmpty(serie.stack))
{
if (serie.index == currSerie.index) return index;
tempList.Add(string.Empty);
index++;
}
else
{
if (!tempList.Contains(serie.stack))
{
if (serie.index == currSerie.index) return index;
tempList.Add(serie.stack);
index++;
}
else
{
if (serie.index == currSerie.index) return tempList.IndexOf(serie.stack);
}
}
}
return 0;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2abce1026caf74ffbb653c6e1a8d1e3f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,148 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
using UnityEngine.UI;
using XUGL;
namespace XCharts
{
public partial class CoordinateChart
{
protected void DrawCandlestickSerie(VertexHelper vh, int colorIndex, Serie serie)
{
if (!IsActive(serie.index)) return;
if (serie.animation.HasFadeOut()) return;
var showData = serie.GetDataList(dataZoom);
var yAxis = m_YAxes[serie.yAxisIndex];
var xAxis = m_XAxes[serie.xAxisIndex];
var grid = GetSerieGridOrDefault(serie);
float categoryWidth = AxisHelper.GetDataWidth(xAxis, grid.runtimeWidth, showData.Count, dataZoom);
float barGap = GetBarGap();
float barWidth = serie.GetBarWidth(categoryWidth);
float space = (categoryWidth - barWidth) / 2;
float barGapWidth = barWidth + barWidth * barGap;
int maxCount = serie.maxShow > 0
? (serie.maxShow > showData.Count ? showData.Count : serie.maxShow)
: showData.Count;
bool dataChanging = false;
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
float yMinValue = yAxis.GetCurrMinValue(dataChangeDuration);
float yMaxValue = yAxis.GetCurrMaxValue(dataChangeDuration);
var isAllBarEnd = true;
var isYAxis = false;
for (int i = serie.minShow; i < maxCount; i++)
{
var serieData = showData[i];
if (serie.IsIgnoreValue(serieData.GetData(1)))
{
serie.dataPoints.Add(Vector3.zero);
continue;
}
var highlight = (tooltip.show && tooltip.IsSelected(i))
|| serie.data[i].highlighted
|| serie.highlighted;
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 = close > open;
var borderWidth = open == 0 ? 0f
: (itemStyle.runtimeBorderWidth == 0 ? m_Theme.serie.candlestickBorderWidth
: itemStyle.runtimeBorderWidth);
if (serieData.IsDataChanged()) dataChanging = true;
float pX = grid.runtimeX + i * categoryWidth;
float zeroY = grid.runtimeY + yAxis.runtimeZeroYOffset;
if (!xAxis.boundaryGap) pX -= categoryWidth / 2;
float pY = zeroY;
var barHig = 0f;
var valueTotal = yMaxValue - yMinValue;
var minCut = (yMinValue > 0 ? yMinValue : 0);
if (valueTotal != 0)
{
barHig = (close - open) / valueTotal * grid.runtimeHeight;
pY += (open - minCut) / valueTotal * grid.runtimeHeight;
}
serieData.runtimeStackHig = barHig;
var isBarEnd = false;
float currHig = CheckAnimation(serie, i, barHig, out isBarEnd);
if (!isBarEnd) isAllBarEnd = false;
Vector3 plb, plt, prt, prb, top;
plb = new Vector3(pX + space + borderWidth, pY + borderWidth);
plt = new Vector3(pX + space + borderWidth, pY + currHig - borderWidth);
prt = new Vector3(pX + space + barWidth - borderWidth, pY + currHig - borderWidth);
prb = new Vector3(pX + space + barWidth - borderWidth, pY + borderWidth);
top = new Vector3(pX + space + barWidth / 2, pY + currHig - borderWidth);
if (serie.clip)
{
plb = ClampInGrid(grid, plb);
plt = ClampInGrid(grid, plt);
prt = ClampInGrid(grid, prt);
prb = ClampInGrid(grid, prb);
top = ClampInGrid(grid, top);
}
serie.dataPoints.Add(top);
var areaColor = isRise
? itemStyle.GetColor(m_Theme.serie.candlestickColor)
: itemStyle.GetColor0(m_Theme.serie.candlestickColor0);
var borderColor = isRise
? itemStyle.GetBorderColor(m_Theme.serie.candlestickBorderColor)
: itemStyle.GetBorderColor0(m_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 + (lowest - minCut) / valueTotal * grid.runtimeHeight);
var heighPos = new Vector3(center.x, zeroY + (heighest - minCut) / valueTotal * grid.runtimeHeight);
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 (ItemStyleHelper.IsNeedCorner(itemStyle))
{
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, areaColor, areaColor, 0,
itemStyle.cornerRadius, isYAxis, 0.5f);
}
else
{
CheckClipAndDrawPolygon(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 (isAllBarEnd)
{
serie.animation.AllBarEnd();
}
if (dataChanging)
{
RefreshPainter(serie);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c404a9bbfdf51409e808fb354c438ca2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,178 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
using UnityEngine.UI;
using XUGL;
namespace XCharts
{
public partial class CoordinateChart
{
protected void DrawGanttSerie(VertexHelper vh, int colorIndex, Serie serie)
{
if (!IsActive(serie.index)) return;
if (serie.animation.HasFadeOut()) return;
var showData = serie.GetDataList(null);
var yAxis = m_YAxes[serie.yAxisIndex];
var xAxis = m_XAxes[serie.xAxisIndex];
var grid = GetSerieGridOrDefault(serie);
var xCategoryWidth = AxisHelper.GetDataWidth(xAxis, grid.runtimeWidth, showData.Count, dataZoom);
var yCategoryWidth = AxisHelper.GetDataWidth(yAxis, grid.runtimeHeight, showData.Count, dataZoom);
var barGap = GetBarGap();
var barWidth = serie.GetBarWidth(yCategoryWidth);
var space = (yCategoryWidth - barWidth) / 2;
var dataChanging = false;
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
var minValue = xAxis.GetCurrMinValue(dataChangeDuration);
var maxValue = xAxis.GetCurrMaxValue(dataChangeDuration);
var pX = grid.runtimeX + (xAxis.boundaryGap ? xCategoryWidth / 2 : 0);
var pY = 0f;
var startY = grid.runtimeY - (yAxis.boundaryGap ? 0 : yCategoryWidth / 2);
var isTime = xAxis.type == Axis.AxisType.Time;
var categoryIndex = GetGanttSerieCategoryIndex(serie, grid.index);
var dataCount = serie.data.Count;
for (int i = 0; i < dataCount; i++)
{
var serieData = serie.data[i];
pY = startY + (categoryIndex - 1 - i) * yCategoryWidth;
DrawSerieData(vh, grid, serie, serieData, colorIndex, pX, pY, space, barWidth, isTime, minValue,
maxValue, xCategoryWidth);
}
if (dataChanging)
{
RefreshPainter(serie);
}
}
private void DrawSerieData(VertexHelper vh, Grid grid, Serie serie, SerieData serieData, int colorIndex,
float pX, float pY, float space, float barWidth, bool isTime, float minValue, float maxValue,
float xCategoryWidth)
{
var xStart = 0f;
var xEnd = 0f;
var xActualStart = 0f;
var xActualEnd = 0f;
var start = (int)serieData.GetData(0);
var end = (int)serieData.GetData(1);
var actualStart = (int)serieData.GetData(2);
var actualEnd = (int)serieData.GetData(3);
var enableActual = actualStart > 0 && actualEnd > 0;
if (isTime)
{
var valueTotal = maxValue - minValue;
xStart = pX + (start - minValue) / valueTotal * grid.runtimeWidth;
xEnd = pX + (end - minValue) / valueTotal * grid.runtimeWidth;
if (enableActual)
{
xActualStart = pX + (actualStart - minValue) / valueTotal * grid.runtimeWidth;
xActualEnd = pX + (actualEnd - minValue) / valueTotal * grid.runtimeWidth;
}
}
else
{
xStart = pX + start * xCategoryWidth;
xEnd = pX + end * xCategoryWidth;
if (enableActual)
{
xActualStart = pX + actualStart * xCategoryWidth;
xActualEnd = pX + actualEnd * xCategoryWidth;
}
}
var highlight = (serieData != null && serieData.highlighted)
|| serie.highlighted;
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, highlight);
var color = SerieHelper.GetItemColor(serie, serieData, m_Theme, colorIndex, highlight);
var borderWidth = itemStyle.borderWidth;
var rect = DrawGanttBar(vh, grid, serie, serieData, itemStyle, color, pY, pY, space, barWidth, xStart,
xEnd);
if (enableActual)
{
var defaultActualColor = SerieHelper.GetItemColor(serie, serieData, m_Theme, colorIndex, true);
var actualColor = SerieHelper.GetItemColor0(serie, serieData, m_Theme, highlight, defaultActualColor);
var rect2 = DrawGanttBar(vh, grid, serie, serieData, itemStyle, actualColor, pY, pY, space, barWidth,
xActualStart, xActualEnd);
var rect3X = Mathf.Min(rect.x, rect2.x);
var rect3Width = Mathf.Max(rect.x + rect.width, rect2.x + rect2.width) - rect3X;
var rect3 = new Rect(rect3X, rect.y, rect3Width, rect.height);
serie.dataPoints.Add(rect3.center);
serieData.runtimePosition = rect3.center;
serieData.labelPosition = rect3.center;
serieData.runtimeRect = rect3;
}
else
{
serie.dataPoints.Add(rect.center);
serieData.runtimePosition = rect.center;
serieData.labelPosition = rect.center;
serieData.runtimeRect = rect;
}
}
private Rect DrawGanttBar(VertexHelper vh, Grid grid, Serie serie, SerieData serieData, ItemStyle itemStyle,
Color32 color, float pX, float pY, float space, float barWidth, float xStart, float xEnd)
{
var borderWidth = itemStyle.borderWidth;
var plb = new Vector3(xStart + borderWidth, pY + space + borderWidth);
var plt = new Vector3(xStart + borderWidth, pY + space + barWidth - borderWidth);
var prt = new Vector3(xEnd - borderWidth, pY + space + barWidth - borderWidth);
var prb = new Vector3(xEnd - borderWidth, pY + space + borderWidth);
var center = new Vector3((plb.x + prt.x) / 2, (plt.y + prb.y) / 2);
var itemWidth = Mathf.Abs(prt.x - plb.x);
var itemHeight = Mathf.Abs(plt.y - prb.y);
if (serie.clip)
{
plb = ClampInGrid(grid, plb);
plt = ClampInGrid(grid, plt);
prt = ClampInGrid(grid, prt);
prb = ClampInGrid(grid, prb);
center = ClampInGrid(grid, center);
}
if (ItemStyleHelper.IsNeedCorner(itemStyle))
{
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, color, color, 0,
itemStyle.cornerRadius, true, 0.5f);
}
else
{
CheckClipAndDrawPolygon(vh, ref prb, ref plb, ref plt, ref prt, color, color,
serie.clip, grid);
}
if (borderWidth != 0)
{
UGL.DrawBorder(vh, center, itemWidth, itemHeight, borderWidth, itemStyle.borderColor, 0,
itemStyle.cornerRadius, true, 0.5f);
}
return new Rect(plb.x, plb.y, xEnd - xStart, barWidth);
}
private int GetGanttSerieCategoryIndex(Serie currSerie, int gridIndex)
{
var count = m_Series.Count;
var index = 0;
for (int i = 0; i < count; i++)
{
var serie = m_Series.GetSerie(i);
if (serie.type != SerieType.Gantt) continue;
var grid = GetSerieGridOrDefault(serie);
if (grid.index != gridIndex) continue;
foreach (var serieData in serie.data)
{
index++;
}
if (serie.index == currSerie.index)
{
return index;
}
}
return index;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 81895b3c97e684e8090572c7e64b396e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,405 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
using UnityEngine.UI;
using XUGL;
namespace XCharts
{
public partial class CoordinateChart
{
private bool m_VisualMapMinDrag;
private bool m_VisualMapMaxDrag;
protected void CheckVisualMap()
{
if (visualMap == null || !visualMap.enable || !visualMap.show) return;
Vector2 local;
if (canvas == null) return;
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform,
Input.mousePosition, canvas.worldCamera, out local))
{
if (visualMap.runtimeSelectedIndex >= 0)
{
visualMap.runtimeSelectedIndex = -1;
RefreshChart();
}
return;
}
if (local.x < chartX || local.x > chartX + chartWidth ||
local.y < chartY || local.y > chartY + chartHeight ||
!visualMap.IsInRangeRect(local, chartRect))
{
if (visualMap.runtimeSelectedIndex >= 0)
{
visualMap.runtimeSelectedIndex = -1;
RefreshChart();
}
return;
}
var pos1 = Vector3.zero;
var pos2 = Vector3.zero;
var halfHig = visualMap.itemHeight / 2;
var centerPos = chartPosition + visualMap.location.GetPosition(chartWidth, chartHeight);
var selectedIndex = -1;
var value = 0f;
switch (visualMap.orient)
{
case Orient.Horizonal:
pos1 = centerPos + Vector3.left * halfHig;
pos2 = centerPos + Vector3.right * halfHig;
value = visualMap.min + (local.x - pos1.x) / (pos2.x - pos1.x) * (visualMap.max - visualMap.min);
selectedIndex = visualMap.GetIndex(value);
break;
case Orient.Vertical:
pos1 = centerPos + Vector3.down * halfHig;
pos2 = centerPos + Vector3.up * halfHig;
value = visualMap.min + (local.y - pos1.y) / (pos2.y - pos1.y) * (visualMap.max - visualMap.min);
selectedIndex = visualMap.GetIndex(value);
break;
}
visualMap.runtimeSelectedValue = value;
visualMap.runtimeSelectedIndex = selectedIndex;
RefreshChart();
}
protected void OnDragVisualMapStart()
{
if (!visualMap.enable || !visualMap.show || !visualMap.calculable) return;
var inMinRect = visualMap.IsInRangeMinRect(pointerPos, chartRect, m_Theme.visualMap.triangeLen);
var inMaxRect = visualMap.IsInRangeMaxRect(pointerPos, chartRect, m_Theme.visualMap.triangeLen);
if (inMinRect || inMaxRect)
{
if (inMinRect)
{
m_VisualMapMinDrag = true;
}
else
{
m_VisualMapMaxDrag = true;
}
}
}
protected void OnDragVisualMap()
{
if (!visualMap.enable || !visualMap.show || !visualMap.calculable) return;
if (!m_VisualMapMinDrag && !m_VisualMapMaxDrag) return;
var value = visualMap.GetValue(pointerPos, chartRect);
if (m_VisualMapMinDrag)
{
visualMap.rangeMin = value;
}
else
{
visualMap.rangeMax = value;
}
RefreshChart();
}
protected void OnDragVisualMapEnd()
{
if (!visualMap.enable || !visualMap.show || !visualMap.calculable) return;
if (m_VisualMapMinDrag || m_VisualMapMaxDrag)
{
RefreshChart();
m_VisualMapMinDrag = false;
m_VisualMapMaxDrag = false;
}
}
protected void DrawHeatmapSerie(VertexHelper vh, int colorIndex, Serie serie)
{
if (serie.animation.HasFadeOut()) return;
var yAxis = m_YAxes[serie.yAxisIndex];
var xAxis = m_XAxes[serie.xAxisIndex];
xAxis.boundaryGap = true;
yAxis.boundaryGap = true;
var grid = GetSerieGridOrDefault(serie);
var xCount = xAxis.data.Count;
var yCount = yAxis.data.Count;
var xWidth = grid.runtimeWidth / xCount;
var yWidth = grid.runtimeHeight / yCount;
var zeroX = grid.runtimeX;
var zeroY = grid.runtimeY;
var dataList = serie.GetDataList();
var rangeMin = visualMap.rangeMin;
var rangeMax = visualMap.rangeMax;
var color = m_Theme.GetColor(serie.index);
var borderWidth = serie.itemStyle.show ? serie.itemStyle.borderWidth : 0;
var borderColor = serie.itemStyle.opacity > 0 ? serie.itemStyle.borderColor : ChartConst.clearColor32;
borderColor.a = (byte)(borderColor.a * serie.itemStyle.opacity);
serie.dataPoints.Clear();
serie.animation.InitProgress(1, 0, xCount);
var animationIndex = serie.animation.GetCurrIndex();
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
var dataChanging = false;
for (int i = 0; i < xCount; i++)
{
for (int j = 0; j < yCount; j++)
{
var dataIndex = i * yCount + j;
if (dataIndex >= dataList.Count) continue;
var serieData = dataList[dataIndex];
var dimension = VisualMapHelper.GetDimension(visualMap, serieData.data.Count);
if (serie.IsIgnoreIndex(dataIndex, dimension))
{
serie.dataPoints.Add(Vector3.zero);
continue;
}
var value = serieData.GetCurrData(dimension, dataChangeDuration, yAxis.inverse,
yAxis.runtimeMinValue, yAxis.runtimeMaxValue);
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.dataPoints.Add(pos);
serieData.canShowLabel = false;
if (value == 0) continue;
if (visualMap.enable)
{
if ((value < rangeMin && rangeMin != visualMap.min)
|| (value > rangeMax && rangeMax != visualMap.max))
{
continue;
}
if (!visualMap.IsInSelectedValue(value)) continue;
color = visualMap.GetColor(value);
}
if (animationIndex >= 0 && i > animationIndex) continue;
serieData.canShowLabel = true;
var emphasis = (tooltip.show
&& i == (int)tooltip.runtimeXValues[0]
&& j == (int)tooltip.runtimeYValues[0])
|| visualMap.runtimeSelectedIndex > 0;
var rectWid = xWidth - 2 * borderWidth;
var rectHig = yWidth - 2 * borderWidth;
UGL.DrawRectangle(vh, pos, rectWid / 2, rectHig / 2, color);
if (borderWidth > 0 && !ChartHelper.IsClearColor(borderColor))
{
UGL.DrawBorder(vh, pos, rectWid, rectHig, borderWidth, borderColor);
}
if (visualMap.hoverLink && emphasis && serie.emphasis.show
&& serie.emphasis.itemStyle.borderWidth > 0)
{
var emphasisBorderWidth = serie.emphasis.itemStyle.borderWidth;
var emphasisBorderColor = serie.emphasis.itemStyle.opacity > 0
? serie.emphasis.itemStyle.borderColor : ChartConst.clearColor32;
UGL.DrawBorder(vh, pos, rectWid, rectHig, emphasisBorderWidth, emphasisBorderColor);
}
}
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress(xCount);
m_IsPlayingAnimation = true;
RefreshPainter(serie);
}
if (dataChanging)
{
RefreshPainter(serie);
}
}
protected void DrawVisualMap(VertexHelper vh)
{
if (!visualMap.enable || !visualMap.show) return;
var centerPos = chartPosition + visualMap.location.GetPosition(chartWidth, chartHeight);
var pos1 = Vector3.zero;
var pos2 = Vector3.zero;
var dir = Vector3.zero;
var halfWid = visualMap.itemWidth / 2;
var halfHig = visualMap.itemHeight / 2;
var xRadius = 0f;
var yRadius = 0f;
var splitNum = visualMap.runtimeInRange.Count;
var splitWid = visualMap.itemHeight / (splitNum - 1);
var isVertical = false;
var colors = visualMap.runtimeInRange;
var triangeLen = m_Theme.visualMap.triangeLen;
switch (visualMap.orient)
{
case Orient.Horizonal:
pos1 = centerPos + Vector3.left * halfHig;
pos2 = centerPos + Vector3.right * halfHig;
dir = Vector3.right;
xRadius = splitWid / 2;
yRadius = halfWid;
isVertical = false;
if (visualMap.calculable)
{
var p0 = pos1 + Vector3.right * visualMap.runtimeRangeMinHeight;
var p1 = p0 + Vector3.up * halfWid;
var p2 = p0 + Vector3.up * (halfWid + triangeLen);
var p3 = p2 + Vector3.left * triangeLen;
var color = visualMap.GetColor(visualMap.rangeMin);
UGL.DrawTriangle(vh, p1, p2, p3, color);
p0 = pos1 + Vector3.right * visualMap.runtimeRangeMaxHeight;
p1 = p0 + Vector3.up * halfWid;
p2 = p0 + Vector3.up * (halfWid + triangeLen);
p3 = p2 + Vector3.right * triangeLen;
color = visualMap.GetColor(visualMap.rangeMax);
UGL.DrawTriangle(vh, p1, p2, p3, color);
}
break;
case Orient.Vertical:
pos1 = centerPos + Vector3.down * halfHig;
pos2 = centerPos + Vector3.up * halfHig;
dir = Vector3.up;
xRadius = halfWid;
yRadius = splitWid / 2;
isVertical = true;
if (visualMap.calculable)
{
var p0 = pos1 + Vector3.up * visualMap.runtimeRangeMinHeight;
var p1 = p0 + Vector3.right * halfWid;
var p2 = p0 + Vector3.right * (halfWid + triangeLen);
var p3 = p2 + Vector3.down * triangeLen;
var color = visualMap.GetColor(visualMap.rangeMin);
UGL.DrawTriangle(vh, p1, p2, p3, color);
p0 = pos1 + Vector3.up * visualMap.runtimeRangeMaxHeight;
p1 = p0 + Vector3.right * halfWid;
p2 = p0 + Vector3.right * (halfWid + triangeLen);
p3 = p2 + Vector3.up * triangeLen;
color = visualMap.GetColor(visualMap.rangeMax);
UGL.DrawTriangle(vh, p1, p2, p3, color);
}
break;
}
if (visualMap.calculable && (visualMap.rangeMin > visualMap.min
|| visualMap.rangeMax < visualMap.max))
{
var rangeMin = visualMap.rangeMin;
var rangeMax = visualMap.rangeMax;
var diff = (visualMap.max - visualMap.min) / (splitNum - 1);
for (int i = 1; i < splitNum; i++)
{
var splitMin = visualMap.min + (i - 1) * diff;
var splitMax = splitMin + diff;
if (rangeMin > splitMax || rangeMax < splitMin)
{
continue;
}
else if (rangeMin <= splitMin && rangeMax >= splitMax)
{
var splitPos = pos1 + dir * (i - 1 + 0.5f) * splitWid;
var startColor = colors[i - 1];
var toColor = visualMap.IsPiecewise() ? startColor : colors[i];
UGL.DrawRectangle(vh, splitPos, xRadius, yRadius, startColor, toColor, isVertical);
}
else if (rangeMin > splitMin && rangeMax >= splitMax)
{
var p0 = pos1 + dir * visualMap.runtimeRangeMinHeight;
var splitMaxPos = pos1 + dir * i * splitWid;
var splitPos = p0 + (splitMaxPos - p0) / 2;
var startColor = visualMap.GetColor(visualMap.rangeMin);
var toColor = visualMap.IsPiecewise() ? startColor : colors[i];
var yRadius1 = Vector3.Distance(p0, splitMaxPos) / 2;
if (visualMap.orient == Orient.Vertical)
UGL.DrawRectangle(vh, splitPos, xRadius, yRadius1, startColor, toColor, isVertical);
else
UGL.DrawRectangle(vh, splitPos, yRadius1, yRadius, startColor, toColor, isVertical);
}
else if (rangeMax < splitMax && rangeMin <= splitMin)
{
var p0 = pos1 + dir * visualMap.runtimeRangeMaxHeight;
var splitMinPos = pos1 + dir * (i - 1) * splitWid;
var splitPos = splitMinPos + (p0 - splitMinPos) / 2;
var startColor = colors[i - 1];
var toColor = visualMap.IsPiecewise() ? startColor : visualMap.GetColor(visualMap.rangeMax);
var yRadius1 = Vector3.Distance(p0, splitMinPos) / 2;
if (visualMap.orient == Orient.Vertical)
UGL.DrawRectangle(vh, splitPos, xRadius, yRadius1, startColor, toColor, isVertical);
else
UGL.DrawRectangle(vh, splitPos, yRadius1, yRadius, startColor, toColor, isVertical);
}
else
{
var p0 = pos1 + dir * visualMap.runtimeRangeMinHeight;
var p1 = pos1 + dir * visualMap.runtimeRangeMaxHeight;
var splitPos = (p0 + p1) / 2;
var startColor = visualMap.GetColor(visualMap.rangeMin);
var toColor = visualMap.GetColor(visualMap.rangeMax);
var yRadius1 = Vector3.Distance(p0, p1) / 2;
if (visualMap.orient == Orient.Vertical)
UGL.DrawRectangle(vh, splitPos, xRadius, yRadius1, startColor, toColor, isVertical);
else
UGL.DrawRectangle(vh, splitPos, yRadius1, yRadius, startColor, toColor, isVertical);
}
}
}
else
{
for (int i = 1; i < splitNum; i++)
{
var splitPos = pos1 + dir * (i - 1 + 0.5f) * splitWid;
var startColor = colors[i - 1];
var toColor = visualMap.IsPiecewise() ? startColor : colors[i];
UGL.DrawRectangle(vh, splitPos, xRadius, yRadius, startColor, toColor, isVertical);
}
}
if (visualMap.rangeMin > visualMap.min)
{
var p0 = pos1 + dir * visualMap.runtimeRangeMinHeight;
UGL.DrawRectangle(vh, pos1, p0, visualMap.itemWidth / 2, m_Theme.visualMap.backgroundColor);
}
if (visualMap.rangeMax < visualMap.max)
{
var p1 = pos1 + dir * visualMap.runtimeRangeMaxHeight;
UGL.DrawRectangle(vh, p1, pos2, visualMap.itemWidth / 2, m_Theme.visualMap.backgroundColor);
}
if (visualMap.hoverLink)
{
if (visualMap.runtimeSelectedIndex >= 0)
{
var p0 = pos1 + dir * visualMap.runtimeRangeMinHeight;
var p1 = pos1 + dir * visualMap.runtimeRangeMaxHeight;
if (visualMap.orient == Orient.Vertical)
{
var p2 = new Vector3(centerPos.x + halfWid, Mathf.Clamp(pointerPos.y + (triangeLen / 2), p0.y, p1.y));
var p3 = new Vector3(centerPos.x + halfWid, Mathf.Clamp(pointerPos.y - (triangeLen / 2), p0.y, p1.y));
var p4 = new Vector3(centerPos.x + halfWid + triangeLen / 2, pointerPos.y);
UGL.DrawTriangle(vh, p2, p3, p4, colors[visualMap.runtimeSelectedIndex]);
}
else
{
var p2 = new Vector3(Mathf.Clamp(pointerPos.x + (triangeLen / 2), p0.x, p1.x), centerPos.y + halfWid);
var p3 = new Vector3(Mathf.Clamp(pointerPos.x - (triangeLen / 2), p0.x, p1.x), centerPos.y + halfWid);
var p4 = new Vector3(pointerPos.x, centerPos.y + halfWid + triangeLen / 2);
UGL.DrawTriangle(vh, p2, p3, p4, colors[visualMap.runtimeSelectedIndex]);
}
}
else if (tooltip.show && tooltip.runtimeXValues[0] >= 0 && tooltip.runtimeYValues[0] >= 0)
{
// var p0 = pos1 + dir * m_VisualMap.rangeMinHeight;
// var p1 = pos1 + dir * m_VisualMap.rangeMaxHeight;
// if (m_VisualMap.orient == Orient.Vertical)
// {
// var p2 = new Vector3(centerPos.x + halfWid, Mathf.Clamp(pointerPos.y + (triangeLen / 2), p0.y, p1.y));
// var p3 = new Vector3(centerPos.x + halfWid, Mathf.Clamp(pointerPos.y - (triangeLen / 2), p0.y, p1.y));
// var p4 = new Vector3(centerPos.x + halfWid + triangeLen / 2, pointerPos.y);
// UGL.DrawTriangle(vh, p2, p3, p4, colors[m_VisualMap.rtSelectedIndex]);
// }
// else
// {
// var p2 = new Vector3(Mathf.Clamp(pointerPos.x + (triangeLen / 2), p0.x, p1.x), centerPos.y + halfWid);
// var p3 = new Vector3(Mathf.Clamp(pointerPos.x - (triangeLen / 2), p0.x, p1.x), centerPos.y + halfWid);
// var p4 = new Vector3(pointerPos.x, centerPos.y + halfWid + triangeLen / 2);
// UGL.DrawTriangle(vh, p2, p3, p4, colors[m_VisualMap.rtSelectedIndex]);
// }
}
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2713cb84109d8491aa61bf37d1fa850e
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: e81383a033c064b2cbc5f63387113bb3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,102 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
public partial class CoordinateChart
{
protected void DrawScatterSerie(VertexHelper vh, int colorIndex, Serie serie)
{
if (serie.animation.HasFadeOut()) return;
if (!serie.show) return;
var yAxis = m_YAxes[serie.yAxisIndex];
var xAxis = m_XAxes[serie.xAxisIndex];
var grid = GetSerieGridOrDefault(serie);
int maxCount = serie.maxShow > 0 ?
(serie.maxShow > serie.dataCount ? serie.dataCount : serie.maxShow)
: serie.dataCount;
serie.animation.InitProgress(1, 0, 1);
var rate = serie.animation.GetCurrRate();
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
var dataChanging = false;
var dataList = serie.GetDataList(dataZoom);
foreach (var serieData in dataList)
{
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
if (!symbol.ShowSymbol(serieData.index, maxCount)) continue;
var highlight = serie.highlighted || serieData.highlighted;
var color = SerieHelper.GetItemColor(serie, serieData, m_Theme, colorIndex, highlight);
var toColor = SerieHelper.GetItemToColor(serie, serieData, m_Theme, colorIndex, highlight);
var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, m_Theme, highlight);
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, highlight);
float xValue = serieData.GetCurrData(0, dataChangeDuration, xAxis.inverse);
float yValue = serieData.GetCurrData(1, dataChangeDuration, yAxis.inverse);
if (serieData.IsDataChanged()) dataChanging = true;
float pX = grid.runtimeX + xAxis.axisLine.GetWidth(m_Theme.axis.lineWidth);
float pY = grid.runtimeY + yAxis.axisLine.GetWidth(m_Theme.axis.lineWidth);
float xDataHig = GetDataHig(xAxis, xValue, grid.runtimeWidth);
float yDataHig = GetDataHig(yAxis, yValue, grid.runtimeHeight);
var pos = new Vector3(pX + xDataHig, pY + yDataHig);
serie.dataPoints.Add(pos);
serieData.runtimePosition = pos;
var datas = serieData.data;
float symbolSize = 0;
if (serie.highlighted || serieData.highlighted)
{
symbolSize = symbol.GetSelectedSize(datas, m_Theme.serie.scatterSymbolSelectedSize);
}
else
{
symbolSize = symbol.GetSize(datas, m_Theme.serie.scatterSymbolSize);
}
symbolSize *= rate;
if (symbolSize > 100) symbolSize = 100;
if (serie.type == SerieType.EffectScatter)
{
for (int count = 0; count < symbol.animationSize.Count; count++)
{
var nowSize = symbol.animationSize[count];
color.a = (byte)(255 * (symbolSize - nowSize) / symbolSize);
DrawSymbol(vh, symbol.type, nowSize, symbolBorder, pos, color, toColor, symbol.gap, cornerRadius);
}
RefreshPainter(serie);
}
else
{
DrawSymbol(vh, symbol.type, symbolSize, symbolBorder, pos, color, toColor, symbol.gap, cornerRadius);
}
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress(1);
m_IsPlayingAnimation = true;
RefreshPainter(serie);
}
if (dataChanging)
{
RefreshPainter(serie);
}
}
private float GetDataHig(Axis axis, float value, float totalWidth)
{
if (axis.IsLog())
{
int minIndex = axis.runtimeMinLogIndex;
float nowIndex = axis.GetLogValue(value);
return (nowIndex - minIndex) / (axis.splitNumber - 1) * totalWidth;
}
else
{
return (value - axis.runtimeMinValue) / (axis.runtimeMaxValue - axis.runtimeMinValue) * totalWidth;
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2f06734940c9e4f92897bb83573394a7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,408 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using XUGL;
namespace XCharts
{
internal class DrawSerieGauge : IDrawSerie
{
public BaseChart chart;
private static readonly string s_SerieLabelObjectName = "label";
private static readonly string s_AxisLabelObjectName = "axis_label";
private bool m_UpdateTitleText = false;
private bool m_UpdateLabelText = false;
public DrawSerieGauge(BaseChart chart)
{
this.chart = chart;
}
public void InitComponent()
{
InitAxisLabel();
}
public void CheckComponent()
{
}
public void Update()
{
if (m_UpdateTitleText)
{
m_UpdateTitleText = false;
foreach (var serie in chart.series.list)
{
if (serie.type == SerieType.Gauge)
{
TitleStyleHelper.UpdateTitleText(serie);
}
}
}
if (m_UpdateLabelText)
{
m_UpdateLabelText = false;
foreach (var serie in chart.series.list)
{
if (serie.type == SerieType.Gauge)
{
SerieLabelHelper.SetGaugeLabelText(serie);
UpdateAxisLabel(serie);
}
}
}
}
public void DrawBase(VertexHelper vh)
{
}
public void DrawSerie(VertexHelper vh, Serie serie)
{
if (serie.type != SerieType.Gauge) return;
DrawGauge(vh, serie);
}
public void RefreshLabel()
{
}
public bool CheckTootipArea(Vector2 local)
{
var serie = GetPointerInSerieIndex(chart.series, local);
if (serie != null)
{
chart.tooltip.runtimeDataIndex.Clear();
chart.tooltip.runtimeDataIndex.Add(serie.index);
chart.tooltip.UpdateContentPos(local + chart.tooltip.offset);
UpdateTooltip();
return true;
}
else if (chart.tooltip.IsActive())
{
chart.tooltip.SetActive(false);
chart.RefreshChart();
}
return false;
}
public bool OnLegendButtonClick(int index, string legendName, bool show)
{
return false;
}
public bool OnLegendButtonEnter(int index, string legendName)
{
return false;
}
public bool OnLegendButtonExit(int index, string legendName)
{
return false;
}
public void OnPointerDown(PointerEventData eventData)
{
}
private void InitAxisLabel()
{
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Gauge)) return;
var labelObject = ChartHelper.AddObject(s_AxisLabelObjectName, chart.transform, chart.chartMinAnchor,
chart.chartMaxAnchor, chart.chartPivot, chart.chartSizeDelta);
labelObject.hideFlags = chart.chartHideFlags;
SerieLabelPool.ReleaseAll(labelObject.transform);
for (int i = 0; i < chart.series.Count; i++)
{
var serie = chart.series.list[i];
var serieLabel = serie.gaugeAxis.axisLabel;
var count = serie.splitNumber > 36 ? 36 : (serie.splitNumber + 1);
var startAngle = serie.startAngle;
serie.gaugeAxis.ClearLabelObject();
SerieHelper.UpdateCenter(serie, chart.chartPosition, chart.chartWidth, chart.chartHeight);
for (int j = 0; j < count; j++)
{
var textName = ChartCached.GetSerieLabelName(s_SerieLabelObjectName, i, j);
var color = Color.grey;
var labelObj = SerieLabelPool.Get(textName, labelObject.transform, serieLabel, color, 100, 100, chart.theme);
var iconImage = labelObj.transform.Find("Icon").GetComponent<Image>();
var isAutoSize = serieLabel.backgroundWidth == 0 || serieLabel.backgroundHeight == 0;
var item = new ChartLabel();
item.SetLabel(labelObj, isAutoSize, serieLabel.paddingLeftRight, serieLabel.paddingTopBottom);
item.SetIcon(iconImage);
item.SetIconActive(false);
serie.gaugeAxis.AddLabelObject(item);
}
UpdateAxisLabel(serie);
}
}
private void UpdateAxisLabel()
{
foreach (var serie in chart.series.list)
{
if (serie.type == SerieType.Gauge)
{
UpdateAxisLabel(serie);
}
}
}
private void UpdateAxisLabel(Serie serie)
{
var show = serie.gaugeAxis.show && serie.gaugeAxis.axisLabel.show;
serie.gaugeAxis.SetLabelObjectActive(show);
if (!show)
{
return;
}
var count = serie.splitNumber > 36 ? 36 : serie.splitNumber;
var startAngle = serie.startAngle;
var totalAngle = serie.endAngle - serie.startAngle;
var totalValue = serie.max - serie.min;
var diffAngle = totalAngle / count;
var diffValue = totalValue / count;
var radius = serie.runtimeInsideRadius - serie.gaugeAxis.axisLabel.margin;
var serieData = serie.GetSerieData(0);
var customLabelText = serie.gaugeAxis.axisLabelText;
for (int j = 0; j <= count; j++)
{
var angle = serie.startAngle + j * diffAngle;
var value = serie.min + j * diffValue;
var pos = ChartHelper.GetPosition(serie.runtimeCenterPos, angle, radius);
var text = customLabelText != null && j < customLabelText.Count ? customLabelText[j] :
SerieLabelHelper.GetFormatterContent(serie, serieData, value, totalValue, serie.gaugeAxis.axisLabel);
serie.gaugeAxis.SetLabelObjectText(j, text);
serie.gaugeAxis.SetLabelObjectPosition(j, pos);
}
}
private void DrawGauge(VertexHelper vh, Serie serie)
{
SerieHelper.UpdateCenter(serie, chart.chartPosition, chart.chartWidth, chart.chartHeight);
var destAngle = GetCurrAngle(serie, true);
serie.animation.InitProgress(0, serie.startAngle, destAngle);
var currAngle = serie.animation.IsFinish() ? GetCurrAngle(serie, false) : serie.animation.GetCurrDetail();
DrawProgressBar(vh, serie, currAngle);
DrawStageColor(vh, serie);
DrawLineStyle(vh, serie);
DrawAxisTick(vh, serie);
DrawPointer(vh, serie, currAngle);
TitleStyleHelper.CheckTitle(serie, ref chart.m_ReinitTitle, ref m_UpdateTitleText);
SerieLabelHelper.CheckLabel(serie, ref chart.m_ReinitLabel, ref m_UpdateLabelText);
CheckAnimation(serie);
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress(destAngle - serie.startAngle);
chart.RefreshPainter(serie);
}
else if (NeedRefresh(serie))
{
chart.RefreshPainter(serie);
}
}
private void DrawProgressBar(VertexHelper vh, Serie serie, float currAngle)
{
if (serie.gaugeType != GaugeType.ProgressBar) return;
if (!serie.gaugeAxis.show || !serie.gaugeAxis.axisLine.show) return;
var color = serie.gaugeAxis.GetAxisLineColor(chart.theme, serie.index);
var backgroundColor = serie.gaugeAxis.GetAxisLineBackgroundColor(chart.theme, serie.index);
var lineWidth = serie.gaugeAxis.axisLine.GetWidth(chart.theme.gauge.lineWidth);
var outsideRadius = serie.runtimeInsideRadius + lineWidth;
var borderWidth = serie.itemStyle.borderWidth;
var borderColor = serie.itemStyle.borderColor;
UGL.DrawDoughnut(vh, serie.runtimeCenterPos, serie.runtimeInsideRadius, outsideRadius,
backgroundColor, backgroundColor, Color.clear, serie.startAngle, serie.endAngle, 0, Color.clear,
0, chart.settings.cicleSmoothness, serie.roundCap);
UGL.DrawDoughnut(vh, serie.runtimeCenterPos, serie.runtimeInsideRadius, outsideRadius,
color, color, Color.clear, serie.startAngle, currAngle, 0, Color.clear,
0, chart.settings.cicleSmoothness, serie.roundCap);
}
private void DrawStageColor(VertexHelper vh, Serie serie)
{
if (serie.gaugeType != GaugeType.Pointer) return;
if (!serie.gaugeAxis.show || !serie.gaugeAxis.axisLine.show) return;
var totalAngle = serie.endAngle - serie.startAngle;
var tempStartAngle = serie.startAngle;
var tempEndAngle = serie.startAngle;
var lineWidth = serie.gaugeAxis.axisLine.GetWidth(chart.theme.gauge.lineWidth);
var outsideRadius = serie.runtimeInsideRadius + lineWidth;
serie.gaugeAxis.runtimeStageAngle.Clear();
for (int i = 0; i < serie.gaugeAxis.axisLine.stageColor.Count; i++)
{
var stageColor = serie.gaugeAxis.axisLine.stageColor[i];
tempEndAngle = serie.startAngle + totalAngle * stageColor.percent;
serie.gaugeAxis.runtimeStageAngle.Add(tempEndAngle);
UGL.DrawDoughnut(vh, serie.runtimeCenterPos, serie.runtimeInsideRadius, outsideRadius,
stageColor.color, stageColor.color, Color.clear, tempStartAngle, tempEndAngle, 0, Color.clear,
0, chart.settings.cicleSmoothness);
tempStartAngle = tempEndAngle;
}
}
private void DrawPointer(VertexHelper vh, Serie serie, float currAngle)
{
if (!serie.gaugePointer.show) return;
var pointerColor = serie.gaugeAxis.GetPointerColor(chart.theme, serie.index, currAngle, serie.itemStyle);
var pointerToColor = !ChartHelper.IsClearColor(serie.itemStyle.toColor) ? serie.itemStyle.toColor : pointerColor;
var len = serie.gaugePointer.length < 1 && serie.gaugePointer.length > -1 ?
serie.runtimeInsideRadius * serie.gaugePointer.length :
serie.gaugePointer.length;
var p1 = ChartHelper.GetPosition(serie.runtimeCenterPos, currAngle, len);
var p2 = ChartHelper.GetPosition(serie.runtimeCenterPos, currAngle + 180, serie.gaugePointer.width);
var p3 = ChartHelper.GetPosition(serie.runtimeCenterPos, currAngle - 90, serie.gaugePointer.width / 2);
var p4 = ChartHelper.GetPosition(serie.runtimeCenterPos, currAngle + 90, serie.gaugePointer.width / 2);
UGL.DrawTriangle(vh, p2, p3, p1, pointerColor, pointerColor, pointerToColor);
UGL.DrawTriangle(vh, p4, p2, p1, pointerColor, pointerColor, pointerToColor);
}
private void DrawLineStyle(VertexHelper vh, Serie serie)
{
if (serie.gaugeType != GaugeType.Pointer) return;
if (!serie.gaugeAxis.show || !serie.gaugeAxis.splitLine.show) return;
if (serie.splitNumber <= 0) return;
var splitLine = serie.gaugeAxis.splitLine;
var totalAngle = serie.endAngle - serie.startAngle;
var diffAngle = totalAngle / serie.splitNumber;
var lineWidth = serie.gaugeAxis.axisLine.GetWidth(chart.theme.gauge.lineWidth);
var splitLineWidth = splitLine.GetWidth(chart.theme.gauge.splitLineWidth);
var splitLineLength = splitLine.GetLength(chart.theme.gauge.splitLineLength);
var outsideRadius = serie.runtimeInsideRadius + lineWidth;
var insideRadius = outsideRadius - splitLineLength;
for (int i = 0; i < serie.splitNumber + 1; i++)
{
var angle = serie.startAngle + i * diffAngle;
var lineColor = serie.gaugeAxis.GetSplitLineColor(chart.theme.gauge.splitLineColor, serie.index, angle);
var p1 = ChartHelper.GetPosition(serie.runtimeCenterPos, angle, insideRadius);
var p2 = ChartHelper.GetPosition(serie.runtimeCenterPos, angle, outsideRadius);
UGL.DrawLine(vh, p1, p2, splitLineWidth, lineColor);
}
}
private void DrawAxisTick(VertexHelper vh, Serie serie)
{
if (serie.gaugeType != GaugeType.Pointer) return;
if (!serie.gaugeAxis.show || !serie.gaugeAxis.axisTick.show) return;
if (serie.splitNumber <= 0) return;
var axisTick = serie.gaugeAxis.axisTick;
var totalAngle = serie.endAngle - serie.startAngle;
var diffAngle = totalAngle / serie.splitNumber;
var lineWidth = serie.gaugeAxis.axisLine.GetWidth(chart.theme.gauge.lineWidth);
var tickWidth = axisTick.GetWidth(chart.theme.gauge.tickWidth);
var tickLength = axisTick.GetLength(chart.theme.gauge.tickLength);
var outsideRadius = serie.runtimeInsideRadius + lineWidth;
var insideRadius = outsideRadius - (tickLength < 1 ? lineWidth * tickLength : tickLength);
for (int i = 0; i < serie.splitNumber; i++)
{
for (int j = 1; j < axisTick.splitNumber; j++)
{
var angle = serie.startAngle + i * diffAngle + j * (diffAngle / axisTick.splitNumber);
var lineColor = serie.gaugeAxis.GetSplitLineColor(chart.theme.gauge.tickColor, serie.index, angle);
var p1 = ChartHelper.GetPosition(serie.runtimeCenterPos, angle, insideRadius);
var p2 = ChartHelper.GetPosition(serie.runtimeCenterPos, angle, outsideRadius);
UGL.DrawLine(vh, p1, p2, tickWidth, lineColor);
}
}
}
private float GetCurrAngle(Serie serie, bool dest)
{
if (serie.animation.HasFadeOut())
{
return serie.animation.GetCurrDetail();
}
float rangeValue = serie.max - serie.min;
float rangeAngle = serie.endAngle - serie.startAngle;
float value = 0;
float angle = serie.startAngle;
if (serie.dataCount > 0)
{
var serieData = serie.data[0];
serieData.labelPosition = serie.runtimeCenterPos + serie.label.offset;
value = dest ? serieData.GetData(1)
: serieData.GetCurrData(1, serie.animation.GetUpdateAnimationDuration());
value = Mathf.Clamp(value, serie.min, serie.max);
}
if (rangeValue > 0)
{
angle += rangeAngle * value / rangeValue;
}
return angle;
}
private void CheckAnimation(Serie serie)
{
var serieData = serie.GetSerieData(0);
if (serieData != null)
{
var value = serieData.GetCurrData(1, serie.animation.GetUpdateAnimationDuration());
var data = serieData.GetData(1);
if (value != data) chart.RefreshPainter(serie);
}
}
private bool NeedRefresh(Serie serie)
{
if (serie.type == SerieType.Gauge)
{
var serieData = serie.GetSerieData(0);
if (serieData != null)
{
var destValue = serieData.GetData(1);
var currValue = serieData.GetCurrData(1, serie.animation.GetUpdateAnimationDuration());
return destValue != currValue;
}
}
return false;
}
private Serie GetPointerInSerieIndex(Series series, Vector2 local)
{
foreach (var serie in series.list)
{
if (serie.type != SerieType.Gauge) continue;
if (!serie.gaugePointer.show) continue;
var len = serie.gaugePointer.length < 1 && serie.gaugePointer.length > -1
? serie.runtimeInsideRadius * serie.gaugePointer.length
: serie.gaugePointer.length;
if (Vector3.Distance(local, serie.runtimeCenterPos) > len) continue;
var currAngle = serie.animation.IsFinish() ? GetCurrAngle(serie, false) : serie.animation.GetCurrDetail();
var p1 = ChartHelper.GetPosition(serie.runtimeCenterPos, currAngle, len);
var p2 = ChartHelper.GetPosition(serie.runtimeCenterPos, currAngle + 180, serie.gaugePointer.width);
var p3 = ChartHelper.GetPosition(serie.runtimeCenterPos, currAngle - 90, serie.gaugePointer.width / 2);
var p4 = ChartHelper.GetPosition(serie.runtimeCenterPos, currAngle + 90, serie.gaugePointer.width / 2);
if (ChartHelper.IsPointInQuadrilateral(local, p1, p3, p2, p4))
{
return serie;
}
}
return null;
}
private void UpdateTooltip()
{
int index = chart.tooltip.runtimeDataIndex[0];
if (index < 0)
{
chart.tooltip.SetActive(false);
return;
}
var content = TooltipHelper.GetFormatterContent(chart.tooltip, index, chart.series, chart.theme);
TooltipHelper.SetContentAndPosition(chart.tooltip, content.TrimStart(), chart.chartRect);
chart.tooltip.SetActive(true);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ca6e74d36e80c4daabf80b165986dfbb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,259 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using XUGL;
namespace XCharts
{
internal class DrawSerieLiquid : IDrawSerie
{
public BaseChart chart;
private bool m_UpdateLabelText = false;
public DrawSerieLiquid(BaseChart chart)
{
this.chart = chart;
}
public void InitComponent()
{
//UpdateRuntimeData();
//SerieLabelHelper.UpdateLabelText(chart.series, chart.theme, m_LegendRealShowName);
}
public void CheckComponent()
{
}
public void Update()
{
if (m_UpdateLabelText)
{
m_UpdateLabelText = false;
foreach (var serie in chart.series.list)
{
if (serie.type == SerieType.Liquid)
{
var colorIndex = chart.m_LegendRealShowName.IndexOf(serie.name);
SerieLabelHelper.SetLiquidLabelText(serie, chart.theme, colorIndex);
}
}
}
}
public void DrawBase(VertexHelper vh)
{
}
public void DrawSerie(VertexHelper vh, Serie serie)
{
if (serie.type != SerieType.Liquid) return;
UpdateRuntimeData(serie);
DrawVesselBackground(vh, serie);
DrawLiquid(vh, serie);
DrawVessel(vh, serie);
}
public void RefreshLabel()
{
}
public bool CheckTootipArea(Vector2 local)
{
return false;
}
public bool OnLegendButtonClick(int index, string legendName, bool show)
{
return false;
}
public bool OnLegendButtonEnter(int index, string legendName)
{
return false;
}
public bool OnLegendButtonExit(int index, string legendName)
{
return false;
}
public void OnPointerDown(PointerEventData eventData)
{
}
private void UpdateRuntimeData()
{
foreach (var vessel in chart.vessels)
{
VesselHelper.UpdateVesselCenter(vessel, chart.chartPosition, chart.chartWidth, chart.chartHeight);
}
}
private void UpdateRuntimeData(Serie serie)
{
var vessel = chart.GetVessel(serie.vesselIndex);
if (vessel != null)
{
VesselHelper.UpdateVesselCenter(vessel, chart.chartPosition, chart.chartWidth, chart.chartHeight);
}
}
private void DrawVesselBackground(VertexHelper vh, Serie serie)
{
var vessel = chart.GetVessel(serie.vesselIndex);
if (vessel != null)
{
if (vessel.backgroundColor.a != 0)
{
var cenPos = vessel.runtimeCenterPos;
var radius = vessel.runtimeRadius;
UGL.DrawCricle(vh, cenPos, vessel.runtimeInnerRadius, vessel.backgroundColor, chart.settings.cicleSmoothness);
}
}
}
private void DrawVessel(VertexHelper vh, Serie serie)
{
var vessel = chart.GetVessel(serie.vesselIndex);
if (vessel != null)
{
DrawCirleVessel(vh, vessel);
}
}
private void DrawCirleVessel(VertexHelper vh, Vessel vessel)
{
var cenPos = vessel.runtimeCenterPos;
var radius = vessel.runtimeRadius;
var serie = SeriesHelper.GetSerieByVesselIndex(chart.series, vessel.index);
var vesselColor = VesselHelper.GetColor(vessel, serie, chart.theme, chart.m_LegendRealShowName);
UGL.DrawDoughnut(vh, cenPos, radius - vessel.shapeWidth, radius, vesselColor, Color.clear, chart.settings.cicleSmoothness);
}
private void DrawLiquid(VertexHelper vh, Serie serie)
{
if (!serie.show) return;
if (serie.animation.HasFadeOut()) return;
var vessel = chart.GetVessel(serie.vesselIndex);
if (vessel == null) return;
var cenPos = vessel.runtimeCenterPos;
var radius = vessel.runtimeInnerRadius;
var serieData = serie.GetSerieData(0);
if (serieData == null) return;
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
var value = serieData.GetCurrData(1, dataChangeDuration);
if (serie.runtimeCheckValue != value)
{
serie.runtimeCheckValue = value;
m_UpdateLabelText = true;
}
if (serieData.labelPosition != cenPos)
{
serieData.labelPosition = cenPos;
m_UpdateLabelText = true;
}
if (value == 0) return;
var colorIndex = chart.m_LegendRealShowName.IndexOf(serie.name);
var realHig = (value - serie.min) / (serie.max - serie.min) * radius * 2;
serie.animation.InitProgress(1, 0, realHig);
var hig = serie.animation.IsFinish() ? realHig : serie.animation.GetCurrDetail();
var a = Mathf.Abs(radius - hig + (hig > radius ? serie.waveHeight : -serie.waveHeight));
var diff = Mathf.Sqrt(radius * radius - Mathf.Pow(a, 2));
var color = SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, false);
var toColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, colorIndex, false);
var isNeedGradient = !ChartHelper.IsValueEqualsColor(color, toColor);
var isFull = hig >= 2 * radius;
if (hig >= 2 * radius) hig = 2 * radius;
if (isFull && !isNeedGradient)
{
UGL.DrawCricle(vh, cenPos, radius, toColor, chart.settings.cicleSmoothness);
}
else
{
var startY = cenPos.y - radius + hig;
var waveStartPos = new Vector3(cenPos.x - diff, startY);
var waveEndPos = new Vector3(cenPos.x + diff, startY);
var startX = hig > radius ? cenPos.x - radius : waveStartPos.x;
var endX = hig > radius ? cenPos.x + radius : waveEndPos.x;
var step = vessel.smoothness;
if (step < 0.5f) step = 0.5f;
var lup = hig > radius ? new Vector3(cenPos.x - radius, cenPos.y) : waveStartPos;
var ldp = lup;
var nup = Vector3.zero;
var ndp = Vector3.zero;
var angle = 0f;
serie.runtimeWaveSpeed += serie.waveSpeed * Time.deltaTime;
var isStarted = false;
var isEnded = false;
var waveHeight = isFull ? 0 : serie.waveHeight;
while (startX < endX)
{
startX += step;
if (startX > endX) startX = endX;
if (startX > waveStartPos.x && !isStarted)
{
startX = waveStartPos.x;
isStarted = true;
}
if (startX > waveEndPos.x && !isEnded)
{
startX = waveEndPos.x;
isEnded = true;
}
var py = Mathf.Sqrt(Mathf.Pow(radius, 2) - Mathf.Pow(Mathf.Abs(cenPos.x - startX), 2));
if (startX < waveStartPos.x || startX > waveEndPos.x)
{
nup = new Vector3(startX, cenPos.y + py);
}
else
{
var py2 = waveHeight * Mathf.Sin(1 / serie.waveLength * angle + serie.runtimeWaveSpeed + serie.waveOffset);
var nupY = waveStartPos.y + py2;
if (nupY > cenPos.y + py) nupY = cenPos.y + py;
else if (nupY < cenPos.y - py) nupY = cenPos.y - py;
nup = new Vector3(startX, nupY);
angle += step;
}
ndp = new Vector3(startX, cenPos.y - py);
if (!ChartHelper.IsValueEqualsColor(color, toColor))
{
var colorMin = cenPos.y - radius;
var colorMax = startY + serie.waveHeight;
var tcolor1 = Color32.Lerp(color, toColor, 1 - (lup.y - colorMin) / (colorMax - colorMin));
var tcolor2 = Color32.Lerp(color, toColor, 1 - (ldp.y - colorMin) / (colorMax - colorMin));
UGL.DrawQuadrilateral(vh, lup, nup, ndp, ldp, tcolor1, tcolor2);
}
else
{
UGL.DrawQuadrilateral(vh, lup, nup, ndp, ldp, color);
}
lup = nup;
ldp = ndp;
}
}
if (serie.waveSpeed != 0 && Application.isPlaying && !isFull)
{
chart.RefreshPainter(serie);
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress(realHig);
chart.m_IsPlayingAnimation = true;
chart.RefreshPainter(serie);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5e68718d39a3042ffb8162149246ef5e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,608 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using XUGL;
namespace XCharts
{
internal class DrawSeriePie : IDrawSerie
{
public BaseChart chart;
protected bool m_IsEnterPieLegendButtom;
public DrawSeriePie(BaseChart chart)
{
this.chart = chart;
}
public void InitComponent()
{
}
public void CheckComponent()
{
}
public void Update()
{
}
public void DrawBase(VertexHelper vh)
{
}
public void DrawSerie(VertexHelper vh, Serie serie)
{
if (serie.type != SerieType.Pie) return;
UpdateRuntimeData(serie);
DrawPieLabelLine(vh, serie);
DrawPie(vh, serie);
DrawPieLabelBackground(vh, serie);
}
public void RefreshLabel()
{
int serieNameCount = -1;
for (int i = 0; i < chart.series.Count; i++)
{
var serie = chart.series.list[i];
serie.index = i;
if (!serie.show || serie.type != SerieType.Pie) continue;
var data = serie.data;
for (int n = 0; n < data.Count; n++)
{
var serieData = data[n];
if (!serieData.canShowLabel || serie.IsIgnoreValue(serieData.GetData(1)))
{
serieData.SetLabelActive(false);
continue;
}
if (!serieData.show) continue;
serieNameCount = chart.m_LegendRealShowName.IndexOf(serieData.name);
Color color = chart.theme.GetColor(serieNameCount);
DrawPieLabel(serie, n, serieData, color);
}
}
}
public bool CheckTootipArea(Vector2 local)
{
if (!PointerIsInPieSerie(chart.series, local)) return false;
bool selected = false;
chart.tooltip.runtimeDataIndex.Clear();
foreach (var serie in chart.series.list)
{
int index = GetPiePosIndex(serie, local);
chart.tooltip.runtimeDataIndex.Add(index);
if (serie.type != SerieType.Pie) continue;
bool refresh = false;
for (int j = 0; j < serie.data.Count; j++)
{
var serieData = serie.data[j];
if (serieData.highlighted != (j == index)) refresh = true;
serieData.highlighted = j == index;
}
if (index >= 0) selected = true;
if (refresh) chart.RefreshChart();
}
if (selected)
{
chart.tooltip.UpdateContentPos(local + chart.tooltip.offset);
UpdatePieTooltip();
}
else if (chart.tooltip.IsActive())
{
chart.tooltip.SetActive(false);
chart.RefreshChart();
}
return true;
}
public bool OnLegendButtonClick(int index, string legendName, bool show)
{
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Pie)) return false;
if (!LegendHelper.IsSerieLegend(chart.series, legendName, SerieType.Pie)) return false;
LegendHelper.CheckDataShow(chart.series, legendName, show);
chart.UpdateLegendColor(legendName, show);
chart.RefreshChart();
return true;
}
public bool OnLegendButtonEnter(int index, string legendName)
{
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Pie)) return false;
if (!LegendHelper.IsSerieLegend(chart.series, legendName, SerieType.Pie)) return false;
m_IsEnterPieLegendButtom = true;
LegendHelper.CheckDataHighlighted(chart.series, legendName, true);
chart.RefreshChart();
return true;
}
public bool OnLegendButtonExit(int index, string legendName)
{
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Pie)) return false;
if (!LegendHelper.IsSerieLegend(chart.series, legendName, SerieType.Pie)) return false;
m_IsEnterPieLegendButtom = false;
LegendHelper.CheckDataHighlighted(chart.series, legendName, false);
chart.RefreshChart();
return true;
}
public void OnPointerDown(PointerEventData eventData)
{
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Pie)) return;
if (chart.pointerPos == Vector2.zero) return;
var refresh = false;
for (int i = 0; i < chart.series.Count; i++)
{
var serie = chart.series.GetSerie(i);
if (serie.type != SerieType.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].selected = !serie.data[j].selected;
else serie.data[j].selected = false;
}
if (chart.onPointerClickPie != null)
{
chart.onPointerClickPie(eventData, i, index);
}
}
}
if (refresh) chart.RefreshChart();
}
private void UpdateRuntimeData(Serie serie)
{
var data = serie.data;
serie.runtimeDataMax = serie.yMax;
serie.runtimePieDataTotal = serie.yTotal;
SerieHelper.UpdateCenter(serie, chart.chartPosition, chart.chartWidth, chart.chartHeight);
float totalDegree = 0;
float startDegree = 0;
float zeroReplaceValue = 0;
int showdataCount = 0;
foreach (var sd in serie.data)
{
if (sd.show && serie.pieRoseType == RoseType.Area) showdataCount++;
sd.canShowLabel = false;
}
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
bool isAllZeroValue = SerieHelper.IsAllZeroValue(serie, 1);
var dataTotalFilterMinAngle = serie.runtimePieDataTotal;
if (isAllZeroValue)
{
totalDegree = 360;
zeroReplaceValue = totalDegree / data.Count;
serie.runtimeDataMax = zeroReplaceValue;
serie.runtimePieDataTotal = 360;
}
else
{
dataTotalFilterMinAngle = GetTotalAngle(serie, serie.runtimePieDataTotal, ref totalDegree);
}
serie.animation.InitProgress(data.Count, 0, 360);
for (int n = 0; n < data.Count; n++)
{
var serieData = data[n];
serieData.index = n;
float value = isAllZeroValue ? zeroReplaceValue : serieData.GetCurrData(1, dataChangeDuration);
serieData.runtimePieStartAngle = startDegree;
serieData.runtimePieToAngle = startDegree;
serieData.runtimePieHalfAngle = startDegree;
serieData.runtimePieCurrAngle = startDegree;
if (!serieData.show)
{
continue;
}
float degree = serie.pieRoseType == RoseType.Area
? (totalDegree / showdataCount)
: (totalDegree * value / dataTotalFilterMinAngle);
if (serie.minAngle > 0 && degree < serie.minAngle) degree = serie.minAngle;
serieData.runtimePieToAngle = startDegree + degree;
serieData.runtimePieOutsideRadius = serie.pieRoseType > 0 ?
serie.runtimeInsideRadius +
(serie.runtimeOutsideRadius - serie.runtimeInsideRadius) * value / serie.runtimeDataMax :
serie.runtimeOutsideRadius;
if (serieData.highlighted)
{
serieData.runtimePieOutsideRadius += chart.theme.serie.pieTooltipExtraRadius;
}
var offset = 0f;
if (serie.pieClickOffset && serieData.selected)
{
offset += chart.theme.serie.pieSelectedOffset;
}
if (serie.animation.CheckDetailBreak(serieData.runtimePieToAngle))
{
serieData.runtimePieCurrAngle = serie.animation.GetCurrDetail();
}
else
{
serieData.runtimePieCurrAngle = serieData.runtimePieToAngle;
}
var halfDegree = (serieData.runtimePieToAngle - startDegree) / 2;
serieData.runtimePieHalfAngle = startDegree + halfDegree;
serieData.runtiemPieOffsetCenter = serie.runtimeCenterPos;
serieData.runtimePieInsideRadius = serie.runtimeInsideRadius;
if (offset > 0)
{
var currRad = serieData.runtimePieHalfAngle * Mathf.Deg2Rad;
var currSin = Mathf.Sin(currRad);
var currCos = Mathf.Cos(currRad);
serieData.runtimePieOffsetRadius = 0;
serieData.runtimePieInsideRadius -= serieData.runtimePieOffsetRadius;
serieData.runtimePieOutsideRadius -= serieData.runtimePieOffsetRadius;
if (serie.pieClickOffset && serieData.selected)
{
serieData.runtimePieOffsetRadius += chart.theme.serie.pieSelectedOffset;
if (serieData.runtimePieInsideRadius > 0)
{
serieData.runtimePieInsideRadius += chart.theme.serie.pieSelectedOffset;
}
serieData.runtimePieOutsideRadius += chart.theme.serie.pieSelectedOffset;
}
serieData.runtiemPieOffsetCenter = new Vector3(
serie.runtimeCenterPos.x + serieData.runtimePieOffsetRadius * currSin,
serie.runtimeCenterPos.y + serieData.runtimePieOffsetRadius * currCos);
}
serieData.canShowLabel = serieData.runtimePieCurrAngle >= serieData.runtimePieHalfAngle;
startDegree = serieData.runtimePieToAngle;
SerieLabelHelper.UpdatePieLabelPosition(serie, serieData);
}
SerieLabelHelper.AvoidLabelOverlap(serie);
}
private float GetTotalAngle(Serie serie, float dataTotal, ref float totalAngle)
{
totalAngle = 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.runtimeCenterPos, radius, itemStyle.centerColor, chart.settings.cicleSmoothness);
}
}
private void DrawPie(VertexHelper vh, Serie serie)
{
var data = serie.data;
serie.animation.InitProgress(data.Count, 0, 360);
if (!serie.show || serie.animation.HasFadeOut())
{
return;
}
bool dataChanging = false;
for (int n = 0; n < data.Count; n++)
{
var serieData = data[n];
if (!serieData.show)
{
continue;
}
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, serieData.highlighted);
if (serieData.IsDataChanged()) dataChanging = true;
var serieNameCount = chart.m_LegendRealShowName.IndexOf(serieData.legendName);
var color = SerieHelper.GetItemColor(serie, serieData, chart.theme, serieNameCount,
serieData.highlighted);
var toColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serieNameCount,
serieData.highlighted);
var borderWidth = itemStyle.borderWidth;
var borderColor = itemStyle.borderColor;
if (serie.pieClickOffset && serieData.selected)
{
var drawEndDegree = serieData.runtimePieCurrAngle;
var needRoundCap = serie.roundCap && serieData.runtimePieInsideRadius > 0;
UGL.DrawDoughnut(vh, serieData.runtiemPieOffsetCenter, serieData.runtimePieInsideRadius,
serieData.runtimePieOutsideRadius, color, toColor, Color.clear, serieData.runtimePieStartAngle,
drawEndDegree, borderWidth, borderColor, serie.pieSpace / 2, chart.settings.cicleSmoothness,
needRoundCap, true);
}
else
{
var drawEndDegree = serieData.runtimePieCurrAngle;
var needRoundCap = serie.roundCap && serieData.runtimePieInsideRadius > 0;
UGL.DrawDoughnut(vh, serie.runtimeCenterPos, serieData.runtimePieInsideRadius,
serieData.runtimePieOutsideRadius, color, toColor, Color.clear, serieData.runtimePieStartAngle,
drawEndDegree, borderWidth, borderColor, serie.pieSpace / 2, chart.settings.cicleSmoothness,
needRoundCap, true);
DrawPieCenter(vh, serie, itemStyle, serieData.runtimePieInsideRadius);
}
if (!serie.animation.CheckDetailBreak(serieData.runtimePieToAngle)) serie.animation.SetDataFinish(n);
else break;
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress(360);
serie.animation.CheckSymbol(serie.symbol.GetSize(null, chart.theme.serie.lineSymbolSize));
chart.RefreshPainter(serie);
}
if (dataChanging)
{
chart.RefreshPainter(serie);
}
chart.raycastTarget = IsAnyPieClickOffset() || IsAnyPieDataHighlight();
}
private bool IsAnyPieClickOffset()
{
foreach (var serie in chart.series.list)
{
if (serie.type == SerieType.Pie && serie.pieClickOffset) return true;
}
return false;
}
private bool IsAnyPieDataHighlight()
{
foreach (var serie in chart.series.list)
{
if (serie.type == SerieType.Pie)
{
foreach (var serieData in serie.data)
{
if (serieData.highlighted) 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 DrawPieLabelBackground(VertexHelper vh, Serie serie)
{
if (serie.avoidLabelOverlap) return;
foreach (var serieData in serie.data)
{
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
if (SerieLabelHelper.CanShowLabel(serie, serieData, serieLabel, 1))
{
SerieLabelHelper.UpdatePieLabelPosition(serie, serieData);
chart.DrawLabelBackground(vh, serie, serieData);
}
}
}
private void DrawPieLabelLine(VertexHelper vh, Serie serie, SerieData serieData, Color color)
{
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
if (serieLabel.show
&& serieLabel.position == SerieLabel.Position.Outside
&& serieLabel.line)
{
var insideRadius = serieData.runtimePieInsideRadius;
var outSideRadius = serieData.runtimePieOutsideRadius;
var center = serie.runtimeCenterPos;
var currAngle = serieData.runtimePieHalfAngle;
if (!ChartHelper.IsClearColor(serieLabel.lineColor)) color = serieLabel.lineColor;
else if (serieLabel.lineType == SerieLabel.LineType.HorizontalLine) color *= color;
float currSin = Mathf.Sin(currAngle * Mathf.Deg2Rad);
float currCos = Mathf.Cos(currAngle * Mathf.Deg2Rad);
var radius1 = serieLabel.lineType == SerieLabel.LineType.HorizontalLine ?
serie.runtimeOutsideRadius : outSideRadius;
var radius2 = serie.runtimeOutsideRadius + serieLabel.lineLength1;
var radius3 = insideRadius + (outSideRadius - insideRadius) / 2;
if (radius1 < serie.runtimeInsideRadius) radius1 = serie.runtimeInsideRadius;
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.labelPosition;
if (pos2.x == 0)
{
pos2 = new Vector3(center.x + radius2 * currSin, center.y + radius2 * currCos);
}
Vector3 pos4, pos6;
var horizontalLineCircleRadius = serieLabel.lineWidth * 4f;
var lineCircleDiff = horizontalLineCircleRadius - 0.3f;
if (currAngle < 90)
{
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos * radius3, 2)) - currSin * radius3;
r4 += serieLabel.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 += serieLabel.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 += serieLabel.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 += serieLabel.lineLength1 - lineCircleDiff;
pos6 = pos0 + Vector3.left * lineCircleDiff;
pos4 = pos6 + Vector3.left * r4;
}
var pos5X = currAngle > 180 ? pos2.x - serieLabel.lineLength2 : pos2.x + serieLabel.lineLength2;
var pos5 = new Vector3(pos5X, pos2.y);
switch (serieLabel.lineType)
{
case SerieLabel.LineType.BrokenLine:
UGL.DrawLine(vh, pos1, pos2, pos5, serieLabel.lineWidth, color);
break;
case SerieLabel.LineType.Curves:
UGL.DrawCurves(vh, pos1, pos5, pos1, pos2, serieLabel.lineWidth, color,
chart.settings.lineSmoothness);
break;
case SerieLabel.LineType.HorizontalLine:
UGL.DrawCricle(vh, pos0, horizontalLineCircleRadius, color);
UGL.DrawLine(vh, pos6, pos4, serieLabel.lineWidth, color);
break;
}
}
}
private void DrawPieLabel(Serie serie, int dataIndex, SerieData serieData, Color serieColor)
{
if (serieData.labelObject == null) return;
var currAngle = serieData.runtimePieHalfAngle;
var isHighlight = (serieData.highlighted && serie.emphasis.label.show);
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
var showLabel = ((serieLabel.show || isHighlight) && serieData.canShowLabel);
if (showLabel || serieData.iconStyle.show)
{
serieData.SetLabelActive(showLabel);
float rotate = 0;
bool isInsidePosition = serieLabel.position == SerieLabel.Position.Inside;
if (serieLabel.textStyle.rotate > 0 && isInsidePosition)
{
if (currAngle > 180) rotate += 270 - currAngle;
else rotate += -(currAngle - 90);
}
Color color = serieColor;
if (isHighlight)
{
if (!ChartHelper.IsClearColor(serie.emphasis.label.textStyle.color))
{
color = serie.emphasis.label.textStyle.color;
}
}
else if (!ChartHelper.IsClearColor(serieLabel.textStyle.color))
{
color = serieLabel.textStyle.color;
}
else
{
color = isInsidePosition ? Color.white : serieColor;
}
var fontSize = isHighlight
? serie.emphasis.label.textStyle.GetFontSize(chart.theme.common)
: serieLabel.textStyle.GetFontSize(chart.theme.common);
var fontStyle = isHighlight
? serie.emphasis.label.textStyle.fontStyle
: serieLabel.textStyle.fontStyle;
serieData.labelObject.label.SetColor(color);
serieData.labelObject.label.SetFontSize(fontSize);
serieData.labelObject.label.SetFontStyle(fontStyle);
serieData.labelObject.SetLabelRotate(rotate);
if (!string.IsNullOrEmpty(serieLabel.formatter))
{
var value = serieData.data[1];
var total = serie.yTotal;
var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, total, serieLabel);
if (serieData.labelObject.SetText(content)) chart.RefreshPainter(serie);
}
else
{
if (serieData.labelObject.SetText(serieData.name)) chart.RefreshPainter(serie);
}
serieData.labelObject.SetPosition(SerieLabelHelper.GetRealLabelPosition(serieData, serieLabel));
if (showLabel) serieData.labelObject.SetLabelPosition(serieLabel.offset);
else serieData.SetLabelActive(false);
}
else
{
serieData.SetLabelActive(false);
}
serieData.labelObject.UpdateIcon(serieData.iconStyle);
}
protected int GetPiePosIndex(Serie serie, Vector2 local)
{
if (serie.type != SerieType.Pie) return -1;
var dist = Vector2.Distance(local, serie.runtimeCenterPos);
if (dist < serie.runtimeInsideRadius || dist > serie.runtimeOutsideRadius) return -1;
Vector2 dir = local - new Vector2(serie.runtimeCenterPos.x, serie.runtimeCenterPos.y);
float angle = ChartHelper.GetAngle360(Vector2.up, dir);
for (int i = 0; i < serie.data.Count; i++)
{
var serieData = serie.data[i];
if (angle >= serieData.runtimePieStartAngle && angle <= serieData.runtimePieToAngle)
{
return i;
}
}
return -1;
}
private bool PointerIsInPieSerie(Series series, Vector2 local)
{
foreach (var serie in series.list)
{
if (serie.type != SerieType.Pie) continue;
var dist = Vector2.Distance(local, serie.runtimeCenterPos);
if (dist >= serie.runtimeInsideRadius && dist <= serie.runtimeOutsideRadius) return true;
}
return false;
}
protected void UpdatePieTooltip()
{
bool showTooltip = false;
foreach (var serie in chart.series.list)
{
int index = chart.tooltip.runtimeDataIndex[serie.index];
if (index < 0) continue;
showTooltip = true;
var content = TooltipHelper.GetFormatterContent(chart.tooltip, index, chart.series, chart.theme);
TooltipHelper.SetContentAndPosition(chart.tooltip, content.TrimStart(), chart.chartRect);
}
chart.tooltip.SetActive(showTooltip);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d5fa46fc54af9401796fc8691221e526
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,757 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using XUGL;
using System.Collections.Generic;
namespace XCharts
{
internal class DrawSerieRadar : IDrawSerie
{
public BaseChart chart;
private const string INDICATOR_TEXT = "indicator";
private bool m_IsEnterLegendButtom;
Dictionary<string, int> serieNameSet = new Dictionary<string, int>();
public DrawSerieRadar(BaseChart chart)
{
this.chart = chart;
}
public void InitComponent()
{
InitRadars();
}
public void CheckComponent()
{
}
public void Update()
{
}
public void DrawBase(VertexHelper vh)
{
serieNameSet.Clear();
for (int i = 0; i < chart.radars.Count; i++)
{
var radar = chart.radars[i];
if (!radar.show) continue;
radar.index = i;
radar.UpdateRadarCenter(chart.chartPosition, chart.chartWidth, chart.chartHeight);
if (radar.shape == Radar.Shape.Circle)
{
DrawCricleRadar(vh, radar);
}
else
{
DrawRadar(vh, radar);
}
}
}
public void DrawSerie(VertexHelper vh, Serie serie)
{
if (serie.type != SerieType.Radar) return;
if (!serie.show) return;
switch (serie.radarType)
{
case RadarType.Multiple:
DrawMutipleRadar(vh, serie, serie.index);
break;
case RadarType.Single:
DrawSingleRadar(vh, serie, serie.index);
break;
}
}
public void RefreshLabel()
{
for (int i = 0; i < chart.series.Count; i++)
{
var serie = chart.series.GetSerie(i);
if (serie.type != SerieType.Radar) continue;
if (!serie.show && serie.radarType != RadarType.Single) continue;
var radar = chart.GetRadar(serie.radarIndex);
if (radar == null) continue;
var center = radar.runtimeCenterPos;
for (int n = 0; n < serie.dataCount; n++)
{
var serieData = serie.data[n];
if (serieData.labelObject == null) continue;
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
var labelPos = serieData.labelPosition;
if (serieLabel.margin != 0)
{
labelPos += serieLabel.margin * (labelPos - center).normalized;
}
serieData.labelObject.SetPosition(labelPos);
serieData.labelObject.UpdateIcon(serieData.iconStyle);
if (serie.show && serieLabel.show && serieData.canShowLabel)
{
var value = serieData.GetCurrData(1);
var max = radar.GetIndicatorMax(n);
SerieLabelHelper.ResetLabel(serieData.labelObject.label, serieLabel, chart.theme, i);
serieData.SetLabelActive(serieData.labelPosition != Vector3.zero);
serieData.labelObject.SetLabelPosition(serieLabel.offset);
var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, max, serieLabel);
if (serieData.labelObject.SetText(content))
{
chart.RefreshPainter(serie);
}
}
else
{
serieData.SetLabelActive(false);
}
}
}
}
public bool CheckTootipArea(Vector2 local)
{
if (m_IsEnterLegendButtom) return false;
if (!IsInRadar(local)) return false;
bool highlight = false;
chart.tooltip.ClearValue();
for (int i = 0; i < chart.series.Count; i++)
{
var serie = chart.series.GetSerie(i);
if (!serie.show || serie.type != SerieType.Radar) continue;
var radar = chart.radars[serie.radarIndex];
var dist = Vector2.Distance(radar.runtimeCenterPos, local);
if (dist > radar.runtimeRadius + serie.symbol.GetSize(null, chart.theme.serie.lineSymbolSize))
{
continue;
}
switch (serie.radarType)
{
case RadarType.Multiple:
for (int n = 0; n < serie.data.Count; n++)
{
var posKey = i * 1000 + n;
if (radar.runtimeDataPosList.ContainsKey(posKey))
{
var posList = radar.runtimeDataPosList[posKey];
var symbolSize = serie.symbol.GetSize(serie.data[n].data, chart.theme.serie.lineSymbolSize);
for (int k = 0; k < posList.Count; k++)
{
if (Vector2.Distance(posList[k], local) <= symbolSize * 1.3f)
{
chart.tooltip.runtimeDataIndex[0] = i;
chart.tooltip.runtimeDataIndex[1] = n;
if (chart.tooltip.runtimeDataIndex.Count >= 3)
chart.tooltip.runtimeDataIndex[2] = k;
else
chart.tooltip.runtimeDataIndex.Add(k);
highlight = true;
break;
}
}
}
}
break;
case RadarType.Single:
for (int n = 0; n < serie.data.Count; n++)
{
var serieData = serie.data[n];
var symbolSize = serie.symbol.GetSize(serie.data[n].data, chart.theme.serie.lineSymbolSize);
if (Vector2.Distance(serieData.labelPosition, local) <= symbolSize * 1.3f)
{
chart.tooltip.runtimeDataIndex[0] = i;
chart.tooltip.runtimeDataIndex[1] = n;
highlight = true;
break;
}
}
break;
}
}
if (!highlight)
{
if (chart.tooltip.IsActive())
{
chart.tooltip.SetActive(false);
chart.RefreshChart();
}
}
else
{
chart.tooltip.UpdateContentPos(local + chart.tooltip.offset);
UpdateTooltip();
chart.RefreshChart();
}
return highlight;
}
public bool OnLegendButtonClick(int index, string legendName, bool show)
{
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Radar)) return false;
if (!LegendHelper.IsSerieLegend(chart.series, legendName, SerieType.Radar)) return false;
LegendHelper.CheckDataShow(chart.series, legendName, show);
chart.UpdateLegendColor(legendName, show);
chart.RefreshChart();
return true;
}
public bool OnLegendButtonEnter(int index, string legendName)
{
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Radar)) return false;
if (!LegendHelper.IsSerieLegend(chart.series, legendName, SerieType.Radar)) return false;
m_IsEnterLegendButtom = true;
LegendHelper.CheckDataHighlighted(chart.series, legendName, true);
chart.RefreshChart();
return true;
}
public bool OnLegendButtonExit(int index, string legendName)
{
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Radar)) return false;
if (!LegendHelper.IsSerieLegend(chart.series, legendName, SerieType.Radar)) return false;
m_IsEnterLegendButtom = false;
LegendHelper.CheckDataHighlighted(chart.series, legendName, false);
chart.RefreshChart();
return true;
}
public void OnPointerDown(PointerEventData eventData)
{
}
private void InitRadars()
{
for (int n = 0; n < chart.radars.Count; n++)
{
Radar radar = chart.radars[n];
radar.index = n;
InitRadar(radar);
}
}
private void InitRadar(Radar radar)
{
float txtWid = 100;
float txtHig = 20;
radar.painter = chart.GetPainter(radar.index);
radar.refreshComponent = delegate ()
{
ChartHelper.HideAllObject(chart.transform, INDICATOR_TEXT + "_" + radar.index);
radar.UpdateRadarCenter(chart.chartPosition, chart.chartWidth, chart.chartHeight);
for (int i = 0; i < radar.indicatorList.Count; i++)
{
var indicator = radar.indicatorList[i];
var pos = radar.GetIndicatorPosition(i);
var textStyle = indicator.textStyle;
var objName = INDICATOR_TEXT + "_" + radar.index + "_" + i;
var txt = ChartHelper.AddTextObject(objName, chart.transform, new Vector2(0.5f, 0.5f),
new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(txtWid, txtHig),
textStyle, chart.theme.radar);
txt.gameObject.hideFlags = chart.chartHideFlags;
txt.SetAlignment(TextAnchor.MiddleCenter);
txt.SetText(radar.indicatorList[i].name);
txt.SetActive(radar.indicator);
var offset = new Vector3(textStyle.offset.x, textStyle.offset.y);
AxisHelper.AdjustCircleLabelPos(txt, pos, radar.runtimeCenterPos, txtHig, offset);
}
chart.RefreshBasePainter();
};
radar.refreshComponent?.Invoke();
}
private void DrawMutipleRadar(VertexHelper vh, Serie serie, int i)
{
if (!serie.show) return;
var radar = chart.GetRadar(serie.radarIndex);
if (radar == null) return;
var startPoint = Vector3.zero;
var toPoint = Vector3.zero;
var firstPoint = Vector3.zero;
var indicatorNum = radar.indicatorList.Count;
var angle = 2 * Mathf.PI / indicatorNum;
var centerPos = radar.runtimeCenterPos;
var serieNameCount = -1;
serie.animation.InitProgress(1, 0, 1);
if (!chart.IsActive(i) || serie.animation.HasFadeOut())
{
return;
}
var rate = serie.animation.GetCurrRate();
var dataChanging = false;
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
SerieHelper.GetAllMinMaxData(serie, radar.ceilRate);
for (int j = 0; j < serie.data.Count; j++)
{
var serieData = serie.data[j];
int key = i * 1000 + j;
if (!radar.runtimeDataPosList.ContainsKey(key))
{
radar.runtimeDataPosList.Add(i * 1000 + j, new List<Vector3>(serieData.data.Count));
}
else
{
radar.runtimeDataPosList[key].Clear();
}
string dataName = serieData.name;
int serieIndex = 0;
if (string.IsNullOrEmpty(dataName))
{
serieNameCount++;
serieIndex = serieNameCount;
}
else if (!serieNameSet.ContainsKey(dataName))
{
serieNameSet.Add(dataName, serieNameCount);
serieNameCount++;
serieIndex = serieNameCount;
}
else
{
serieIndex = serieNameSet[dataName];
}
if (!serieData.show)
{
continue;
}
var isHighlight = IsHighlight(radar, serie, serieData, j, 0);
var areaColor = SerieHelper.GetAreaColor(serie, chart.theme, serieIndex, isHighlight);
var areaToColor = SerieHelper.GetAreaToColor(serie, chart.theme, serieIndex, isHighlight);
var lineColor = SerieHelper.GetLineColor(serie, chart.theme, serieIndex, isHighlight);
var lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
int dataCount = radar.indicatorList.Count;
List<Vector3> pointList = radar.runtimeDataPosList[key];
for (int n = 0; n < dataCount; n++)
{
if (n >= serieData.data.Count) break;
float max = radar.GetIndicatorMax(n);
float value = serieData.GetCurrData(n, dataChangeDuration);
if (serieData.IsDataChanged()) dataChanging = true;
if (max == 0)
{
max = serie.runtimeDataMax;
}
var radius = max < 0 ? radar.runtimeDataRadius - radar.runtimeDataRadius * value / max
: radar.runtimeDataRadius * value / max;
var currAngle = (n + (radar.positionType == Radar.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 (serie.areaStyle.show)
{
UGL.DrawTriangle(vh, startPoint, toPoint, centerPos, areaColor, areaColor, areaToColor);
}
if (serie.lineStyle.show)
{
ChartDrawer.DrawLineStyle(vh, serie.lineStyle.type, lineWidth, startPoint, toPoint, lineColor);
}
startPoint = toPoint;
}
pointList.Add(startPoint);
}
if (serie.areaStyle.show)
{
UGL.DrawTriangle(vh, startPoint, firstPoint, centerPos, areaColor, areaColor, areaToColor);
}
if (serie.lineStyle.show)
{
ChartDrawer.DrawLineStyle(vh, serie.lineStyle.type, lineWidth, startPoint, firstPoint, lineColor);
}
if (serie.symbol.show && serie.symbol.type != SerieSymbolType.None)
{
for (int m = 0; m < pointList.Count; m++)
{
var point = pointList[m];
isHighlight = IsHighlight(radar, serie, serieData, j, m);
var symbolSize = isHighlight
? serie.symbol.GetSelectedSize(null, chart.theme.serie.lineSymbolSelectedSize)
: serie.symbol.GetSize(null, 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 symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, chart.theme, isHighlight);
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, isHighlight);
chart.DrawSymbol(vh, serie.symbol.type, symbolSize, symbolBorder, point, symbolColor,
symbolToColor, serie.symbol.gap, cornerRadius);
}
}
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress(1);
chart.RefreshPainter(serie);
}
if (dataChanging)
{
chart.RefreshPainter(serie);
}
}
private bool IsHighlight(Radar radar, Serie serie, SerieData serieData, int dataIndex, int dimension)
{
if (serie.highlighted || serieData.highlighted) return true;
if (!chart.tooltip.show) return false;
var selectedSerieIndex = chart.tooltip.runtimeDataIndex[0];
if (selectedSerieIndex < 0) return false;
if (chart.series.GetSerie(selectedSerieIndex).radarIndex != serie.radarIndex) return false;
switch (serie.radarType)
{
case RadarType.Multiple:
if (radar.isAxisTooltip)
{
var selectedDimension = chart.tooltip.runtimeDataIndex[2];
return selectedDimension == dimension;
}
else if (chart.tooltip.runtimeDataIndex.Count >= 2)
{
return chart.tooltip.runtimeDataIndex[0] == serie.index && chart.tooltip.runtimeDataIndex[1] == dataIndex;
}
else
{
return false;
}
case RadarType.Single:
return chart.tooltip.runtimeDataIndex[1] == dataIndex;
}
return false;
}
private void DrawSingleRadar(VertexHelper vh, Serie serie, int i)
{
var startPoint = Vector3.zero;
var toPoint = Vector3.zero;
var firstPoint = Vector3.zero;
var radar = chart.radars[serie.radarIndex];
var indicatorNum = radar.indicatorList.Count;
var angle = 2 * Mathf.PI / indicatorNum;
var centerPos = radar.runtimeCenterPos;
var serieNameCount = -1;
serie.animation.InitProgress(1, 0, 1);
if (!chart.IsActive(i) || serie.animation.HasFadeOut())
{
return;
}
var rate = serie.animation.GetCurrRate();
var dataChanging = false;
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
int key = i * 1000;
if (!radar.runtimeDataPosList.ContainsKey(key))
{
radar.runtimeDataPosList.Add(i * 1000, new List<Vector3>(serie.dataCount));
}
else
{
radar.runtimeDataPosList[key].Clear();
}
var pointList = radar.runtimeDataPosList[key];
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;
int serieIndex = 0;
if (string.IsNullOrEmpty(dataName))
{
serieNameCount++;
serieIndex = serieNameCount;
}
else if (!serieNameSet.ContainsKey(dataName))
{
serieNameSet.Add(dataName, serieNameCount);
serieNameCount++;
serieIndex = serieNameCount;
}
else
{
serieIndex = serieNameSet[dataName];
}
if (!serieData.show)
{
serieData.labelPosition = Vector3.zero;
continue;
}
var isHighlight = IsHighlight(radar, serie, serieData, j, 0);
var areaColor = SerieHelper.GetAreaColor(serie, chart.theme, serieIndex, isHighlight);
var areaToColor = SerieHelper.GetAreaToColor(serie, chart.theme, serieIndex, isHighlight);
var lineColor = SerieHelper.GetLineColor(serie, chart.theme, serieIndex, isHighlight);
int dataCount = radar.indicatorList.Count;
var index = serieData.index;
var p = radar.runtimeCenterPos;
var max = radar.GetIndicatorMax(index);
var value = serieData.GetCurrData(1, dataChangeDuration);
if (serieData.IsDataChanged()) dataChanging = true;
if (max == 0)
{
max = serie.runtimeDataMax;
}
var radius = max < 0 ? radar.runtimeDataRadius - radar.runtimeDataRadius * value / max
: radar.runtimeDataRadius * value / max;
var currAngle = (index + (radar.positionType == Radar.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;
}
else
{
toPoint = new Vector3(p.x + radius * Mathf.Sin(currAngle),
p.y + radius * Mathf.Cos(currAngle));
if (serie.areaStyle.show)
{
UGL.DrawTriangle(vh, startPoint, toPoint, p, areaColor, areaColor, areaToColor);
}
if (serie.lineStyle.show)
{
ChartDrawer.DrawLineStyle(vh, serie.lineStyle, startPoint, toPoint, lineColor,
chart.theme.serie.lineWidth, LineStyle.Type.Solid);
}
startPoint = toPoint;
}
serieData.labelPosition = startPoint;
pointList.Add(startPoint);
if (serie.areaStyle.show && j == endIndex)
{
UGL.DrawTriangle(vh, startPoint, firstPoint, centerPos, areaColor, areaColor, areaToColor);
}
if (serie.lineStyle.show && j == endIndex)
{
ChartDrawer.DrawLineStyle(vh, serie.lineStyle, startPoint, firstPoint, lineColor,
chart.theme.serie.lineWidth, LineStyle.Type.Solid);
}
}
if (serie.symbol.show && serie.symbol.type != SerieSymbolType.None)
{
for (int j = 0; j < serie.data.Count; j++)
{
var serieData = serie.data[j];
if (!serieData.show) continue;
var isHighlight = serie.highlighted || serieData.highlighted ||
(chart.tooltip.show && chart.tooltip.runtimeDataIndex[0] == i && chart.tooltip.runtimeDataIndex[1] == j);
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 symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, chart.theme, isHighlight);
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, isHighlight);
chart.DrawSymbol(vh, serie.symbol.type, symbolSize, symbolBorder, serieData.labelPosition, symbolColor,
symbolToColor, 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 != SerieSymbolType.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 symbolBorder = SerieHelper.GetSymbolBorder(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, serie.symbol.gap, cornerRadius);
}
}
}
private void DrawRadar(VertexHelper vh, Radar radar)
{
if (!radar.splitLine.show && !radar.splitArea.show)
{
return;
}
float insideRadius = 0, outsideRadius = 0;
float block = radar.runtimeRadius / radar.splitNumber;
int indicatorNum = radar.indicatorList.Count;
Vector3 p1, p2, p3, p4;
Vector3 p = radar.runtimeCenterPos;
float angle = 2 * Mathf.PI / indicatorNum;
var lineColor = radar.axisLine.GetColor(chart.theme.radar.lineColor);
var lineWidth = radar.axisLine.GetWidth(chart.theme.radar.lineWidth);
var lineType = radar.axisLine.GetType(chart.theme.radar.lineType);
var splitLineColor = radar.splitLine.GetColor(chart.theme.radar.splitLineColor);
var splitLineWidth = radar.splitLine.GetWidth(chart.theme.radar.splitLineWidth);
var splitLineType = radar.splitLine.GetType(chart.theme.radar.splitLineType);
for (int i = 0; i < radar.splitNumber; i++)
{
var isLast = i == radar.splitNumber - 1;
var color = radar.splitArea.GetColor(i, chart.theme.radar);
outsideRadius = insideRadius + block;
p1 = new Vector3(p.x + insideRadius * Mathf.Sin(0), p.y + insideRadius * Mathf.Cos(0));
p2 = new Vector3(p.x + outsideRadius * Mathf.Sin(0), p.y + outsideRadius * Mathf.Cos(0));
for (int j = 0; j <= indicatorNum; j++)
{
float currAngle = j * angle;
p3 = new Vector3(p.x + outsideRadius * Mathf.Sin(currAngle),
p.y + outsideRadius * Mathf.Cos(currAngle));
p4 = new Vector3(p.x + insideRadius * Mathf.Sin(currAngle),
p.y + insideRadius * Mathf.Cos(currAngle));
if (radar.splitArea.show)
{
UGL.DrawQuadrilateral(vh, p1, p2, p3, p4, color);
}
if (radar.splitLine.NeedShow(i))
{
if (isLast)
ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, p2, p3, lineColor);
else
ChartDrawer.DrawLineStyle(vh, splitLineType, splitLineWidth, p2, p3, splitLineColor);
}
p1 = p4;
p2 = p3;
}
insideRadius = outsideRadius;
}
for (int j = 0; j <= indicatorNum; j++)
{
float currAngle = j * angle;
p3 = new Vector3(p.x + outsideRadius * Mathf.Sin(currAngle),
p.y + outsideRadius * Mathf.Cos(currAngle));
if (radar.splitLine.show)
{
ChartDrawer.DrawLineStyle(vh, splitLineType, splitLineWidth, p, p3, splitLineColor);
}
}
}
private void DrawCricleRadar(VertexHelper vh, Radar radar)
{
if (!radar.splitLine.show && !radar.splitArea.show)
{
return;
}
float insideRadius = 0, outsideRadius = 0;
float block = radar.runtimeRadius / radar.splitNumber;
int indicatorNum = radar.indicatorList.Count;
Vector3 p = radar.runtimeCenterPos;
Vector3 p1;
float angle = 2 * Mathf.PI / indicatorNum;
var lineColor = radar.axisLine.GetColor(chart.theme.radar.lineColor);
var lineWidth = radar.splitLine.GetWidth(chart.theme.radar.splitLineWidth);
for (int i = 0; i < radar.splitNumber; i++)
{
Color color = radar.splitArea.color[i % radar.splitArea.color.Count];
outsideRadius = insideRadius + block;
if (radar.splitArea.show)
{
UGL.DrawDoughnut(vh, p, insideRadius, outsideRadius, color, Color.clear,
0, 360, chart.settings.cicleSmoothness);
}
if (radar.splitLine.show)
{
UGL.DrawEmptyCricle(vh, p, outsideRadius, lineWidth, lineColor,
Color.clear, chart.settings.cicleSmoothness);
}
insideRadius = outsideRadius;
}
for (int j = 0; j <= indicatorNum; j++)
{
float currAngle = j * angle;
p1 = new Vector3(p.x + outsideRadius * Mathf.Sin(currAngle),
p.y + outsideRadius * Mathf.Cos(currAngle));
if (radar.splitLine.show)
{
UGL.DrawLine(vh, p, p1, lineWidth / 2, lineColor);
}
}
}
private bool IsInRadar(Vector2 local)
{
foreach (var radar in chart.radars)
{
var dist = Vector2.Distance(radar.runtimeCenterPos, local);
if (dist < radar.runtimeRadius + chart.theme.serie.lineSymbolSize)
{
return true;
}
}
return false;
}
protected void UpdateTooltip()
{
int serieIndex = chart.tooltip.runtimeDataIndex[0];
if (serieIndex < 0)
{
if (chart.tooltip.IsActive())
{
chart.tooltip.SetActive(false);
chart.RefreshChart();
}
return;
}
chart.tooltip.SetActive(true);
var serie = chart.series.GetSerie(serieIndex);
var radar = chart.radars[serie.radarIndex];
var dataIndex = chart.tooltip.runtimeDataIndex[1];
var content = TooltipHelper.GetFormatterContent(chart.tooltip, dataIndex, chart.series, chart.theme,
null, null, false, radar);
TooltipHelper.SetContentAndPosition(chart.tooltip, content, chart.chartRect);
}
private bool IsAnyRadarDirty()
{
foreach (var radar in chart.radars)
{
if (radar.anyDirty) return true;
}
return false;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8b5a823d3c59a461f872211f9580a28c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,361 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using XUGL;
namespace XCharts
{
internal class DrawSerieRing : IDrawSerie
{
public BaseChart chart;
private bool m_UpdateTitleText = false;
private bool m_UpdateLabelText = false;
private bool m_IsEnterLegendButtom;
public DrawSerieRing(BaseChart chart)
{
this.chart = chart;
}
public void InitComponent()
{
}
public void CheckComponent()
{
}
public void Update()
{
if (m_UpdateTitleText)
{
m_UpdateTitleText = false;
foreach (var serie in chart.series.list)
{
if (serie.type == SerieType.Ring)
{
TitleStyleHelper.UpdateTitleText(serie);
}
}
}
if (m_UpdateLabelText)
{
m_UpdateLabelText = false;
foreach (var serie in chart.series.list)
{
if (serie.type == SerieType.Ring)
{
SerieLabelHelper.SetRingLabelText(serie, chart.theme);
}
}
}
}
public void DrawBase(VertexHelper vh)
{
}
public void DrawSerie(VertexHelper vh, Serie serie)
{
if (serie.type != SerieType.Ring) return;
if (!serie.show || serie.animation.HasFadeOut()) return;
var data = serie.data;
serie.animation.InitProgress(data.Count, serie.startAngle, serie.startAngle + 360);
SerieHelper.UpdateCenter(serie, chart.chartPosition, chart.chartWidth, chart.chartHeight);
TitleStyleHelper.CheckTitle(serie, ref chart.m_ReinitTitle, ref m_UpdateTitleText);
SerieLabelHelper.CheckLabel(serie, ref chart.m_ReinitLabel, ref m_UpdateLabelText);
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
var ringWidth = serie.runtimeOutsideRadius - serie.runtimeInsideRadius;
var dataChanging = false;
for (int j = 0; j < data.Count; j++)
{
var serieData = data[j];
if (!serieData.show) continue;
if (serieData.IsDataChanged()) dataChanging = true;
var value = serieData.GetFirstData(dataChangeDuration);
var max = serieData.GetLastData();
var degree = 360 * value / max;
var startDegree = GetStartAngle(serie);
var toDegree = GetToAngle(serie, degree);
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, serieData.highlighted);
var itemColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, j, serieData.highlighted);
var itemToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, j, serieData.highlighted);
var outsideRadius = serie.runtimeOutsideRadius - j * (ringWidth + serie.ringGap);
var insideRadius = outsideRadius - ringWidth;
var centerRadius = (outsideRadius + insideRadius) / 2;
var borderWidth = itemStyle.borderWidth;
var borderColor = itemStyle.borderColor;
var roundCap = serie.roundCap && insideRadius > 0;
serieData.runtimePieStartAngle = serie.clockwise ? startDegree : toDegree;
serieData.runtimePieToAngle = serie.clockwise ? toDegree : startDegree;
serieData.runtimePieInsideRadius = insideRadius;
serieData.runtimePieOutsideRadius = outsideRadius;
UGL.DrawDoughnut(vh, serie.runtimeCenterPos, 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);
UpateLabelPosition(serie, serieData, j, startDegree, toDegree, centerRadius);
}
if (!serie.animation.IsFinish())
{
serie.animation.CheckProgress(360);
chart.RefreshChart();
}
if (dataChanging)
{
chart.RefreshChart();
}
}
public void RefreshLabel()
{
}
public bool CheckTootipArea(Vector2 local)
{
if (!PointerIsInRingSerie(chart.series, local)) return false;
if (m_IsEnterLegendButtom) return false;
bool selected = false;
chart.tooltip.runtimeDataIndex.Clear();
foreach (var serie in chart.series.list)
{
int index = GetRingIndex(serie, local);
chart.tooltip.runtimeDataIndex.Add(index);
if (serie.type != SerieType.Ring) continue;
bool refresh = false;
for (int j = 0; j < serie.data.Count; j++)
{
var serieData = serie.data[j];
if (serieData.highlighted != (j == index)) refresh = true;
serieData.highlighted = j == index;
}
if (index >= 0) selected = true;
if (refresh) chart.RefreshChart();
}
if (selected)
{
chart.tooltip.UpdateContentPos(local + chart.tooltip.offset);
UpdateTooltip();
}
else if (chart.tooltip.IsActive())
{
chart.tooltip.SetActive(false);
chart.RefreshChart();
}
return true;
}
public bool OnLegendButtonClick(int index, string legendName, bool show)
{
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Ring)) return false;
if (!LegendHelper.IsSerieLegend(chart.series, legendName, SerieType.Ring)) return false;
LegendHelper.CheckDataShow(chart.series, legendName, show);
chart.UpdateLegendColor(legendName, show);
chart.RefreshChart();
return true;
}
public bool OnLegendButtonEnter(int index, string legendName)
{
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Ring)) return false;
if (!LegendHelper.IsSerieLegend(chart.series, legendName, SerieType.Ring)) return false;
m_IsEnterLegendButtom = true;
LegendHelper.CheckDataHighlighted(chart.series, legendName, true);
chart.RefreshChart();
return true;
}
public bool OnLegendButtonExit(int index, string legendName)
{
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Ring)) return false;
if (!LegendHelper.IsSerieLegend(chart.series, legendName, SerieType.Ring)) return false;
m_IsEnterLegendButtom = false;
LegendHelper.CheckDataHighlighted(chart.series, legendName, false);
chart.RefreshChart();
return true;
}
public 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.runtimeCenterPos, radius, itemStyle.centerColor, smoothness);
}
}
private void UpateLabelPosition(Serie serie, SerieData serieData, int index, float startAngle,
float toAngle, float centerRadius)
{
if (!serie.label.show) return;
if (serieData.labelObject == null) return;
switch (serie.label.position)
{
case SerieLabel.Position.Center:
serieData.labelPosition = serie.runtimeCenterPos + serie.label.offset;
break;
case SerieLabel.Position.Bottom:
var px1 = Mathf.Sin(startAngle * Mathf.Deg2Rad) * centerRadius;
var py1 = Mathf.Cos(startAngle * Mathf.Deg2Rad) * centerRadius;
var xDiff = serie.clockwise ? -serie.label.margin : serie.label.margin;
serieData.labelPosition = serie.runtimeCenterPos + new Vector3(px1 + xDiff, py1);
break;
case SerieLabel.Position.Top:
startAngle += serie.clockwise ? -serie.label.margin : serie.label.margin;
toAngle += serie.clockwise ? serie.label.margin : -serie.label.margin;
var px2 = Mathf.Sin(toAngle * Mathf.Deg2Rad) * centerRadius;
var py2 = Mathf.Cos(toAngle * Mathf.Deg2Rad) * centerRadius;
serieData.labelPosition = serie.runtimeCenterPos + new Vector3(px2, py2);
break;
}
serieData.labelObject.SetLabelPosition(serieData.labelPosition);
}
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.runtimeCenterPos, inradius,
outradius, backgroundColor, Color.clear, chart.settings.cicleSmoothness);
}
else
{
UGL.DrawDoughnut(vh, serie.runtimeCenterPos, 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.runtimeCenterPos, outsideRadius,
outsideRadius + itemStyle.borderWidth, itemStyle.borderColor,
Color.clear, chart.settings.cicleSmoothness);
UGL.DrawDoughnut(vh, serie.runtimeCenterPos, insideRadius,
insideRadius + itemStyle.borderWidth, itemStyle.borderColor,
Color.clear, chart.settings.cicleSmoothness);
}
}
private void DrawRoundCap(VertexHelper vh, Serie serie, Vector3 centerPos, Color color,
float insideRadius, float outsideRadius, ref float drawStartDegree, ref float drawEndDegree)
{
if (serie.roundCap && insideRadius > 0 && drawStartDegree != drawEndDegree)
{
var width = (outsideRadius - insideRadius) / 2;
var radius = insideRadius + width;
var diffDegree = Mathf.Asin(width / radius) * Mathf.Rad2Deg;
drawStartDegree += serie.clockwise ? diffDegree : -diffDegree;
drawEndDegree -= serie.clockwise ? diffDegree : -diffDegree;
UGL.DrawRoundCap(vh, centerPos, width, radius, drawStartDegree, serie.clockwise, color, false);
UGL.DrawRoundCap(vh, centerPos, width, radius, drawEndDegree, serie.clockwise, color, true);
}
}
private int GetRingIndex(Serie serie, Vector2 local)
{
if (serie.type != SerieType.Ring) return -1;
var dist = Vector2.Distance(local, serie.runtimeCenterPos);
if (dist > serie.runtimeOutsideRadius) return -1;
Vector2 dir = local - new Vector2(serie.runtimeCenterPos.x, serie.runtimeCenterPos.y);
float angle = VectorAngle(Vector2.up, dir);
for (int i = 0; i < serie.data.Count; i++)
{
var serieData = serie.data[i];
if (dist >= serieData.runtimePieInsideRadius &&
dist <= serieData.runtimePieOutsideRadius &&
angle >= serieData.runtimePieStartAngle &&
angle <= serieData.runtimePieToAngle)
{
return i;
}
}
return -1;
}
private bool PointerIsInRingSerie(Series series, Vector2 local)
{
foreach (var serie in series.list)
{
if (serie.type != SerieType.Ring) continue;
if (GetRingIndex(serie, local) >= 0) return true;
}
return false;
}
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;
}
private void UpdateTooltip()
{
bool showTooltip = false;
foreach (var serie in chart.series.list)
{
int index = chart.tooltip.runtimeDataIndex[serie.index];
if (index < 0) continue;
showTooltip = true;
var content = TooltipHelper.GetFormatterContent(chart.tooltip, index, chart.series, chart.theme);
TooltipHelper.SetContentAndPosition(chart.tooltip, content.TrimStart(), chart.chartRect);
}
chart.tooltip.SetActive(showTooltip);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 27eff3714a61b44d2968104598e3566e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,71 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using XUGL;
namespace XCharts
{
internal class DrawSerieTemplate : IDrawSerie
{
public BaseChart chart;
public DrawSerieTemplate(BaseChart chart)
{
this.chart = chart;
}
public void InitComponent()
{
}
public void CheckComponent()
{
}
public void Update()
{
}
public void DrawBase(VertexHelper vh)
{
}
public void DrawSerie(VertexHelper vh, Serie serie)
{
}
public void RefreshLabel()
{
}
public bool CheckTootipArea(Vector2 local)
{
return false;
}
public bool OnLegendButtonClick(int index, string legendName, bool show)
{
return false;
}
public bool OnLegendButtonEnter(int index, string legendName)
{
return false;
}
public bool OnLegendButtonExit(int index, string legendName)
{
return false;
}
public void OnPointerDown(PointerEventData eventData)
{
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 35f409612108b4fdead9ddce4426c9b0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b3dbff4f83d24491da3a8a88e3e3ace4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,412 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using System.Text;
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
public static class AxisHelper
{
/// <summary>
/// 包含箭头偏移的轴线长度
/// </summary>
/// <param name="axis"></param>
/// <returns></returns>
public static float GetAxisLineSymbolOffset(Axis axis)
{
if (axis.axisLine.show && axis.axisLine.showArrow && axis.axisLine.arrow.offset > 0)
{
return axis.axisLine.arrow.offset;
}
return 0;
}
/// <summary>
/// 获得分割段数
/// </summary>
/// <param name="dataZoom"></param>
/// <returns></returns>
public static int GetSplitNumber(Axis axis, float coordinateWid, DataZoom dataZoom)
{
if (axis.type == Axis.AxisType.Value)
{
if (axis.interval > 0)
{
if (coordinateWid <= 0) return 0;
int num = Mathf.CeilToInt(axis.runtimeMinMaxRange / axis.interval);
int maxNum = Mathf.CeilToInt(coordinateWid / 15);
if (num > maxNum)
{
axis.interval *= 2;
num = Mathf.CeilToInt(axis.runtimeMinMaxRange / axis.interval);
}
return num;
}
else
{
return axis.splitNumber > 0 ? axis.splitNumber : 4;
}
}
else if (axis.type == Axis.AxisType.Time)
{
if (axis.interval > 0)
{
if (coordinateWid <= 0) return 0;
int num = Mathf.CeilToInt(axis.runtimeMinMaxRange / axis.interval);
int maxNum = Mathf.CeilToInt(coordinateWid / 15);
if (num > maxNum)
{
axis.interval *= 2;
num = Mathf.CeilToInt(axis.runtimeMinMaxRange / axis.interval);
}
return num;
}
else
{
return axis.splitNumber > 0 ? axis.splitNumber : 4;
}
}
else if (axis.type == Axis.AxisType.Log)
{
return axis.splitNumber > 0 ? axis.splitNumber : 4;
}
else if (axis.type == Axis.AxisType.Category)
{
int dataCount = axis.GetDataList(dataZoom).Count;
if (axis.splitNumber <= 0 || axis.splitNumber > dataCount) return dataCount;
if (dataCount >= axis.splitNumber * 2) return axis.splitNumber;
else return dataCount;
}
return 0;
}
/// <summary>
/// 获得分割段的宽度
/// </summary>
/// <param name="coordinateWidth"></param>
/// <param name="dataZoom"></param>
/// <returns></returns>
public static float GetSplitWidth(Axis axis, float coordinateWidth, DataZoom dataZoom)
{
int split = GetSplitNumber(axis, coordinateWidth, dataZoom);
int segment = (axis.boundaryGap ? split : split - 1);
segment = segment <= 0 ? 1 : segment;
return coordinateWidth / segment;
}
/// <summary>
/// 获得一个类目数据在坐标系中代表的宽度
/// </summary>
/// <param name="coordinateWidth"></param>
/// <param name="dataZoom"></param>
/// <returns></returns>
public static float GetDataWidth(Axis axis, float coordinateWidth, int dataCount, DataZoom dataZoom)
{
if (dataCount < 1) dataCount = 1;
var categoryCount = axis.GetDataNumber(dataZoom);
int segment = (axis.boundaryGap ? categoryCount : categoryCount - 1);
segment = segment <= 0 ? dataCount : segment;
if (segment <= 0) segment = 1;
return coordinateWidth / segment;
}
/// <summary>
/// 获得标签显示的名称
/// </summary>
/// <param name="index"></param>
/// <param name="minValue"></param>
/// <param name="maxValue"></param>
/// <param name="dataZoom"></param>
/// <returns></returns>
internal static string GetLabelName(Axis axis, float coordinateWidth, int index, float minValue, float maxValue,
DataZoom dataZoom, bool forcePercent)
{
int split = GetSplitNumber(axis, coordinateWidth, dataZoom);
if (axis.type == Axis.AxisType.Value)
{
if (minValue == 0 && maxValue == 0) return string.Empty;
var value = 0f;
if (forcePercent) maxValue = 100;
if (axis.interval > 0)
{
if (index == split) value = maxValue;
else value = minValue + index * axis.interval;
}
else
{
value = minValue + (maxValue - minValue) * index / split;
if (!axis.clockwise && value != minValue) value = maxValue - value;
}
if (axis.inverse)
{
value = -value;
minValue = -minValue;
maxValue = -maxValue;
}
if (forcePercent) return string.Format("{0}%", (int)value);
else return axis.axisLabel.GetFormatterContent(value, minValue, maxValue);
}
else if (axis.type == Axis.AxisType.Log)
{
float value = axis.logBaseE ? Mathf.Exp(axis.runtimeMinLogIndex + index) :
Mathf.Pow(axis.logBase, axis.runtimeMinLogIndex + index);
if (axis.inverse)
{
value = -value;
minValue = -minValue;
maxValue = -maxValue;
}
return axis.axisLabel.GetFormatterContent(value, minValue, maxValue, true);
}
else if (axis.type == Axis.AxisType.Time)
{
if (minValue == 0 && maxValue == 0) return string.Empty;
var value = 0f;
if (axis.interval > 0)
{
if (index == split) value = maxValue;
else value = minValue + index * axis.interval;
}
else
{
value = minValue + (maxValue - minValue) * index / split;
}
var timestamp = (int)value;
var dateTime = DateTimeUtil.GetDateTime(timestamp);
return axis.axisLabel.GetFormatterDateTime(dateTime);
}
var showData = axis.GetDataList(dataZoom);
int dataCount = showData.Count;
if (dataCount <= 0) return "";
int rate = Mathf.RoundToInt(dataCount * 1f / split);
int newIndex = index * rate;
if (newIndex <= dataCount - 1)
{
return axis.axisLabel.GetFormatterContent(showData[newIndex]);
}
else
{
if (rate == 1) return string.Empty;
else if (axis.boundaryGap && coordinateWidth / dataCount > 10) return string.Empty;
else
{
if ((index - 1) * rate > dataCount - 1) return string.Empty;
else return axis.axisLabel.GetFormatterContent(showData[dataCount - 1]);
}
}
}
/// <summary>
/// 获得分割线条数
/// </summary>
/// <param name="dataZoom"></param>
/// <returns></returns>
internal static int GetScaleNumber(Axis axis, float coordinateWidth, DataZoom dataZoom = null)
{
int splitNum = GetSplitNumber(axis, coordinateWidth, dataZoom);
if (axis.IsCategory())
{
var data = axis.GetDataList();
int tick = Mathf.RoundToInt(data.Count * 1f / splitNum);
if (axis.boundaryGap)
return Mathf.CeilToInt(data.Count * 1.0f / tick) + 1;
else
return Mathf.CeilToInt(data.Count * 1.0f / tick);
}
else
{
return splitNum + 1;
}
}
/// <summary>
/// 获得分割段宽度
/// </summary>
/// <param name="coordinateWidth"></param>
/// <param name="dataZoom"></param>
/// <returns></returns>
internal static float GetScaleWidth(Axis axis, float coordinateWidth, int index, DataZoom dataZoom = null)
{
if (index < 0) return 0;
int num = GetScaleNumber(axis, coordinateWidth, dataZoom);
int splitNum = GetSplitNumber(axis, coordinateWidth, dataZoom);
if (num <= 0) num = 1;
if (axis.type == Axis.AxisType.Value && axis.interval > 0)
{
if (axis.runtimeMinMaxRange <= 0) return 0;
if (index >= splitNum) return coordinateWidth - (index - 1) * axis.interval * coordinateWidth / axis.runtimeMinMaxRange;
else return axis.interval * coordinateWidth / axis.runtimeMinMaxRange;
}
else
{
var data = axis.GetDataList();
if (axis.IsCategory() && data.Count > 0)
{
int tick = Mathf.RoundToInt(data.Count * 1f / splitNum);
var count = axis.boundaryGap ? data.Count : data.Count - 1;
if (count <= 0) return 0;
var each = coordinateWidth / count;
if (index >= num - 1)
{
if (axis.axisTick.alignWithLabel) return each * tick;
else return coordinateWidth - each * tick * (index - 1);
}
else return each * tick;
}
else
{
if (splitNum <= 0) return 0;
else return coordinateWidth / splitNum;
}
}
}
internal static float GetEachWidth(Axis axis, float coordinateWidth, DataZoom dataZoom = null)
{
var data = axis.GetDataList();
if (data.Count > 0)
{
var count = axis.boundaryGap ? data.Count : data.Count - 1;
return count > 0 ? coordinateWidth / count : coordinateWidth;
}
else
{
int num = GetScaleNumber(axis, coordinateWidth, dataZoom) - 1;
return num > 0 ? coordinateWidth / num : coordinateWidth;
}
}
/// <summary>
/// 调整最大最小值
/// </summary>
/// <param name="minValue"></param>
/// <param name="maxValue"></param>
internal static void AdjustMinMaxValue(Axis axis, ref float minValue, ref float maxValue, bool needFormat, int ceilRate = 0)
{
if (axis.type == Axis.AxisType.Log)
{
int minSplit = 0;
int maxSplit = 0;
maxValue = ChartHelper.GetMaxLogValue(maxValue, axis.logBase, axis.logBaseE, out maxSplit);
minValue = ChartHelper.GetMinLogValue(minValue, axis.logBase, axis.logBaseE, out minSplit);
axis.splitNumber = (minSplit > 0 && maxSplit > 0) ? (maxSplit + minSplit - 1) : (maxSplit + minSplit);
return;
}
if (axis.minMaxType == Axis.AxisMinMaxType.Custom)
{
if (axis.min != 0 || axis.max != 0)
{
if (axis.inverse)
{
minValue = -axis.max;
maxValue = -axis.min;
}
else
{
minValue = axis.min;
maxValue = axis.max;
}
}
}
else
{
if (ceilRate == 0) ceilRate = axis.ceilRate;
switch (axis.minMaxType)
{
case Axis.AxisMinMaxType.Default:
if (minValue == 0 && maxValue == 0)
{
}
else if (minValue > 0 && maxValue > 0)
{
minValue = 0;
maxValue = needFormat ? ChartHelper.GetMaxDivisibleValue(maxValue, ceilRate) : maxValue;
}
else if (minValue < 0 && maxValue < 0)
{
minValue = needFormat ? ChartHelper.GetMinDivisibleValue(minValue, ceilRate) : minValue;
maxValue = 0;
}
else
{
minValue = needFormat ? ChartHelper.GetMinDivisibleValue(minValue, ceilRate) : minValue;
maxValue = needFormat ? ChartHelper.GetMaxDivisibleValue(maxValue, ceilRate) : maxValue;
}
break;
case Axis.AxisMinMaxType.MinMax:
minValue = needFormat ? ChartHelper.GetMinDivisibleValue(minValue, ceilRate) : minValue;
maxValue = needFormat ? ChartHelper.GetMaxDivisibleValue(maxValue, ceilRate) : maxValue;
break;
}
}
var tempRange = maxValue - minValue;
if (axis.runtimeMinMaxRange != tempRange)
{
axis.runtimeMinMaxRange = tempRange;
if (axis.type == Axis.AxisType.Value && axis.interval > 0)
{
axis.SetComponentDirty();
}
}
}
internal static bool NeedShowSplit(Axis axis)
{
if (!axis.show) return false;
if (axis.IsCategory() && axis.GetDataList().Count <= 0) return false;
else if (axis.IsValue() && axis.runtimeMinValue == 0 && axis.runtimeMaxValue == 0) return false;
else return true;
}
internal static void AdjustCircleLabelPos(ChartText txt, Vector3 pos, Vector3 cenPos, float txtHig, Vector3 offset)
{
var txtWidth = txt.GetPreferredWidth();
var sizeDelta = new Vector2(txtWidth, txt.GetPreferredHeight());
txt.SetSizeDelta(sizeDelta);
var diff = pos.x - cenPos.x;
if (diff < -1f) //left
{
pos = new Vector3(pos.x - txtWidth / 2, pos.y);
}
else if (diff > 1f) //right
{
pos = new Vector3(pos.x + txtWidth / 2, pos.y);
}
else
{
float y = pos.y > cenPos.y ? pos.y + txtHig / 2 : pos.y - txtHig / 2;
pos = new Vector3(pos.x, y);
}
txt.SetLocalPosition(pos + offset);
}
internal static void AdjustRadiusAxisLabelPos(ChartText txt, Vector3 pos, Vector3 cenPos, float txtHig, Vector3 offset)
{
var txtWidth = txt.GetPreferredWidth();
var sizeDelta = new Vector2(txtWidth, txt.GetPreferredHeight());
txt.SetSizeDelta(sizeDelta);
var diff = pos.y - cenPos.y;
if (diff > 20f) //left
{
pos = new Vector3(pos.x - txtWidth / 2, pos.y);
}
else if (diff < -20f) //right
{
pos = new Vector3(pos.x + txtWidth / 2, pos.y);
}
else
{
float y = pos.y > cenPos.y ? pos.y + txtHig / 2 : pos.y - txtHig / 2;
pos = new Vector3(pos.x, y);
}
txt.SetLocalPosition(pos);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 502c2be6d197b40f59ae65d9c659700f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,24 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
internal static class ItemStyleHelper
{
public static bool IsNeedCorner(ItemStyle itemStyle)
{
if (itemStyle.cornerRadius == null) return false;
foreach (var value in itemStyle.cornerRadius)
{
if (value != 0) return true;
}
return false;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 14c20b85c2c6d44b08f57c928307080d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,307 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
internal static class LegendHelper
{
public static Color GetContentColor(Legend legend, ChartTheme theme, bool active)
{
var textStyle = legend.textStyle;
if (active) return !ChartHelper.IsClearColor(textStyle.color) ? textStyle.color : theme.legend.textColor;
else return theme.legend.unableColor;
}
public static Color GetIconColor(Legend legend, int readIndex, ChartTheme theme, Series series, string legendName, bool active)
{
if (active)
{
if (legend.itemAutoColor || legend.GetIcon(readIndex) == null)
{
return SeriesHelper.GetNameColor(series, readIndex, legendName, theme);
}
else
return Color.white;
}
else return theme.legend.unableColor;
}
public static LegendItem AddLegendItem(Legend legend, int i, string legendName, Transform parent,
ChartTheme theme, string content, Color itemColor, bool active)
{
var objName = i + "_" + legendName;
var anchorMin = new Vector2(0, 0.5f);
var anchorMax = new Vector2(0, 0.5f);
var pivot = new Vector2(0, 0.5f);
var sizeDelta = new Vector2(100, 30);
var iconSizeDelta = new Vector2(legend.itemWidth, legend.itemHeight);
var textStyle = legend.textStyle;
var contentColor = GetContentColor(legend, theme, active);
var objAnchorMin = new Vector2(0, 1);
var objAnchorMax = new Vector2(0, 1);
var objPivot = new Vector2(0, 1);
var btnObj = ChartHelper.AddObject(objName, parent, objAnchorMin, objAnchorMax, objPivot, sizeDelta, i);
var iconObj = ChartHelper.AddObject("icon", btnObj.transform, anchorMin, anchorMax, pivot, iconSizeDelta);
var contentObj = ChartHelper.AddObject("content", btnObj.transform, anchorMin, anchorMax, pivot, sizeDelta);
var img = ChartHelper.GetOrAddComponent<Image>(btnObj);
img.color = Color.clear;
ChartHelper.GetOrAddComponent<Button>(btnObj);
ChartHelper.GetOrAddComponent<Image>(iconObj);
ChartHelper.GetOrAddComponent<Image>(contentObj);
var txt = ChartHelper.AddTextObject("Text", contentObj.transform, anchorMin, anchorMax, pivot, sizeDelta,
textStyle, theme.legend);
txt.SetAlignment(TextAnchor.MiddleLeft);
txt.SetColor(contentColor);
var item = new LegendItem();
item.index = i;
item.name = objName;
item.legendName = legendName;
item.SetObject(btnObj);
item.SetIconSize(legend.itemWidth, legend.itemHeight);
item.SetIconColor(itemColor);
item.SetIconImage(legend.GetIcon(i));
item.SetContentPosition(textStyle.offsetv3);
item.SetContent(content);
item.SetContentBackgroundColor(textStyle.backgroundColor);
return item;
}
public static void ResetItemPosition(Legend legend, Vector3 chartPos, float chartWidth, float chartHeight)
{
var startX = 0f;
var startY = 0f;
var legendMaxWidth = chartWidth - legend.location.left - legend.location.right;
var legendMaxHeight = chartHeight - legend.location.top - legend.location.bottom;
UpdateLegendWidthAndHeight(legend, legendMaxWidth, legendMaxHeight);
var legendRuntimeWidth = legend.runtimeWidth;
var legendRuntimeHeight = legend.runtimeHeight;
var isVertical = legend.orient == Orient.Vertical;
switch (legend.location.align)
{
case Location.Align.TopCenter:
startX = chartPos.x + chartWidth / 2 - legendRuntimeWidth / 2;
startY = chartPos.y + chartHeight - legend.location.top;
break;
case Location.Align.TopLeft:
startX = chartPos.x + legend.location.left;
startY = chartPos.y + chartHeight - legend.location.top;
break;
case Location.Align.TopRight:
startX = chartPos.x + chartWidth - legendRuntimeWidth - legend.location.right;
startY = chartPos.y + chartHeight - legend.location.top;
break;
case Location.Align.Center:
startX = chartPos.x + chartWidth / 2 - legendRuntimeWidth / 2;
startY = chartPos.y + chartHeight / 2 + legendRuntimeHeight / 2;
break;
case Location.Align.CenterLeft:
startX = chartPos.x + legend.location.left;
startY = chartPos.y + chartHeight / 2 + legendRuntimeHeight / 2;
break;
case Location.Align.CenterRight:
startX = chartPos.x + chartWidth - legendRuntimeWidth - legend.location.right;
startY = chartPos.y + chartHeight / 2 + legendRuntimeHeight / 2;
break;
case Location.Align.BottomCenter:
startX = chartPos.x + chartWidth / 2 - legendRuntimeWidth / 2;
startY = chartPos.y + legendRuntimeHeight + legend.location.bottom;
break;
case Location.Align.BottomLeft:
startX = chartPos.x + legend.location.left;
startY = chartPos.y + legendRuntimeHeight + legend.location.bottom;
break;
case Location.Align.BottomRight:
startX = chartPos.x + chartWidth - legendRuntimeWidth - legend.location.right;
startY = chartPos.y + legendRuntimeHeight + legend.location.bottom;
break;
}
if (isVertical) SetVerticalItemPosition(legend, legendMaxHeight, startX, startY);
else SetHorizonalItemPosition(legend, legendMaxWidth, startX, startY);
}
private static void SetVerticalItemPosition(Legend legend, float legendMaxHeight, float startX, float startY)
{
var currHeight = 0f;
var offsetX = 0f;
var row = 0;
foreach (var kv in legend.buttonList)
{
var item = kv.Value;
if (currHeight + item.height > legendMaxHeight)
{
currHeight = 0;
offsetX += legend.runtimeEachWidth[row];
row++;
}
item.SetPosition(new Vector3(startX + offsetX, startY - currHeight));
currHeight += item.height + legend.itemGap;
}
}
private static void SetHorizonalItemPosition(Legend legend, float legendMaxWidth, float startX, float startY)
{
var currWidth = 0f;
var offsetY = 0f;
foreach (var kv in legend.buttonList)
{
var item = kv.Value;
if (currWidth + item.width > legendMaxWidth)
{
currWidth = 0;
offsetY += legend.runtimeEachHeight;
}
item.SetPosition(new Vector3(startX + currWidth, startY - offsetY));
currWidth += item.width + legend.itemGap;
}
}
private static void UpdateLegendWidthAndHeight(Legend legend, float maxWidth, float maxHeight)
{
var width = 0f;
var height = 0f;
var realHeight = 0f;
var realWidth = 0f;
legend.runtimeEachWidth.Clear();
legend.runtimeEachHeight = 0;
if (legend.orient == Orient.Horizonal)
{
foreach (var kv in legend.buttonList)
{
if (width + kv.Value.width > maxWidth)
{
realWidth = width - legend.itemGap;
realHeight += height + legend.itemGap;
if (legend.runtimeEachHeight < height + legend.itemGap)
{
legend.runtimeEachHeight = height + legend.itemGap;
}
height = 0;
width = 0;
}
width += kv.Value.width + legend.itemGap;
if (kv.Value.height > height)
height = kv.Value.height;
}
width -= legend.itemGap;
legend.runtimeHeight = realHeight + height;
legend.runtimeWidth = realWidth > 0 ? realWidth : width;
}
else
{
var row = 0;
foreach (var kv in legend.buttonList)
{
if (height + kv.Value.height > maxHeight)
{
realHeight = height - legend.itemGap;
realWidth += width + legend.itemGap;
legend.runtimeEachWidth[row] = width + legend.itemGap;
row++;
height = 0;
width = 0;
}
height += kv.Value.height + legend.itemGap;
if (kv.Value.width > width)
width = kv.Value.width;
}
height -= legend.itemGap;
legend.runtimeHeight = realHeight > 0 ? realHeight : height;
legend.runtimeWidth = realWidth + width;
}
}
private static bool IsBeyondWidth(Legend legend, float maxWidth)
{
var totalWidth = 0f;
foreach (var kv in legend.buttonList)
{
var item = kv.Value;
totalWidth += item.width + legend.itemGap;
if (totalWidth > maxWidth) return true;
}
return false;
}
public static bool CheckDataShow(Series series, string legendName, bool show)
{
bool needShow = false;
foreach (var serie in series.list)
{
if (legendName.Equals(serie.name))
{
serie.show = show;
serie.highlighted = false;
if (serie.show) needShow = true;
}
else
{
foreach (var data in serie.data)
{
if (legendName.Equals(data.name))
{
data.show = show;
data.highlighted = false;
if (data.show) needShow = true;
}
}
}
}
return needShow;
}
public static bool CheckDataHighlighted(Series series, string legendName, bool heighlight)
{
bool show = false;
foreach (var serie in series.list)
{
if (legendName.Equals(serie.name))
{
serie.highlighted = heighlight;
}
else
{
foreach (var data in serie.data)
{
if (legendName.Equals(data.name))
{
data.highlighted = heighlight;
if (data.highlighted) show = true;
}
}
}
}
return show;
}
public static bool IsSerieLegend(Series series, string legendName, SerieType type)
{
foreach (var serie in series.list)
{
if (serie.type == type)
{
switch (serie.type)
{
case SerieType.Pie:
case SerieType.Radar:
case SerieType.Ring:
foreach (var serieData in serie.data)
{
if (legendName.Equals(serieData.name)) return true;
}
break;
default:
if (legendName.Equals(serie.name)) return true;
break;
}
}
}
return false;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d03ce7a11ecde41b6930883612bf8f05
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,34 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
namespace XCharts
{
internal static class PolarHelper
{
internal static void UpdatePolarCenter(Polar polar, Vector3 chartPosition, float chartWidth, float chartHeight)
{
if (polar.center.Length < 2) return;
var centerX = polar.center[0] <= 1 ? chartWidth * polar.center[0] : polar.center[0];
var centerY = polar.center[1] <= 1 ? chartHeight * polar.center[1] : polar.center[1];
polar.runtimeCenterPos = chartPosition + new Vector3(centerX, centerY);
if (polar.radius <= 0)
{
polar.runtimeRadius = 0;
}
else if (polar.radius <= 1)
{
polar.runtimeRadius = Mathf.Min(chartWidth, chartHeight) * polar.radius;
}
else
{
polar.runtimeRadius = polar.radius;
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 64e494d13836f430ea7f4fe3e2a716b0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,443 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using System.Collections.Generic;
using UnityEngine;
namespace XCharts
{
public static partial class SerieHelper
{
internal static Color32 GetItemBackgroundColor(Serie serie, SerieData serieData, ChartTheme theme, int index,
bool highlight, bool useDefault = true)
{
var color = ChartConst.clearColor32;
if (highlight)
{
var itemStyleEmphasis = GetItemStyleEmphasis(serie, serieData);
if (itemStyleEmphasis != null && !ChartHelper.IsClearColor(itemStyleEmphasis.backgroundColor))
{
color = itemStyleEmphasis.backgroundColor;
ChartHelper.SetColorOpacity(ref color, itemStyleEmphasis.opacity);
return color;
}
}
var itemStyle = GetItemStyle(serie, serieData);
if (!ChartHelper.IsClearColor(itemStyle.backgroundColor))
{
color = itemStyle.backgroundColor;
if (highlight) color = ChartHelper.GetHighlightColor(color);
ChartHelper.SetColorOpacity(ref color, itemStyle.opacity);
return color;
}
else if (useDefault)
{
color = theme.GetColor(index);
if (highlight) color = ChartHelper.GetHighlightColor(color);
color.a = 50;
return color;
}
return color;
}
internal static Color32 GetItemColor(Serie serie, SerieData serieData, ChartTheme theme, int index, bool highlight)
{
if (serie == null) return ChartConst.clearColor32;
if (highlight)
{
var itemStyleEmphasis = GetItemStyleEmphasis(serie, serieData);
if (itemStyleEmphasis != null && !ChartHelper.IsClearColor(itemStyleEmphasis.color))
{
var color = itemStyleEmphasis.color;
ChartHelper.SetColorOpacity(ref color, itemStyleEmphasis.opacity);
return color;
}
}
var itemStyle = GetItemStyle(serie, serieData);
if (!ChartHelper.IsClearColor(itemStyle.color))
{
return itemStyle.GetColor();
}
else
{
var color = theme.GetColor(index);
if (highlight) color = ChartHelper.GetHighlightColor(color);
ChartHelper.SetColorOpacity(ref color, itemStyle.opacity);
return color;
}
}
internal static Color32 GetItemColor0(Serie serie, SerieData serieData, ChartTheme theme, bool highlight, Color32 defaultColor)
{
if (serie == null) return ChartConst.clearColor32;
if (highlight)
{
var itemStyleEmphasis = GetItemStyleEmphasis(serie, serieData);
if (itemStyleEmphasis != null && !ChartHelper.IsClearColor(itemStyleEmphasis.color))
{
var color = itemStyleEmphasis.color0;
ChartHelper.SetColorOpacity(ref color, itemStyleEmphasis.opacity);
return color;
}
}
var itemStyle = GetItemStyle(serie, serieData);
if (!ChartHelper.IsClearColor(itemStyle.color0))
{
return itemStyle.GetColor0();
}
else
{
var color = defaultColor;
if (highlight) color = ChartHelper.GetHighlightColor(color);
ChartHelper.SetColorOpacity(ref color, itemStyle.opacity);
return color;
}
}
internal static Color32 GetItemToColor(Serie serie, SerieData serieData, ChartTheme theme, int index, bool highlight)
{
if (highlight)
{
var itemStyleEmphasis = GetItemStyleEmphasis(serie, serieData);
if (itemStyleEmphasis != null && !ChartHelper.IsClearColor(itemStyleEmphasis.toColor))
{
return itemStyleEmphasis.GetColor();
}
}
var itemStyle = GetItemStyle(serie, serieData, highlight);
if (itemStyle == null) itemStyle = serieData.itemStyle;
if (!ChartHelper.IsClearColor(itemStyle.toColor))
{
var color = itemStyle.toColor;
if (highlight) color = ChartHelper.GetHighlightColor(color);
ChartHelper.SetColorOpacity(ref color, itemStyle.opacity);
return color;
}
if (!ChartHelper.IsClearColor(itemStyle.color))
{
var color = itemStyle.color;
if (highlight) color = ChartHelper.GetHighlightColor(color);
ChartHelper.SetColorOpacity(ref color, itemStyle.opacity);
return color;
}
else
{
var color = theme.GetColor(index);
if (highlight) color = ChartHelper.GetHighlightColor(color);
ChartHelper.SetColorOpacity(ref color, itemStyle.opacity);
return color;
}
}
internal static bool IsDownPoint(Serie serie, int index)
{
var dataPoints = serie.dataPoints;
if (dataPoints.Count < 2) return false;
else if (index > 0 && index < dataPoints.Count - 1)
{
var lp = dataPoints[index - 1];
var np = dataPoints[index + 1];
var cp = dataPoints[index];
var dot = Vector3.Cross(np - lp, cp - np);
return dot.z < 0;
}
else if (index == 0)
{
return dataPoints[0].y < dataPoints[1].y;
}
else if (index == dataPoints.Count - 1)
{
return dataPoints[index].y < dataPoints[index - 1].y;
}
else
{
return false;
}
}
internal static ItemStyle GetItemStyle(Serie serie, SerieData serieData, bool highlight = false)
{
if (highlight)
{
var style = GetItemStyleEmphasis(serie, serieData);
if (style == null) return GetItemStyle(serie, serieData, false);
else return style;
}
else if (serie.IsPerformanceMode()) return serie.itemStyle;
else if (serieData != null && serieData.enableItemStyle) return serieData.itemStyle;
else return serie.itemStyle;
}
internal static ItemStyle GetItemStyleEmphasis(Serie serie, SerieData serieData)
{
if (!serie.IsPerformanceMode() && serieData != null && serieData.enableEmphasis && serieData.emphasis.show)
return serieData.emphasis.itemStyle;
else if (serie.emphasis.show) return serie.emphasis.itemStyle;
else return null;
}
internal static SerieLabel GetSerieLabel(Serie serie, SerieData serieData, bool highlight = false)
{
if (highlight)
{
if (!serie.IsPerformanceMode() && serieData.enableEmphasis && serieData.emphasis.show)
return serieData.emphasis.label;
else if (serie.emphasis.show) return serie.emphasis.label;
else return serie.label;
}
else
{
if (!serie.IsPerformanceMode() && serieData.enableLabel) return serieData.label;
else return serie.label;
}
}
internal static SerieSymbol GetSerieSymbol(Serie serie, SerieData serieData)
{
if (!serie.IsPerformanceMode() && serieData.enableSymbol) return serieData.symbol;
else return serie.symbol;
}
internal static Color32 GetAreaColor(Serie serie, ChartTheme theme, int index, bool highlight)
{
var areaStyle = serie.areaStyle;
var color = !ChartHelper.IsClearColor(areaStyle.color) ? areaStyle.color : theme.GetColor(index);
if (highlight)
{
if (!ChartHelper.IsClearColor(areaStyle.highlightColor)) color = areaStyle.highlightColor;
else color = ChartHelper.GetHighlightColor(color);
}
ChartHelper.SetColorOpacity(ref color, areaStyle.opacity);
return color;
}
internal static Color32 GetAreaToColor(Serie serie, ChartTheme theme, int index, bool highlight)
{
var areaStyle = serie.areaStyle;
if (!ChartHelper.IsClearColor(areaStyle.toColor))
{
var color = areaStyle.toColor;
if (highlight)
{
if (!ChartHelper.IsClearColor(areaStyle.highlightToColor)) color = areaStyle.highlightToColor;
else color = ChartHelper.GetHighlightColor(color);
}
ChartHelper.SetColorOpacity(ref color, areaStyle.opacity);
return color;
}
else
{
return GetAreaColor(serie, theme, index, highlight);
}
}
internal static Color32 GetLineColor(Serie serie, ChartTheme theme, int index, bool highlight)
{
Color32 color = ChartConst.clearColor32;
if (highlight)
{
var itemStyleEmphasis = GetItemStyleEmphasis(serie, null);
if (itemStyleEmphasis != null && !ChartHelper.IsClearColor(itemStyleEmphasis.color))
{
color = itemStyleEmphasis.color;
ChartHelper.SetColorOpacity(ref color, itemStyleEmphasis.opacity);
return color;
}
}
if (!ChartHelper.IsClearColor(serie.lineStyle.color)) color = serie.lineStyle.GetColor();
else if (!ChartHelper.IsClearColor(serie.itemStyle.color)) color = serie.itemStyle.GetColor();
if (ChartHelper.IsClearColor(color))
{
color = theme.GetColor(index);
ChartHelper.SetColorOpacity(ref color, serie.lineStyle.opacity);
}
if (highlight) color = ChartHelper.GetHighlightColor(color);
return color;
}
internal static float GetSymbolBorder(Serie serie, SerieData serieData, ChartTheme theme, bool highlight, bool useLineWidth = true)
{
var itemStyle = GetItemStyle(serie, serieData, highlight);
if (itemStyle != null && itemStyle.borderWidth != 0) return itemStyle.borderWidth;
else return serie.lineStyle.GetWidth(theme.serie.lineWidth);
}
internal static float[] GetSymbolCornerRadius(Serie serie, SerieData serieData, bool highlight)
{
var itemStyle = GetItemStyle(serie, serieData, highlight);
if (itemStyle != null) return itemStyle.cornerRadius;
else return null;
}
/// <summary>
/// 更新运行时中心点和半径
/// </summary>
/// <param name="chartWidth"></param>
/// <param name="chartHeight"></param>
internal static void UpdateCenter(Serie serie, Vector3 chartPosition, float chartWidth, float chartHeight)
{
if (serie.center.Length < 2) return;
var centerX = serie.center[0] <= 1 ? chartWidth * serie.center[0] : serie.center[0];
var centerY = serie.center[1] <= 1 ? chartHeight * serie.center[1] : serie.center[1];
serie.runtimeCenterPos = chartPosition + new Vector3(centerX, centerY);
var minWidth = Mathf.Min(chartWidth, chartHeight);
serie.runtimeInsideRadius = serie.radius[0] <= 1 ? minWidth * serie.radius[0] : serie.radius[0];
serie.runtimeOutsideRadius = serie.radius[1] <= 1 ? minWidth * serie.radius[1] : serie.radius[1];
}
internal static string GetNumericFormatter(Serie serie, SerieData serieData)
{
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
if (!string.IsNullOrEmpty(itemStyle.numericFormatter)) return itemStyle.numericFormatter;
else return string.Empty;
}
/// <summary>
/// 获得指定维数的最大最小值
/// </summary>
/// <param name="dimension"></param>
/// <param name="dataZoom"></param>
/// <returns></returns>
internal static void UpdateMinMaxData(Serie serie, int dimension, int ceilRate = 0, DataZoom dataZoom = null)
{
float min = 0, max = 0;
GetMinMaxData(serie, dimension, out min, out max, dataZoom);
if (ceilRate < 0)
{
serie.runtimeDataMin = min;
serie.runtimeDataMax = max;
}
else
{
serie.runtimeDataMin = ChartHelper.GetMinDivisibleValue(min, ceilRate);
serie.runtimeDataMax = ChartHelper.GetMaxDivisibleValue(max, ceilRate);
}
}
internal static void GetAllMinMaxData(Serie serie, int ceilRate = 0, DataZoom dataZoom = null)
{
float min = 0, max = 0;
GetMinMaxData(serie, out min, out max, dataZoom);
if (ceilRate < 0)
{
serie.runtimeDataMin = min;
serie.runtimeDataMax = max;
}
else
{
serie.runtimeDataMin = ChartHelper.GetMinDivisibleValue(min, ceilRate);
serie.runtimeDataMax = ChartHelper.GetMaxDivisibleValue(max, ceilRate);
}
}
private static List<SerieData> emptyFilter = new List<SerieData>();
/// <summary>
/// 根据dataZoom更新数据列表缓存
/// </summary>
/// <param name="dataZoom"></param>
internal static void UpdateFilterData(Serie serie, DataZoom dataZoom)
{
if (dataZoom == null || !dataZoom.enable) return;
if (dataZoom.xAxisIndexs.Contains(serie.xAxisIndex))
{
if (dataZoom.IsXAxisIndexValue(serie.xAxisIndex))
{
float min = 0, max = 0;
dataZoom.GetXAxisIndexValue(serie.xAxisIndex, out min, out max);
UpdateFilterData_XAxisValue(serie, dataZoom, 0, min, max);
}
else
{
UpdateFilterData_Category(serie, dataZoom);
}
}
else if (dataZoom.yAxisIndexs.Contains(serie.yAxisIndex))
{
if (dataZoom.IsYAxisIndexValue(serie.yAxisIndex))
{
float min = 0, max = 0;
dataZoom.GetYAxisIndexValue(serie.yAxisIndex, out min, out max);
UpdateFilterData_XAxisValue(serie, dataZoom, 0, min, max);
}
else
{
UpdateFilterData_Category(serie, dataZoom);
}
}
}
private static void UpdateFilterData_XAxisValue(Serie serie, DataZoom dataZoom, int dimension, float min, float max)
{
var data = serie.data;
var startValue = min + (max - min) * dataZoom.start / 100;
var endValue = min + (max - min) * dataZoom.end / 100;
if (endValue < startValue) endValue = startValue;
if (startValue != serie.m_FilterStartValue || endValue != serie.m_FilterEndValue
|| dataZoom.minShowNum != serie.m_FilterMinShow || serie.m_NeedUpdateFilterData)
{
serie.m_FilterStartValue = startValue;
serie.m_FilterEndValue = endValue;
serie.m_FilterMinShow = dataZoom.minShowNum;
serie.m_NeedUpdateFilterData = false;
serie.m_FilterData.Clear();
foreach (var serieData in data)
{
var value = serieData.GetData(dimension);
if (value >= startValue && value <= endValue)
{
serie.m_FilterData.Add(serieData);
}
}
}
else if (endValue == 0)
{
serie.m_FilterData = emptyFilter;
}
}
private static void UpdateFilterData_Category(Serie serie, DataZoom dataZoom)
{
var data = serie.data;
var startIndex = (int)((data.Count - 1) * dataZoom.start / 100);
var endIndex = (int)((data.Count - 1) * dataZoom.end / 100);
if (endIndex < startIndex) endIndex = startIndex;
if (startIndex != serie.m_FilterStart || endIndex != serie.m_FilterEnd
|| dataZoom.minShowNum != serie.m_FilterMinShow || serie.m_NeedUpdateFilterData)
{
serie.m_FilterStart = startIndex;
serie.m_FilterEnd = endIndex;
serie.m_FilterMinShow = dataZoom.minShowNum;
serie.m_NeedUpdateFilterData = false;
var count = endIndex == startIndex ? 1 : endIndex - startIndex + 1;
if (count < dataZoom.minShowNum)
{
if (dataZoom.minShowNum > data.Count) count = data.Count;
else count = dataZoom.minShowNum;
}
if (data.Count > 0)
{
if (startIndex + count > data.Count)
{
int start = endIndex - count;
data = data.GetRange(start < 0 ? 0 : start, count);
}
else serie.m_FilterData = data.GetRange(startIndex, count);
}
else
{
serie.m_FilterData = data;
}
}
else if (endIndex == 0)
{
serie.m_FilterData = emptyFilter;
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e5c421b17fb6f45a283f4f57efce686f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,315 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
internal static class SerieLabelHelper
{
public static void CheckLabel(Serie serie, ref bool m_ReinitLabel, ref bool m_UpdateLabelText)
{
switch (serie.type)
{
case SerieType.Gauge:
case SerieType.Ring:
var serieData = serie.GetSerieData(0);
if (serieData != null)
{
if (serie.label.show && serie.show)
{
if (serieData.labelObject != null)
{
serieData.SetLabelActive(true);
m_UpdateLabelText = true;
}
else
{
m_ReinitLabel = true;
}
}
else if (serieData.labelObject != null)
{
serieData.SetLabelActive(false);
}
}
break;
}
}
public static void UpdateLabelText(Series series, ChartTheme theme, List<string> legendRealShowName)
{
foreach (var serie in series.list)
{
if (!serie.label.show) continue;
var colorIndex = legendRealShowName.IndexOf(serie.name);
switch (serie.type)
{
case SerieType.Gauge:
SetGaugeLabelText(serie);
break;
case SerieType.Ring:
SetRingLabelText(serie, theme);
break;
case SerieType.Liquid:
SetLiquidLabelText(serie, theme, colorIndex);
break;
}
}
}
public static Color GetLabelColor(Serie serie, ChartTheme theme, int index)
{
if (!ChartHelper.IsClearColor(serie.label.textStyle.color))
{
return serie.label.textStyle.color;
}
else
{
return theme.GetColor(index);
}
}
public static void ResetLabel(ChartText labelObject, SerieLabel label, ChartTheme theme, int colorIndex)
{
if (labelObject == null) return;
labelObject.SetColor(!ChartHelper.IsClearColor(label.textStyle.color) ? label.textStyle.color :
(Color)theme.GetColor(colorIndex));
labelObject.SetFontSize(label.textStyle.GetFontSize(theme.common));
labelObject.SetFontStyle(label.textStyle.fontStyle);
}
public static bool CanShowLabel(Serie serie, SerieData serieData, SerieLabel label, int dimesion)
{
return serie.show && serieData.canShowLabel && !serie.IsIgnoreValue(serieData.GetData(dimesion));
}
public static string GetFormatterContent(Serie serie, SerieData serieData,
float dataValue, float dataTotal, SerieLabel serieLabel = null)
{
if (serieLabel == null)
{
serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
}
var numericFormatter = serieLabel == null ? serie.label.numericFormatter : serieLabel.numericFormatter;
var serieName = serie.name;
var dataName = serieData != null ? serieData.name : null;
if (string.IsNullOrEmpty(serieLabel.formatter))
return ChartCached.NumberToStr(dataValue, numericFormatter);
else
{
var content = serieLabel.formatter;
FormatterHelper.ReplaceSerieLabelContent(ref content, numericFormatter, dataValue,
dataTotal, serieName, dataName);
return content;
}
}
public static void SetGaugeLabelText(Serie serie)
{
var serieData = serie.GetSerieData(0);
if (serieData == null) return;
if (serieData.labelObject == null) return;
var value = serieData.GetData(1);
var total = serie.max;
var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, total);
serieData.labelObject.SetText(content);
serieData.labelObject.SetLabelPosition(serie.runtimeCenterPos + serie.label.offset);
if (!ChartHelper.IsClearColor(serie.label.textStyle.color))
{
serieData.labelObject.label.SetColor(serie.label.textStyle.color);
}
}
public static void SetRingLabelText(Serie serie, ChartTheme theme)
{
for (int i = 0; i < serie.dataCount; i++)
{
var serieData = serie.data[i];
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData, serieData.highlighted);
if (serieLabel.show && serieData.labelObject != null)
{
if (!serie.show || !serieData.show)
{
serieData.SetLabelActive(false);
continue;
}
var value = serieData.GetData(0);
var total = serieData.GetData(1);
var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, total);
serieData.SetLabelActive(true);
serieData.labelObject.SetText(content);
serieData.labelObject.SetLabelColor(GetLabelColor(serie, theme, i));
if (serie.label.position == SerieLabel.Position.Bottom)
{
var labelWidth = serieData.GetLabelWidth();
if (serie.clockwise)
serieData.labelObject.SetLabelPosition(serieData.labelPosition - new Vector3(labelWidth / 2, 0));
else
serieData.labelObject.SetLabelPosition(serieData.labelPosition + new Vector3(labelWidth / 2, 0));
}
else
{
serieData.labelObject.SetLabelPosition(serieData.labelPosition);
}
}
}
}
public static void SetLiquidLabelText(Serie serie, ChartTheme theme, int colorIndex)
{
var serieData = serie.GetSerieData(0);
if (serieData == null) return;
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData, serieData.highlighted);
if (serieLabel.show && serieData.labelObject != null)
{
if (!serie.show || !serieData.show)
{
serieData.SetLabelActive(false);
return;
}
var value = serieData.GetData(1);
var total = serie.max - serie.min;
var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, total);
serieData.SetLabelActive(true);
serieData.labelObject.SetText(content);
serieData.labelObject.SetLabelColor(GetLabelColor(serie, theme, colorIndex));
serieData.labelObject.SetLabelPosition(serieData.labelPosition + serieLabel.offset);
}
}
public static void UpdatePieLabelPosition(Serie serie, SerieData serieData)
{
if (serieData.labelObject == null) return;
var currAngle = serieData.runtimePieHalfAngle;
var currRad = currAngle * Mathf.Deg2Rad;
var offsetRadius = serieData.runtimePieOffsetRadius;
var insideRadius = serieData.runtimePieInsideRadius;
var outsideRadius = serieData.runtimePieOutsideRadius;
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
switch (serieLabel.position)
{
case SerieLabel.Position.Center:
serieData.labelPosition = serie.runtimeCenterPos;
break;
case SerieLabel.Position.Inside:
var labelRadius = offsetRadius + insideRadius + (outsideRadius - insideRadius) / 2;
var labelCenter = new Vector2(serie.runtimeCenterPos.x + labelRadius * Mathf.Sin(currRad),
serie.runtimeCenterPos.y + labelRadius * Mathf.Cos(currRad));
serieData.labelPosition = labelCenter;
break;
case SerieLabel.Position.Outside:
if (serieLabel.lineType == SerieLabel.LineType.HorizontalLine)
{
var radius1 = serie.runtimeOutsideRadius;
var radius3 = insideRadius + (outsideRadius - insideRadius) / 2;
var currSin = Mathf.Sin(currRad);
var currCos = Mathf.Cos(currRad);
var pos0 = new Vector3(serie.runtimeCenterPos.x + radius3 * currSin, serie.runtimeCenterPos.y + radius3 * currCos);
if (currAngle > 180)
{
currSin = Mathf.Sin((360 - currAngle) * Mathf.Deg2Rad);
currCos = Mathf.Cos((360 - currAngle) * Mathf.Deg2Rad);
}
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos * radius3, 2)) - currSin * radius3;
r4 += serieLabel.lineLength1 + serieLabel.lineWidth * 4;
r4 += serieData.labelObject.label.GetPreferredWidth() / 2;
serieData.labelPosition = pos0 + (currAngle > 180 ? Vector3.left : Vector3.right) * r4;
}
else
{
labelRadius = serie.runtimeOutsideRadius + serieLabel.lineLength1;
labelCenter = new Vector2(serie.runtimeCenterPos.x + labelRadius * Mathf.Sin(currRad),
serie.runtimeCenterPos.y + labelRadius * Mathf.Cos(currRad));
serieData.labelPosition = labelCenter;
}
break;
}
}
internal static void AvoidLabelOverlap(Serie serie)
{
if (!serie.avoidLabelOverlap) return;
var lastCheckPos = Vector3.zero;
var data = serie.data;
var splitCount = 0;
for (int n = 0; n < data.Count; n++)
{
var serieData = data[n];
if (serieData.labelPosition.x != 0 && serieData.labelPosition.x < serie.runtimeCenterPos.x)
{
splitCount = n;
break;
}
}
for (int n = 0; n < splitCount; n++)
{
var serieData = data[n];
CheckSerieDataLabel(serie, serieData, false, ref lastCheckPos);
}
lastCheckPos = Vector3.zero;
for (int n = data.Count - 1; n >= splitCount; n--)
{
var serieData = data[n];
CheckSerieDataLabel(serie, serieData, true, ref lastCheckPos);
}
}
private static void CheckSerieDataLabel(Serie serie, SerieData serieData, bool isLeft, ref Vector3 lastCheckPos)
{
if (!serieData.canShowLabel)
{
serieData.SetLabelActive(false);
return;
}
if (!serieData.show) return;
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
if (!serieLabel.show) return;
if (serieLabel.position != SerieLabel.Position.Outside) return;
if (lastCheckPos == Vector3.zero)
{
lastCheckPos = serieData.labelPosition;
}
else if (serieData.labelPosition.x != 0)
{
float hig = serieLabel.textStyle.fontSize;
if (lastCheckPos.y - serieData.labelPosition.y < hig)
{
var labelRadius = serie.runtimeOutsideRadius + serieLabel.lineLength1;
var y1 = lastCheckPos.y - hig;
var cy = serie.runtimeCenterPos.y;
var diff = Mathf.Abs(y1 - cy);
var diffX = labelRadius * labelRadius - diff * diff;
diffX = diffX <= 0 ? 0 : diffX;
var x1 = serie.runtimeCenterPos.x + Mathf.Sqrt(diffX) * (isLeft ? -1 : 1);
serieData.labelPosition = new Vector3(x1, y1);
}
lastCheckPos = serieData.labelPosition;
serieData.labelObject.SetPosition(SerieLabelHelper.GetRealLabelPosition(serieData, serieLabel));
}
}
internal static Vector3 GetRealLabelPosition(SerieData serieData, SerieLabel label)
{
if (label.position == SerieLabel.Position.Outside && label.lineType != SerieLabel.LineType.HorizontalLine)
{
var currAngle = serieData.runtimePieHalfAngle;
var offset = label.lineLength2 + serieData.labelObject.GetLabelWidth() / 2;
if (currAngle > 180)
return serieData.labelPosition + new Vector3(-offset, 0, 0);
else
return serieData.labelPosition + new Vector3(offset, 0, 0);
}
else
{
return serieData.labelPosition;
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bbd57df98f6f145f299cf942b04229a4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,548 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using System.Collections.Generic;
using UnityEngine;
namespace XCharts
{
public static class SeriesHelper
{
public static bool IsNeedLabelUpdate(Series series)
{
foreach (var serie in series.list)
{
if (serie.label.vertsDirty) return true;
}
return false;
}
public static bool IsLabelDirty(Series series)
{
if (series.labelDirty) return true;
foreach (var serie in series.list)
{
if (serie.label.componentDirty) return true;
}
return false;
}
public static bool IsNameDirty(Series series)
{
foreach (var serie in series.list)
{
if (serie.nameDirty) return true;
}
return false;
}
public static void ClearNameDirty(Series series)
{
foreach (var serie in series.list)
{
serie.ClearNameDirty();
}
}
public static bool IsLegalLegendName(string name)
{
int numName = -1;
if (int.TryParse(name, out numName))
{
if (numName >= 0 && numName < 100) return false;
}
return true;
}
public static List<string> GetLegalSerieNameList(Series series)
{
var list = new List<string>();
for (int n = 0; n < series.list.Count; n++)
{
var serie = series.GetSerie(n);
switch (serie.type)
{
case SerieType.Pie:
case SerieType.Radar:
case SerieType.Ring:
for (int i = 0; i < serie.data.Count; i++)
{
var dataName = serie.data[i].name;
if (!string.IsNullOrEmpty(dataName) && IsLegalLegendName(dataName) && !list.Contains(dataName))
list.Add(dataName);
}
break;
default:
if (!string.IsNullOrEmpty(serie.name) && !list.Contains(serie.name) && IsLegalLegendName(serie.name))
list.Add(serie.name);
break;
}
}
return list;
}
/// <summary>
/// 获得所有系列名,不包含空名字。
/// </summary>
/// <returns></returns>
internal static void UpdateSerieNameList(Series series, ref List<string> serieNameList)
{
serieNameList.Clear();
for (int n = 0; n < series.list.Count; n++)
{
var serie = series.GetSerie(n);
switch (serie.type)
{
case SerieType.Pie:
case SerieType.Radar:
case SerieType.Ring:
for (int i = 0; i < serie.data.Count; i++)
{
if (serie.type == SerieType.Pie && serie.IsIgnoreValue(serie.data[i].GetData(1))) continue;
if (string.IsNullOrEmpty(serie.data[i].name))
serieNameList.Add(ChartCached.IntToStr(i));
else if (!serieNameList.Contains(serie.data[i].name))
serieNameList.Add(serie.data[i].name);
}
break;
default:
if (string.IsNullOrEmpty(serie.name))
serieNameList.Add(ChartCached.IntToStr(n));
else if (!serieNameList.Contains(serie.name))
serieNameList.Add(serie.name);
break;
}
}
}
internal static Color GetNameColor(Series series, int index, string name, ChartTheme theme)
{
Serie destSerie = null;
SerieData destSerieData = null;
for (int n = 0; n < series.list.Count; n++)
{
var serie = series.GetSerie(n);
if (serie.type == SerieType.Pie || serie.type == SerieType.Radar || serie.type == SerieType.Ring)
{
bool found = false;
for (int i = 0; i < serie.data.Count; i++)
{
if (name.Equals(serie.data[i].name))
{
destSerie = serie;
destSerieData = serie.data[i];
found = true;
break;
}
}
if (found) break;
}
else
{
if (name.Equals(serie.name))
{
destSerie = serie;
destSerieData = null;
break;
}
}
}
return SerieHelper.GetItemColor(destSerie, destSerieData, theme, index, false);
}
/// <summary>
/// 同堆叠的serie是否有渐变色的。
/// </summary>
/// <param name="stack"></param>
/// <returns></returns>
internal static bool IsAnyGradientSerie(Series series, string stack)
{
if (string.IsNullOrEmpty(stack)) return false;
foreach (var serie in series.list)
{
if (serie.show && serie.areaStyle.show && stack.Equals(serie.stack))
{
if (!ChartHelper.IsValueEqualsColor(serie.areaStyle.color, serie.areaStyle.toColor)
&& !ChartHelper.IsClearColor(serie.areaStyle.toColor))
return true;
}
}
return false;
}
/// <summary>
/// 是否有需裁剪的serie。
/// </summary>
/// <returns></returns>
internal static bool IsAnyClipSerie(Series series)
{
foreach (var serie in series.list)
{
if (serie.clip) return true;
}
return false;
}
internal static bool ContainsSerie(Series series, SerieType type)
{
foreach (var serie in series.list)
{
if (serie.type == type) return true;
}
return false;
}
internal static bool IsAnyUpdateAnimationSerie(Series series)
{
foreach (var serie in series.list)
{
if (serie.animation.enable && serie.animation.dataChangeEnable)
{
return true;
}
}
return false;
}
/// <summary>
/// 获得上一个同堆叠且显示的serie。
/// </summary>
/// <param name="serie"></param>
/// <returns></returns>
internal static Serie GetLastStackSerie(Series series, Serie serie)
{
if (serie == null || string.IsNullOrEmpty(serie.stack)) return null;
for (int i = serie.index - 1; i >= 0; i--)
{
var temp = series.list[i];
if (temp.show && serie.stack.Equals(temp.stack)) return temp;
}
return null;
}
/// <summary>
/// 获得上一个同堆叠且显示的serie。
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
internal static Serie GetLastStackSerie(Series series, int index)
{
var serie = series.GetSerie(index);
return GetLastStackSerie(series, serie);
}
internal static Serie GetSerieByVesselIndex(Series series, int vesselIndex)
{
foreach (var serie in series.list)
{
if (serie.vesselIndex == vesselIndex) return serie;
}
return null;
}
private static HashSet<string> _setForStack = new HashSet<string>();
/// <summary>
/// 是否由数据堆叠
/// </summary>
/// <returns></returns>
internal static bool IsStack(Series series)
{
_setForStack.Clear();
foreach (var serie in series.list)
{
if (string.IsNullOrEmpty(serie.stack)) continue;
if (_setForStack.Contains(serie.stack)) return true;
else
{
_setForStack.Add(serie.stack);
}
}
return false;
}
/// <summary>
/// 是否堆叠
/// </summary>
/// <param name="stackName"></param>
/// <param name="type"></param>
/// <returns></returns>
internal static bool IsStack(Series series, string stackName, SerieType type)
{
if (string.IsNullOrEmpty(stackName)) return false;
int count = 0;
foreach (var serie in series.list)
{
if (serie.show && serie.type == type)
{
if (stackName.Equals(serie.stack)) count++;
if (count >= 2) return true;
}
}
return false;
}
/// <summary>
/// 是否时百分比堆叠
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
internal static bool IsPercentStack(Series series, SerieType type)
{
int count = 0;
bool isPercentStack = false;
foreach (var serie in series.list)
{
if (serie.show && serie.type == type)
{
if (!string.IsNullOrEmpty(serie.stack))
{
count++;
if (serie.barPercentStack) isPercentStack = true;
}
if (count >= 2 && isPercentStack) return true;
}
}
return false;
}
/// <summary>
/// 是否时百分比堆叠
/// </summary>
/// <param name="stackName"></param>
/// <param name="type"></param>
/// <returns></returns>
internal static bool IsPercentStack(Series series, string stackName, SerieType type)
{
if (string.IsNullOrEmpty(stackName)) return false;
int count = 0;
bool isPercentStack = false;
foreach (var serie in series.list)
{
if (serie.show && serie.type == type)
{
if (stackName.Equals(serie.stack))
{
count++;
if (serie.barPercentStack) isPercentStack = true;
}
if (count >= 2 && isPercentStack) return true;
}
}
return false;
}
private static Dictionary<string, int> sets = new Dictionary<string, int>();
/// <summary>
/// 获得堆叠系列列表
/// </summary>
/// <param name="Dictionary<int"></param>
/// <param name="stackSeries"></param>
internal static void GetStackSeries(Series series, ref Dictionary<int, List<Serie>> stackSeries)
{
int count = 0;
var serieCount = series.list.Count;
sets.Clear();
if (stackSeries == null)
{
stackSeries = new Dictionary<int, List<Serie>>(serieCount);
}
else
{
foreach (var kv in stackSeries)
{
kv.Value.Clear();
}
}
for (int i = 0; i < serieCount; i++)
{
var serie = series.GetSerie(i);
serie.index = i;
if (string.IsNullOrEmpty(serie.stack))
{
if (!stackSeries.ContainsKey(count))
stackSeries[count] = new List<Serie>(serieCount);
stackSeries[count].Add(serie);
count++;
}
else
{
if (!sets.ContainsKey(serie.stack))
{
sets.Add(serie.stack, count);
if (!stackSeries.ContainsKey(count))
stackSeries[count] = new List<Serie>(serieCount);
stackSeries[count].Add(serie);
count++;
}
else
{
int stackIndex = sets[serie.stack];
stackSeries[stackIndex].Add(serie);
}
}
}
}
internal static void UpdateStackDataList(Series series, Serie currSerie, DataZoom dataZoom, List<List<SerieData>> dataList)
{
dataList.Clear();
for (int i = 0; i <= currSerie.index; i++)
{
var serie = series.list[i];
if (serie.type == currSerie.type && ChartHelper.IsValueEqualsString(serie.stack, currSerie.stack))
{
dataList.Add(serie.GetDataList(dataZoom));
}
}
}
/// <summary>
/// 获得维度X的最大最小值
/// </summary>
/// <param name="dataZoom"></param>
/// <param name="axisIndex"></param>
/// <param name="minVaule"></param>
/// <param name="maxValue"></param>
internal static void GetXMinMaxValue(Series series, DataZoom dataZoom, int axisIndex, bool isValueAxis,
bool inverse, out float minVaule, out float maxValue, bool isPolar = false)
{
GetMinMaxValue(series, dataZoom, axisIndex, isValueAxis, inverse, false, out minVaule, out maxValue, isPolar);
}
/// <summary>
/// 获得维度Y的最大最小值
/// </summary>
/// <param name="dataZoom"></param>
/// <param name="axisIndex"></param>
/// <param name="minVaule"></param>
/// <param name="maxValue"></param>
internal static void GetYMinMaxValue(Series series, DataZoom dataZoom, int axisIndex, bool isValueAxis,
bool inverse, out float minVaule, out float maxValue, bool isPolar = false)
{
GetMinMaxValue(series, dataZoom, axisIndex, isValueAxis, inverse, true, out minVaule, out maxValue, isPolar);
}
private static Dictionary<int, List<Serie>> _stackSeriesForMinMax = new Dictionary<int, List<Serie>>();
private static Dictionary<int, float> _serieTotalValueForMinMax = new Dictionary<int, float>();
internal static void GetMinMaxValue(Series series, DataZoom dataZoom, int axisIndex, bool isValueAxis,
bool inverse, bool yValue, out float minVaule, out float maxValue, bool isPolar = false)
{
float min = int.MaxValue;
float max = int.MinValue;
var isPercentStack = SeriesHelper.IsPercentStack(series, SerieType.Bar);
if (!SeriesHelper.IsStack(series) || (isValueAxis && !yValue))
{
for (int i = 0; i < series.list.Count; i++)
{
var serie = series.GetSerie(i);
if ((isPolar && serie.polarIndex != axisIndex)
|| (!isPolar && serie.yAxisIndex != axisIndex)) continue;
if (series.IsActive(i))
{
if (isPercentStack && SeriesHelper.IsPercentStack(series, serie.name, SerieType.Bar))
{
if (100 > max) max = 100;
if (0 < min) min = 0;
}
else
{
var showData = serie.GetDataList(dataZoom);
foreach (var data in showData)
{
if (serie.type == SerieType.Candlestick)
{
var dataMin = data.min;
var dataMax = data.max;
if (dataMax > max) max = dataMax;
if (dataMin < min) min = dataMin;
}
else
{
var currData = data.GetData(yValue ? 1 : 0, inverse);
if (currData > max) max = currData;
if (currData < min) min = currData;
}
}
}
}
}
}
else
{
SeriesHelper.GetStackSeries(series, ref _stackSeriesForMinMax);
foreach (var ss in _stackSeriesForMinMax)
{
_serieTotalValueForMinMax.Clear();
for (int i = 0; i < ss.Value.Count; i++)
{
var serie = ss.Value[i];
if ((isPolar && serie.polarIndex != axisIndex)
|| (!isPolar && serie.yAxisIndex != axisIndex)
|| !series.IsActive(i)) continue;
var showData = serie.GetDataList(dataZoom);
if (SeriesHelper.IsPercentStack(series, serie.stack, SerieType.Bar))
{
for (int j = 0; j < showData.Count; j++)
{
_serieTotalValueForMinMax[j] = 100;
}
}
else
{
for (int j = 0; j < showData.Count; j++)
{
if (!_serieTotalValueForMinMax.ContainsKey(j))
_serieTotalValueForMinMax[j] = 0;
var currData = 0f;
if (serie.type == SerieType.Candlestick)
{
currData = showData[j].max;
}
else
{
currData = yValue ? showData[j].GetData(1) : showData[j].GetData(0);
}
if (inverse) currData = -currData;
_serieTotalValueForMinMax[j] = _serieTotalValueForMinMax[j] + currData;
}
}
}
float tmax = int.MinValue;
float tmin = int.MaxValue;
foreach (var tt in _serieTotalValueForMinMax)
{
if (tt.Value > tmax) tmax = tt.Value;
if (tt.Value < tmin) tmin = tt.Value;
}
if (tmax > max) max = tmax;
if (tmin < min) min = tmin;
}
}
if (max == int.MinValue && min == int.MaxValue)
{
minVaule = 0;
maxValue = 0;
}
else
{
minVaule = min > 1 ? Mathf.FloorToInt(min) : min;
maxValue = max > 1 ? Mathf.CeilToInt(max) : max;
}
}
public static int GetMaxSerieDataCount(Series series)
{
int max = 0;
foreach (var serie in series.list)
{
if (serie.dataCount > max) max = serie.dataCount;
}
return max;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e7411a13172764cf89b10e643089c832
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,20 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
namespace XCharts
{
internal static class ThemeHelper
{
public static Color32 GetBackgroundColor(ChartTheme theme, Background background)
{
if (background.show && background.hideThemeBackgroundColor) return ChartConst.clearColor32;
else return theme.backgroundColor;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5093880c2dbba4c01bb0231653ed3252
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,43 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
internal static class TitleStyleHelper
{
public static void CheckTitle(Serie serie, ref bool m_ReinitTitle, ref bool m_UpdateTitleText)
{
if (serie.titleStyle.show)
{
if (serie.titleStyle.IsInited())
{
serie.titleStyle.UpdatePosition(serie.runtimeCenterPos);
m_UpdateTitleText = true;
}
else
{
m_ReinitTitle = true;
}
}
}
public static void UpdateTitleText(Series series)
{
foreach (var serie in series.list) UpdateTitleText(serie);
}
public static void UpdateTitleText(Serie serie)
{
if (serie.titleStyle.show)
{
serie.titleStyle.SetText(serie.name);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 35fa58aecc0f4414e8a2f03195b66175
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,571 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using System.Text;
using UnityEngine;
namespace XCharts
{
internal static class TooltipHelper
{
private static void InitScatterTooltip(ref StringBuilder sb, Tooltip tooltip, Serie serie, int index,
ChartTheme theme)
{
if (!tooltip.runtimeSerieIndex.ContainsKey(serie.index)) return;
var dataIndexList = tooltip.runtimeSerieIndex[serie.index];
if (!string.IsNullOrEmpty(serie.name))
{
sb.Append(serie.name).Append(FormatterHelper.PH_NN);
}
for (int i = 0; i < dataIndexList.Count; i++)
{
var dataIndex = dataIndexList[i];
var serieData = serie.GetSerieData(dataIndex);
var numericFormatter = GetItemNumericFormatter(tooltip, serie, serieData);
float xValue, yValue;
serie.GetXYData(dataIndex, null, out xValue, out yValue);
sb.Append("<color=#").Append(theme.GetColorStr(serie.index)).Append(">● </color>");
if (!string.IsNullOrEmpty(serieData.name))
sb.Append(serieData.name).Append(": ");
sb.AppendFormat("({0},{1})", ChartCached.FloatToStr(xValue, numericFormatter),
ChartCached.FloatToStr(yValue, numericFormatter));
if (i != dataIndexList.Count - 1)
{
sb.Append("\n");
}
}
}
private static void InitPieTooltip(ref StringBuilder sb, Tooltip tooltip, Serie serie, int index,
ChartTheme theme)
{
if (tooltip.runtimeDataIndex[serie.index] < 0) return;
string key = serie.data[index].name;
var serieData = serie.GetSerieData(index);
var numericFormatter = GetItemNumericFormatter(tooltip, serie, serieData);
float value = serieData.GetData(1);
sb.Length = 0;
if (!string.IsNullOrEmpty(serie.name))
{
sb.Append(serie.name).Append(FormatterHelper.PH_NN);
}
sb.Append("<color=#").Append(theme.GetColorStr(index)).Append(">● </color>");
if (!string.IsNullOrEmpty(key))
sb.Append(key).Append(": ");
sb.Append(ChartCached.FloatToStr(value, numericFormatter));
}
private static void InitRingTooltip(ref StringBuilder sb, Tooltip tooltip, Serie serie, int index,
ChartTheme theme)
{
var serieData = serie.GetSerieData(index);
var numericFormatter = GetItemNumericFormatter(tooltip, serie, serieData);
float value = serieData.GetFirstData();
sb.Length = 0;
if (!string.IsNullOrEmpty(serieData.name))
{
sb.Append("<color=#").Append(theme.GetColorStr(index)).Append(">● </color>")
.Append(serieData.name).Append(": ").Append(ChartCached.FloatToStr(value, numericFormatter));
}
else
{
sb.Append(ChartCached.FloatToStr(value, numericFormatter));
}
}
private static void InitGaugeTooltip(ref StringBuilder sb, Tooltip tooltip, Serie serie, int index,
ChartTheme theme)
{
if (tooltip.runtimeGridIndex >= 0) return;
if (serie.index != index || serie.type != SerieType.Gauge) return;
var serieData = serie.GetSerieData(0);
var numericFormatter = GetItemNumericFormatter(tooltip, serie, serieData);
float value = serieData.data[1];
sb.Length = 0;
if (!string.IsNullOrEmpty(serie.name))
{
sb.Append(serie.name).Append("\n");
}
if (!string.IsNullOrEmpty(serieData.name))
{
//sb.Append("<color=#").Append(theme.GetColorStr(index)).Append(">● </color>")
sb.Append(serieData.name).Append(": ").Append(ChartCached.FloatToStr(value, numericFormatter));
}
else
{
sb.Append(ChartCached.FloatToStr(value, numericFormatter));
}
}
public static void InitRadarTooltip(ref StringBuilder sb, Tooltip tooltip, Serie serie, Radar radar,
ChartTheme theme)
{
if (radar == null) return;
if (!serie.show) return;
if (tooltip.runtimeGridIndex >= 0) return;
if (serie.radarIndex != radar.index) return;
var dataIndex = tooltip.runtimeDataIndex[1];
var serieData = serie.GetSerieData(dataIndex);
if (!serieData.show) return;
var numericFormatter = GetItemNumericFormatter(tooltip, serie, serieData);
switch (serie.radarType)
{
case RadarType.Multiple:
if (radar.isAxisTooltip)
{
var dimension = tooltip.runtimeDataIndex[2];
if (!string.IsNullOrEmpty(serie.name))
sb.Append(serie.name).Append("\n");
var total = serie.GetDataTotal(dimension);
var first = true;
for (int i = 0; i < serie.dataCount; i++)
{
var sd = serie.GetSerieData(i);
if (!sd.show) continue;
var key = sd.name;
var value = sd.GetData(dimension);
var itemFormatter = GetItemFormatter(tooltip, serie, sd);
numericFormatter = GetItemNumericFormatter(tooltip, serie, sd);
if (!first) sb.Append("\n");
first = false;
sb.Append("<color=#").Append(theme.GetColorStr(i)).Append(">● </color>");
if (string.IsNullOrEmpty(itemFormatter))
{
if (string.IsNullOrEmpty(key)) key = radar.indicatorList[dataIndex].name;
if (string.IsNullOrEmpty(key))
sb.AppendFormat("{0}\n", ChartCached.FloatToStr(value, numericFormatter));
else
sb.AppendFormat("{0}: {1}\n", key, ChartCached.FloatToStr(value, numericFormatter));
}
else
{
string content = itemFormatter;
FormatterHelper.ReplaceSerieLabelContent(ref content, numericFormatter, value, total, serie.name, sd.name);
sb.Append(content);
}
}
}
else
{
if (serie.index != tooltip.runtimeDataIndex[0]) return;
sb.Append(serieData.name);
for (int i = 0; i < radar.indicatorList.Count; i++)
{
string key = radar.indicatorList[i].name;
float value = serieData.GetData(i);
if ((i == 0 && !string.IsNullOrEmpty(serieData.name)) || i > 0) sb.Append(FormatterHelper.PH_NN);
sb.AppendFormat("{0}: {1}", key, ChartCached.FloatToStr(value, numericFormatter));
}
}
break;
case RadarType.Single:
var key2 = serieData.name;
var value2 = serieData.GetData(1);
var total2 = serie.GetDataTotal(1);
var itemFormatter2 = GetItemFormatter(tooltip, serie, serieData);
if (string.IsNullOrEmpty(itemFormatter2))
{
if (string.IsNullOrEmpty(key2))
{
key2 = radar.indicatorList[dataIndex].name;
}
sb.AppendFormat("{0}: {1}", key2, ChartCached.FloatToStr(value2, numericFormatter));
}
else
{
string content = itemFormatter2;
FormatterHelper.ReplaceSerieLabelContent(ref content, numericFormatter, value2, total2, serie.name, serieData.name);
sb.Append(content);
}
break;
}
}
private static void InitCoordinateTooltip(ref StringBuilder sb, Tooltip tooltip, Serie serie, int index,
ChartTheme theme, bool isCartesian, DataZoom dataZoom = null)
{
string key = serie.name;
float xValue, yValue;
serie.GetXYData(index, dataZoom, out xValue, out yValue);
var isIngore = serie.IsIgnorePoint(index);
var serieData = serie.GetSerieData(index, dataZoom);
var numericFormatter = GetItemNumericFormatter(tooltip, serie, serieData);
if (isCartesian)
{
if (serieData != null && serieData.highlighted)
{
sb.Append(key).Append(!string.IsNullOrEmpty(key) ? " : " : "");
sb.Append("[").Append(ChartCached.FloatToStr(xValue, numericFormatter)).Append(",")
.Append(ChartCached.FloatToStr(yValue, numericFormatter)).Append("]");
}
}
else if (!isIngore || (isIngore && tooltip.ignoreDataShow))
{
var valueTxt = isIngore ? tooltip.ignoreDataDefaultContent :
ChartCached.FloatToStr(yValue, numericFormatter);
sb.Append("<color=#").Append(theme.GetColorStr(serie.index)).Append(">● </color>");
if (serie.type == SerieType.Candlestick)
{
sb.Append(key).Append(FormatterHelper.PH_NN);
var data = serieData.data;
var open = ChartCached.FloatToStr(data[0], numericFormatter);
var close = ChartCached.FloatToStr(data[1], numericFormatter);
var lowest = ChartCached.FloatToStr(data[2], numericFormatter);
var heighest = ChartCached.FloatToStr(data[3], numericFormatter);
sb.Append(" open: ").Append(open).Append(FormatterHelper.PH_NN);
sb.Append(" close: ").Append(close).Append(FormatterHelper.PH_NN);
sb.Append(" lowest: ").Append(lowest).Append(FormatterHelper.PH_NN);
sb.Append(" heighest: ").Append(heighest);
}
else
{
sb.Append(key).Append(!string.IsNullOrEmpty(key) ? " : " : "");
sb.Append(valueTxt);
}
}
}
private static void InitGanttTooltip(ref StringBuilder sb, Tooltip tooltip, Serie serie, int index,
ChartTheme theme, string category)
{
//if (tooltip.runtimeGridIndex >= 0) return;
//if (serie.index != index || serie.type != SerieType.Gantt) return;
sb.Append(serie.name);
}
private static void InitDefaultContent(ref StringBuilder sb, Tooltip tooltip, Serie serie, int index,
string category, ChartTheme theme = null, DataZoom dataZoom = null, bool isCartesian = false,
Radar radar = null)
{
switch (serie.type)
{
case SerieType.Line:
case SerieType.Bar:
case SerieType.Candlestick:
InitCoordinateTooltip(ref sb, tooltip, serie, index, theme, isCartesian, dataZoom);
break;
case SerieType.Scatter:
case SerieType.EffectScatter:
InitScatterTooltip(ref sb, tooltip, serie, index, theme);
break;
case SerieType.Radar:
InitRadarTooltip(ref sb, tooltip, serie, radar, theme);
break;
case SerieType.Pie:
InitPieTooltip(ref sb, tooltip, serie, index, theme);
break;
case SerieType.Ring:
InitRingTooltip(ref sb, tooltip, serie, index, theme);
break;
case SerieType.Heatmap:
break;
case SerieType.Gauge:
InitGaugeTooltip(ref sb, tooltip, serie, index, theme);
break;
case SerieType.Gantt:
InitGanttTooltip(ref sb, tooltip, serie, index, theme, category);
break;
}
}
public static void SetContentAndPosition(Tooltip tooltip, string content, Rect chartRect)
{
tooltip.UpdateContentText(content);
var pos = tooltip.GetContentPos();
if (pos.x + tooltip.runtimeWidth > chartRect.x + chartRect.width)
{
pos.x = chartRect.x + chartRect.width - tooltip.runtimeWidth;
}
if (pos.y - tooltip.runtimeHeight < chartRect.y)
{
pos.y = chartRect.y + tooltip.runtimeHeight;
}
tooltip.UpdateContentPos(pos);
}
public static string GetPolarFormatterContent(Tooltip tooltip, Series series, ChartTheme theme, AngleAxis angleAxis)
{
if (string.IsNullOrEmpty(tooltip.formatter))
{
var sb = ChartHelper.sb;
sb.Length = 0;
var title = tooltip.titleFormatter;
var formatTitle = !string.IsNullOrEmpty(title);
if ("{i}".Equals(tooltip.titleFormatter))
{
title = string.Empty;
formatTitle = false;
}
else if (string.IsNullOrEmpty(title))
{
var angle = angleAxis.clockwise ? tooltip.runtimeAngle : 360 - tooltip.runtimeAngle;
title = ChartCached.FloatToStr(angle);
}
foreach (var serie in series.list)
{
if (serie.show && IsSelectedSerie(tooltip, serie.index))
{
if (formatTitle)
{
FormatterHelper.ReplaceContent(ref title, 0, tooltip.numericFormatter, serie, series, theme, null, null);
}
var dataIndexList = tooltip.runtimeSerieIndex[serie.index];
for (int i = 0; i < dataIndexList.Count; i++)
{
var dataIndex = dataIndexList[i];
var serieData = serie.GetSerieData(dataIndex);
var itemFormatter = GetItemFormatter(tooltip, serie, serieData);
var numericFormatter = GetItemNumericFormatter(tooltip, serie, serieData);
float xValue, yValue;
serie.GetXYData(dataIndex, null, out xValue, out yValue);
if (string.IsNullOrEmpty(itemFormatter))
{
sb.Append("<color=#").Append(theme.GetColorStr(serie.index)).Append(">● </color>");
if (!string.IsNullOrEmpty(serie.name))
sb.Append(serie.name).Append(": ");
sb.AppendFormat("{0}", ChartCached.FloatToStr(xValue, numericFormatter));
if (i != dataIndexList.Count - 1)
{
sb.Append(FormatterHelper.PH_NN);
}
}
else
{
string content = itemFormatter;
FormatterHelper.ReplaceContent(ref content, dataIndex, tooltip.numericFormatter, serie, series, theme, null, null);
var dotColorIndex = serie.type == SerieType.Pie || serie.type == SerieType.Radar || serie.type == SerieType.Ring ? dataIndex : serie.index;
sb.Append(ChartCached.ColorToDotStr(theme.GetColor(dotColorIndex)));
sb.Append(content);
}
}
sb.Append(FormatterHelper.PH_NN);
}
}
if (string.IsNullOrEmpty(title))
{
return FormatterHelper.TrimAndReplaceLine(sb);
}
else
{
title = FormatterHelper.TrimAndReplaceLine(title);
return title + FormatterHelper.PH_NN + FormatterHelper.TrimAndReplaceLine(sb);
}
}
else
{
string content = tooltip.formatter;
FormatterHelper.ReplaceContent(ref content, 0, tooltip.numericFormatter, null, series, theme, null, null);
return content;
}
}
public static string GetFormatterContent(Tooltip tooltip, int dataIndex, Series series, ChartTheme theme,
string category = null, DataZoom dataZoom = null, bool isCartesian = false, Radar radar = null)
{
if (string.IsNullOrEmpty(tooltip.formatter))
{
var sb = ChartHelper.sb;
var title = tooltip.titleFormatter;
var formatTitle = !string.IsNullOrEmpty(title);
var titleIsIgnroe = false;
var needCategory = false;
var first = true;
var isScatter = false;
sb.Length = 0;
if ("{i}".Equals(tooltip.titleFormatter))
{
title = string.Empty;
formatTitle = false;
titleIsIgnroe = true;
}
for (int i = 0; i < series.Count; i++)
{
var serie = series.GetSerie(i);
if (tooltip.runtimeGridIndex >= 0 && serie.runtimeGridIndex != tooltip.runtimeGridIndex) continue;
if (serie.type == SerieType.Scatter || serie.type == SerieType.EffectScatter)
{
if (serie.show && IsSelectedSerie(tooltip, serie.index))
{
isScatter = true;
var itemFormatter = GetItemFormatter(tooltip, serie, null);
if (string.IsNullOrEmpty(itemFormatter))
{
if (!first) sb.Append(FormatterHelper.PH_NN);
InitDefaultContent(ref sb, tooltip, serie, dataIndex, category, theme, dataZoom, isCartesian, radar);
first = false;
continue;
}
var itemTitle = title;
if (!string.IsNullOrEmpty(itemTitle))
{
FormatterHelper.ReplaceContent(ref itemTitle, dataIndex, tooltip.numericFormatter, serie, series, theme, category, dataZoom);
sb.Append(itemTitle).Append(FormatterHelper.PH_NN);
}
var dataIndexList = tooltip.runtimeSerieIndex[serie.index];
foreach (var tempIndex in dataIndexList)
{
string content = itemFormatter;
var foundDot = FormatterHelper.ReplaceContent(ref content, tempIndex, tooltip.numericFormatter, serie, series, theme, category, dataZoom);
if (!foundDot)
{
sb.Append(ChartCached.ColorToDotStr(theme.GetColor(serie.index)));
}
sb.Append(content).Append(FormatterHelper.PH_NN);
}
}
}
else if (IsNeedTooltipSerie(serie, tooltip))
{
var itemFormatter = string.Empty;
if (serie.type == SerieType.Gauge)
{
var serieData = serie.GetSerieData(0, dataZoom);
if (serieData == null) continue;
itemFormatter = GetItemFormatter(tooltip, serie, serieData);
}
else
{
var serieData = serie.GetSerieData(dataIndex, dataZoom);
if (serieData == null) continue;
itemFormatter = GetItemFormatter(tooltip, serie, serieData);
}
needCategory = needCategory || (serie.type == SerieType.Line || serie.type == SerieType.Bar);
if (formatTitle)
{
FormatterHelper.ReplaceContent(ref title, dataIndex, tooltip.numericFormatter, serie, series, theme, category, dataZoom);
}
if (serie.show)
{
if (string.IsNullOrEmpty(itemFormatter) || serie.type == SerieType.Radar)
{
if (!first) sb.Append(FormatterHelper.PH_NN);
InitDefaultContent(ref sb, tooltip, serie, dataIndex, category, theme, dataZoom, isCartesian, radar);
first = false;
continue;
}
string content = itemFormatter;
FormatterHelper.ReplaceContent(ref content, dataIndex, tooltip.numericFormatter, serie, series, theme, category, dataZoom);
if (!first) sb.Append(FormatterHelper.PH_NN);
var dotColorIndex = serie.type == SerieType.Pie || serie.type == SerieType.Radar || serie.type == SerieType.Ring ? dataIndex : i;
sb.Append(ChartCached.ColorToDotStr(theme.GetColor(dotColorIndex)));
sb.Append(content);
first = false;
}
}
}
if (isScatter)
{
return FormatterHelper.TrimAndReplaceLine(sb);
}
else if (string.IsNullOrEmpty(title))
{
if (needCategory && !titleIsIgnroe)
return category + FormatterHelper.PH_NN + FormatterHelper.TrimAndReplaceLine(sb);
else
return FormatterHelper.TrimAndReplaceLine(sb);
}
else
{
title = FormatterHelper.TrimAndReplaceLine(title);
return title + FormatterHelper.PH_NN + FormatterHelper.TrimAndReplaceLine(sb);
}
}
else
{
string content = tooltip.formatter;
FormatterHelper.ReplaceContent(ref content, dataIndex, tooltip.numericFormatter, null, series, theme, category, dataZoom);
return content;
}
}
private static bool IsNeedTooltipSerie(Serie serie, Tooltip tooltip)
{
//if (serie.type == SerieType.Pie || serie.type == SerieType.Radar || serie.type == SerieType.Ring)
if (serie.type == SerieType.Pie || serie.type == SerieType.Ring)
{
if (serie.index < tooltip.runtimeDataIndex.Count)
return tooltip.runtimeDataIndex[serie.index] >= 0;
else
return false;
}
else if (serie.type == SerieType.Gauge)
{
return serie.index == tooltip.runtimeDataIndex[0];
}
else
{
return true;
}
}
private static bool IsSelectedSerie(Tooltip tooltip, int serieIndex)
{
if (tooltip.runtimeSerieIndex.ContainsKey(serieIndex))
{
return tooltip.runtimeSerieIndex[serieIndex].Count > 0;
}
return false;
}
private static string GetItemFormatter(Tooltip tooltip, Serie serie, SerieData serieData)
{
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
if (!string.IsNullOrEmpty(itemStyle.tooltipFormatter)) return itemStyle.tooltipFormatter;
else return tooltip.itemFormatter;
}
private static string GetItemNumericFormatter(Tooltip tooltip, Serie serie, SerieData serieData)
{
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
if (!string.IsNullOrEmpty(itemStyle.numericFormatter)) return itemStyle.numericFormatter;
else return tooltip.numericFormatter;
}
public static Color32 GetLineColor(Tooltip tooltip, ChartTheme theme)
{
var lineStyle = tooltip.lineStyle;
if (!ChartHelper.IsClearColor(lineStyle.color))
{
return lineStyle.GetColor();
}
else
{
var color = theme.tooltip.lineColor;
ChartHelper.SetColorOpacity(ref color, lineStyle.opacity);
return color;
}
}
public static Color GetTexColor(Tooltip tooltip, ComponentTheme theme)
{
if (!ChartHelper.IsClearColor(tooltip.textStyle.color))
{
return tooltip.textStyle.color;
}
else
{
return theme.textColor;
}
}
public static Color GetTexBackgroundColor(Tooltip tooltip, ComponentTheme theme)
{
if (!ChartHelper.IsClearColor(tooltip.textStyle.backgroundColor))
{
return tooltip.textStyle.backgroundColor;
}
else
{
return theme.textBackgroundColor;
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f0fa1b19683a8424bb335802de5c9726
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,39 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using System.Collections.Generic;
using UnityEngine;
namespace XCharts
{
public static class VesselHelper
{
internal static Color32 GetColor(Vessel vessel, Serie serie, ChartTheme theme, List<string> legendRealShowName)
{
if (serie != null && vessel.autoColor)
{
var colorIndex = legendRealShowName.IndexOf(serie.name);
return SerieHelper.GetItemColor(serie, null, theme, colorIndex, false);
}
else
{
return vessel.color;
}
}
internal static void UpdateVesselCenter(Vessel vessel, Vector3 chartPosition, float chartWidth, float chartHeight)
{
if (vessel.center.Length < 2) return;
var centerX = vessel.center[0] <= 1 ? chartWidth * vessel.center[0] : vessel.center[0];
var centerY = vessel.center[1] <= 1 ? chartHeight * vessel.center[1] : vessel.center[1];
var checkWidth = Mathf.Min(chartWidth, chartHeight);
vessel.runtimeCenterPos = chartPosition + new Vector3(centerX, centerY);
vessel.runtimeRadius = ChartHelper.GetRuntimeRelativeOrAbsoluteValue(vessel.radius, checkWidth);
vessel.runtimeInnerRadius = vessel.runtimeRadius - vessel.shapeWidth - vessel.gap;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c0c82cb73437a4004bf946cf4dcaa567
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,142 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using System;
using UnityEngine;
namespace XCharts
{
public static class VisualMapHelper
{
public static void AutoSetLineMinMax(VisualMap visualMap, Serie serie, XAxis xAxis, YAxis yAxis)
{
if (!IsNeedGradient(visualMap) || !visualMap.autoMinMax) return;
float min = 0;
float max = 0;
switch (visualMap.direction)
{
case VisualMap.Direction.Default:
case VisualMap.Direction.X:
min = xAxis.IsCategory() ? 0 : xAxis.runtimeMinValue;
max = xAxis.IsCategory() ? serie.dataCount : xAxis.runtimeMaxValue;
SetMinMax(visualMap, min, max);
break;
case VisualMap.Direction.Y:
min = yAxis.IsCategory() ? 0 : yAxis.runtimeMinValue;
max = yAxis.IsCategory() ? serie.dataCount : yAxis.runtimeMaxValue;
SetMinMax(visualMap, min, max);
break;
}
}
public static void SetMinMax(VisualMap visualMap, float min, float max)
{
if (visualMap.enable && (visualMap.min != min || visualMap.max != max))
{
if (max >= min)
{
visualMap.min = min;
visualMap.max = max;
}
else
{
throw new Exception("SetMinMax:max < min:" + min + "," + max);
}
}
}
public static void GetLineGradientColor(VisualMap visualMap, float xValue, float yValue,
out Color32 startColor, out Color32 toColor)
{
startColor = ChartConst.clearColor32;
toColor = ChartConst.clearColor32;
switch (visualMap.direction)
{
case VisualMap.Direction.Default:
case VisualMap.Direction.X:
startColor = visualMap.IsPiecewise() ? visualMap.GetColor(xValue) : visualMap.GetColor(xValue - 1);
toColor = visualMap.IsPiecewise() ? startColor : visualMap.GetColor(xValue);
break;
case VisualMap.Direction.Y:
startColor = visualMap.IsPiecewise() ? visualMap.GetColor(yValue) : visualMap.GetColor(yValue - 1);
toColor = visualMap.IsPiecewise() ? startColor : visualMap.GetColor(yValue);
break;
}
}
internal static Color32 GetLineGradientColor(VisualMap visualMap, Vector3 pos, CoordinateChart chart, Axis axis, Color32 defaultColor)
{
float value = 0;
switch (visualMap.direction)
{
case VisualMap.Direction.Default:
case VisualMap.Direction.X:
var min = axis.runtimeMinValue;
var max = axis.runtimeMaxValue;
var grid = chart.GetAxisGridOrDefault(axis);
value = min + (pos.x - grid.runtimeX) / grid.runtimeWidth * (max - min);
break;
case VisualMap.Direction.Y:
if (axis is YAxis)
{
var yAxis = chart.xAxes[axis.index];
min = yAxis.runtimeMinValue;
max = yAxis.runtimeMaxValue;
}
else
{
var yAxis = chart.yAxes[axis.index];
min = yAxis.runtimeMinValue;
max = yAxis.runtimeMaxValue;
}
grid = chart.GetAxisGridOrDefault(axis);
value = min + (pos.y - grid.runtimeY) / grid.runtimeHeight * (max - min);
break;
}
var color = visualMap.GetColor(value);
if (ChartHelper.IsClearColor(color)) return defaultColor;
else return color;
}
internal static Color32 GetItemStyleGradientColor(ItemStyle itemStyle, Vector3 pos, CoordinateChart chart, Axis axis, Color32 defaultColor)
{
var min = axis.runtimeMinValue;
var max = axis.runtimeMaxValue;
var grid = chart.GetAxisGridOrDefault(axis);
var value = min + (pos.x - grid.runtimeX) / grid.runtimeWidth * (max - min);
var rate = (value - min) / (max - min);
var color = itemStyle.GetGradientColor(rate, defaultColor);
if (ChartHelper.IsClearColor(color)) return defaultColor;
else return color;
}
internal static Color32 GetLineStyleGradientColor(LineStyle lineStyle, Vector3 pos, CoordinateChart chart, Axis axis, Color32 defaultColor)
{
var min = axis.runtimeMinValue;
var max = axis.runtimeMaxValue;
var grid = chart.GetAxisGridOrDefault(axis);
var value = min + (pos.x - grid.runtimeX) / grid.runtimeWidth * (max - min);
var rate = (value - min) / (max - min);
var color = lineStyle.GetGradientColor(rate, defaultColor);
if (ChartHelper.IsClearColor(color)) return defaultColor;
else return color;
}
public static bool IsNeedGradient(VisualMap visualMap)
{
if (!visualMap.enable || visualMap.inRange.Count <= 0) return false;
return true;
}
public static int GetDimension(VisualMap visualMap, int serieDataCount)
{
var dimension = visualMap.enable && visualMap.dimension >= 0 ? visualMap.dimension : serieDataCount - 1;
if (dimension > serieDataCount - 1) dimension = serieDataCount - 1;
return dimension;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 15e5106bd46f5484596429d512f6af5d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4e4276d289bef4136b22e6cc8b207d99
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,28 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace XCharts
{
public interface IDrawSerie
{
void InitComponent();
void CheckComponent();
void Update();
void DrawBase(VertexHelper vh);
void DrawSerie(VertexHelper vh, Serie serie);
void RefreshLabel();
bool CheckTootipArea(Vector2 local);
bool OnLegendButtonClick(int index, string legendName, bool show);
bool OnLegendButtonEnter(int index, string legendName);
bool OnLegendButtonExit(int index, string legendName);
void OnPointerDown(PointerEventData eventData);
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0c4b04c07f5704c06a54b54193558c1b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,18 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
namespace XCharts
{
/// <summary>
/// 属性变更接口
/// </summary>
public interface IPropertyChanged
{
void OnChanged();
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 24f32e2d632f08245ae885545f14a2a3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3d225ec4fe992405d91714722649cc93
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,155 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
public class ChartLabel : ChartObject
{
private bool m_LabelAutoSize = true;
private float m_LabelPaddingLeftRight = 3f;
private float m_LabelPaddingTopBottom = 3f;
private ChartText m_LabelText;
private RectTransform m_LabelRect;
private RectTransform m_IconRect;
private RectTransform m_ObjectRect;
private Image m_IconImage;
public GameObject gameObject { get { return m_GameObject; } }
public Image icon { get { return m_IconImage; } }
public ChartText label { get { return m_LabelText; } }
public ChartLabel()
{
}
public void SetLabel(GameObject labelObj, bool autoSize, float paddingLeftRight, float paddingTopBottom)
{
m_GameObject = labelObj;
m_LabelAutoSize = autoSize;
m_LabelPaddingLeftRight = paddingLeftRight;
m_LabelPaddingTopBottom = paddingTopBottom;
m_LabelText = new ChartText(labelObj);
m_LabelRect = m_LabelText.gameObject.GetComponent<RectTransform>();
m_ObjectRect = labelObj.GetComponent<RectTransform>();
}
public void SetIcon(Image image)
{
m_IconImage = image;
if (image != null)
{
m_IconRect = m_IconImage.GetComponent<RectTransform>();
}
}
public void SetIconSprite(Sprite sprite)
{
if (m_IconImage != null) m_IconImage.sprite = sprite;
}
public void SetIconSize(float width, float height)
{
if (m_IconRect != null) m_IconRect.sizeDelta = new Vector3(width, height);
}
public void UpdateIcon(IconStyle iconStyle)
{
if (m_IconImage == null) return;
if (iconStyle.show)
{
ChartHelper.SetActive(m_IconImage.gameObject, true);
m_IconImage.sprite = iconStyle.sprite;
m_IconImage.color = iconStyle.color;
m_IconRect.sizeDelta = new Vector2(iconStyle.width, iconStyle.height);
m_IconImage.transform.localPosition = iconStyle.offset;
if (iconStyle.layer == IconStyle.Layer.UnderLabel)
m_IconRect.SetSiblingIndex(0);
else
m_IconRect.SetSiblingIndex(m_GameObject.transform.childCount - 1);
}
else
{
ChartHelper.SetActive(m_IconImage.gameObject, false);
}
}
public float GetLabelWidth()
{
if (m_LabelRect) return m_LabelRect.sizeDelta.x;
else return 0;
}
public float GetLabelHeight()
{
if (m_LabelRect) return m_LabelRect.sizeDelta.y;
return 0;
}
public void SetLabelColor(Color color)
{
if (m_LabelText != null) m_LabelText.SetColor(color);
}
public void SetLabelRotate(float rotate)
{
if (m_LabelText != null) m_LabelText.SetLocalEulerAngles(new Vector3(0, 0, rotate));
}
public void SetPosition(Vector3 position)
{
if (m_GameObject != null)
{
m_GameObject.transform.localPosition = position;
}
}
public void SetLabelPosition(Vector3 position)
{
if (m_LabelRect) m_LabelRect.localPosition = position;
}
public void SetActive(bool flag)
{
if (m_GameObject) ChartHelper.SetActive(m_GameObject, flag);
}
public void SetLabelActive(bool flag)
{
if (m_LabelText != null) m_LabelText.SetActive(flag);
}
public void SetIconActive(bool flag)
{
if (m_IconImage) ChartHelper.SetActive(m_IconImage, flag);
}
public bool SetText(string text)
{
if (m_LabelRect == null) return false;
if (m_LabelText != null && !m_LabelText.GetText().Equals(text))
{
m_LabelText.SetText(text);
if (m_LabelAutoSize)
{
var newSize = string.IsNullOrEmpty(text) ? Vector2.zero :
new Vector2(m_LabelText.GetPreferredWidth() + m_LabelPaddingLeftRight * 2,
m_LabelText.GetPreferredHeight() + m_LabelPaddingTopBottom * 2);
var sizeChange = newSize.x != m_LabelRect.sizeDelta.x || newSize.y != m_LabelRect.sizeDelta.y;
if (sizeChange)
{
m_LabelRect.sizeDelta = newSize;
m_ObjectRect.sizeDelta = newSize;
}
return sizeChange;
}
}
return false;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 61287841bdc4142caba8e77985cd8715
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,22 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using System;
using UnityEngine;
namespace XCharts
{
public class ChartObject
{
protected GameObject m_GameObject;
public virtual void Destroy()
{
GameObject.Destroy(m_GameObject);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0fe3102b0eea042938d30af910ca86d6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,255 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
using UnityEngine.UI;
#if dUI_TextMeshPro
using TMPro;
#endif
namespace XCharts
{
public class ChartText
{
private Text m_Text;
private TextGenerationSettings m_RelatedTextSettings;
public Text text
{
get { return m_Text; }
set
{
m_Text = value;
if (value != null)
{
m_RelatedTextSettings = m_Text.GetGenerationSettings(Vector2.zero);
}
}
}
#if dUI_TextMeshPro
private TextMeshProUGUI m_TMPText;
public TextMeshProUGUI tmpText { get { return m_TMPText; } set { m_TMPText = value; } }
#endif
public GameObject gameObject
{
get
{
#if dUI_TextMeshPro
if (m_TMPText != null) return m_TMPText.gameObject;
#else
if (m_Text != null) return m_Text.gameObject;
#endif
return null;
}
}
public ChartText()
{
}
public ChartText(GameObject textParent)
{
#if dUI_TextMeshPro
m_TMPText = textParent.GetComponentInChildren<TextMeshProUGUI>();
if (m_TMPText == null)
{
Debug.LogError("can't find TextMeshProUGUI component:" + textParent);
}
#else
m_Text = textParent.GetComponentInChildren<Text>();
if (m_Text == null)
{
Debug.LogError("can't find Text component:" + textParent);
}
#endif
}
public void SetFontSize(float fontSize)
{
#if dUI_TextMeshPro
if (m_TMPText != null) m_TMPText.fontSize = fontSize;
#else
if (m_Text != null) m_Text.fontSize = (int)fontSize;
#endif
}
public void SetText(string text)
{
if (text == null) text = string.Empty;
else text = text.Replace("\\n", "\n");
#if dUI_TextMeshPro
if(m_TMPText != null) m_TMPText.text = text;
#else
if (m_Text != null) m_Text.text = text;
#endif
}
public string GetText()
{
#if dUI_TextMeshPro
if (m_TMPText != null) return m_TMPText.text;
#else
if (m_Text != null) return m_Text.text;
#endif
return string.Empty;
}
public void SetColor(Color color)
{
#if dUI_TextMeshPro
if (m_TMPText != null) m_TMPText.color = color;
#else
if (m_Text != null) m_Text.color = color;
#endif
}
public void SetLineSpacing(float lineSpacing)
{
#if dUI_TextMeshPro
if (m_TMPText != null) m_TMPText.lineSpacing = lineSpacing;
#else
if (m_Text != null) m_Text.lineSpacing = lineSpacing;
#endif
}
public void SetActive(bool flag)
{
#if dUI_TextMeshPro
//m_TMPText.gameObject.SetActive(flag);
if (m_TMPText != null) ChartHelper.SetActive(m_TMPText.gameObject, flag);
#else
//m_Text.gameObject.SetActive(flag);
if (m_Text != null) ChartHelper.SetActive(m_Text.gameObject, flag);
#endif
}
public void SetLocalPosition(Vector3 position)
{
#if dUI_TextMeshPro
if (m_TMPText != null) m_TMPText.transform.localPosition = position;
#else
if (m_Text != null) m_Text.transform.localPosition = position;
#endif
}
public void SetSizeDelta(Vector2 sizeDelta)
{
#if dUI_TextMeshPro
if (m_TMPText != null) m_TMPText.GetComponent<RectTransform>().sizeDelta = sizeDelta;
#else
if (m_Text != null) m_Text.GetComponent<RectTransform>().sizeDelta = sizeDelta;
#endif
}
public void SetLocalEulerAngles(Vector3 position)
{
#if dUI_TextMeshPro
if (m_TMPText != null) m_TMPText.transform.localEulerAngles = position;
#else
if (m_Text != null) m_Text.transform.localEulerAngles = position;
#endif
}
public void SetAlignment(TextAnchor alignment)
{
#if dUI_TextMeshPro
if (m_TMPText == null) return;
switch (alignment)
{
case TextAnchor.LowerCenter: m_TMPText.alignment = TextAlignmentOptions.Bottom; break;
case TextAnchor.LowerLeft: m_TMPText.alignment = TextAlignmentOptions.BottomLeft; break;
case TextAnchor.LowerRight: m_TMPText.alignment = TextAlignmentOptions.BottomRight; break;
case TextAnchor.MiddleCenter: m_TMPText.alignment = TextAlignmentOptions.Center; break;
case TextAnchor.MiddleLeft: m_TMPText.alignment = TextAlignmentOptions.Left; break;
case TextAnchor.MiddleRight: m_TMPText.alignment = TextAlignmentOptions.Right; break;
case TextAnchor.UpperCenter: m_TMPText.alignment = TextAlignmentOptions.Top; break;
case TextAnchor.UpperLeft: m_TMPText.alignment = TextAlignmentOptions.TopLeft; break;
case TextAnchor.UpperRight: m_TMPText.alignment = TextAlignmentOptions.TopRight; break;
}
#else
if (m_Text != null) m_Text.alignment = alignment;
#endif
}
public void SetFont(Font font)
{
if (m_Text) m_Text.font = font;
}
public void SetFontStyle(FontStyle fontStyle)
{
#if dUI_TextMeshPro
if (m_TMPText == null) return;
switch (fontStyle)
{
case FontStyle.Normal: m_TMPText.fontStyle = FontStyles.Normal; break;
case FontStyle.Bold: m_TMPText.fontStyle = FontStyles.Bold; break;
case FontStyle.BoldAndItalic: m_TMPText.fontStyle = FontStyles.Bold | FontStyles.Italic; break;
case FontStyle.Italic: m_TMPText.fontStyle = FontStyles.Italic; break;
}
#else
if (m_Text != null) m_Text.fontStyle = fontStyle;
#endif
}
public void SetFontAndSizeAndStyle(TextStyle textStyle, ComponentTheme theme)
{
#if dUI_TextMeshPro
if (m_TMPText == null) return;
m_TMPText.font = textStyle.tmpFont == null ? theme.tmpFont : textStyle.tmpFont;
m_TMPText.fontSize = textStyle.fontSize == 0 ? theme.fontSize : textStyle.fontSize;
m_TMPText.fontStyle = textStyle.tmpFontStyle;
#else
if (m_Text != null)
{
m_Text.font = textStyle.font == null ? theme.font : textStyle.font;
m_Text.fontSize = textStyle.fontSize == 0 ? theme.fontSize : textStyle.fontSize;
m_Text.fontStyle = textStyle.fontStyle;
}
#endif
}
public float GetPreferredWidth(string content)
{
#if dUI_TextMeshPro
if (m_TMPText != null) return 0; // TODO:
#else
if (m_Text != null) return m_Text.cachedTextGenerator.GetPreferredWidth(content, m_RelatedTextSettings);
#endif
return 0;
}
public float GetPreferredWidth()
{
#if dUI_TextMeshPro
if (m_TMPText != null) return m_TMPText.preferredWidth;
#else
if (m_Text != null) return m_Text.preferredWidth;
#endif
return 0;
}
public float GetPreferredHeight()
{
#if dUI_TextMeshPro
if (m_TMPText != null) return m_TMPText.preferredHeight;
#else
if (m_Text != null) return m_Text.preferredHeight;
#endif
return 0;
}
#if dUI_TextMeshPro
public void SetAlignment(TextAlignmentOptions alignment)
{
if (m_TMPText != null) m_TMPText.alignment = alignment;
}
public void SetFont(TMP_FontAsset font)
{
if (m_TMPText != null) m_TMPText.font = font;
}
#endif
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4e2466c1fe5874bea8373b071405a930
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,220 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using System;
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
public class LegendItem
{
private int m_Index;
private string m_Name;
private string m_LegendName;
private GameObject m_GameObject;
private Button m_Button;
private Image m_Icon;
private ChartText m_Text;
private Image m_TextBackground;
private RectTransform m_Rect;
private RectTransform m_IconRect;
private RectTransform m_TextRect;
private RectTransform m_TextBackgroundRect;
private float m_Gap = 0f;
private float m_LabelPaddingLeftRight = 0f;
private float m_LabelPaddingTopBottom = 0f;
private bool m_LabelAutoSize = true;
public int index { get { return m_Index; } set { m_Index = value; } }
public string name { get { return m_Name; } set { m_Name = value; } }
public string legendName { get { return m_LegendName; } set { m_LegendName = value; } }
public GameObject gameObject { get { return m_GameObject; } }
public Button button { get { return m_Button; } }
public float width
{
get
{
if (m_IconRect && m_TextBackgroundRect)
{
return m_IconRect.sizeDelta.x + m_Gap + m_TextBackgroundRect.sizeDelta.x;
}
else
{
return 0;
}
}
}
public float height
{
get
{
if (m_IconRect && m_TextBackgroundRect)
{
return Mathf.Max(m_IconRect.sizeDelta.y, m_TextBackgroundRect.sizeDelta.y);
}
else
{
return 0;
}
}
}
public void SetObject(GameObject obj)
{
m_GameObject = obj;
m_Button = obj.GetComponent<Button>();
m_Rect = obj.GetComponent<RectTransform>();
m_Icon = obj.transform.Find("icon").gameObject.GetComponent<Image>();
m_TextBackground = obj.transform.Find("content").gameObject.GetComponent<Image>();
m_Text = new ChartText(obj);
m_IconRect = m_Icon.gameObject.GetComponent<RectTransform>();
m_TextRect = m_Text.gameObject.GetComponent<RectTransform>();
m_TextBackgroundRect = m_TextBackground.gameObject.GetComponent<RectTransform>();
}
public void SetButton(Button button)
{
m_Button = button;
}
public void SetIcon(Image icon)
{
m_Icon = icon;
}
public void SetText(ChartText text)
{
m_Text = text;
}
public void SetTextBackground(Image image)
{
m_TextBackground = image;
}
public void SetIconSize(float width, float height)
{
if (m_IconRect)
{
m_IconRect.sizeDelta = new Vector2(width, height);
}
}
public Rect GetIconRect()
{
if (m_GameObject && m_IconRect)
{
var pos = m_GameObject.transform.localPosition;
var sizeDelta = m_IconRect.sizeDelta;
var y = pos.y - (m_Rect.sizeDelta.y - sizeDelta.y) / 2 - sizeDelta.y;
return new Rect(pos.x, y, m_IconRect.sizeDelta.x, m_IconRect.sizeDelta.y);
}
else
{
return Rect.zero;
}
}
public Color GetIconColor()
{
if (m_Icon) return m_Icon.color;
else return Color.clear;
}
public void SetIconColor(Color color)
{
if (m_Icon)
{
m_Icon.color = color;
}
}
public void SetIconImage(Sprite image)
{
if (m_Icon)
{
m_Icon.sprite = image;
}
}
public void SetIconActive(bool active)
{
if (m_Icon)
{
m_Icon.gameObject.SetActive(active);
}
}
public void SetContentColor(Color color)
{
if (m_Text != null)
{
m_Text.SetColor(color);
}
}
public void SetContentBackgroundColor(Color color)
{
if (m_TextBackground)
{
m_TextBackground.color = color;
}
}
public void SetContentPosition(Vector3 offset)
{
m_Gap = offset.x;
if (m_TextBackgroundRect)
{
var posX = m_IconRect.sizeDelta.x + offset.x;
m_TextBackgroundRect.anchoredPosition3D = new Vector3(posX, offset.y, 0);
}
}
public bool SetContent(string content)
{
if (m_Text != null && !m_Text.GetText().Equals(content))
{
m_Text.SetText(content);
if (m_LabelAutoSize)
{
var newSize = string.IsNullOrEmpty(content) ? Vector2.zero :
new Vector2(m_Text.GetPreferredWidth(), m_Text.GetPreferredHeight());
var sizeChange = newSize.x != m_TextRect.sizeDelta.x || newSize.y != m_TextRect.sizeDelta.y;
if (sizeChange)
{
m_TextRect.sizeDelta = newSize;
m_TextRect.anchoredPosition3D = new Vector3(m_LabelPaddingLeftRight, 0);
m_TextBackgroundRect.sizeDelta = new Vector2(m_Text.GetPreferredWidth() + m_LabelPaddingLeftRight * 2,
m_Text.GetPreferredHeight() + m_LabelPaddingTopBottom * 2 - 4);
m_Rect.sizeDelta = new Vector3(width, height);
}
return sizeChange;
}
}
return false;
}
public void SetPosition(Vector3 position)
{
if (m_GameObject)
{
m_GameObject.transform.localPosition = position;
}
}
public void SetActive(bool active)
{
if (m_GameObject)
{
m_GameObject.SetActive(active);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3e5abcb8f339f41f5b3680ecdab67509
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,79 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
using UnityEngine.UI;
using System;
namespace XCharts
{
[RequireComponent(typeof(CanvasRenderer))]
public class Painter : MaskableGraphic
{
public enum Type
{
Base,
Serie,
Top
}
protected int m_Index = -1;
protected Type m_Type = Type.Base;
protected bool m_Refresh;
protected Action<VertexHelper, Painter> m_OnPopulateMesh;
public Action<VertexHelper, Painter> onPopulateMesh { set { m_OnPopulateMesh = value; } }
public int index { get { return m_Index; } set { m_Index = value; } }
public Type type { get { return m_Type; } set { m_Type = value; } }
public void Refresh()
{
if (gameObject == null) return;
if (!gameObject.activeSelf) return;
m_Refresh = true;
}
public void Init()
{
raycastTarget = false;
}
public void SetActive(bool flag, bool isDebugMode = false)
{
if (gameObject.activeInHierarchy != flag)
{
gameObject.SetActive(flag);
}
// var higFlags = !flag || !isDebugMode ? HideFlags.HideInHierarchy : HideFlags.None;
// if (gameObject.hideFlags != higFlags)
// {
// gameObject.hideFlags = hideFlags;
// }
}
protected override void Awake()
{
Init();
}
internal void CheckRefresh()
{
if (m_Refresh && gameObject.activeSelf)
{
m_Refresh = false;
SetVerticesDirty();
}
}
protected override void OnPopulateMesh(VertexHelper vh)
{
vh.Clear();
if (m_OnPopulateMesh != null)
{
m_OnPopulateMesh(vh, this);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 01c85cd323a9f4dfb803470695bd0944
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 576ce681815d348d0a2abbbadf3dd9f7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,39 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
namespace XCharts
{
internal static class XAxisPool
{
private static readonly ObjectPool<XAxis> s_ListPool = new ObjectPool<XAxis>(null, null);
public static XAxis Get()
{
return s_ListPool.Get();
}
public static void Release(XAxis toRelease)
{
s_ListPool.Release(toRelease);
}
}
internal static class YAxisPool
{
private static readonly ObjectPool<YAxis> s_ListPool = new ObjectPool<YAxis>(null, null);
public static YAxis Get()
{
return s_ListPool.Get();
}
public static void Release(YAxis toRelease)
{
s_ListPool.Release(toRelease);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3a709ca44e9a445bd86bde1bbfae80de
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,43 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using System.Collections.Generic;
using UnityEngine;
namespace XCharts
{
internal static class ListPool<T>
{
private static readonly ObjectPool<List<T>> s_ListPool = new ObjectPool<List<T>>(OnGet, OnClear);
static void OnGet(List<T> l)
{
if (l.Capacity < 50)
{
l.Capacity = 50;
}
}
static void OnClear(List<T> l)
{
l.Clear();
}
public static List<T> Get()
{
return s_ListPool.Get();
}
public static void Release(List<T> toRelease)
{
s_ListPool.Release(toRelease);
}
public static void ClearAll()
{
s_ListPool.ClearAll();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 02c30457469c746dc96f00f24cb6e1c6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,61 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
namespace XCharts
{
internal class ObjectPool<T> where T : new()
{
private readonly Stack<T> m_Stack = new Stack<T>();
private readonly UnityAction<T> m_ActionOnGet;
private readonly UnityAction<T> m_ActionOnRelease;
public int countAll { get; private set; }
public int countActive { get { return countAll - countInactive; } }
public int countInactive { get { return m_Stack.Count; } }
public ObjectPool(UnityAction<T> actionOnGet, UnityAction<T> actionOnRelease)
{
m_ActionOnGet = actionOnGet;
m_ActionOnRelease = actionOnRelease;
}
public T Get()
{
T element;
if (m_Stack.Count == 0)
{
element = new T();
countAll++;
}
else
{
element = m_Stack.Pop();
}
if (m_ActionOnGet != null)
m_ActionOnGet(element);
return element;
}
public void Release(T element)
{
if (m_Stack.Count > 0 && ReferenceEquals(m_Stack.Peek(), element))
Debug.LogError("Internal error. Trying to destroy object that is already released to pool.");
if (m_ActionOnRelease != null)
m_ActionOnRelease(element);
m_Stack.Push(element);
}
public void ClearAll()
{
m_Stack.Clear();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 09e67988253cb4f568b82d52b4113797
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,35 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
namespace XCharts
{
internal static class SerieDataPool
{
private static readonly ObjectPool<SerieData> s_ListPool = new ObjectPool<SerieData>(null, OnClear);
static void OnGet(SerieData serieData)
{
}
static void OnClear(SerieData serieData)
{
serieData.Reset();
}
public static SerieData Get()
{
return s_ListPool.Get();
}
public static void Release(SerieData toRelease)
{
s_ListPool.Release(toRelease);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: faf4da15b01d74648bd13f73125e27bd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,82 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
internal static class SerieLabelPool
{
private static readonly Stack<GameObject> m_Stack = new Stack<GameObject>(200);
private static Dictionary<int, bool> m_ReleaseDic = new Dictionary<int, bool>(1000);
public static GameObject Get(string name, Transform parent, SerieLabel label, Color color,
float iconWidth, float iconHeight, ChartTheme theme)
{
GameObject element;
if (m_Stack.Count == 0 || !Application.isPlaying)
{
element = CreateSerieLabel(name, parent, label, color, iconWidth, iconHeight, theme);
}
else
{
element = m_Stack.Pop();
if (element == null)
{
element = CreateSerieLabel(name, parent, label, color, iconWidth, iconHeight, theme);
}
m_ReleaseDic.Remove(element.GetInstanceID());
element.name = name;
element.transform.SetParent(parent);
element.transform.localEulerAngles = new Vector3(0, 0, label.textStyle.rotate);
var text = new ChartText(element);
text.SetColor(color);
text.SetFontAndSizeAndStyle(label.textStyle, theme.common);
ChartHelper.SetActive(element, true);
}
return element;
}
private static GameObject CreateSerieLabel(string name, Transform parent, SerieLabel label, Color color,
float iconWidth, float iconHeight, ChartTheme theme)
{
var element = ChartHelper.AddSerieLabel(name, parent, label.backgroundWidth, label.backgroundHeight,
color, label.textStyle, theme);
ChartHelper.AddIcon("Icon", element.transform, iconWidth, iconHeight);
return element;
}
public static void Release(GameObject element)
{
if (element == null) return;
ChartHelper.SetActive(element, false);
if (!Application.isPlaying) return;
if (!m_ReleaseDic.ContainsKey(element.GetInstanceID()))
{
m_Stack.Push(element);
m_ReleaseDic.Add(element.GetInstanceID(), true);
}
}
public static void ReleaseAll(Transform parent)
{
int count = parent.childCount;
for (int i = 0; i < count; i++)
{
Release(parent.GetChild(i).gameObject);
}
}
public static void ClearAll()
{
m_Stack.Clear();
m_ReleaseDic.Clear();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e960aeb14c09844e3bdcdc4138af0761
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fb2e76e18ed3b4ffd8ad1e65a0710fb4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,172 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using System.Collections.Generic;
using System.Globalization;
using UnityEngine;
namespace XCharts
{
public static class ChartCached
{
private const string NUMERIC_FORMATTER_D = "D";
private const string NUMERIC_FORMATTER_d = "d";
private const string NUMERIC_FORMATTER_X = "X";
private const string NUMERIC_FORMATTER_x = "x";
private static readonly string s_DefaultAxisY = "axis_y";
private static readonly string s_DefaultAxisX = "axis_x";
private static CultureInfo ci = new CultureInfo("en-us");// "en-us", "zh-cn", "ar-iq", "de-de"
private static Dictionary<Color, string> s_ColorToStr = new Dictionary<Color, string>(100);
private static Dictionary<int, string> s_SerieLabelName = new Dictionary<int, string>(1000);
private static Dictionary<Color, string> s_ColorDotStr = new Dictionary<Color, string>(100);
private static Dictionary<int, string> s_XAxisName = new Dictionary<int, string>();
private static Dictionary<int, string> s_YAxisName = new Dictionary<int, string>();
private static Dictionary<string, string> s_AxisLabel = new Dictionary<string, string>();
private static Dictionary<float, Dictionary<string, string>> s_NumberToStr = new Dictionary<float, Dictionary<string, string>>();
private static Dictionary<int, Dictionary<string, string>> s_PrecisionToStr = new Dictionary<int, Dictionary<string, string>>();
public static string FloatToStr(float value, string numericFormatter = "F", int precision = 0)
{
if (precision > 0 && numericFormatter.Length == 1)
{
if (!s_PrecisionToStr.ContainsKey(precision))
{
s_PrecisionToStr[precision] = new Dictionary<string, string>();
}
if (!s_PrecisionToStr[precision].ContainsKey(numericFormatter))
{
s_PrecisionToStr[precision][numericFormatter] = numericFormatter + precision;
}
return NumberToStr(value, s_PrecisionToStr[precision][numericFormatter]);
}
else
{
return NumberToStr(value, numericFormatter);
}
}
public static string NumberToStr(float value, string formatter)
{
if (!s_NumberToStr.ContainsKey(value))
{
s_NumberToStr[value] = new Dictionary<string, string>();
}
if (!s_NumberToStr[value].ContainsKey(formatter))
{
if (string.IsNullOrEmpty(formatter))
{
if (value - (int)value == 0)
s_NumberToStr[value][formatter] = ((int)value).ToString();
else
s_NumberToStr[value][formatter] = value.ToString();
}
else if (formatter.StartsWith(NUMERIC_FORMATTER_D)
|| formatter.StartsWith(NUMERIC_FORMATTER_d)
|| formatter.StartsWith(NUMERIC_FORMATTER_X)
|| formatter.StartsWith(NUMERIC_FORMATTER_x)
)
{
s_NumberToStr[value][formatter] = ((int)value).ToString(formatter, ci);
}
else
{
s_NumberToStr[value][formatter] = value.ToString(formatter, ci);
}
}
return s_NumberToStr[value][formatter];
}
public static string IntToStr(int value, string numericFormatter = "")
{
return NumberToStr(value, numericFormatter);
}
public static string ColorToStr(Color color)
{
if (s_ColorToStr.ContainsKey(color))
{
return s_ColorToStr[color];
}
else
{
s_ColorToStr[color] = ColorUtility.ToHtmlStringRGBA(color);
return s_ColorToStr[color];
}
}
public static string ColorToDotStr(Color color)
{
if (!s_ColorDotStr.ContainsKey(color))
{
s_ColorDotStr[color] = "<color=#" + ColorToStr(color) + ">● </color>";
}
return s_ColorDotStr[color];
}
internal static string GetSerieLabelName(string prefix, int i, int j)
{
int key = i * 10000000 + j;
if (s_SerieLabelName.ContainsKey(key))
{
return s_SerieLabelName[key];
}
else
{
string name = prefix + "_" + i + "_" + j;
s_SerieLabelName[key] = name;
return name;
}
}
internal static string GetXAxisName(int axisIndex, int index = -1)
{
if (index >= 0)
{
int key = (axisIndex + 1) * 10000 + index;
if (!s_XAxisName.ContainsKey(key))
{
s_XAxisName[key] = axisIndex > 0 ? s_DefaultAxisX + axisIndex + index : s_DefaultAxisX + index;
}
return s_XAxisName[key];
}
else if (!s_XAxisName.ContainsKey(axisIndex))
{
s_XAxisName[axisIndex] = axisIndex > 0 ? s_DefaultAxisX + axisIndex : s_DefaultAxisX;
}
return s_XAxisName[axisIndex];
}
internal static string GetYAxisName(int axisIndex, int index = -1)
{
if (index >= 0)
{
int key = (axisIndex + 1) * 10000 + index;
if (!s_YAxisName.ContainsKey(key))
{
s_YAxisName[key] = axisIndex > 0 ? s_DefaultAxisY + axisIndex + index : s_DefaultAxisY + index;
}
return s_YAxisName[key];
}
else if (!s_YAxisName.ContainsKey(axisIndex))
{
s_YAxisName[axisIndex] = axisIndex > 0 ? s_DefaultAxisY + axisIndex : s_DefaultAxisY;
}
return s_YAxisName[axisIndex];
}
internal static string GetAxisTooltipLabel(string axisName)
{
if (!s_AxisLabel.ContainsKey(axisName))
{
s_AxisLabel[axisName] = axisName + "_label";
}
return s_AxisLabel[axisName];
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 403191b8caeb44430b89d9f3260c4a76
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,18 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
namespace XCharts
{
public static class ChartConst
{
public static readonly Color32 clearColor32 = new Color32(0, 0, 0, 0);
public static readonly Color32 greyColor32 = new Color32(128, 128, 128, 255);
public static readonly Color clearColor = Color.clear;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e19d8fc0680be46b5ac9babf7dd9fe27
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,122 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using XUGL;
namespace XCharts
{
public static class ChartDrawer
{
public static void DrawSymbol(VertexHelper vh, SerieSymbolType type, float symbolSize,
float tickness, Vector3 pos, Color32 color, Color32 toColor, float gap, float[] cornerRadius,
Color32 backgroundColor, float smoothness)
{
switch (type)
{
case SerieSymbolType.None:
break;
case SerieSymbolType.Circle:
if (gap > 0)
{
UGL.DrawDoughnut(vh, pos, symbolSize, symbolSize + gap, backgroundColor, backgroundColor, color, smoothness);
}
else
{
UGL.DrawCricle(vh, pos, symbolSize, color, toColor, smoothness);
}
break;
case SerieSymbolType.EmptyCircle:
if (gap > 0)
{
UGL.DrawCricle(vh, pos, symbolSize + gap, backgroundColor, smoothness);
UGL.DrawEmptyCricle(vh, pos, symbolSize, tickness, color, color, backgroundColor, smoothness);
}
else
{
UGL.DrawEmptyCricle(vh, pos, symbolSize, tickness, color, color, backgroundColor, smoothness);
}
break;
case SerieSymbolType.Rect:
if (gap > 0)
{
UGL.DrawSquare(vh, pos, symbolSize + gap, backgroundColor);
UGL.DrawSquare(vh, pos, symbolSize, color, toColor);
}
else
{
UGL.DrawRoundRectangle(vh, pos, symbolSize, symbolSize, color, color, 0, cornerRadius, true);
}
break;
case SerieSymbolType.Triangle:
if (gap > 0)
{
UGL.DrawTriangle(vh, pos, symbolSize + gap, backgroundColor);
UGL.DrawTriangle(vh, pos, symbolSize, color, toColor);
}
else
{
UGL.DrawTriangle(vh, pos, symbolSize, color, toColor);
}
break;
case SerieSymbolType.Diamond:
if (gap > 0)
{
UGL.DrawDiamond(vh, pos, symbolSize + gap, backgroundColor);
UGL.DrawDiamond(vh, pos, symbolSize, color, toColor);
}
else
{
UGL.DrawDiamond(vh, pos, symbolSize, color, toColor);
}
break;
}
}
// public static void DrawLineStyle(VertexHelper vh, LineStyle lineStyle,
// Vector3 startPos, Vector3 endPos, Color32 color, float themeWidth)
// {
// var type = lineStyle.type;
// var width = lineStyle.GetWidth(themeWidth);
// DrawLineStyle(vh, type, width, startPos, endPos, color);
// }
public static void DrawLineStyle(VertexHelper vh, LineStyle lineStyle,
Vector3 startPos, Vector3 endPos, Color32 color, float themeWidth, LineStyle.Type themeType)
{
var type = lineStyle.GetType(themeType);
var width = lineStyle.GetWidth(themeWidth);
DrawLineStyle(vh, type, width, startPos, endPos, color);
}
public static void DrawLineStyle(VertexHelper vh, LineStyle.Type lineType, float lineWidth,
Vector3 startPos, Vector3 endPos, Color32 color)
{
switch (lineType)
{
case LineStyle.Type.Dashed:
UGL.DrawDashLine(vh, startPos, endPos, lineWidth, color);
break;
case LineStyle.Type.Dotted:
UGL.DrawDotLine(vh, startPos, endPos, lineWidth, color);
break;
case LineStyle.Type.Solid:
UGL.DrawLine(vh, startPos, endPos, lineWidth, color);
break;
case LineStyle.Type.DashDot:
UGL.DrawDashDotLine(vh, startPos, endPos, lineWidth, color);
break;
case LineStyle.Type.DashDotDot:
UGL.DrawDashDotDotLine(vh, startPos, endPos, lineWidth, color);
break;
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 712f08d71f1bf4ab6a1785526bcd5c30
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: 47cfa7bd879be4069bd187e46346d73d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: