0.2版本,重构代码,增加Editor

This commit is contained in:
monitor1394
2019-05-11 04:33:54 +08:00
parent ba1e2c29a2
commit 60c3f7b036
121 changed files with 81427 additions and 21465 deletions

164
Scripts/UI/BarChart.cs Normal file
View File

@@ -0,0 +1,164 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
[AddComponentMenu("XCharts/BarChart", 13)]
[ExecuteInEditMode]
[RequireComponent(typeof(RectTransform))]
[DisallowMultipleComponent]
public class BarChart : CoordinateChart
{
[System.Serializable]
public class Bar
{
[SerializeField] private float m_BarWidth = 0.7f;
[SerializeField] private float m_Space;
public float barWidth { get { return m_BarWidth; } set { m_BarWidth = value; } }
public float space { get { return m_Space; } set { m_Space = value; } }
}
[SerializeField] private Bar m_Bar = new Bar();
protected override void Awake()
{
base.Awake();
}
protected override void Update()
{
base.Update();
}
protected override void DrawChart(VertexHelper vh)
{
base.DrawChart(vh);
if (m_YAxis.type == Axis.AxisType.Category)
{
var stackSeries = m_Series.GetStackSeries();
int seriesCount = stackSeries.Count;
float scaleWid = m_YAxis.GetDataWidth(coordinateHig);
float barWid = m_Bar.barWidth > 1 ? m_Bar.barWidth : scaleWid * m_Bar.barWidth;
float offset = (scaleWid - barWid * seriesCount - m_Bar.space * (seriesCount - 1)) / 2;
float max = GetMaxValue();
int serieCount = 0;
for (int j = 0; j < seriesCount; j++)
{
var seriesCurrHig = new Dictionary<int, float>();
var serieList = stackSeries[j];
for (int n = 0; n < serieList.Count; n++)
{
Serie serie = serieList[n];
if (!m_Legend.IsShowSeries(serie.name)) continue;
Color color = m_ThemeInfo.GetColor(serieCount);
int maxCount = maxShowDataNumber > 0 ?
(maxShowDataNumber > serie.data.Count ? serie.data.Count : maxShowDataNumber)
: serie.data.Count;
for (int i = minShowDataNumber; i < maxCount; i++)
{
if (!seriesCurrHig.ContainsKey(i))
{
seriesCurrHig[i] = 0;
}
float data = serie.data[i];
float pX = seriesCurrHig[i] + zeroX + m_Coordinate.tickness;
float pY = zeroY + i * scaleWid;
if (!m_YAxis.boundaryGap) pY -= scaleWid / 2;
float barHig = data / max * coordinateWid;
float space = offset + j * (barWid + m_Bar.space);
seriesCurrHig[i] += barHig;
Vector3 p1 = new Vector3(pX, pY + space + barWid);
Vector3 p2 = new Vector3(pX + barHig, pY + space + barWid);
Vector3 p3 = new Vector3(pX + barHig, pY + space);
Vector3 p4 = new Vector3(pX, pY + space);
if (serie.show)
{
ChartHelper.DrawPolygon(vh, p1, p2, p3, p4, color);
}
}
if (serie.show)
{
serieCount++;
}
}
}
if (m_Tooltip.show && m_Tooltip.dataIndex > 0)
{
float tooltipSplitWid = scaleWid < 1 ? 1 : scaleWid;
float pX = zeroX + coordinateWid;
float pY = zeroY + scaleWid * (m_Tooltip.dataIndex - 1) - (m_YAxis.boundaryGap ? 0 : scaleWid / 2);
Vector3 p1 = new Vector3(zeroX, pY);
Vector3 p2 = new Vector3(zeroX, pY + tooltipSplitWid);
Vector3 p3 = new Vector3(pX, pY + tooltipSplitWid);
Vector3 p4 = new Vector3(pX, pY);
ChartHelper.DrawPolygon(vh, p1, p2, p3, p4, m_ThemeInfo.tooltipFlagAreaColor);
}
}
else
{
var stackSeries = m_Series.GetStackSeries();
int seriesCount = stackSeries.Count;
float scaleWid = m_XAxis.GetDataWidth(coordinateWid);
float barWid = m_Bar.barWidth > 1 ? m_Bar.barWidth : scaleWid * m_Bar.barWidth;
float offset = (scaleWid - barWid * seriesCount - m_Bar.space * (seriesCount - 1)) / 2;
float max = GetMaxValue();
int serieCount = 0;
for (int j = 0; j < seriesCount; j++)
{
var seriesCurrHig = new Dictionary<int, float>();
var serieList = stackSeries[j];
for (int n = 0; n < serieList.Count; n++)
{
Serie serie = serieList[n];
if (!m_Legend.IsShowSeries(serie.name)) continue;
Color color = m_ThemeInfo.GetColor(serieCount);
int maxCount = maxShowDataNumber > 0 ?
(maxShowDataNumber > serie.data.Count ? serie.data.Count : maxShowDataNumber)
: serie.data.Count;
for (int i = minShowDataNumber; i < maxCount; i++)
{
if (!seriesCurrHig.ContainsKey(i))
{
seriesCurrHig[i] = 0;
}
float data = serie.data[i];
float pX = zeroX + i * scaleWid;
if (!m_XAxis.boundaryGap) pX -= scaleWid / 2;
float pY = seriesCurrHig[i] + zeroY + m_Coordinate.tickness;
float barHig = data / max * coordinateHig;
seriesCurrHig[i] += barHig;
float space = offset + j * (barWid + m_Bar.space);
Vector3 p1 = new Vector3(pX + space, pY);
Vector3 p2 = new Vector3(pX + space, pY + barHig);
Vector3 p3 = new Vector3(pX + space + barWid, pY + barHig);
Vector3 p4 = new Vector3(pX + space + barWid, pY);
if (serie.show)
{
ChartHelper.DrawPolygon(vh, p1, p2, p3, p4, color);
}
}
if (serie.show)
{
serieCount++;
}
}
}
if (m_Tooltip.show && m_Tooltip.dataIndex > 0)
{
float tooltipSplitWid = scaleWid < 1 ? 1 : scaleWid;
float pX = zeroX + scaleWid * (m_Tooltip.dataIndex - 1) - (m_XAxis.boundaryGap?0:scaleWid/2);
float pY = zeroY + coordinateHig;
Vector3 p1 = new Vector3(pX, zeroY);
Vector3 p2 = new Vector3(pX, pY);
Vector3 p3 = new Vector3(pX + tooltipSplitWid, pY);
Vector3 p4 = new Vector3(pX + tooltipSplitWid, zeroY);
ChartHelper.DrawPolygon(vh, p1, p2, p3, p4, m_ThemeInfo.tooltipFlagAreaColor);
}
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 535d2697503c2a94a887354e22a5414d
timeCreated: 1536795169
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

10
Scripts/UI/Interface.meta Normal file
View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 253203a243755c744880211dbbc988a2
folderAsset: yes
timeCreated: 1554979427
licenseType: Free
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
using UnityEngine;
using System.Collections;
namespace XCharts
{
public interface IJsonData
{
void ParseJsonData(string json);
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: e9132f4c137015247b44450c2cb23606
timeCreated: 1555379601
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
using UnityEngine;
using System.Collections;
namespace XCharts
{
public interface IPropertyChanged
{
void OnChanged();
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 24f32e2d632f08245ae885545f14a2a3
timeCreated: 1554979427
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

10
Scripts/UI/Internal.meta Normal file
View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 750348e0c6842d74e872391f6ea942da
folderAsset: yes
timeCreated: 1554221587
licenseType: Free
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

259
Scripts/UI/Internal/Axis.cs Normal file
View File

@@ -0,0 +1,259 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace XCharts
{
[System.Serializable]
public class Axis : JsonDataSupport,IEquatable<Axis>
{
public enum AxisType
{
Value,
Category,
Time,
Log
}
public enum SplitLineType
{
None,
Solid,
Dashed,
Dotted
}
[System.Serializable]
public class AxisTick
{
[SerializeField] private bool m_Show;
[SerializeField] private bool m_AlignWithLabel;
[SerializeField] private bool m_Inside;
[SerializeField] private float m_Length;
public bool show { get { return m_Show; }set { m_Show = value; } }
public bool alignWithLabel { get { return m_AlignWithLabel; } set { m_AlignWithLabel = value; } }
public bool inside { get { return m_Inside; }set { m_Inside = value; } }
public float length { get { return m_Length; }set { m_Length = value; } }
public static AxisTick defaultTick
{
get
{
var tick = new AxisTick
{
m_Show = true,
m_AlignWithLabel = false,
m_Inside = false,
m_Length = 5f
};
return tick;
}
}
}
[SerializeField] protected bool m_Show = true;
[SerializeField] protected AxisType m_Type;
[SerializeField] protected int m_SplitNumber = 5;
[SerializeField] protected int m_TextRotation = 0;
[SerializeField] protected bool m_ShowSplitLine = false;
[SerializeField] protected SplitLineType m_SplitLineType = SplitLineType.Dashed;
[SerializeField] protected bool m_BoundaryGap = true;
[SerializeField] protected List<string> m_Data = new List<string>();
[SerializeField] protected AxisTick m_AxisTick = AxisTick.defaultTick;
public bool show { get { return m_Show; }set { m_Show = value; } }
public AxisType type { get { return m_Type; } set { m_Type = value; } }
public int splitNumber { get { return m_SplitNumber; } set { m_SplitNumber = value; } }
public int textRotation { get { return m_TextRotation; } set { m_TextRotation = value; } }
public bool showSplitLine { get { return m_ShowSplitLine; } set { m_ShowSplitLine = value; } }
public SplitLineType splitLineType { get { return m_SplitLineType; } set { m_SplitLineType = value; } }
public bool boundaryGap { get { return m_BoundaryGap; } set { m_BoundaryGap = value; } }
public List<string> data { get { return m_Data; } }
public AxisTick axisTick { get { return m_AxisTick; }set { m_AxisTick = value; } }
public void Copy(Axis other)
{
m_Show = other.show;
m_Type = other.type;
m_SplitNumber = other.splitNumber;
m_TextRotation = other.textRotation;
m_ShowSplitLine = other.showSplitLine;
m_SplitLineType = other.splitLineType;
m_BoundaryGap = other.boundaryGap;
m_Data.Clear();
foreach (var d in other.data) m_Data.Add(d);
}
public void ClearData()
{
m_Data.Clear();
}
public void AddData(string category,int maxDataNumber)
{
if (maxDataNumber > 0)
{
while (m_Data.Count > maxDataNumber) m_Data.RemoveAt(0);
}
m_Data.Add(category);
}
public string GetData(int index)
{
if (index >= 0 && index < data.Count)
return data[index];
else
return "";
}
public int GetSplitNumber()
{
if (data.Count > 2 * m_SplitNumber || data.Count <= 0)
return m_SplitNumber;
else
return data.Count;
}
public float GetSplitWidth(float coordinateWidth)
{
return coordinateWidth / (m_BoundaryGap ? GetSplitNumber() : GetSplitNumber() - 1);
}
public int GetDataNumber()
{
return data.Count;
}
public float GetDataWidth(float coordinateWidth)
{
return coordinateWidth / (m_BoundaryGap ? data.Count : data.Count - 1);
}
public string GetScaleName(int index, float maxData = 0)
{
if (m_Type == AxisType.Value)
{
return ((int)(maxData * index / (GetSplitNumber() -1))).ToString();
}
int dataCount = data.Count;
if (dataCount <= 0) return "";
if(index == GetSplitNumber() - 1 && !m_BoundaryGap)
{
return data[data.Count-1];
}
else
{
float rate = dataCount / GetSplitNumber();
if (rate < 1) rate = 1;
int offset = m_BoundaryGap ? (int)(rate / 2) : 0;
int newIndex = (int)(index * rate >= dataCount - 1 ? dataCount - 1 : offset + index * rate);
return data[newIndex];
}
}
public int GetScaleNumber()
{
if (data.Count > 2 * splitNumber || data.Count <= 0)
return m_BoundaryGap ? m_SplitNumber + 1 : m_SplitNumber;
else
return m_BoundaryGap ? data.Count + 1 : data.Count;
}
public float GetScaleWidth(float coordinateWidth)
{
int num = GetScaleNumber() - 1;
if (num <= 0) num = 1;
return coordinateWidth / num;
}
public override bool Equals(object obj)
{
if (!(obj is Axis)) return false;
return Equals((Axis)obj);
}
public bool Equals(Axis other)
{
return show == other.show &&
type == other.type &&
splitNumber == other.splitNumber &&
showSplitLine == other.showSplitLine &&
textRotation == other.textRotation &&
splitLineType == other.splitLineType &&
boundaryGap == other.boundaryGap &&
ChartHelper.IsValueEqualsList<string>(m_Data, other.data);
}
public static bool operator ==(Axis point1, Axis point2)
{
return point1.Equals(point2);
}
public static bool operator !=(Axis point1, Axis point2)
{
return !point1.Equals(point2);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public override void ParseJsonData(string jsonData)
{
if (string.IsNullOrEmpty(jsonData) || !m_DataFromJson) return;
m_Data = ChartHelper.ParseStringFromString(jsonData);
}
}
[System.Serializable]
public class XAxis : Axis
{
public static XAxis defaultXAxis
{
get
{
var axis = new XAxis
{
m_Show = true,
m_Type = AxisType.Category,
m_SplitNumber = 5,
m_TextRotation = 0,
m_ShowSplitLine = false,
m_SplitLineType = SplitLineType.Dashed,
m_BoundaryGap = true,
m_Data = new List<string>()
{
"x1","x2","x3","x4","x5"
}
};
return axis;
}
}
}
[System.Serializable]
public class YAxis : Axis
{
public static YAxis defaultYAxis
{
get
{
var axis = new YAxis
{
m_Show = true,
m_Type = AxisType.Value,
m_SplitNumber = 5,
m_TextRotation = 0,
m_ShowSplitLine = false,
m_SplitLineType = SplitLineType.Dashed,
m_BoundaryGap = false,
m_Data = new List<string>(5),
};
return axis;
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 84f640465300fb34facae554552063b9
timeCreated: 1554422468
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,367 @@
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using System;
namespace XCharts
{
public class BaseChart : MaskableGraphic
{
private static readonly string s_TitleObjectName = "title";
private static readonly string s_LegendObjectName = "legend";
[SerializeField] protected Theme m_Theme = Theme.Default;
[SerializeField] protected ThemeInfo m_ThemeInfo;
[SerializeField] protected Title m_Title = Title.defaultTitle;
[SerializeField] protected Legend m_Legend = Legend.defaultLegend;
[SerializeField] protected Tooltip m_Tooltip = Tooltip.defaultTooltip;
[SerializeField] protected Series m_Series;
[SerializeField] protected bool m_Large;
[SerializeField] protected int m_MinShowDataNumber;
[SerializeField] protected int m_MaxShowDataNumber;
[SerializeField] protected int m_MaxCacheDataNumber;
[NonSerialized] private Theme m_CheckTheme = 0;
[NonSerialized] private Title m_CheckTitle = Title.defaultTitle;
[NonSerialized] private Legend m_CheckLegend = Legend.defaultLegend;
[NonSerialized] private float m_CheckWidth = 0;
[NonSerialized] private float m_CheckHeight = 0;
[NonSerialized] protected List<Text> m_LegendTextList = new List<Text>();
protected float chartWidth { get { return rectTransform.sizeDelta.x; } }
protected float chartHeight { get { return rectTransform.sizeDelta.y; } }
protected Vector2 chartAnchorMax { get { return rectTransform.anchorMax; } }
protected Vector2 chartAnchorMin { get { return rectTransform.anchorMin; } }
protected Vector2 chartPivot { get { return rectTransform.pivot; } }
public Title title { get { return m_Title; } }
public Legend legend { get { return m_Legend; } }
public Tooltip tooltip { get { return m_Tooltip; } }
public Series series { get { return m_Series; } }
public bool large { get { return m_Large; } set { m_Large = value; } }
public int minShowDataNumber
{
get { return m_MinShowDataNumber; }
set { m_MinShowDataNumber = value; if (m_MinShowDataNumber < 0) m_MinShowDataNumber = 0; }
}
public int maxShowDataNumber
{
get { return m_MaxShowDataNumber; }
set { m_MaxShowDataNumber = value; if (m_MaxShowDataNumber < 0) m_MaxShowDataNumber = 0; }
}
public int maxCacheDataNumber
{
get { return m_MaxCacheDataNumber; }
set { m_MaxCacheDataNumber = value; if (m_MaxCacheDataNumber < 0) m_MaxCacheDataNumber = 0; }
}
protected override void Awake()
{
m_ThemeInfo = ThemeInfo.Default;
rectTransform.anchorMax = Vector2.zero;
rectTransform.anchorMin = Vector2.zero;
rectTransform.pivot = Vector2.zero;
m_CheckWidth = chartWidth;
m_CheckHeight = chartHeight;
m_CheckTheme = m_Theme;
InitTitle();
InitLegend();
InitTooltip();
}
protected virtual void Update()
{
CheckSize();
CheckTheme();
CheckTile();
CheckLegend();
CheckTooltip();
}
protected override void Reset()
{
ChartHelper.DestoryAllChilds(transform);
m_ThemeInfo = ThemeInfo.Dark;
m_Title = Title.defaultTitle;
m_Legend = Legend.defaultLegend;
m_Tooltip = Tooltip.defaultTooltip;
m_Series = Series.defaultSeries;
InitTitle();
InitLegend();
InitTooltip();
}
protected override void OnDestroy()
{
for (int i = transform.childCount - 1; i >= 0; i--)
{
DestroyImmediate(transform.GetChild(i).gameObject);
}
}
public void AddData(string legend, float value)
{
m_Series.AddData(legend, value, m_MaxCacheDataNumber);
RefreshChart();
}
public void AddData(int legend, float value)
{
m_Series.AddData(legend, value, m_MaxCacheDataNumber);
}
public void UpdateData(string legend, float value, int dataIndex = 0)
{
m_Series.UpdateData(legend, value, dataIndex);
RefreshChart();
}
public void UpdateData(int legendIndex, float value, int dataIndex = 0)
{
m_Series.UpdateData(legendIndex, value, dataIndex);
RefreshChart();
}
public void UpdateTheme(Theme theme)
{
this.m_Theme = theme;
OnThemeChanged();
SetAllDirty();
}
private void InitTitle()
{
m_Title.OnChanged();
TextAnchor anchor = m_Title.location.textAnchor;
Vector2 anchorMin = m_Title.location.anchorMin;
Vector2 anchorMax = m_Title.location.anchorMax;
Vector2 pivot = m_Title.location.pivot;
Vector3 titlePosition = m_Title.location.GetPosition(chartWidth, chartHeight);
Vector3 subTitlePosition = -new Vector3(0, m_Title.textFontSize + m_Title.itemGap, 0);
float titleWid = chartWidth;
var titleObject = ChartHelper.AddObject(s_TitleObjectName, transform, anchorMin, anchorMax,
pivot, new Vector2(chartWidth, chartHeight));
titleObject.transform.localPosition = titlePosition;
ChartHelper.HideAllObject(titleObject, s_TitleObjectName);
Text titleText = ChartHelper.AddTextObject(s_TitleObjectName, titleObject.transform,
m_ThemeInfo.font, m_ThemeInfo.textColor, anchor, anchorMin, anchorMax, pivot,
new Vector2(titleWid, m_Title.textFontSize), m_Title.textFontSize);
titleText.alignment = anchor;
titleText.gameObject.SetActive(m_Title.show);
titleText.transform.localPosition = Vector2.zero;
titleText.text = m_Title.text;
Text subText = ChartHelper.AddTextObject(s_TitleObjectName + "_sub", titleObject.transform,
m_ThemeInfo.font, m_ThemeInfo.textColor, anchor, anchorMin, anchorMax, pivot,
new Vector2(titleWid, m_Title.subTextFontSize), m_Title.subTextFontSize);
subText.alignment = anchor;
subText.gameObject.SetActive(m_Title.show && !string.IsNullOrEmpty(m_Title.subText));
subText.transform.localPosition = subTitlePosition;
subText.text = m_Title.subText;
}
private void InitLegend()
{
m_Legend.OnChanged();
ChartHelper.HideAllObject(transform, s_LegendObjectName);
TextAnchor anchor = m_Legend.location.textAnchor;
Vector2 anchorMin = m_Legend.location.anchorMin;
Vector2 anchorMax = m_Legend.location.anchorMax;
Vector2 pivot = m_Legend.location.pivot;
var legendObject = ChartHelper.AddObject(s_LegendObjectName, transform, anchorMin, anchorMax,
pivot, new Vector2(chartWidth, chartHeight));
legendObject.transform.localPosition = m_Legend.location.GetPosition(chartWidth, chartHeight);
ChartHelper.HideAllObject(legendObject, s_LegendObjectName);
for (int i = 0; i < m_Legend.data.Count; i++)
{
Button btn = ChartHelper.AddButtonObject(s_LegendObjectName + "_" + i, legendObject.transform,
m_ThemeInfo.font, m_Legend.itemFontSize, m_ThemeInfo.legendTextColor, anchor,
anchorMin, anchorMax, pivot, new Vector2(m_Legend.itemWidth, m_Legend.itemHeight));
m_Legend.SetButton(i, btn);
m_Legend.UpdateButtonColor(i, m_ThemeInfo.GetColor(i), m_ThemeInfo.unableColor);
btn.GetComponentInChildren<Text>().text = m_Legend.data[i];
btn.onClick.AddListener(delegate ()
{
int index = int.Parse(btn.name.Split('_')[1]);
m_Legend.SetShowData(index, !m_Legend.IsShowSeries(index));
m_Legend.UpdateButtonColor(index, m_ThemeInfo.GetColor(index), m_ThemeInfo.unableColor);
OnYMaxValueChanged();
OnLegendButtonClicked();
RefreshChart();
});
}
}
private void InitTooltip()
{
GameObject obj = ChartHelper.AddTooltipObject("tooltip", transform, m_ThemeInfo.font);
m_Tooltip.SetObj(obj);
m_Tooltip.SetBackgroundColor(m_ThemeInfo.tooltipBackgroundColor);
m_Tooltip.SetTextColor(m_ThemeInfo.tooltipTextColor);
m_Tooltip.SetActive(false);
}
private Vector3 GetLegendPosition(int i)
{
return m_Legend.location.GetPosition(chartWidth, chartHeight);
}
protected float GetMaxValue()
{
if (m_Series == null) return 100;
else return m_Series.GetMaxValue(m_Legend);
}
protected float GetMaxValue(int index)
{
if (m_Series == null) return 100;
else return m_Series.GetMaxValue(index);
}
private void CheckSize()
{
if (m_CheckWidth != chartWidth || m_CheckHeight != chartHeight)
{
m_CheckWidth = chartWidth;
m_CheckHeight = chartHeight;
OnSizeChanged();
}
}
private void CheckTheme()
{
if (m_CheckTheme != m_Theme)
{
m_CheckTheme = m_Theme;
OnThemeChanged();
}
}
private void CheckTile()
{
if (!m_CheckTitle.Equals(m_Title))
{
m_CheckTitle.Copy(m_Title);
OnTitleChanged();
}
}
private void CheckLegend()
{
if (m_CheckLegend != m_Legend)
{
m_CheckLegend.Copy(m_Legend);
OnLegendChanged();
}
}
private void CheckTooltip()
{
if (!m_Tooltip.show) return;
m_Tooltip.dataIndex = 0;
Vector2 local;
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform,
Input.mousePosition, null, out local))
return;
if (local.x < 0 || local.x > chartWidth ||
local.y < 0 || local.y > chartHeight)
return;
CheckTootipArea(local);
}
protected virtual void CheckTootipArea(Vector2 localPostion)
{
}
protected virtual void OnSizeChanged()
{
InitTitle();
InitLegend();
}
protected virtual void OnThemeChanged()
{
switch (m_Theme)
{
case Theme.Dark:
m_ThemeInfo.Copy(ThemeInfo.Dark);
break;
case Theme.Default:
m_ThemeInfo.Copy(ThemeInfo.Default);
break;
case Theme.Light:
m_ThemeInfo.Copy(ThemeInfo.Light);
break;
}
InitTitle();
InitLegend();
}
protected virtual void OnTitleChanged()
{
InitTitle();
}
protected virtual void OnLegendChanged()
{
InitLegend();
}
protected virtual void OnYMaxValueChanged()
{
}
protected virtual void OnLegendButtonClicked()
{
}
public void RefreshChart()
{
int tempWid = (int)chartWidth;
rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, tempWid - 1);
rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, tempWid);
}
protected virtual void RefreshTooltip()
{
}
protected override void OnPopulateMesh(VertexHelper vh)
{
vh.Clear();
DrawBackground(vh);
DrawChart(vh);
DrawTooltip(vh);
}
protected virtual void DrawChart(VertexHelper vh)
{
}
protected virtual void DrawTooltip(VertexHelper vh)
{
}
private void DrawBackground(VertexHelper vh)
{
// draw bg
Vector3 p1 = new Vector3(0, chartHeight);
Vector3 p2 = new Vector3(chartWidth, chartHeight);
Vector3 p3 = new Vector3(chartWidth, 0);
Vector3 p4 = new Vector3(0, 0);
ChartHelper.DrawPolygon(vh, p1, p2, p3, p4, m_ThemeInfo.backgroundColor);
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: d5053a63a1ebdfe4f8972f194156c3d3
timeCreated: 1536967243
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
[Serializable]
public class Coordinate : IEquatable<Coordinate>
{
[SerializeField] private float m_Left;
[SerializeField] private float m_Right;
[SerializeField] private float m_Top;
[SerializeField] private float m_Bottom;
[SerializeField] private float m_Tickness;
[SerializeField] private int m_FontSize;
public float left { get { return m_Left; } set { m_Left = value; } }
public float right { get { return m_Right; } set { m_Right = value; } }
public float top { get { return m_Top; } set { m_Top = value; } }
public float bottom { get { return m_Bottom; } set { m_Bottom = value; } }
public float tickness { get { return m_Tickness; } set { m_Tickness = value; } }
public int fontSize { get { return m_FontSize; } set { m_FontSize = value; } }
public static Coordinate defaultCoordinate
{
get
{
var coordinate = new Coordinate
{
m_Left = 40f,
m_Right = 80f,
m_Top = 40f,
m_Bottom = 25f,
m_Tickness = 0.6f,
m_FontSize = 16,
};
return coordinate;
}
}
public void Copy(Coordinate other)
{
m_Left = other.left;
m_Right = other.right;
m_Top = other.top;
m_Bottom = other.bottom;
m_Tickness = other.tickness;
}
public override bool Equals(object obj)
{
if (!(obj is Coordinate)) return false;
return Equals((Coordinate)obj);
}
public bool Equals(Coordinate other)
{
return m_Left == other.left &&
m_Right == other.right &&
m_Top == other.top &&
m_Bottom == other.bottom &&
m_Tickness == other.tickness &&
m_FontSize == other.fontSize;
}
public static bool operator ==(Coordinate point1, Coordinate point2)
{
return point1.Equals(point2);
}
public static bool operator !=(Coordinate point1, Coordinate point2)
{
return !point1.Equals(point2);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: e7dea6e12aeb93945888247ea97dbd13
timeCreated: 1554422468
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,497 @@
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using System.Text;
using System;
namespace XCharts
{
public class CoordinateChart : BaseChart
{
private static readonly string s_DefaultSplitNameY = "split_y";
private static readonly string s_DefaultSplitNameX = "split_x";
[SerializeField] protected Coordinate m_Coordinate = Coordinate.defaultCoordinate;
[SerializeField] protected XAxis m_XAxis = XAxis.defaultXAxis;
[SerializeField] protected YAxis m_YAxis = YAxis.defaultYAxis;
[NonSerialized] private float m_LastXMaxValue;
[NonSerialized] private float m_LastYMaxValue;
[NonSerialized] private XAxis m_CheckXAxis = XAxis.defaultXAxis;
[NonSerialized] private YAxis m_CheckYAxis = YAxis.defaultYAxis;
[NonSerialized] private Coordinate m_CheckCoordinate = Coordinate.defaultCoordinate;
protected List<Text> m_SplitYTextList = new List<Text>();
protected List<Text> m_SplitXTextList = new List<Text>();
public float zeroX { get { return m_Coordinate.left; } }
public float zeroY { get { return m_Coordinate.bottom; } }
public float coordinateWid { get { return chartWidth - m_Coordinate.left - m_Coordinate.right; } }
public float coordinateHig { get { return chartHeight - m_Coordinate.top - m_Coordinate.bottom; } }
public Axis xAxis { get { return m_XAxis; } }
public Axis yAxis { get { return m_YAxis; } }
protected override void Awake()
{
base.Awake();
InitSplitX();
InitSplitY();
}
protected override void Update()
{
base.Update();
CheckYAxis();
CheckXAxis();
CheckMaxValue();
CheckCoordinate();
}
protected override void Reset()
{
base.Reset();
m_Coordinate = Coordinate.defaultCoordinate;
m_XAxis = XAxis.defaultXAxis;
m_YAxis = YAxis.defaultYAxis;
InitSplitX();
InitSplitY();
}
protected override void DrawChart(VertexHelper vh)
{
base.DrawChart(vh);
DrawCoordinate(vh);
}
protected override void CheckTootipArea(Vector2 local)
{
if (local.x < zeroX || local.x > zeroX + coordinateWid ||
local.y < zeroY || local.y > zeroY + coordinateHig)
{
m_Tooltip.dataIndex = 0;
RefreshTooltip();
}
else
{
if (m_XAxis.type == Axis.AxisType.Value)
{
float splitWid = m_YAxis.GetDataWidth(coordinateHig);
for (int i = 0; i < m_YAxis.GetDataNumber(); i++)
{
float pY = zeroY + i * splitWid;
if (m_YAxis.boundaryGap)
{
if (local.y > pY && local.y <= pY + splitWid)
{
m_Tooltip.dataIndex = i + 1;
break;
}
}
else
{
if (local.y > pY - splitWid / 2 && local.y <= pY + splitWid / 2)
{
m_Tooltip.dataIndex = i + 1;
break;
}
}
}
}
else
{
float splitWid = m_XAxis.GetDataWidth(coordinateWid);
for (int i = 0; i < m_XAxis.GetDataNumber(); i++)
{
float pX = zeroX + i * splitWid;
if (m_XAxis.boundaryGap)
{
if (local.x > pX && local.x <= pX + splitWid)
{
m_Tooltip.dataIndex = i + 1;
break;
}
}
else
{
if (local.x > pX - splitWid / 2 && local.x <= pX + splitWid / 2)
{
m_Tooltip.dataIndex = i + 1;
break;
}
}
}
}
}
if (m_Tooltip.dataIndex > 0)
{
m_Tooltip.UpdatePos(new Vector2(local.x + 18, local.y - 25));
RefreshTooltip();
if (m_Tooltip.lastDataIndex != m_Tooltip.dataIndex)
{
RefreshChart();
}
m_Tooltip.lastDataIndex = m_Tooltip.dataIndex;
}
}
protected override void RefreshTooltip()
{
base.RefreshTooltip();
int index = m_Tooltip.dataIndex - 1;
Axis tempAxis = m_XAxis.type == Axis.AxisType.Value ? (Axis)m_YAxis : (Axis)m_XAxis;
if (index < 0)
{
m_Tooltip.SetActive(false);
return;
}
m_Tooltip.SetActive(true);
if (m_Series.Count == 1)
{
string txt = tempAxis.GetData(index) + ": " + m_Series.GetData(0,index);
m_Tooltip.UpdateTooltipText(txt);
}
else
{
StringBuilder sb = new StringBuilder(tempAxis.GetData(index));
for (int i = 0; i < m_Series.Count; i++)
{
if (m_Series.series[i].show)
{
string strColor = ColorUtility.ToHtmlStringRGBA(m_ThemeInfo.GetColor(i));
string key = m_Series.series[i].name;
float value = m_Series.series[i].data[index];
sb.Append("\n");
sb.AppendFormat("<color=#{0}>● </color>", strColor);
sb.AppendFormat("{0}: {1}", key, value);
}
}
m_Tooltip.UpdateTooltipText(sb.ToString());
}
var pos = m_Tooltip.GetPos();
if (pos.x + m_Tooltip.width > chartWidth)
{
pos.x = chartWidth - m_Tooltip.width;
}
if (pos.y - m_Tooltip.height < 0)
{
pos.y = m_Tooltip.height;
}
m_Tooltip.UpdatePos(pos);
}
TextGenerationSettings GetTextSetting()
{
var setting = new TextGenerationSettings();
var fontdata = FontData.defaultFontData;
//setting.generationExtents = rectTransform.rect.size;
setting.generationExtents = new Vector2(200.0F, 50.0F);
setting.fontSize = 14;
setting.textAnchor = TextAnchor.MiddleCenter;
setting.scaleFactor = 1f;
setting.color = Color.red;
setting.font = m_ThemeInfo.font;
setting.pivot = new Vector2(0.5f, 0.5f);
setting.richText = false;
setting.lineSpacing = 0;
setting.fontStyle = FontStyle.Normal;
setting.resizeTextForBestFit = false;
setting.horizontalOverflow = HorizontalWrapMode.Overflow;
setting.verticalOverflow = VerticalWrapMode.Overflow;
return setting;
}
protected override void OnThemeChanged()
{
base.OnThemeChanged();
InitSplitX();
InitSplitY();
}
public void AddXAxisData(string category)
{
m_XAxis.AddData(category,m_MaxCacheDataNumber);
OnXAxisChanged();
}
public void AddYAxisData(string category)
{
m_YAxis.AddData(category, m_MaxCacheDataNumber);
OnYAxisChanged();
}
private void InitSplitY()
{
m_SplitYTextList.Clear();
float max = GetMaxValue();
float splitWidth = m_YAxis.GetScaleWidth(coordinateHig);
var titleObject = ChartHelper.AddObject(s_DefaultSplitNameY, transform, chartAnchorMin,
chartAnchorMax, chartPivot, new Vector2(chartWidth, chartHeight));
titleObject.transform.localPosition = Vector3.zero;
ChartHelper.HideAllObject(titleObject, s_DefaultSplitNameY);
for (int i = 0; i < m_YAxis.splitNumber; i++)
{
Text txt = ChartHelper.AddTextObject(s_DefaultSplitNameY + i, titleObject.transform,
m_ThemeInfo.font, m_ThemeInfo.textColor, TextAnchor.MiddleRight, Vector2.zero,
Vector2.zero, new Vector2(1, 0.5f), new Vector2(m_Coordinate.left, 20),
m_Coordinate.fontSize, m_XAxis.textRotation);
txt.transform.localPosition = GetSplitYPosition(splitWidth, i);
txt.text = m_YAxis.GetScaleName(i, max);
txt.gameObject.SetActive(m_YAxis.show);
m_SplitYTextList.Add(txt);
}
}
public void InitSplitX()
{
m_SplitXTextList.Clear();
float max = GetMaxValue();
float splitWidth = m_XAxis.GetScaleWidth(coordinateWid);
var titleObject = ChartHelper.AddObject(s_DefaultSplitNameX, transform, chartAnchorMin,
chartAnchorMax, chartPivot, new Vector2(chartWidth, chartHeight));
titleObject.transform.localPosition = Vector3.zero;
ChartHelper.HideAllObject(titleObject, s_DefaultSplitNameX);
for (int i = 0; i < m_XAxis.splitNumber; i++)
{
Text txt = ChartHelper.AddTextObject(s_DefaultSplitNameX + i, titleObject.transform,
m_ThemeInfo.font, m_ThemeInfo.textColor, TextAnchor.MiddleCenter, Vector2.zero,
Vector2.zero, new Vector2(1, 0.5f), new Vector2(splitWidth, 20),
m_Coordinate.fontSize, m_XAxis.textRotation);
txt.transform.localPosition = GetSplitXPosition(splitWidth, i);
txt.text = m_XAxis.GetScaleName(i, max);
txt.gameObject.SetActive(m_XAxis.show);
m_SplitXTextList.Add(txt);
}
}
private Vector3 GetSplitYPosition(float scaleWid, int i)
{
if (m_YAxis.boundaryGap)
{
return new Vector3(zeroX - m_YAxis.axisTick.length - 2f,
zeroY + (i + 0.5f) * scaleWid, 0);
}
else
{
return new Vector3(zeroX - m_YAxis.axisTick.length - 2f,
zeroY + i * scaleWid, 0);
}
}
private Vector3 GetSplitXPosition(float scaleWid, int i)
{
if (m_XAxis.boundaryGap)
{
return new Vector3(zeroX + (i + 1) * scaleWid, zeroY - m_XAxis.axisTick.length - 5, 0);
}
else
{
return new Vector3(zeroX + (i + 1 - 0.5f) * scaleWid,
zeroY - m_XAxis.axisTick.length - 10, 0);
}
}
private void CheckCoordinate()
{
if (m_CheckCoordinate != m_Coordinate)
{
m_CheckCoordinate.Copy(m_Coordinate);
OnCoordinateChanged();
}
}
private void CheckYAxis()
{
if (m_CheckYAxis != m_YAxis)
{
m_CheckYAxis.Copy(m_YAxis);
OnYAxisChanged();
}
}
private void CheckXAxis()
{
if (!m_CheckXAxis.Equals(m_XAxis))
{
m_CheckXAxis.Copy(m_XAxis);
OnXAxisChanged();
}
}
private void CheckMaxValue()
{
if (m_XAxis.type == Axis.AxisType.Value)
{
float max = GetMaxValue();
if (m_LastXMaxValue != max)
{
m_LastXMaxValue = max;
OnXMaxValueChanged();
}
}
else if (m_YAxis.type == Axis.AxisType.Value)
{
float max = GetMaxValue();
if (m_LastYMaxValue != max)
{
m_LastYMaxValue = max;
OnYMaxValueChanged();
}
}
}
protected virtual void OnCoordinateChanged()
{
InitSplitX();
InitSplitY();
}
protected virtual void OnYAxisChanged()
{
InitSplitY();
}
protected virtual void OnXAxisChanged()
{
InitSplitX();
}
protected virtual void OnXMaxValueChanged()
{
float max = GetMaxValue();
for (int i = 0; i < m_SplitXTextList.Count; i++)
{
m_SplitXTextList[i].text = m_XAxis.GetScaleName(i, max);
}
}
protected override void OnSizeChanged()
{
base.OnSizeChanged();
InitSplitX();
InitSplitY();
}
protected override void OnYMaxValueChanged()
{
float max = GetMaxValue();
for (int i = 0; i < m_SplitYTextList.Count; i++)
{
m_SplitYTextList[i].text = m_YAxis.GetScaleName(i, max);
}
}
private void DrawCoordinate(VertexHelper vh)
{
#region draw tick and splitline
if (m_YAxis.show)
{
for (int i = 1; i < m_YAxis.GetScaleNumber(); i++)
{
float pX = zeroX - m_YAxis.axisTick.length;
float pY = zeroY + i * m_YAxis.GetScaleWidth(coordinateHig);
if (m_YAxis.boundaryGap && m_YAxis.axisTick.alignWithLabel)
{
pY -= m_YAxis.GetScaleWidth(coordinateHig) / 2;
}
if (m_YAxis.axisTick.show)
{
ChartHelper.DrawLine(vh, new Vector3(pX, pY), new Vector3(zeroX, pY),
m_Coordinate.tickness, m_ThemeInfo.axisLineColor);
}
if (m_YAxis.showSplitLine)
{
DrawSplitLine(vh, true, m_YAxis.splitLineType, new Vector3(zeroX, pY),
new Vector3(zeroX + coordinateWid, pY));
}
}
}
if (m_XAxis.show)
{
for (int i = 1; i < m_XAxis.GetScaleNumber(); i++)
{
float pX = zeroX + i * m_XAxis.GetScaleWidth(coordinateWid);
float pY = zeroY - m_XAxis.axisTick.length - 2;
if (m_XAxis.boundaryGap && m_XAxis.axisTick.alignWithLabel)
{
pX -= m_XAxis.GetScaleWidth(coordinateWid) / 2;
}
if (m_XAxis.axisTick.show)
{
ChartHelper.DrawLine(vh, new Vector3(pX, zeroY), new Vector3(pX, pY), m_Coordinate.tickness,
m_ThemeInfo.axisLineColor);
}
if (m_XAxis.showSplitLine)
{
DrawSplitLine(vh, false, m_XAxis.splitLineType, new Vector3(pX, zeroY),
new Vector3(pX, zeroY + coordinateHig));
}
}
}
#endregion
//draw x,y axis
if (m_YAxis.show)
{
ChartHelper.DrawLine(vh, new Vector3(zeroX, zeroY - m_YAxis.axisTick.length),
new Vector3(zeroX, zeroY + coordinateHig + 2), m_Coordinate.tickness,
m_ThemeInfo.axisLineColor);
}
if (m_XAxis.show)
{
ChartHelper.DrawLine(vh, new Vector3(zeroX - m_XAxis.axisTick.length, zeroY),
new Vector3(zeroX + coordinateWid + 2, zeroY), m_Coordinate.tickness,
m_ThemeInfo.axisLineColor);
}
}
private void DrawSplitLine(VertexHelper vh, bool isYAxis, Axis.SplitLineType type, Vector3 startPos,
Vector3 endPos)
{
switch (type)
{
case Axis.SplitLineType.Dashed:
case Axis.SplitLineType.Dotted:
var startX = startPos.x;
var startY = startPos.y;
var dashLen = type == Axis.SplitLineType.Dashed ? 6 : 2.5f;
var count = isYAxis ? (endPos.x - startPos.x) / (dashLen * 2) :
(endPos.y - startPos.y) / (dashLen * 2);
for (int i = 0; i < count; i++)
{
if (isYAxis)
{
var toX = startX + dashLen;
ChartHelper.DrawLine(vh, new Vector3(startX, startY), new Vector3(toX, startY),
m_Coordinate.tickness, m_ThemeInfo.axisSplitLineColor);
startX += dashLen * 2;
}
else
{
var toY = startY + dashLen;
ChartHelper.DrawLine(vh, new Vector3(startX, startY), new Vector3(startX, toY),
m_Coordinate.tickness, m_ThemeInfo.axisSplitLineColor);
startY += dashLen * 2;
}
}
break;
case Axis.SplitLineType.Solid:
ChartHelper.DrawLine(vh, startPos, endPos, m_Coordinate.tickness,
m_ThemeInfo.axisSplitLineColor);
break;
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: c20b1e83703d1084c899f1f1b605c278
timeCreated: 1538087401
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,32 @@
using UnityEngine;
using UnityEditor;
using System;
namespace XCharts
{
public class JsonDataSupport: IJsonData,ISerializationCallbackReceiver
{
[SerializeField] protected string m_JsonData;
[SerializeField] protected bool m_DataFromJson;
public string jsonData { get { return m_JsonData; } set { m_JsonData = value; ParseJsonData(value); } }
public void OnAfterDeserialize()
{
if (m_DataFromJson)
{
ParseJsonData(m_JsonData);
m_DataFromJson = false;
}
}
public void OnBeforeSerialize()
{
}
public virtual void ParseJsonData(string json)
{
throw new Exception("no support yet");
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 73e326ed8a76f90408bfa9feb1797433
timeCreated: 1555379601
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,243 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
[System.Serializable]
public class Legend : JsonDataSupport, IPropertyChanged, IEquatable<Legend>
{
public enum Orient
{
Horizonal,
Vertical
}
[SerializeField] private bool m_Show = true;
[SerializeField] private Orient m_Orient = Orient.Horizonal;
[SerializeField] private Location m_Location = Location.defaultRight;
[SerializeField] private float m_ItemWidth = 50.0f;
[SerializeField] private float m_ItemHeight = 20.0f;
[SerializeField] private float m_ItemGap = 5;
[SerializeField] private int m_ItemFontSize = 18;
[SerializeField] private List<string> m_Data = new List<string>();
[NonSerialized] private List<bool> m_DataShowList = new List<bool>();
[NonSerialized] private List<Button> m_DataBtnList = new List<Button>();
public bool show { get { return m_Show; } set { m_Show = value; } }
public Orient orient { get { return m_Orient; } set { m_Orient = value; } }
public Location location { get { return m_Location; } set { m_Location = value; } }
public float itemWidth { get { return m_ItemWidth; } set { m_ItemWidth = value; } }
public float itemHeight { get { return m_ItemHeight; } set { m_ItemHeight = value; } }
public float itemGap { get { return m_ItemGap; } set { m_ItemGap = value; } }
public int itemFontSize { get { return m_ItemFontSize; } set { m_ItemFontSize = value; } }
public List<string> data { get { return m_Data; } }
public static Legend defaultLegend
{
get
{
var legend = new Legend
{
m_Show = true,
m_Orient = Orient.Horizonal,
m_Location = Location.defaultRight,
m_ItemWidth = 60.0f,
m_ItemHeight = 20.0f,
m_ItemGap = 5,
m_ItemFontSize = 16,
m_Data = new List<string>()
{
"Legend"
}
};
return legend;
}
}
public void Copy(Legend legend)
{
m_Show = legend.show;
m_Orient = legend.orient;
m_Location.Copy(legend.location);
m_ItemWidth = legend.itemWidth;
m_ItemHeight = legend.itemHeight;
m_ItemGap = legend.itemGap;
m_ItemFontSize = legend.itemFontSize;
m_Data.Clear();
foreach (var d in legend.data) m_Data.Add(d);
}
public override bool Equals(object obj)
{
if (!(obj is Legend)) return false;
return Equals((Legend)obj);
}
public bool Equals(Legend other)
{
return show == other.show &&
orient == other.orient &&
location == other.location &&
itemWidth == other.itemWidth &&
itemHeight == other.itemHeight &&
itemGap == other.itemGap &&
itemFontSize == other.itemFontSize &&
ChartHelper.IsValueEqualsList<string>(m_Data, other.data);
}
public static bool operator ==(Legend point1, Legend point2)
{
return point1.Equals(point2);
}
public static bool operator !=(Legend point1, Legend point2)
{
return !point1.Equals(point2);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public bool IsShowSeries(string name)
{
if (string.IsNullOrEmpty(name)) return true;
for(int i = 0; i < data.Count; i++)
{
if (name.Equals(data[i])) return m_DataShowList[i];
}
return true;
}
public bool IsShowSeries(int seriesIndex)
{
if (seriesIndex < 0 || seriesIndex > data.Count - 1) seriesIndex = 0;
if (seriesIndex >= data.Count) return false;
if (seriesIndex < 0 || seriesIndex > m_DataShowList.Count - 1)
{
return true;
}
else
{
return m_DataShowList[seriesIndex];
}
}
public void SetShowData(int index, bool flag)
{
m_DataShowList[index] = flag;
}
public void SetButton(int index, Button btn)
{
btn.transform.localPosition = GetButtonLocationPosition(index);
if (index < 0 || index > m_DataBtnList.Count - 1)
{
m_DataBtnList.Add(btn);
m_DataShowList.Add(true);
}
else
{
m_DataBtnList[index] = btn;
}
btn.gameObject.SetActive(show);
btn.GetComponentInChildren<Text>().text = data[index];
}
public void UpdateButtonColor(int index,Color ableColor,Color unableColor)
{
if (IsShowSeries(index))
{
m_DataBtnList[index].GetComponent<Image>().color = ableColor;
}
else
{
m_DataBtnList[index].GetComponent<Image>().color = unableColor;
}
}
public void SetShowData(string name, bool flag)
{
for (int i = 0; i < data.Count; i++)
{
if (data[i].Equals(name))
{
m_DataShowList[i] = flag;
break;
}
}
}
public void OnChanged()
{
m_Location.OnChanged();
}
private Vector2 GetButtonLocationPosition(int index)
{
int size = m_Data.Count;
switch (m_Orient)
{
case Orient.Vertical:
switch (m_Location.align)
{
case Location.Align.TopCenter:
case Location.Align.TopLeft:
case Location.Align.TopRight:
return new Vector2(0, -index * (itemHeight + itemGap));
case Location.Align.Center:
case Location.Align.CenterLeft:
case Location.Align.CenterRight:
float totalHeight = size * itemHeight + (size - 1) * itemGap;
float startY = totalHeight / 2;
return new Vector2(0, startY - index * (itemHeight + itemGap));
case Location.Align.BottomCenter:
case Location.Align.BottomLeft:
case Location.Align.BottomRight:
return new Vector2(0, (size - index - 1) * (itemHeight + itemGap));
}
return Vector2.zero;
case Orient.Horizonal:
switch (m_Location.align)
{
case Location.Align.TopLeft:
case Location.Align.CenterLeft:
case Location.Align.BottomLeft:
return new Vector2(index * (itemWidth + itemGap), 0);
case Location.Align.TopCenter:
case Location.Align.Center:
case Location.Align.BottomCenter:
float totalWidth = size * itemWidth + (size - 1) * itemGap;
float startX = totalWidth / 2;
return new Vector2(-startX + itemWidth / 2 + index * (itemWidth + itemGap), 0);
case Location.Align.TopRight:
case Location.Align.CenterRight:
case Location.Align.BottomRight:
return new Vector2(-(size - index - 1) * (itemWidth + itemGap), 0);
}
return Vector2.zero;
}
return Vector2.zero;
}
public override void ParseJsonData(string jsonData)
{
if (string.IsNullOrEmpty(jsonData) || !m_DataFromJson) return;
m_Data = ChartHelper.ParseStringFromString(jsonData);
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 3fba76b49d7dd644cb3953355d6caae4
timeCreated: 1554222818
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,41 @@
using UnityEngine;
namespace XCharts
{
[System.Serializable]
public class Line
{
[SerializeField] private float m_Tickness;
[SerializeField] private bool m_Point;
[SerializeField] private float m_PointWidth;
[SerializeField] private bool m_Smooth;
[SerializeField] [Range(1f, 10f)] private float m_SmoothStyle;
[SerializeField] private bool m_Area;
[SerializeField] private Color m_AreaColor;
public float tickness { get { return m_Tickness; } set { m_Tickness = value; } }
public bool point { get { return m_Point; } set { m_Point = value; } }
public float pointWidth { get { return m_PointWidth; } set { m_PointWidth = value; } }
public bool smooth { get { return m_Smooth; } set { m_Smooth = value; } }
public float smoothStyle { get { return m_SmoothStyle; } set { m_SmoothStyle = value; } }
public bool area { get { return m_Area; } set { m_Area = value; } }
public Color areaColor { get { return m_AreaColor; } set { m_AreaColor = value; } }
public static Line defaultLine
{
get
{
var line = new Line
{
m_Tickness = 0.8f,
m_Point = true,
m_PointWidth = 2.5f,
m_Smooth = false,
m_SmoothStyle = 2f,
m_Area = false
};
return line;
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 86acdbfd671c43949bf0cc4880a4ccb7
timeCreated: 1555671450
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,240 @@
using System;
using UnityEngine;
namespace XCharts
{
[Serializable]
public class Location : IPropertyChanged, IEquatable<Location>
{
public enum Align
{
TopLeft,
TopRight,
TopCenter,
BottomLeft,
BottomRight,
BottomCenter,
Center,
CenterLeft,
CenterRight
}
[SerializeField] private Align m_Align = Align.TopCenter;
[SerializeField] private float m_Left;
[SerializeField] private float m_Right;
[SerializeField] private float m_Top;
[SerializeField] private float m_Bottom;
private TextAnchor m_TextAnchor;
private Vector2 m_AnchorMin;
private Vector2 m_AnchorMax;
private Vector2 m_Pivot;
public Align align { get { return m_Align; } set { m_Align = value; UpdateAlign(); } }
public float left { get { return m_Left; } set { m_Left = value; UpdateAlign(); } }
public float right { get { return m_Right; } set { m_Right = value; UpdateAlign(); } }
public float top { get { return m_Top; } set { m_Top = value; UpdateAlign(); } }
public float bottom { get { return m_Bottom; } set { m_Bottom = value; UpdateAlign(); } }
public TextAnchor textAnchor { get { return m_TextAnchor; } }
public Vector2 anchorMin { get { return m_AnchorMin; } }
public Vector2 anchorMax { get { return m_AnchorMax; } }
public Vector2 pivot { get { return m_Pivot; } }
public static Location defaultLeft
{
get
{
return new Location()
{
align = Align.CenterRight,
left = 5,
right = 0,
top = 0,
bottom = 0
};
}
}
public static Location defaultRight
{
get
{
return new Location()
{
align = Align.CenterRight,
left = 0,
right = 5,
top = 0,
bottom = 0
};
}
}
public static Location defaultTop
{
get
{
return new Location()
{
align = Align.TopCenter,
left = 0,
right = 0,
top = 5,
bottom = 0
};
}
}
public static Location defaultBottom
{
get
{
return new Location()
{
align = Align.BottomCenter,
left = 0,
right = 0,
top = 0,
bottom = 5
};
}
}
private void UpdateAlign()
{
switch (m_Align)
{
case Align.BottomCenter:
m_TextAnchor = TextAnchor.LowerCenter;
m_AnchorMin = new Vector2(0.5f, 0);
m_AnchorMax = new Vector2(0.5f, 0);
m_Pivot = new Vector2(0.5f, 0);
break;
case Align.BottomLeft:
m_TextAnchor = TextAnchor.LowerLeft;
m_AnchorMin = new Vector2(0, 0);
m_AnchorMax = new Vector2(0, 0);
m_Pivot = new Vector2(0, 0);
break;
case Align.BottomRight:
m_TextAnchor = TextAnchor.LowerRight;
m_AnchorMin = new Vector2(1, 0);
m_AnchorMax = new Vector2(1, 0);
m_Pivot = new Vector2(1, 0);
break;
case Align.Center:
m_TextAnchor = TextAnchor.MiddleCenter;
m_AnchorMin = new Vector2(0.5f, 0.5f);
m_AnchorMax = new Vector2(0.5f, 0.5f);
m_Pivot = new Vector2(0.5f, 0.5f);
break;
case Align.CenterLeft:
m_TextAnchor = TextAnchor.MiddleLeft;
m_AnchorMin = new Vector2(0, 0.5f);
m_AnchorMax = new Vector2(0, 0.5f);
m_Pivot = new Vector2(0, 0.5f);
break;
case Align.CenterRight:
m_TextAnchor = TextAnchor.MiddleRight;
m_AnchorMin = new Vector2(1, 0.5f);
m_AnchorMax = new Vector2(1, 0.5f);
m_Pivot = new Vector2(1, 0.5f);
break;
case Align.TopCenter:
m_TextAnchor = TextAnchor.UpperCenter;
m_AnchorMin = new Vector2(0.5f, 1);
m_AnchorMax = new Vector2(0.5f, 1);
m_Pivot = new Vector2(0.5f, 1);
break;
case Align.TopLeft:
m_TextAnchor = TextAnchor.UpperLeft;
m_AnchorMin = new Vector2(0, 1);
m_AnchorMax = new Vector2(0, 1);
m_Pivot = new Vector2(0, 1);
break;
case Align.TopRight:
m_TextAnchor = TextAnchor.UpperRight;
m_AnchorMin = new Vector2(1, 1);
m_AnchorMax = new Vector2(1, 1);
m_Pivot = new Vector2(1, 1);
break;
default:
break;
}
}
public Vector2 GetPosition(float chartWidht, float chartHeight)
{
switch (align)
{
case Align.BottomCenter:
return new Vector2(chartWidht / 2, bottom);
case Align.BottomLeft:
return new Vector2(left, bottom);
case Align.BottomRight:
return new Vector2(chartWidht - right, bottom);
case Align.Center:
return new Vector2(chartWidht / 2, chartHeight / 2);
case Align.CenterLeft:
return new Vector2(left, chartHeight / 2);
case Align.CenterRight:
return new Vector2(chartWidht - right, chartHeight / 2);
case Align.TopCenter:
return new Vector2(chartWidht / 2, chartHeight - top);
case Align.TopLeft:
return new Vector2(left, chartHeight - top);
case Align.TopRight:
return new Vector2(chartWidht - right, chartHeight - top);
default:
return Vector2.zero;
}
}
public void Copy(Location location)
{
m_Align = location.align;
m_Left = location.left;
m_Right = location.right;
m_Top = location.top;
m_Bottom = location.bottom;
}
public override bool Equals(object obj)
{
if (!(obj is Location))
return false;
return Equals((Location)obj);
}
public bool Equals(Location other)
{
return align == other.align &&
left == other.left &&
right == other.right &&
top == other.top &&
bottom == other.bottom;
}
public static bool operator ==(Location point1, Location point2)
{
return point1.Equals(point2);
}
public static bool operator !=(Location point1, Location point2)
{
return !point1.Equals(point2);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public void OnChanged()
{
UpdateAlign();
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 453c586e78719f046a387172174edb36
timeCreated: 1554306777
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
using UnityEngine;
namespace XCharts
{
[System.Serializable]
public class Pie
{
[SerializeField] private string m_Name;
[SerializeField] private float m_InsideRadius;
[SerializeField] private float m_OutsideRadius;
[SerializeField] private float m_TooltipExtraRadius;
[SerializeField] private bool m_Rose;
[SerializeField] private float m_Space;
[SerializeField] private float m_Left;
[SerializeField] private float m_Right;
[SerializeField] private float m_Top;
[SerializeField] private float m_Bottom;
public string name { get { return m_Name; } set { m_Name = value; } }
public float insideRadius { get { return m_InsideRadius; } set { m_InsideRadius = value; } }
public float outsideRadius { get { return m_OutsideRadius; } set { m_OutsideRadius = value; } }
public float tooltipExtraRadius { get { return m_TooltipExtraRadius; } set { m_TooltipExtraRadius = value; } }
public bool rose { get { return m_Rose; } set { m_Rose = value; } }
public float space { get { return m_Space; } set { m_Space = value; } }
public float left { get { return m_Left; } set { m_Left = value; } }
public float right { get { return m_Right; } set { m_Right = value; } }
public float top { get { return m_Top; } set { m_Top = value; } }
public float bottom { get { return m_Bottom; } set { m_Bottom = value; } }
public static Pie defaultPie
{
get
{
var pie = new Pie
{
m_Name = "Pie",
m_InsideRadius = 0f,
m_OutsideRadius = 80f,
m_TooltipExtraRadius = 10f,
m_Rose = false
};
return pie;
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 7f38ef4633bae5247a8c382a4d20fc39
timeCreated: 1555671161
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,189 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System;
using System.Text.RegularExpressions;
namespace XCharts
{
[System.Serializable]
public class Radar : JsonDataSupport, IEquatable<Radar>
{
[System.Serializable]
public class Indicator: IEquatable<Indicator>
{
public string m_Name;
public float m_Max;
public string name { get { return m_Name; }set { m_Name = value; } }
public float max { get { return m_Max; }set { m_Max = value; } }
public Indicator Clone()
{
return new Indicator()
{
name = name,
max = max
};
}
public bool Equals(Indicator other)
{
return name.Equals(other.name);
}
}
[SerializeField] private bool m_Cricle;
[SerializeField] private bool m_Area;
[SerializeField] private float m_Radius = 100;
[SerializeField] private int m_SplitNumber = 5;
[SerializeField] private float m_Left;
[SerializeField] private float m_Right;
[SerializeField] private float m_Top;
[SerializeField] private float m_Bottom;
[SerializeField] private float m_LineTickness = 1f;
[SerializeField] private float m_LinePointSize = 5f;
[SerializeField] private Color m_LineColor = Color.grey;
[SerializeField] private List<Color> m_BackgroundColorList = new List<Color>();
[SerializeField] private bool m_Indicator = true;
[SerializeField] private List<Indicator> m_IndicatorList = new List<Indicator>();
public bool cricle { get { return m_Cricle; } set { m_Cricle = value; } }
public bool area { get { return m_Area; } set { m_Area = value; } }
public float radius { get { return m_Radius; } set { m_Radius = value; } }
public int splitNumber { get { return m_SplitNumber; } set { m_SplitNumber = value; } }
public float left { get { return m_Left; } set { m_Left = value; } }
public float right { get { return m_Right; } set { m_Right = value; } }
public float top { get { return m_Top; } set { m_Top = value; } }
public float bottom { get { return m_Bottom; } set { m_Bottom = value; } }
public float lineTickness { get { return m_LineTickness; } set { m_LineTickness = value; } }
public float linePointSize { get { return m_LinePointSize; } set { m_LinePointSize = value; } }
public Color lineColor { get { return m_LineColor; } set { m_LineColor = value; } }
public List<Color> backgroundColorList { get { return m_BackgroundColorList; } }
public bool indicator { get { return m_Indicator; } set { m_Indicator = value; } }
public List<Indicator> indicatorList { get { return m_IndicatorList; } }
public static Radar defaultRadar
{
get {
var radar = new Radar
{
m_Cricle = false,
m_Area = false,
m_Radius = 100,
m_SplitNumber = 5,
m_Left = 0,
m_Right = 0,
m_Top = 0,
m_Bottom = 0,
m_LineTickness = 1f,
m_LinePointSize = 5f,
m_LineColor = Color.grey,
m_Indicator = true,
m_BackgroundColorList = new List<Color> {
new Color32(194, 53, 49, 255),
new Color32(47, 69, 84, 255)
},
m_IndicatorList = new List<Indicator>(5)
};
return radar;
}
}
public void Copy(Radar other)
{
m_Radius = other.radius;
m_SplitNumber = other.splitNumber;
m_Left = other.left;
m_Right = other.right;
m_Top = other.top;
m_Bottom = other.bottom;
m_Indicator = other.indicator;
indicatorList.Clear();
foreach (var d in other.indicatorList) indicatorList.Add(d.Clone());
}
public override bool Equals(object obj)
{
if (!(obj is Radar)) return false;
return Equals((Radar)obj);
}
public bool Equals(Radar other)
{
return radius == other.radius &&
splitNumber == other.splitNumber &&
left == other.left &&
right == other.right &&
top == other.top &&
bottom == other.bottom &&
indicator == other.indicator &&
IsEqualsIndicatorList(indicatorList, other.indicatorList);
}
private bool IsEqualsIndicatorList(List<Indicator> indicators1,List<Indicator> indicators2)
{
if (indicators1.Count != indicators2.Count) return false;
for(int i = 0; i < indicators1.Count; i++)
{
var indicator1 = indicators1[i];
var indicator2 = indicators2[i];
if (!indicator1.Equals(indicator2)) return false;
}
return true;
}
public static bool operator ==(Radar point1, Radar point2)
{
return point1.Equals(point2);
}
public static bool operator !=(Radar point1, Radar point2)
{
return !point1.Equals(point2);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public override void ParseJsonData(string jsonData)
{
if (string.IsNullOrEmpty(jsonData) || !m_DataFromJson) return;
string pattern = "[\"|'](.*?)[\"|']";
if (Regex.IsMatch(jsonData, pattern))
{
m_IndicatorList.Clear();
MatchCollection m = Regex.Matches(jsonData, pattern);
foreach (Match match in m)
{
m_IndicatorList.Add(new Indicator() {
name = match.Groups[1].Value
});
}
}
pattern = "(\\d+)";
if (Regex.IsMatch(jsonData, pattern))
{
MatchCollection m = Regex.Matches(jsonData, pattern);
int index = 0;
foreach (Match match in m)
{
if (m_IndicatorList[index]!=null)
{
m_IndicatorList[index].max = int.Parse(match.Groups[1].Value);
}
index++;
}
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: e3a368484f9598e4eb9dfce2471d34da
timeCreated: 1555562622
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace XCharts
{
[System.Serializable]
public class Serie : JsonDataSupport
{
public enum SerieType
{
Line,
Bar
}
[SerializeField] private bool m_Show = true;
[SerializeField] private SerieType m_Type;
[SerializeField] private string m_Name;
[SerializeField] private string m_Stack;
[SerializeField] private List<float> m_Data = new List<float>();
[SerializeField] private bool m_Flodout;
public bool show { get { return m_Show; }set { m_Show = value; } }
public SerieType type { get { return m_Type; } set { m_Type = value; } }
public string name { get { return m_Name; } set { m_Name = value; } }
public string stack { get { return m_Stack; } set { m_Stack = value; } }
public List<float> data { get { return m_Data; } }
public float Max
{
get
{
float max = int.MinValue;
foreach (var data in data)
{
if (data > max)
{
max = data;
}
}
return max;
}
}
public float Total
{
get
{
float total = 0;
foreach (var data in data)
{
total += data;
}
return total;
}
}
public void ClearData()
{
m_Data.Clear();
}
public void RemoveData(int index)
{
m_Data.RemoveAt(index);
}
public void AddData(float value, int maxDataNumber)
{
if (maxDataNumber > 0)
{
while (m_Data.Count > maxDataNumber) m_Data.RemoveAt(0);
}
m_Data.Add(value);
}
public float GetData(int index)
{
if (index >= 0 && index <= data.Count - 1)
{
return data[index];
}
return 0;
}
public void UpdateData(int index, float value)
{
if (index >= 0 && index <= m_Data.Count - 1)
{
m_Data[index] = value;
}
}
public override void ParseJsonData(string jsonData)
{
if (string.IsNullOrEmpty(jsonData) || !m_DataFromJson) return;
m_Data = ChartHelper.ParseFloatFromString(jsonData);
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 5bde61eb0785bad4d91d84d5511514ba
timeCreated: 1554222818
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,221 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System;
namespace XCharts
{
[System.Serializable]
public class Series : JsonDataSupport
{
[SerializeField] protected List<Serie> m_Series;
public List<Serie> series { get { return m_Series; } }
public int Count { get { return m_Series.Count; } }
public static Series defaultSeries
{
get
{
var series = new Series
{
m_Series = new List<Serie>()
};
return series;
}
}
public void ClearData()
{
foreach(var serie in m_Series)
{
serie.ClearData();
}
}
public float GetData(int serieIndex,int dataIndex)
{
if(serieIndex >= 0 && serieIndex < Count)
{
return m_Series[serieIndex].GetData(dataIndex);
}
else
{
return 0;
}
}
public void AddData(string legend, float value, int maxDataNumber = 0)
{
for (int i = 0; i < m_Series.Count; i++)
{
if (m_Series[i].name.Equals(legend))
{
m_Series[i].AddData(value, maxDataNumber);
break;
}
}
}
public void AddData(int legend, float value, int maxDataNumber = 0)
{
if (legend >= 0 && legend < Count)
{
m_Series[legend].AddData(value, maxDataNumber);
}
}
public void UpdateData(string legend, float value, int dataIndex = 0)
{
for (int i = 0; i < m_Series.Count; i++)
{
if (m_Series[i].name.Equals(legend))
{
m_Series[i].UpdateData(dataIndex, value);
break;
}
}
}
public void UpdateData(int legendIndex, float value, int dataIndex = 0)
{
for (int i = 0; i < m_Series.Count; i++)
{
if (i == legendIndex)
{
m_Series[i].UpdateData(dataIndex, value);
break;
}
}
}
public float GetMaxValue(Legend legend)
{
float max = int.MinValue;
if (IsStack())
{
var stackSeries = GetStackSeries();
foreach (var ss in stackSeries)
{
var seriesTotalValue = new Dictionary<int, float>();
for (int i = 0; i < ss.Value.Count; i++)
{
var serie = ss.Value[i];
for (int j = 0; j < serie.data.Count; j++)
{
if (!seriesTotalValue.ContainsKey(j))
seriesTotalValue[j] = 0;
seriesTotalValue[j] = seriesTotalValue[j] + serie.data[j];
}
}
float tmax = 0;
foreach (var tt in seriesTotalValue)
{
if (tt.Value > tmax) tmax = tt.Value;
}
if (tmax > max) max = tmax;
}
}
else
{
for (int i = 0; i < m_Series.Count; i++)
{
if (legend.IsShowSeries(i) && m_Series[i].Max > max) max = m_Series[i].Max;
}
}
if (max == int.MinValue) return 100;
if (max < 1 && max > -1) return max;
int bigger = (int)Mathf.Abs(max);
int n = 1;
while (bigger / (Mathf.Pow(10, n)) > 10)
{
n++;
}
float mm = bigger < 10 ? bigger : ((bigger - bigger % (Mathf.Pow(10, n))) + Mathf.Pow(10, n));
if (max < 0) return -mm;
else return mm;
}
public float GetMaxValue(int index,int splitNumber = 0)
{
float max = int.MinValue;
float min = int.MaxValue;
for (int i = 0; i < m_Series.Count; i++)
{
if (m_Series[i].data[index] > max)
{
max = Mathf.Ceil(m_Series[i].data[index]);
}
if (m_Series[i].data[index] < min)
{
min = Mathf.Ceil(m_Series[i].data[index]);
}
}
if (max < 1 && max > -1) return max;
if (max < 0 && min < 0) max = min;
int bigger = (int)Mathf.Abs(max);
int n = 1;
while (bigger / (Mathf.Pow(10, n)) > 10)
{
n++;
}
float mm = bigger < 10 ? bigger : ((bigger - bigger % (Mathf.Pow(10, n))) + Mathf.Pow(10, n));
if (max < 1 && max > -1) return max;
else if (max < 0) return -mm;
else return mm;
}
public bool IsStack()
{
HashSet<string> sets = new HashSet<string>();
foreach (var serie in m_Series)
{
if (string.IsNullOrEmpty(serie.stack)) continue;
if (sets.Contains(serie.stack)) return true;
else
{
sets.Add(serie.stack);
}
}
return false;
}
public Dictionary<int, List<Serie>> GetStackSeries()
{
int count = 0;
Dictionary<string, int> sets = new Dictionary<string, int>();
Dictionary<int, List<Serie>> stackSeries = new Dictionary<int, List<Serie>>();
foreach (var serie in m_Series)
{
if (string.IsNullOrEmpty(serie.stack))
{
stackSeries[count] = new List<Serie>();
stackSeries[count].Add(serie);
count++;
}
else
{
if (!sets.ContainsKey(serie.stack))
{
sets.Add(serie.stack, count);
stackSeries[count] = new List<Serie>();
stackSeries[count].Add(serie);
count++;
}
else
{
int stackIndex = sets[serie.stack];
stackSeries[stackIndex].Add(serie);
}
}
}
return stackSeries;
}
public override void ParseJsonData(string jsonData)
{
//TODO:
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 137f78d348f866943a9fb8c1c8eaceef
timeCreated: 1556016849
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,232 @@

using UnityEngine;
using System;
namespace XCharts
{
public enum Theme
{
Default = 1,
Light,
Dark
}
[Serializable]
public class ThemeInfo : IEquatable<ThemeInfo>
{
[SerializeField] private Font m_Font;
[SerializeField] private Color32 m_BackgroundColor;
[SerializeField] private Color32 m_ContrastColor;
[SerializeField] private Color32 m_TextColor;
[SerializeField] private Color32 m_SubTextColor;
[SerializeField] private Color32 m_LegendTextColor;
[SerializeField] private Color32 m_UnableColor;
[SerializeField] private Color32 m_AxisLineColor;
[SerializeField] private Color32 m_AxisSplitLineColor;
[SerializeField] private Color32 m_TooltipBackgroundColor;
[SerializeField] private Color32 m_TooltipFlagAreaColor;
[SerializeField] private Color32 m_TooltipTextColor;
[SerializeField] private Color32[] m_ColorPalette;
public Font font { get { return m_Font; } set { m_Font = value; } }
public Color32 backgroundColor { get { return m_BackgroundColor; } set { m_BackgroundColor = value; } }
public Color32 contrastColor { get { return m_ContrastColor; } set { m_ContrastColor = value; } }
public Color32 textColor { get { return m_TextColor; } set { m_TextColor = value; } }
public Color32 subTextColor { get { return m_SubTextColor; } set { m_SubTextColor = value; } }
public Color32 legendTextColor { get { return m_LegendTextColor; } set { m_LegendTextColor = value; } }
public Color32 unableColor { get { return m_UnableColor; } set { m_UnableColor = value; } }
public Color32 axisLineColor { get { return m_AxisLineColor; } set { m_AxisLineColor = value; } }
public Color32 axisSplitLineColor { get { return m_AxisSplitLineColor; } set { m_AxisSplitLineColor = value; } }
public Color32 tooltipBackgroundColor { get { return m_TooltipBackgroundColor; } set { m_TooltipBackgroundColor = value; } }
public Color32 tooltipFlagAreaColor { get { return m_TooltipFlagAreaColor; } set { m_TooltipFlagAreaColor = value; } }
public Color32 tooltipTextColor { get { return m_TooltipTextColor; } set { m_TooltipTextColor = value; } }
public Color32[] colorPalette { get { return m_ColorPalette; } set { m_ColorPalette = value; } }
public Color32 GetColor(int index)
{
if (index < 0)
{
index = 0;
}
index = index % m_ColorPalette.Length;
return m_ColorPalette[index];
}
public void Copy(ThemeInfo theme)
{
m_Font = theme.m_Font;
m_BackgroundColor = theme.m_BackgroundColor;
m_ContrastColor = theme.m_ContrastColor;
m_UnableColor = theme.m_UnableColor;
m_TextColor = theme.m_TextColor;
m_SubTextColor = theme.m_SubTextColor;
m_LegendTextColor = theme.m_LegendTextColor;
m_AxisLineColor = theme.m_AxisLineColor;
m_AxisSplitLineColor = theme.m_AxisSplitLineColor;
m_TooltipBackgroundColor = theme.m_TooltipBackgroundColor;
m_TooltipTextColor = theme.m_TooltipTextColor;
m_ColorPalette = new Color32[theme.m_ColorPalette.Length];
for (int i = 0; i < theme.m_ColorPalette.Length; i++)
{
m_ColorPalette[i] = theme.m_ColorPalette[i];
}
}
public static ThemeInfo Default
{
get
{
return new ThemeInfo()
{
m_Font = Resources.GetBuiltinResource<Font>("Arial.ttf"),
m_BackgroundColor = new Color32(255, 255, 255, 255),
m_ContrastColor = GetColor("#514D4D"),
m_UnableColor = GetColor("#cccccc"),
m_TextColor = GetColor("#514D4D"),
m_SubTextColor = GetColor("#514D4D"),
m_LegendTextColor = GetColor("#eee"),
m_AxisLineColor = GetColor("#514D4D"),
m_AxisSplitLineColor = GetColor("#51515120"),
m_TooltipBackgroundColor = GetColor("#515151B5"),
m_TooltipTextColor = GetColor("#FFFFFFFF"),
m_TooltipFlagAreaColor = GetColor("#51515120"),
m_ColorPalette = new Color32[]
{
new Color32(194, 53, 49, 255),
new Color32(47, 69, 84, 255),
new Color32(97, 160, 168, 255),
new Color32(212, 130, 101, 255),
new Color32(145, 199, 174, 255),
new Color32(116, 159, 131, 255),
new Color32(202, 134, 34, 255),
new Color32(189, 162, 154, 255),
new Color32(110, 112, 116, 255),
new Color32(84, 101, 112, 255),
new Color32(196, 204, 211, 255)
}
};
}
}
public static ThemeInfo Light
{
get
{
return new ThemeInfo()
{
m_Font = Resources.GetBuiltinResource<Font>("Arial.ttf"),
m_BackgroundColor = new Color32(255, 255, 255, 255),
m_ContrastColor = GetColor("#514D4D"),
m_UnableColor = GetColor("#cccccc"),
m_TextColor = GetColor("#514D4D"),
m_SubTextColor = GetColor("#514D4D"),
m_LegendTextColor = GetColor("#514D4D"),
m_AxisLineColor = GetColor("#514D4D"),
m_AxisSplitLineColor = GetColor("#51515120"),
m_TooltipBackgroundColor = GetColor("#515151B5"),
m_TooltipTextColor = GetColor("#FFFFFFFF"),
m_TooltipFlagAreaColor = GetColor("#51515120"),
m_ColorPalette = new Color32[]
{
new Color32(55, 162, 218, 255),
new Color32(255, 159, 127, 255),
new Color32(50, 197, 233, 255),
new Color32(251, 114, 147, 255),
new Color32(103, 224, 227, 255),
new Color32(224, 98, 174, 255),
new Color32(159, 230, 184, 255),
new Color32(230, 144, 209, 255),
new Color32(255, 219, 92, 255),
new Color32(230, 188, 243, 255),
new Color32(157, 150, 245, 255),
new Color32(131, 120, 234, 255),
new Color32(150, 191, 255, 255)
}
};
}
}
public static ThemeInfo Dark
{
get
{
return new ThemeInfo()
{
m_Font = Resources.GetBuiltinResource<Font>("Arial.ttf"),
m_UnableColor = GetColor("#cccccc"),
m_BackgroundColor = new Color32(34, 34, 34, 255),
m_ContrastColor = GetColor("#eee"),
m_TextColor = GetColor("#eee"),
m_SubTextColor = GetColor("#eee"),
m_LegendTextColor = GetColor("#eee"),
m_AxisLineColor = GetColor("#eee"),
m_AxisSplitLineColor = GetColor("#aaa"),
m_TooltipBackgroundColor = GetColor("#515151B5"),
m_TooltipTextColor = GetColor("#FFFFFFFF"),
m_TooltipFlagAreaColor = GetColor("#51515120"),
m_ColorPalette = new Color32[]
{
new Color32(221, 107, 102, 255),
new Color32(117, 154, 160, 255),
new Color32(230, 157, 135, 255),
new Color32(141, 193, 169, 255),
new Color32(234, 126, 83, 255),
new Color32(238, 221, 120, 255),
new Color32(115, 163, 115, 255),
new Color32(115, 185, 188, 255),
new Color32(114, 137, 171, 255),
new Color32(145, 202, 140, 255),
new Color32(244, 159, 66, 255)
}
};
}
}
public static Color32 GetColor(string hexColorStr)
{
Color color;
ColorUtility.TryParseHtmlString(hexColorStr, out color);
return (Color32)color;
}
public override bool Equals(object obj)
{
if (!(obj is ThemeInfo))
return false;
return Equals((ThemeInfo)obj);
}
public bool Equals(ThemeInfo other)
{
return m_Font == other.m_Font &&
ChartHelper.IsValueEqualsColor(m_UnableColor, other.m_UnableColor) &&
ChartHelper.IsValueEqualsColor(m_BackgroundColor, other.m_BackgroundColor) &&
ChartHelper.IsValueEqualsColor(m_ContrastColor, other.m_ContrastColor) &&
ChartHelper.IsValueEqualsColor(m_TextColor, other.m_TextColor) &&
ChartHelper.IsValueEqualsColor(m_SubTextColor, other.m_SubTextColor) &&
ChartHelper.IsValueEqualsColor(m_AxisLineColor, other.m_AxisLineColor) &&
ChartHelper.IsValueEqualsColor(m_AxisSplitLineColor, other.m_AxisSplitLineColor) &&
ChartHelper.IsValueEqualsColor(m_TooltipBackgroundColor, other.m_TooltipBackgroundColor) &&
ChartHelper.IsValueEqualsColor(m_AxisSplitLineColor, other.m_AxisSplitLineColor) &&
ChartHelper.IsValueEqualsColor(m_TooltipTextColor, other.m_TooltipTextColor) &&
ChartHelper.IsValueEqualsColor(m_TooltipFlagAreaColor, other.m_TooltipFlagAreaColor) &&
m_ColorPalette.Length == other.m_ColorPalette.Length;
}
public static bool operator ==(ThemeInfo point1, ThemeInfo point2)
{
return point1.Equals(point2);
}
public static bool operator !=(ThemeInfo point1, ThemeInfo point2)
{
return !point1.Equals(point2);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 337565e835799d44bb794677abf84498
timeCreated: 1554221927
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,91 @@
using UnityEngine;
using System.Collections;
using System;
namespace XCharts
{
[Serializable]
public class Title: IPropertyChanged,IEquatable<Title>
{
[SerializeField] private bool m_Show;
[SerializeField] private string m_Text;
[SerializeField] private int m_TextFontSize;
[SerializeField] private string m_SubText;
[SerializeField] private int m_SubTextFontSize;
[SerializeField] private float m_ItemGap;
[SerializeField] private Location m_Location;
public bool show { get { return m_Show; } set { m_Show = value; } }
public string text { get { return m_Text; } set { m_Text = value; } }
public int textFontSize { get { return m_TextFontSize; }set { m_TextFontSize = value; } }
public string subText { get { return m_SubText; } set { m_Text = value; } }
public int subTextFontSize { get { return m_SubTextFontSize; } set { m_SubTextFontSize = value; } }
public float itemGap { get { return m_ItemGap; } set { m_ItemGap = value; } }
public Location location { get { return m_Location; } set { m_Location = value; } }
public static Title defaultTitle
{
get
{
var title = new Title
{
m_Show = true,
m_Text = "Chart Title",
m_TextFontSize = 16,
m_SubText = "",
m_SubTextFontSize = 14,
m_ItemGap = 14,
m_Location = Location.defaultTop
};
return title;
}
}
public void Copy(Title title)
{
m_Show = title.show;
m_Text = title.text;
m_TextFontSize = title.textFontSize;
m_SubText = title.subText;
m_SubTextFontSize = title.subTextFontSize;
m_ItemGap = title.itemGap;
m_Location.Copy(title.location);
}
public override bool Equals(object obj)
{
if (!(obj is Title)) return false;
return Equals((Title)obj);
}
public bool Equals(Title other)
{
return m_Show == other.show &&
m_Text.Equals(other.text) &&
m_TextFontSize == other.textFontSize &&
m_SubText.Equals(other.subText) &&
m_SubTextFontSize == other.subTextFontSize &&
m_ItemGap == other.itemGap &&
m_Location.Equals(other.location);
}
public static bool operator == (Title point1, Title point2)
{
return point1.Equals(point2);
}
public static bool operator != (Title point1, Title point2)
{
return !point1.Equals(point2);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public void OnChanged()
{
m_Location.OnChanged();
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 1e41a7f82b5a931408f301257fbc09e2
timeCreated: 1554222818
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,74 @@
using System;
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
[System.Serializable]
public class Tooltip
{
[SerializeField] private bool m_Show;
[NonSerialized] private GameObject m_GameObject;
[NonSerialized] private Text m_Text;
[NonSerialized] private RectTransform m_BackgroudRect;
public bool show { get { return m_Show; }set { m_Show = value; } }
public int dataIndex { get; set; }
public int lastDataIndex { get; set; }
public float width { get { return m_BackgroudRect.sizeDelta.x; } }
public float height { get { return m_BackgroudRect.sizeDelta.y; } }
public static Tooltip defaultTooltip
{
get
{
var tooltip = new Tooltip
{
m_Show = true
};
return tooltip;
}
}
public void SetObj(GameObject obj)
{
m_GameObject = obj;
m_BackgroudRect = m_GameObject.GetComponent<RectTransform>();
m_Text = m_GameObject.GetComponentInChildren<Text>();
}
public void SetBackgroundColor(Color color)
{
m_GameObject.GetComponent<Image>().color = color;
}
public void SetTextColor(Color color)
{
m_Text.color = color;
}
public void UpdateTooltipText(string txt)
{
m_Text.text = txt;
m_BackgroudRect.sizeDelta = new Vector2(m_Text.preferredWidth + 8, m_Text.preferredHeight + 8);
}
public void SetActive(bool flag)
{
if(m_GameObject)
m_GameObject.SetActive(flag);
}
public void UpdatePos(Vector2 pos)
{
if(m_GameObject)
m_GameObject.transform.localPosition = pos;
}
public Vector3 GetPos()
{
return m_GameObject.transform.localPosition;
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 015f1aafb9c2e8940be9ef79b984b843
timeCreated: 1554222818
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

116
Scripts/UI/LineChart.cs Normal file
View File

@@ -0,0 +1,116 @@
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
public class LineChart : CoordinateChart
{
[SerializeField] private Line m_Line = Line.defaultLine;
protected override void Awake()
{
base.Awake();
}
protected override void Update()
{
base.Update();
}
protected override void Reset()
{
base.Reset();
m_Line = Line.defaultLine;
}
protected override void DrawChart(VertexHelper vh)
{
base.DrawChart(vh);
int seriesCount = m_Series.Count;
float max = GetMaxValue();
float scaleWid = m_XAxis.GetDataWidth(coordinateWid);
for (int j = 0; j < seriesCount; j++)
{
if (!m_Legend.IsShowSeries(j)) continue;
Serie serie = m_Series.series[j];
Color32 color = m_ThemeInfo.GetColor(j);
Vector3 lp = Vector3.zero;
Vector3 np = Vector3.zero;
float startX = zeroX + (m_XAxis.boundaryGap ? scaleWid / 2 : 0);
int maxCount = maxShowDataNumber > 0 ?
(maxShowDataNumber > serie.data.Count ? serie.data.Count : maxShowDataNumber)
: serie.data.Count;
for (int i = minShowDataNumber; i < maxCount; i++)
{
float value = serie.data[i];
np = new Vector3(startX + i * scaleWid, zeroY + value * coordinateHig / max);
if (i > 0)
{
if (m_Line.smooth)
{
var list = ChartHelper.GetBezierList(lp, np, m_Line.smoothStyle);
Vector3 start, to;
start = list[0];
for (int k = 1; k < list.Length; k++)
{
to = list[k];
ChartHelper.DrawLine(vh, start, to, m_Line.tickness, color);
start = to;
}
}
else
{
ChartHelper.DrawLine(vh, lp, np, m_Line.tickness, color);
if (m_Line.area)
{
ChartHelper.DrawPolygon(vh, lp, np, new Vector3(np.x, zeroY),
new Vector3(lp.x, zeroY), color);
}
}
}
lp = np;
}
// draw point
if (m_Line.point)
{
for (int i = 0; i < serie.data.Count; i++)
{
float value = serie.data[i];
Vector3 p = new Vector3(startX + i * scaleWid,
zeroY + value * coordinateHig / max);
float pointWid = m_Line.pointWidth;
if (m_Tooltip.show && i == m_Tooltip.dataIndex - 1)
{
pointWid = pointWid * 1.8f;
}
if (m_Theme == Theme.Dark)
{
ChartHelper.DrawCricle(vh, p, pointWid, color,
(int)m_Line.pointWidth * 5);
}
else
{
ChartHelper.DrawCricle(vh, p, pointWid, Color.white);
ChartHelper.DrawDoughnut(vh, p, pointWid - m_Line.tickness,
pointWid, 0, 360, color);
}
}
}
}
//draw tooltip line
if (m_Tooltip.show && m_Tooltip.dataIndex > 0)
{
float splitWidth = m_XAxis.GetSplitWidth(coordinateWid);
float px = zeroX + (m_Tooltip.dataIndex - 1) * splitWidth + (m_XAxis.boundaryGap ? splitWidth / 2 : 0);
Vector2 sp = new Vector2(px, zeroY);
Vector2 ep = new Vector2(px, zeroY + coordinateHig);
ChartHelper.DrawLine(vh, sp, ep, m_Coordinate.tickness, m_ThemeInfo.tooltipFlagAreaColor);
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: b4f38bd00b4648c448cabfc167538f7c
timeCreated: 1536101435
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

202
Scripts/UI/PieChart.cs Normal file
View File

@@ -0,0 +1,202 @@
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
public class PieChart : BaseChart
{
[SerializeField] private Pie m_Pie = Pie.defaultPie;
private float m_PieCenterX = 0f;
private float m_PieCenterY = 0f;
private float m_PieRadius = 0;
private Vector2 m_PieCenter;
private List<float> m_AngleList = new List<float>();
protected override void Awake()
{
base.Awake();
}
protected override void Update()
{
base.Update();
}
protected override void DrawChart(VertexHelper vh)
{
base.DrawChart(vh);
UpdatePieCenter();
float totalDegree = 360;
float startDegree = 0;
float dataTotal = GetDataTotal();
float dataMax = GetDataMax();
m_AngleList.Clear();
for (int i = 0; i < m_Series.Count; i++)
{
if (!m_Legend.IsShowSeries(i))
{
m_AngleList.Add(0);
continue;
}
float value = m_Series.series[i].data[0];
float degree = totalDegree * value / dataTotal;
float toDegree = startDegree + degree;
float outSideRadius = m_Pie.rose ?
m_Pie.insideRadius + (m_PieRadius - m_Pie.insideRadius) * value / dataMax :
m_PieRadius;
if (m_Tooltip.show && m_Tooltip.dataIndex == i + 1)
{
outSideRadius += m_Pie.tooltipExtraRadius;
}
ChartHelper.DrawDoughnut(vh, m_PieCenter, m_Pie.insideRadius,
outSideRadius, startDegree, toDegree, m_ThemeInfo.GetColor(i));
m_AngleList.Add(toDegree);
startDegree = toDegree;
}
}
protected override void OnLegendButtonClicked()
{
base.OnLegendButtonClicked();
}
private float GetDataTotal()
{
float total = 0;
for (int i = 0; i < m_Series.Count; i++)
{
if (m_Legend.IsShowSeries(i))
{
total += m_Series.series[i].GetData(0);
}
}
return total;
}
private float GetDataMax()
{
float max = 0;
for (int i = 0; i < m_Series.Count; i++)
{
if (m_Legend.IsShowSeries(i) && m_Series.series[i].GetData(0) > max)
{
max = m_Series.series[i].GetData(0);
}
}
return max;
}
private void UpdatePieCenter()
{
float diffX = chartWidth - m_Pie.left - m_Pie.right;
float diffY = chartHeight - m_Pie.top - m_Pie.bottom;
float diff = Mathf.Min(diffX, diffY);
if (m_Pie.outsideRadius <= 0)
{
m_PieRadius = diff / 3 * 2;
m_PieCenterX = m_Pie.left + m_PieRadius;
m_PieCenterY = m_Pie.bottom + m_PieRadius;
}
else
{
m_PieRadius = m_Pie.outsideRadius;
m_PieCenterX = chartWidth / 2;
m_PieCenterY = chartHeight / 2;
if (m_Pie.left > 0) m_PieCenterX = m_Pie.left + m_PieRadius;
if (m_Pie.right > 0) m_PieCenterX = chartWidth - m_Pie.right - m_PieRadius;
if (m_Pie.top > 0) m_PieCenterY = chartHeight - m_Pie.top - m_PieRadius;
if (m_Pie.bottom > 0) m_PieCenterY = m_Pie.bottom + m_PieRadius;
}
m_PieCenter = new Vector2(m_PieCenterX, m_PieCenterY);
}
protected override void CheckTootipArea(Vector2 local)
{
float dist = Vector2.Distance(local, m_PieCenter);
if (dist > m_PieRadius)
{
m_Tooltip.dataIndex = 0;
m_Tooltip.SetActive(false);
}
else
{
Vector2 dir = local - m_PieCenter;
float angle = VectorAngle(Vector2.up, dir);
m_Tooltip.dataIndex = 0;
for (int i = m_AngleList.Count - 1; i >= 0; i--)
{
if (i == 0 && angle < m_AngleList[i])
{
m_Tooltip.dataIndex = 1;
break;
}
else if (angle < m_AngleList[i] && angle > m_AngleList[i - 1])
{
m_Tooltip.dataIndex = i + 1;
break;
}
}
}
if (m_Tooltip.dataIndex > 0)
{
m_Tooltip.UpdatePos(new Vector2(local.x + 18, local.y - 25));
RefreshTooltip();
if (m_Tooltip.lastDataIndex != m_Tooltip.dataIndex)
{
RefreshChart();
}
m_Tooltip.lastDataIndex = m_Tooltip.dataIndex;
}
}
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;
}
protected override void RefreshTooltip()
{
base.RefreshTooltip();
int index = m_Tooltip.dataIndex - 1;
if (index < 0)
{
m_Tooltip.SetActive(false);
return;
}
m_Tooltip.SetActive(true);
string strColor = ColorUtility.ToHtmlStringRGBA(m_ThemeInfo.GetColor(index));
string key = m_Legend.data[index];
float value = m_Series.series[index].data[0];
string txt = "";
if (!string.IsNullOrEmpty(m_Pie.name))
{
txt += m_Pie.name + "\n";
}
txt += string.Format("<color=#{0}>● </color>{1}: {2}", strColor, key, value);
m_Tooltip.UpdateTooltipText(txt);
var pos = m_Tooltip.GetPos();
if (pos.x + m_Tooltip.width > chartWidth)
{
pos.x = chartWidth - m_Tooltip.width;
}
if (pos.y - m_Tooltip.height < 0)
{
pos.y = m_Tooltip.height;
}
m_Tooltip.UpdatePos(pos);
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: d44276ba809fd92408b296835f6f7658
timeCreated: 1537541828
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

347
Scripts/UI/RadarChart.cs Normal file
View File

@@ -0,0 +1,347 @@
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
public class RadarChart : BaseChart
{
private const string INDICATOR_TEXT = "indicator";
[SerializeField]
private Radar m_Radar = Radar.defaultRadar;
private Radar m_CheckRadar = Radar.defaultRadar;
private float m_RadarCenterX = 0f;
private float m_RadarCenterY = 0f;
private float m_RadarRadius = 0;
private List<Text> indicatorTextList = new List<Text>();
private List<List<Vector3>> dataPosList = new List<List<Vector3>>();
protected override void Awake()
{
base.Awake();
UpdateRadarCenter();
}
protected override void Update()
{
base.Update();
CheckRadarInfoChanged();
}
private void InitIndicator()
{
indicatorTextList.Clear();
ChartHelper.HideAllObject(transform, INDICATOR_TEXT);
int indicatorNum = m_Radar.indicatorList.Count;
float txtWid = 100;
float txtHig = 20;
for (int i = 0; i < indicatorNum; i++)
{
var pos = GetIndicatorPosition(i);
TextAnchor anchor = TextAnchor.MiddleCenter;
var diff = pos.x - m_RadarCenterX;
if (diff < -1f)
{
pos = new Vector3(pos.x - 5, pos.y);
anchor = TextAnchor.MiddleRight;
}
else if (diff > 1f)
{
anchor = TextAnchor.MiddleLeft;
pos = new Vector3(pos.x + txtWid + 5, pos.y);
}
else
{
anchor = TextAnchor.MiddleCenter;
float y = pos.y > m_RadarCenterY ? pos.y + txtHig / 2 : pos.y - txtHig / 2;
pos = new Vector3(pos.x + txtWid / 2, y);
}
Text txt = ChartHelper.AddTextObject(INDICATOR_TEXT + i, transform, m_ThemeInfo.font,
m_ThemeInfo.textColor, anchor, Vector2.zero, Vector2.zero, new Vector2(1, 0.5f),
new Vector2(txtWid, txtHig));
txt.transform.localPosition = pos;
txt.text = m_Radar.indicatorList[i].name;
txt.gameObject.SetActive(m_Radar.indicator);
indicatorTextList.Add(txt);
}
}
private void CheckRadarInfoChanged()
{
if (!m_CheckRadar.Equals(m_Radar))
{
m_CheckRadar.Copy(m_Radar);
OnRadarChanged();
}
}
private void OnRadarChanged()
{
UpdateRadarCenter();
InitIndicator();
}
private Vector3 GetIndicatorPosition(int i)
{
int indicatorNum = m_Radar.indicatorList.Count;
var angle = 2 * Mathf.PI / indicatorNum * i;
var x = m_RadarCenterX + m_Radar.radius * Mathf.Sin(angle);
var y = m_RadarCenterY + m_Radar.radius * Mathf.Cos(angle);
return new Vector3(x, y);
}
protected override void DrawChart(VertexHelper vh)
{
base.DrawChart(vh);
UpdateRadarCenter();
if (m_Radar.cricle)
DrawCricleRadar(vh);
else
DrawRadar(vh);
DrawData(vh);
}
protected override void OnLegendButtonClicked()
{
base.OnLegendButtonClicked();
}
protected override void OnThemeChanged()
{
base.OnThemeChanged();
m_Radar.backgroundColorList.Clear();
switch (m_Theme)
{
case Theme.Dark:
m_Radar.backgroundColorList.Add(ThemeInfo.GetColor("#6f6f6f"));
m_Radar.backgroundColorList.Add(ThemeInfo.GetColor("#606060"));
break;
case Theme.Default:
m_Radar.backgroundColorList.Add(ThemeInfo.GetColor("#f6f6f6"));
m_Radar.backgroundColorList.Add(ThemeInfo.GetColor("#e7e7e7"));
break;
case Theme.Light:
m_Radar.backgroundColorList.Add(ThemeInfo.GetColor("#f6f6f6"));
m_Radar.backgroundColorList.Add(ThemeInfo.GetColor("#e7e7e7"));
break;
}
InitIndicator();
}
private void DrawData(VertexHelper vh)
{
int indicatorNum = m_Radar.indicatorList.Count;
var angle = 2 * Mathf.PI / indicatorNum;
var p = new Vector3(m_RadarCenterX, m_RadarCenterY);
Vector3 startPoint = Vector3.zero;
Vector3 toPoint = Vector3.zero;
Vector3 firstPoint = Vector3.zero;
dataPosList.Clear();
dataPosList.Capacity = m_Series.Count;
for (int i = 0; i < m_Series.Count; i++)
{
if (!m_Legend.IsShowSeries(i))
{
dataPosList.Add(new List<Vector3>());
continue;
}
var dataList = m_Series.series[i].data;
var color = m_ThemeInfo.GetColor(i);
var areaColor = new Color(color.r, color.g, color.b, color.a * 0.7f);
List<Vector3> pointList = new List<Vector3>(dataList.Count);
dataPosList.Add(pointList);
for (int j = 0; j < dataList.Count; j++)
{
var max = m_Radar.indicatorList[j].max > 0 ?
m_Radar.indicatorList[j].max :
GetMaxValue(j);
var radius = max<0? m_Radar.radius - m_Radar.radius * dataList[j] / max : m_Radar.radius * dataList[j] / max ;
var currAngle = j * angle;
if (j == 0)
{
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 (m_Radar.area)
{
ChartHelper.DrawTriangle(vh, p, startPoint, toPoint, areaColor);
}
ChartHelper.DrawLine(vh, startPoint, toPoint, m_Radar.lineTickness, color);
startPoint = toPoint;
}
pointList.Add(startPoint);
}
if (m_Radar.area) ChartHelper.DrawTriangle(vh, p, startPoint, firstPoint, areaColor);
ChartHelper.DrawLine(vh, startPoint, firstPoint, m_Radar.lineTickness, color);
foreach (var point in pointList)
{
float radius = m_Radar.linePointSize - m_Radar.lineTickness * 2;
ChartHelper.DrawCricle(vh, point, radius, Color.white);
ChartHelper.DrawDoughnut(vh, point, radius, m_Radar.linePointSize, 0, 360, color);
}
}
}
private void DrawRadar(VertexHelper vh)
{
float insideRadius = 0, outsideRadius = 0;
float block = m_Radar.radius / m_Radar.splitNumber;
int indicatorNum = m_Radar.indicatorList.Count;
Vector3 p1, p2, p3, p4;
Vector3 p = new Vector3(m_RadarCenterX, m_RadarCenterY);
float angle = 2 * Mathf.PI / indicatorNum;
for (int i = 0; i < m_Radar.splitNumber; i++)
{
Color color = m_Radar.backgroundColorList[i % m_Radar.backgroundColorList.Count];
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));
ChartHelper.DrawPolygon(vh, p1, p2, p3, p4, color);
ChartHelper.DrawLine(vh, p2, p3, m_Radar.lineTickness, m_Radar.lineColor);
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));
ChartHelper.DrawLine(vh, p, p3, m_Radar.lineTickness / 2, m_Radar.lineColor);
}
}
private void DrawCricleRadar(VertexHelper vh)
{
float insideRadius = 0, outsideRadius = 0;
float block = m_Radar.radius / m_Radar.splitNumber;
int indicatorNum = m_Radar.indicatorList.Count;
Vector3 p = new Vector3(m_RadarCenterX, m_RadarCenterY);
Vector3 p1;
float angle = 2 * Mathf.PI / indicatorNum;
for (int i = 0; i < m_Radar.splitNumber; i++)
{
Color color = m_Radar.backgroundColorList[i % m_Radar.backgroundColorList.Count];
outsideRadius = insideRadius + block;
ChartHelper.DrawDoughnut(vh, p, insideRadius, outsideRadius, 0, 360, color);
ChartHelper.DrawCicleNotFill(vh, p, outsideRadius, m_Radar.lineTickness,
m_Radar.lineColor);
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));
ChartHelper.DrawLine(vh, p, p1, m_Radar.lineTickness / 2, m_Radar.lineColor);
}
}
private void UpdateRadarCenter()
{
float diffX = chartWidth - m_Radar.left - m_Radar.right;
float diffY = chartHeight - m_Radar.top - m_Radar.bottom;
float diff = Mathf.Min(diffX, diffY);
if (m_Radar.radius <= 0)
{
m_RadarRadius = diff / 3 * 2;
m_RadarCenterX = m_Radar.left + m_RadarRadius;
m_RadarCenterY = m_Radar.bottom + m_RadarRadius;
}
else
{
m_RadarRadius = m_Radar.radius;
m_RadarCenterX = chartWidth / 2;
m_RadarCenterY = chartHeight / 2;
if (m_Radar.left > 0) m_RadarCenterX = m_Radar.left + m_RadarRadius;
if (m_Radar.right > 0) m_RadarCenterX = chartWidth - m_Radar.right - m_RadarRadius;
if (m_Radar.top > 0) m_RadarCenterY = chartHeight - m_Radar.top - m_RadarRadius;
if (m_Radar.bottom > 0) m_RadarCenterY = m_Radar.bottom + m_RadarRadius;
}
}
protected override void CheckTootipArea(Vector2 local)
{
if (dataPosList.Count <= 0) return;
m_Tooltip.dataIndex = 0;
for (int i = 0; i < m_Series.Count; i++)
{
if (!m_Legend.IsShowSeries(i)) continue;
for (int j = 0; j < dataPosList[i].Count; j++)
{
if (Vector3.Distance(local, dataPosList[i][j]) <= m_Radar.linePointSize * 1.2f)
{
m_Tooltip.dataIndex = i + 1;
break;
}
}
}
if (m_Tooltip.dataIndex > 0)
{
m_Tooltip.UpdatePos(new Vector2(local.x + 18, local.y - 25));
RefreshTooltip();
if (m_Tooltip.lastDataIndex != m_Tooltip.dataIndex)
{
RefreshChart();
}
m_Tooltip.lastDataIndex = m_Tooltip.dataIndex;
}
else
{
m_Tooltip.SetActive(false);
}
}
protected override void RefreshTooltip()
{
base.RefreshTooltip();
int index = m_Tooltip.dataIndex - 1;
if (index < 0)
{
m_Tooltip.SetActive(false);
return;
}
m_Tooltip.SetActive(true);
StringBuilder sb = new StringBuilder(m_Legend.data[index]);
for (int i = 0; i < m_Radar.indicatorList.Count; i++)
{
string key = m_Radar.indicatorList[i].name;
float value = m_Series.series[index].data[i];
sb.Append("\n");
sb.AppendFormat("{0}: {1}", key, value);
}
m_Tooltip.UpdateTooltipText(sb.ToString());
var pos = m_Tooltip.GetPos();
if (pos.x + m_Tooltip.width > chartWidth)
{
pos.x = chartWidth - m_Tooltip.width;
}
if (pos.y - m_Tooltip.height < 0)
{
pos.y = m_Tooltip.height;
}
m_Tooltip.UpdatePos(pos);
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: d2231a0d3e3a5b043b074f6739be4a86
timeCreated: 1537742341
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

10
Scripts/UI/Utility.meta Normal file
View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: e3f97e494bd29fb43a2e17e14bd12b28
folderAsset: yes
timeCreated: 1554221615
licenseType: Free
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,440 @@
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
public static class ChartHelper
{
private static float CRICLE_SMOOTHNESS = 1f;
private static UIVertex[] vertex = new UIVertex[4];
public static void HideAllObject(GameObject obj, string match)
{
HideAllObject(obj.transform, match);
}
public static void HideAllObject(Transform parent, string match)
{
for (int i = 0; i < parent.childCount; i++)
{
if (match == null)
parent.GetChild(i).gameObject.SetActive(false);
else
{
var go = parent.GetChild(i);
if (go.name.StartsWith(match))
{
go.gameObject.SetActive(false);
}
}
}
}
public static void DestoryAllChilds(Transform parent)
{
while (parent.childCount > 0)
{
var go = parent.GetChild(0);
if (go.childCount > 0) DestoryAllChilds(go);
else GameObject.DestroyImmediate(go.gameObject);
}
}
public static T GetOrAddComponent<T>(Transform transform) where T : Component
{
return GetOrAddComponent<T>(transform.gameObject);
}
public static T GetOrAddComponent<T>(GameObject gameObject) where T : Component
{
if (gameObject.GetComponent<T>() == null)
{
gameObject.AddComponent<T>();
}
return gameObject.GetComponent<T>();
}
public static GameObject AddObject(string name, Transform parent, Vector2 anchorMin,
Vector2 anchorMax, Vector2 pivot, Vector2 sizeDelta)
{
GameObject obj;
if (parent.Find(name))
{
obj = parent.Find(name).gameObject;
obj.SetActive(true);
obj.transform.localPosition = Vector3.zero;
}
else
{
obj = new GameObject();
obj.name = name;
obj.transform.parent = parent;
obj.transform.localScale = Vector3.one;
obj.transform.localPosition = Vector3.zero;
}
RectTransform rect = GetOrAddComponent<RectTransform>(obj);
rect.localPosition = Vector3.zero;
rect.sizeDelta = sizeDelta;
rect.anchorMin = anchorMin;
rect.anchorMax = anchorMax;
rect.pivot = pivot;
return obj;
}
public static Text AddTextObject(string name, Transform parent, Font font, Color color,
TextAnchor anchor, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot, Vector2 sizeDelta,
int fontSize = 14,float textRotation = 0)
{
GameObject txtObj = AddObject(name, parent, anchorMin, anchorMax, pivot, sizeDelta);
Text txt = GetOrAddComponent<Text>(txtObj);
txt.font = font;
txt.fontSize = fontSize;
txt.text = "Text";
txt.alignment = anchor;
txt.horizontalOverflow = HorizontalWrapMode.Overflow;
txt.verticalOverflow = VerticalWrapMode.Overflow;
txt.color = color;
if (textRotation > 0)
{
txtObj.transform.localEulerAngles = new Vector3(0,0,textRotation);
}
RectTransform rect = GetOrAddComponent<RectTransform>(txtObj);
rect.localPosition = Vector3.zero;
rect.sizeDelta = sizeDelta;
rect.anchorMin = anchorMin;
rect.anchorMax = anchorMax;
rect.pivot = pivot;
return txtObj.GetComponent<Text>();
}
public static Button AddButtonObject(string name, Transform parent, Font font, int fontSize,
Color color, TextAnchor anchor, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot,
Vector2 sizeDelta)
{
GameObject btnObj = AddObject(name, parent, anchorMin, anchorMax, pivot, sizeDelta);
GetOrAddComponent<Image>(btnObj);
GetOrAddComponent<Button>(btnObj);
Text txt = AddTextObject("Text", btnObj.transform, font, color, TextAnchor.MiddleCenter,
new Vector2(0, 0), new Vector2(1, 1), new Vector2(0.5f, 0.5f),
sizeDelta, fontSize);
txt.rectTransform.offsetMin = Vector2.zero;
txt.rectTransform.offsetMax = Vector2.zero;
return btnObj.GetComponent<Button>();
}
public static GameObject AddTooltipObject(string name, Transform parent, Font font)
{
var anchorMax = new Vector2(0, 1);
var anchorMin = new Vector2(0, 1);
var pivot = new Vector2(0, 1);
var sizeDelta = new Vector2(100, 100);
GameObject tooltipObj = AddObject(name, parent, anchorMin, anchorMax, pivot, sizeDelta);
var img = GetOrAddComponent<Image>(tooltipObj);
img.color = Color.black;
Text txt = AddTextObject("Text", tooltipObj.transform, font, Color.white, TextAnchor.UpperLeft,
anchorMin, anchorMax, pivot, sizeDelta);
txt.text = "Text";
txt.transform.localPosition = new Vector2(3, -3);
return tooltipObj;
}
public static void DrawLine(VertexHelper vh, Vector3 p1, Vector3 p2, float size, Color32 color)
{
Vector3 v = Vector3.Cross(p2 - p1, Vector3.forward).normalized * size;
vertex[0].position = p1 + v;
vertex[1].position = p2 + v;
vertex[2].position = p2 - v;
vertex[3].position = p1 - v;
for (int j = 0; j < 4; j++)
{
vertex[j].color = color;
vertex[j].uv0 = Vector2.zero;
}
vh.AddUIVertexQuad(vertex);
}
public static void DrawPolygon(VertexHelper vh, Vector3 p, float size, Color32 color)
{
Vector3 p1 = new Vector3(p.x - size, p.y - size);
Vector3 p2 = new Vector3(p.x + size, p.y - size);
Vector3 p3 = new Vector3(p.x + size, p.y + size);
Vector3 p4 = new Vector3(p.x - size, p.y + size);
DrawPolygon(vh, p1, p2, p3, p4, color, color);
}
public static void DrawPolygon(VertexHelper vh, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4,
Color32 color)
{
DrawPolygon(vh, p1, p2, p3, p4, color, color);
}
public static void DrawPolygon(VertexHelper vh, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4,
Color32 startColor, Color32 toColor)
{
vertex[0].position = p1;
vertex[1].position = p2;
vertex[2].position = p3;
vertex[3].position = p4;
for (int j = 0; j < 4; j++)
{
vertex[j].color = j >= 2 ? toColor : startColor;
vertex[j].uv0 = Vector2.zero;
}
vh.AddUIVertexQuad(vertex);
}
public static void DrawTriangle(VertexHelper vh, Vector3 p1,
Vector3 p2, Vector3 p3, Color32 color)
{
UIVertex v1 = new UIVertex();
v1.position = p1;
v1.color = color;
v1.uv0 = Vector3.zero;
UIVertex v2 = new UIVertex();
v2.position = p2;
v2.color = color;
v2.uv0 = Vector3.zero;
UIVertex v3 = new UIVertex();
v3.position = p3;
v3.color = color;
v3.uv0 = Vector3.zero;
int startIndex = vh.currentVertCount;
vh.AddVert(v1);
vh.AddVert(v2);
vh.AddVert(v3);
vh.AddTriangle(startIndex, startIndex + 1, startIndex + 2);
}
public static void DrawCricle(VertexHelper vh, Vector3 p, float radius, Color32 color,
int segments = 0, bool fill = true)
{
if (segments <= 0)
{
segments = (int)((2 * Mathf.PI * radius) / CRICLE_SMOOTHNESS);
}
DrawSector(vh, p, radius, color, 0, 360, segments);
}
public static void DrawCicleNotFill(VertexHelper vh, Vector3 p, float radius, float tickness,
Color32 color, int segments = 0)
{
if (segments <= 0)
{
segments = (int)((2 * Mathf.PI * radius) / CRICLE_SMOOTHNESS);
}
float startDegree = 0, toDegree = 360;
Vector3 p2, p3;
float startAngle = startDegree * Mathf.Deg2Rad;
float angle = (toDegree - startDegree) * Mathf.Deg2Rad / segments;
p2 = new Vector3(p.x + radius * Mathf.Sin(startAngle), p.y + radius * Mathf.Cos(startAngle));
for (int i = 0; i <= segments; i++)
{
float currAngle = startAngle + i * angle;
p3 = new Vector3(p.x + radius * Mathf.Sin(currAngle), p.y + radius * Mathf.Cos(currAngle));
DrawLine(vh, p2, p3, tickness, color);
p2 = p3;
}
}
public static void DrawSector(VertexHelper vh, Vector3 p, float radius, Color32 color,
float startDegree, float toDegree, int segments = 0)
{
if (segments <= 0)
{
segments = (int)((2 * Mathf.PI * radius) / CRICLE_SMOOTHNESS);
}
Vector3 p2, p3;
float startAngle = startDegree * Mathf.Deg2Rad;
float angle = (toDegree - startDegree) * Mathf.Deg2Rad / segments;
p2 = new Vector3(p.x + radius * Mathf.Sin(startAngle), p.y + radius * Mathf.Cos(startAngle));
for (int i = 0; i <= segments; i++)
{
float currAngle = startAngle + i * angle;
p3 = new Vector3(p.x + radius * Mathf.Sin(currAngle),
p.y + radius * Mathf.Cos(currAngle));
DrawTriangle(vh, p, p2, p3, color);
p2 = p3;
}
}
public static void DrawDoughnut(VertexHelper vh, Vector3 p, float insideRadius, float outsideRadius,
float startDegree, float toDegree, Color32 color, int segments = 0)
{
if (insideRadius <= 0)
{
DrawSector(vh, p, outsideRadius, color, startDegree, toDegree, segments);
return;
}
if (segments <= 0)
{
segments = (int)((2 * Mathf.PI * outsideRadius) / CRICLE_SMOOTHNESS);
}
Vector3 p1, p2, p3, p4;
float startAngle = startDegree * Mathf.Deg2Rad;
float angle = (toDegree - startDegree) * Mathf.Deg2Rad / segments;
p1 = new Vector3(p.x + insideRadius * Mathf.Sin(startAngle),
p.y + insideRadius * Mathf.Cos(startAngle));
p2 = new Vector3(p.x + outsideRadius * Mathf.Sin(startAngle),
p.y + outsideRadius * Mathf.Cos(startAngle));
for (int i = 0; i <= segments; i++)
{
float currAngle = startAngle + i * 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));
DrawPolygon(vh, p1, p2, p3, p4, color);
p1 = p4;
p2 = p3;
}
}
public static Vector3[] GetBezierList(Vector3 sp, Vector3 ep, float k = 2.0f)
{
Vector3 dir = (ep - sp).normalized;
float dist = Vector3.Distance(sp, ep);
Vector3 cp1 = sp + dist / k * dir * 1;
Vector3 cp2 = sp + dist / k * dir * (k - 1);
cp1.y = sp.y;
cp2.y = ep.y;
int segment = (int)(dist / 0.3f);
return GetBezierList2(sp, ep, segment, cp1, cp2);
}
public static List<Vector3> GetBezierList(Vector3 sp, Vector3 ep, int segment, Vector3 cp)
{
List<Vector3> list = new List<Vector3>();
for (int i = 0; i < segment; i++)
{
list.Add(GetBezier(i / (float)segment, sp, cp, ep));
}
list.Add(ep);
return list;
}
public static Vector3[] GetBezierList2(Vector3 sp, Vector3 ep, int segment, Vector3 cp,
Vector3 cp2)
{
Vector3[] list = new Vector3[segment + 1];
for (int i = 0; i < segment; i++)
{
list[i] = (GetBezier2(i / (float)segment, sp, cp, cp2, ep));
}
list[segment] = ep;
return list;
}
public static Vector3 GetBezier(float t, Vector3 sp, Vector3 cp, Vector3 ep)
{
Vector3 aa = sp + (cp - sp) * t;
Vector3 bb = cp + (ep - cp) * t;
return aa + (bb - aa) * t;
}
public static Vector3 GetBezier2(float t, Vector3 sp, Vector3 p1, Vector3 p2, Vector3 ep)
{
t = Mathf.Clamp01(t);
var oneMinusT = 1f - t;
return oneMinusT * oneMinusT * oneMinusT * sp +
3f * oneMinusT * oneMinusT * t * p1 +
3f * oneMinusT * t * t * p2 +
t * t * t * ep;
}
public static List<Vector3> GetBezierN(List<Vector3> arrayToCurve, float smoothness = 1.0f)
{
List<Vector3> points;
List<Vector3> curvedPoints;
int pointsLength = 0;
int curvedLength = 0;
if (smoothness < 1.0f) smoothness = 1.0f;
pointsLength = arrayToCurve.Count;
curvedLength = (pointsLength * Mathf.RoundToInt(smoothness)) - 1;
curvedPoints = new List<Vector3>(curvedLength);
float t = 0.0f;
for (int pointInTimeOnCurve = 0; pointInTimeOnCurve < curvedLength + 1; pointInTimeOnCurve++)
{
t = Mathf.InverseLerp(0, curvedLength, pointInTimeOnCurve);
points = new List<Vector3>(arrayToCurve);
for (int j = pointsLength - 1; j > 0; j--)
{
for (int i = 0; i < j; i++)
{
points[i] = (1 - t) * points[i] + t * points[i + 1];
}
}
curvedPoints.Add(points[0]);
}
return curvedPoints;
}
public static bool IsValueEqualsColor(Color32 color1, Color32 color2)
{
return color1.a == color2.a &&
color1.b == color2.b &&
color1.g == color2.g &&
color1.r == color2.r;
}
public static bool IsValueEqualsList<T>(List<T> list1, List<T> list2)
{
if (list1 == null || list2 == null) return false;
if (list1.Count != list2.Count) return false;
for (int i = 0; i < list1.Count; i++)
{
if (!list1[i].Equals(list2[i])) return false;
}
return true;
}
public static List<float> ParseFloatFromString(string jsonData)
{
List<float> list = new List<float>();
if (string.IsNullOrEmpty(jsonData)) return list;
int startIndex = jsonData.IndexOf("[");
int endIndex = jsonData.IndexOf("]");
string temp = jsonData.Substring(startIndex + 1, endIndex - startIndex - 1);
string[] datas = temp.Split(',');
for (int i = 0; i < datas.Length; i++)
{
list.Add(float.Parse(datas[i].Trim()));
}
return list;
}
public static List<string> ParseStringFromString(string jsonData)
{
List<string> list = new List<string>();
if (string.IsNullOrEmpty(jsonData)) return list;
string pattern = "[\"'](.*?)[\"']";
if (Regex.IsMatch(jsonData, pattern))
{
MatchCollection m = Regex.Matches(jsonData, pattern);
foreach(Match match in m)
{
list.Add(match.Groups[1].Value);
}
}
return list;
}
public static Color32 GetColor(string hexColorStr)
{
Color color;
ColorUtility.TryParseHtmlString(hexColorStr, out color);
return (Color32)color;
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 049a2733eed58154eb8336d4e17312ad
timeCreated: 1536792022
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: