작업 조건 분석 기능 개발
This commit is contained in:
202
Assets/Chart And Graph/Script/RadarChart/CanvasRadarChart.cs
Normal file
202
Assets/Chart And Graph/Script/RadarChart/CanvasRadarChart.cs
Normal file
@@ -0,0 +1,202 @@
|
||||
#define Graph_And_Chart_PRO
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ChartAndGraph
|
||||
{
|
||||
public class CanvasRadarChart : RadarChart
|
||||
{
|
||||
protected RadarFill CreateFillObject(GameObject conatiner)
|
||||
{
|
||||
GameObject obj = ChartCommon.CreateCanvasChartItem();
|
||||
ChartCommon.HideObject(obj, hideHierarchy);
|
||||
obj.AddComponent<ChartItem>();
|
||||
var rend = obj.AddComponent<CanvasRenderer>();
|
||||
rend.cullTransparentMesh = false;
|
||||
RadarFill fill = obj.AddComponent<RadarFill>();
|
||||
obj.transform.SetParent(conatiner.transform, false);
|
||||
obj.transform.localScale = new Vector3(1f, 1f, 1f);
|
||||
obj.transform.localPosition = Vector3.zero;
|
||||
obj.transform.localRotation = Quaternion.identity;
|
||||
return fill;
|
||||
}
|
||||
|
||||
protected CanvasLines CreateLinesObject(GameObject conatiner)
|
||||
{
|
||||
GameObject obj = ChartCommon.CreateCanvasChartItem();
|
||||
ChartCommon.HideObject(obj, hideHierarchy);
|
||||
obj.AddComponent<ChartItem>();
|
||||
var rend = obj.AddComponent<CanvasRenderer>();
|
||||
rend.cullTransparentMesh = false;
|
||||
CanvasLines lines = obj.AddComponent<CanvasLines>();
|
||||
obj.transform.SetParent(conatiner.transform,false);
|
||||
obj.transform.localScale = new Vector3(1f, 1f, 1f);
|
||||
obj.transform.localPosition = Vector3.zero;
|
||||
obj.transform.localRotation = Quaternion.identity;
|
||||
return lines;
|
||||
}
|
||||
|
||||
protected override GameObject CreateAxisObject(float thickness, Vector3[] path)
|
||||
{
|
||||
Vector3[] newPath = new Vector3[path.Length + 1];
|
||||
path.CopyTo(newPath, 0);
|
||||
newPath[path.Length] = path[0];
|
||||
path = newPath;
|
||||
List<CanvasLines.LineSegement> seg = new List<CanvasLines.LineSegement>();
|
||||
seg.Add(new CanvasLines.LineSegement(path));
|
||||
GameObject conatiner = ChartCommon.CreateChartItem();
|
||||
ChartCommon.HideObject(conatiner, hideHierarchy);
|
||||
conatiner.transform.SetParent(transform,false);
|
||||
conatiner.transform.localScale = new Vector3(1f, 1f, 1f);
|
||||
conatiner.transform.localPosition = Vector3.zero;
|
||||
conatiner.transform.localRotation = Quaternion.identity;
|
||||
|
||||
if (AxisLineMaterial != null && AxisThickness > 0f)
|
||||
{
|
||||
CanvasLines lines = CreateLinesObject(conatiner);
|
||||
lines.material = AxisLineMaterial;
|
||||
lines.Thickness = thickness;
|
||||
lines.SetLines(seg);
|
||||
}
|
||||
|
||||
if (AxisPointMaterial != null && AxisPointSize > 0f)
|
||||
{
|
||||
CanvasLines points = CreateLinesObject(conatiner);
|
||||
points.material = AxisPointMaterial;
|
||||
points.MakePointRender(AxisPointSize);
|
||||
points.SetLines(seg);
|
||||
}
|
||||
|
||||
return conatiner;
|
||||
}
|
||||
|
||||
public override void InternalGenerateChart()
|
||||
{
|
||||
base.InternalGenerateChart();
|
||||
if (TextController != null && TextController.gameObject)
|
||||
TextController.gameObject.transform.SetAsLastSibling();
|
||||
}
|
||||
|
||||
protected override GameObject CreateCategoryObject(Vector3[] path, int category)
|
||||
{
|
||||
Vector3[] newPath = new Vector3[path.Length + 1];
|
||||
path.CopyTo(newPath, 0);
|
||||
newPath[path.Length] = path[0];
|
||||
path = newPath;
|
||||
List<CanvasLines.LineSegement> seg = new List<CanvasLines.LineSegement>();
|
||||
seg.Add(new CanvasLines.LineSegement(path));
|
||||
RadarChartData.CategoryData cat = ((IInternalRadarData)DataSource).getCategoryData(category);
|
||||
GameObject container = ChartCommon.CreateChartItem();
|
||||
ChartCommon.HideObject(container, hideHierarchy);
|
||||
container.transform.SetParent(transform, false);
|
||||
container.transform.localScale = new Vector3(1f, 1f, 1f);
|
||||
container.transform.localPosition = Vector3.zero;
|
||||
container.transform.localRotation = Quaternion.identity;
|
||||
|
||||
if (cat.FillMaterial != null)
|
||||
{
|
||||
RadarFill fill = CreateFillObject(container);
|
||||
fill.material = cat.FillMaterial;
|
||||
fill.SetPath(path, Radius);
|
||||
}
|
||||
|
||||
if (cat.LineMaterial != null && cat.LineThickness > 0)
|
||||
{
|
||||
CanvasLines lines = CreateLinesObject(container);
|
||||
lines.material = cat.LineMaterial;
|
||||
lines.Thickness = cat.LineThickness;
|
||||
lines.SetHoverPrefab(cat.LineHover);
|
||||
lines.SetLines(seg);
|
||||
}
|
||||
|
||||
if (cat.PointMaterial != null && cat.PointSize > 0f)
|
||||
{
|
||||
CanvasLines points = CreateLinesObject(container);
|
||||
points.material = cat.PointMaterial;
|
||||
points.MakePointRender(cat.PointSize);
|
||||
points.SetHoverPrefab(cat.PointHover);
|
||||
points.SetLines(seg);
|
||||
string name = cat.Name;
|
||||
points.Hover += (int arg1,int t,object d, Vector2 arg2) => Points_Hover(name, arg1, arg2);
|
||||
points.Leave += () => Points_Leave(name);
|
||||
points.Click += (int arg1, int t, object d, Vector2 arg2) => Points_Click(name, arg1, arg2);
|
||||
}
|
||||
|
||||
if(mCategoryLabels != null && mCategoryLabels.isActiveAndEnabled)
|
||||
{
|
||||
for(int i=0; i<path.Length-1; i++)
|
||||
{
|
||||
string group = DataSource.GetGroupName(i);
|
||||
double val = DataSource.GetValue(cat.Name, group);
|
||||
Vector3 labelPos = path[i];
|
||||
Vector3 dir = labelPos.normalized;
|
||||
labelPos += dir * mCategoryLabels.Seperation;
|
||||
labelPos += new Vector3(mCategoryLabels.Location.Breadth, 0f, mCategoryLabels.Location.Depth);
|
||||
int fractionDigits = 2;
|
||||
if (mItemLabels != null)
|
||||
fractionDigits = mItemLabels.FractionDigits;
|
||||
string toSet = mCategoryLabels.TextFormat.Format(ChartAdancedSettings.Instance.FormatFractionDigits(fractionDigits, val, CustomNumberFormat), cat.Name, group);
|
||||
BillboardText billboard = ChartCommon.CreateBillboardText(null,mCategoryLabels.TextPrefab, transform, toSet, labelPos.x, labelPos.y, labelPos.z, 0f, null, hideHierarchy, mCategoryLabels.FontSize, mCategoryLabels.FontSharpness);
|
||||
TextController.AddText(billboard);
|
||||
AddBillboardText(cat.Name, billboard);
|
||||
}
|
||||
}
|
||||
return container;
|
||||
}
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
protected override void OnItemHoverted(object userData)
|
||||
{
|
||||
base.OnItemHoverted(userData);
|
||||
}
|
||||
|
||||
protected override void OnItemLeave(object userData,string type)
|
||||
{
|
||||
base.OnItemLeave(userData, type);
|
||||
}
|
||||
public override bool IsCanvas
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
protected override void OnItemSelected(object userData)
|
||||
{
|
||||
base.OnItemSelected(userData);
|
||||
}
|
||||
|
||||
private void Points_Click(string category,int index, Vector2 position)
|
||||
{
|
||||
index = index % DataSource.TotalGroups;
|
||||
string group = DataSource.GetGroupName(index);
|
||||
double amount = DataSource.GetValue(category, group);
|
||||
RadarEventArgs args = new RadarEventArgs(category, group, amount, position, index);
|
||||
OnItemSelected(args);
|
||||
}
|
||||
|
||||
private void Points_Leave(string category)
|
||||
{
|
||||
RadarEventArgs args = new RadarEventArgs(category, "",0.0,Vector3.zero,0);
|
||||
OnItemLeave(args,"none");
|
||||
}
|
||||
|
||||
private void Points_Hover(string category, int index, Vector2 position)
|
||||
{
|
||||
index = index % DataSource.TotalGroups;
|
||||
string group = DataSource.GetGroupName(index);
|
||||
double amount = DataSource.GetValue(category, group);
|
||||
RadarEventArgs args = new RadarEventArgs(category, group, amount, position, index);
|
||||
OnItemHoverted(args);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c464cf59e9a4ba541a0d4e7075fca70a
|
||||
timeCreated: 1489791118
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
#define Graph_And_Chart_PRO
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace ChartAndGraph
|
||||
{
|
||||
interface IInternalRadarData
|
||||
{
|
||||
ChartSparseDataSource InternalDataSource { get; }
|
||||
double GetMinValue();
|
||||
double GetMaxValue();
|
||||
event EventHandler InternalDataChanged;
|
||||
RadarChartData.CategoryData getCategoryData(int i);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 046040936f1f8ea4284661c490961035
|
||||
timeCreated: 1489344710
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
609
Assets/Chart And Graph/Script/RadarChart/RadarChart.cs
Normal file
609
Assets/Chart And Graph/Script/RadarChart/RadarChart.cs
Normal file
@@ -0,0 +1,609 @@
|
||||
#define Graph_And_Chart_PRO
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace ChartAndGraph
|
||||
{
|
||||
[ExecuteInEditMode]
|
||||
public abstract class RadarChart : AnyChart
|
||||
{
|
||||
protected Dictionary<string, List<BillboardText>> mTexts = new Dictionary<string, List<BillboardText>>();
|
||||
protected HashSet<BillboardText> mActiveTexts = new HashSet<BillboardText>();
|
||||
HashSet<string> mOccupiedCateogies = new HashSet<string>();
|
||||
Vector3[] mDirections;
|
||||
public class RadarEventArgs
|
||||
{
|
||||
public RadarEventArgs(string category,string group,double value,Vector3 position, int index)
|
||||
{
|
||||
Position = position;
|
||||
Category = category;
|
||||
Group = group;
|
||||
Value = value;
|
||||
Index = index;
|
||||
}
|
||||
|
||||
public int Index { get; private set; }
|
||||
public string Category { get; private set; }
|
||||
public string Group { get; private set; }
|
||||
public double Value { get; private set; }
|
||||
public Vector3 Position { get; private set; }
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private float radius = 3f;
|
||||
|
||||
public float Radius
|
||||
{
|
||||
get { return radius; }
|
||||
set
|
||||
{
|
||||
radius = value;
|
||||
GenerateChart();
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private float angle = 0f;
|
||||
|
||||
public float Angle
|
||||
{
|
||||
get { return angle; }
|
||||
set
|
||||
{
|
||||
angle = value;
|
||||
GenerateChart();
|
||||
}
|
||||
}
|
||||
[SerializeField]
|
||||
private Material axisPointMaterial;
|
||||
|
||||
|
||||
protected void AddBillboardText(string cat, BillboardText text)
|
||||
{
|
||||
List<BillboardText> addTo;
|
||||
if (mTexts.TryGetValue(cat, out addTo) == false)
|
||||
{
|
||||
addTo = new List<BillboardText>();
|
||||
mTexts.Add(cat, addTo);
|
||||
}
|
||||
addTo.Add(text);
|
||||
}
|
||||
|
||||
public Material AxisPointMaterial
|
||||
{
|
||||
get
|
||||
{
|
||||
return axisPointMaterial;
|
||||
}
|
||||
set
|
||||
{
|
||||
axisPointMaterial = value;
|
||||
GenerateChart();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[SerializeField]
|
||||
private Material axisLineMaterial;
|
||||
public Material AxisLineMaterial
|
||||
{
|
||||
get
|
||||
{
|
||||
return axisLineMaterial;
|
||||
}
|
||||
set
|
||||
{
|
||||
axisLineMaterial = value;
|
||||
GenerateChart();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
if (ChartCommon.IsInEditMode == false)
|
||||
{
|
||||
HookEvents();
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private float axisThickness = 0.1f;
|
||||
|
||||
public float AxisThickness
|
||||
{
|
||||
get
|
||||
{
|
||||
return axisThickness;
|
||||
}
|
||||
set
|
||||
{
|
||||
axisThickness = value;
|
||||
GenerateChart();
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private float axisPointSize = 1f;
|
||||
|
||||
public float AxisPointSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return axisPointSize;
|
||||
}
|
||||
set
|
||||
{
|
||||
axisPointSize = value;
|
||||
GenerateChart();
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private float axisAdd = 0f;
|
||||
|
||||
public float AxisAdd
|
||||
{
|
||||
get
|
||||
{
|
||||
return axisAdd;
|
||||
}
|
||||
set
|
||||
{
|
||||
axisAdd = value;
|
||||
GenerateChart();
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private int totalAxisDevisions = 5;
|
||||
|
||||
public int TotalAxisDevisions
|
||||
{
|
||||
get
|
||||
{
|
||||
return totalAxisDevisions;
|
||||
}
|
||||
set
|
||||
{
|
||||
totalAxisDevisions = value;
|
||||
GenerateChart();
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class RadarEvent : UnityEvent<RadarEventArgs>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// occures when a point is clicked
|
||||
/// </summary>
|
||||
public RadarEvent PointClicked = new RadarEvent();
|
||||
/// <summary>
|
||||
/// occurs when a point is hovered
|
||||
/// </summary>
|
||||
public RadarEvent PointHovered = new RadarEvent();
|
||||
|
||||
/// <summary>
|
||||
/// occurs when no point is hovered any longer
|
||||
/// </summary>
|
||||
public UnityEvent NonHovered = new UnityEvent();
|
||||
|
||||
List<GameObject> mAxisObjects = new List<GameObject>();
|
||||
/// <summary>
|
||||
/// the radar data
|
||||
/// </summary>
|
||||
[HideInInspector]
|
||||
[SerializeField]
|
||||
private RadarChartData Data = new RadarChartData();
|
||||
|
||||
/// <summary>
|
||||
/// Holds the radar chart data. including values, categories and groups.
|
||||
/// </summary>
|
||||
public RadarChartData DataSource { get { return Data; } }
|
||||
|
||||
void HookEvents()
|
||||
{
|
||||
Data.ProperyUpdated -= DataUpdated;
|
||||
Data.ProperyUpdated += DataUpdated;
|
||||
((IInternalRadarData)Data).InternalDataSource.DataStructureChanged -= StructureUpdated;
|
||||
((IInternalRadarData)Data).InternalDataSource.DataStructureChanged += StructureUpdated;
|
||||
((IInternalRadarData)Data).InternalDataSource.DataValueChanged -= ValueChanged; ;
|
||||
((IInternalRadarData)Data).InternalDataSource.DataValueChanged += ValueChanged;
|
||||
}
|
||||
|
||||
private void ValueChanged(object sender, DataSource.ChartDataSourceBase.DataValueChangedEventArgs e)
|
||||
{
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
private void StructureUpdated(object sender, EventArgs e)
|
||||
{
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
private void DataUpdated()
|
||||
{
|
||||
Invalidate();
|
||||
}
|
||||
public override bool SupportRealtimeGeneration
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
protected override LegenedData LegendInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
LegenedData legend = new LegenedData();
|
||||
if (Data == null)
|
||||
return legend;
|
||||
foreach (var column in ((IInternalRadarData)Data).InternalDataSource.Columns)
|
||||
{
|
||||
var item = new LegenedData.LegenedItem();
|
||||
var catData = column.UserData as RadarChartData.CategoryData;
|
||||
item.Name = column.Name;
|
||||
if (catData.FillMaterial != null)
|
||||
item.Material = catData.FillMaterial;
|
||||
else
|
||||
{
|
||||
if (catData.LineMaterial != null)
|
||||
{
|
||||
item.Material = catData.LineMaterial;
|
||||
}
|
||||
else
|
||||
item.Material = null;
|
||||
}
|
||||
legend.AddLegenedItem(item);
|
||||
}
|
||||
return legend;
|
||||
}
|
||||
}
|
||||
|
||||
protected override IChartData DataLink
|
||||
{
|
||||
get
|
||||
{
|
||||
return Data;
|
||||
}
|
||||
}
|
||||
protected override bool SupportsCategoryLabels
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool SupportsGroupLables
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool SupportsItemLabels
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected override float TotalDepthLink
|
||||
{
|
||||
get
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
||||
protected override float TotalHeightLink
|
||||
{
|
||||
get
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
||||
protected override float TotalWidthLink
|
||||
{
|
||||
get
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// used internally , do not call this method
|
||||
/// </summary>
|
||||
protected override void OnValidate()
|
||||
{
|
||||
base.OnValidate();
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
HookEvents();
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
protected override void ClearChart()
|
||||
{
|
||||
base.ClearChart();
|
||||
mActiveTexts.Clear();
|
||||
mTexts.Clear();
|
||||
}
|
||||
|
||||
protected override void LateUpdate()
|
||||
{
|
||||
base.LateUpdate();
|
||||
}
|
||||
|
||||
public bool ItemToWorldPosition(string group, double amount, out Vector3 worldposition)
|
||||
{
|
||||
worldposition = Vector3.zero;
|
||||
if (mDirections == null || mDirections.Length == 0)
|
||||
return false;
|
||||
int index = Data.GetGroupIndex(group);
|
||||
Vector3 dir = mDirections[index];
|
||||
double max = Data.GetMaxValue();
|
||||
worldposition = ((float)(amount / max) * Radius) * dir;
|
||||
worldposition = transform.TransformPoint(worldposition);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool SnapWorldPointToPosition(Vector3 worldSpace,out string group,out double amount)
|
||||
{
|
||||
group = null;
|
||||
amount = 0f;
|
||||
if (mDirections == null || mDirections.Length == 0)
|
||||
return false;
|
||||
Vector3 pos = transform.InverseTransformPoint(worldSpace);
|
||||
pos.z = 0;
|
||||
|
||||
// Vector3 dir = mDirections[0];
|
||||
group = Data.GetGroupName(0);
|
||||
if (Math.Abs(pos.x) < 0.001f && Math.Abs(pos.y) < 0.001f)
|
||||
{
|
||||
//zero vector do nothing we are taking the first direction in the array
|
||||
}
|
||||
else
|
||||
{
|
||||
float dot = float.MinValue;
|
||||
for (int i = 0; i < mDirections.Length; i++)
|
||||
{
|
||||
float newDot = Vector3.Dot(mDirections[i], pos);
|
||||
if(newDot > dot)
|
||||
{
|
||||
dot = newDot;
|
||||
// dir = mDirections[i];
|
||||
group = Data.GetGroupName(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float mag = pos.magnitude;
|
||||
double max = Data.GetMaxValue();
|
||||
amount = ((mag/Radius) * max);
|
||||
amount = Math.Max(0, Math.Min(max, amount));
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void InternalGenerateChart()
|
||||
{
|
||||
if (gameObject.activeInHierarchy == false)
|
||||
return;
|
||||
|
||||
ClearChart();
|
||||
|
||||
base.InternalGenerateChart();
|
||||
|
||||
if (((IInternalRadarData)Data).InternalDataSource == null)
|
||||
return;
|
||||
|
||||
double[,] data = ((IInternalRadarData)Data).InternalDataSource.getRawData();
|
||||
int rowCount = data.GetLength(0);
|
||||
int columnCount = data.GetLength(1);
|
||||
|
||||
//restrict to 3 groups
|
||||
if (rowCount <3)
|
||||
return;
|
||||
|
||||
mDirections = new Vector3[rowCount];
|
||||
float[] angles = new float[rowCount];
|
||||
|
||||
for (int i = 0; i < rowCount; i++)
|
||||
{
|
||||
float angle = (float)((((float)i) / (float)rowCount) * Math.PI * 2f) + Angle * Mathf.Deg2Rad;
|
||||
angles[i] = angle;
|
||||
mDirections[i] = new Vector3(Mathf.Cos(angle), Mathf.Sin(angle), 0f);
|
||||
}
|
||||
|
||||
Vector3[] path = new Vector3[rowCount];
|
||||
Vector3 zAdd = Vector3.zero;
|
||||
|
||||
for (int i = 0; i < TotalAxisDevisions; i++)
|
||||
{
|
||||
float rad = Radius * ((float)(i + 1) / (float)TotalAxisDevisions);
|
||||
for (int j = 0; j < rowCount; j++)
|
||||
path[j] = (mDirections[j] * rad) + zAdd;
|
||||
// path[rowCount] = path[0];
|
||||
zAdd.z += AxisAdd;
|
||||
GameObject axisObject = CreateAxisObject(AxisThickness, path);
|
||||
mAxisObjects.Add(axisObject);
|
||||
axisObject.transform.SetParent(transform, false);
|
||||
}
|
||||
|
||||
if (mGroupLabels != null && mGroupLabels.isActiveAndEnabled)
|
||||
{
|
||||
for (int i = 0; i < rowCount; i++)
|
||||
{
|
||||
string group = Data.GetGroupName(i);
|
||||
Vector3 basePosition = mDirections[i] * Radius;
|
||||
Vector3 breadthAxis = Vector3.Cross(mDirections[i], Vector3.forward);
|
||||
Vector3 position = basePosition + mDirections[i] * mGroupLabels.Seperation;
|
||||
position += breadthAxis * mGroupLabels.Location.Breadth;
|
||||
position += new Vector3(0f , 0f, mGroupLabels.Location.Depth);
|
||||
string toSet = mGroupLabels.TextFormat.Format(group, "", "");
|
||||
BillboardText billboard = ChartCommon.CreateBillboardText(null,mGroupLabels.TextPrefab, transform, toSet, position.x, position.y, position.z, angles[i],transform,hideHierarchy, mGroupLabels.FontSize, mGroupLabels.FontSharpness);
|
||||
billboard.UserData = group;
|
||||
TextController.AddText(billboard);
|
||||
}
|
||||
}
|
||||
|
||||
double maxValue = Data.GetMaxValue();
|
||||
double minValue = Data.GetMinValue();
|
||||
|
||||
if (maxValue > 0.000001f)
|
||||
{
|
||||
|
||||
for (int i = 0; i < columnCount; i++)
|
||||
{
|
||||
double finalMaxValue = DataSource.GetCategoryMaxValue(i);
|
||||
if (finalMaxValue < 0f)
|
||||
finalMaxValue = maxValue;
|
||||
for (int j = 0; j < rowCount; j++)
|
||||
{
|
||||
float rad = ((float)((data[j, i]- minValue) / (finalMaxValue - minValue))) * Radius;
|
||||
path[j] = mDirections[j] * rad;
|
||||
}
|
||||
// path[rowCount] = path[0];
|
||||
GameObject category = CreateCategoryObject(path, i);
|
||||
category.transform.SetParent(transform, false);
|
||||
}
|
||||
|
||||
if (mItemLabels != null && mItemLabels.isActiveAndEnabled)
|
||||
{
|
||||
float angle = mItemLabels.Location.Breadth;
|
||||
float blend = (angle / 360f);
|
||||
blend -= Mathf.Floor(blend);
|
||||
blend *= rowCount;
|
||||
int index = (int)blend;
|
||||
int nextIndex = (index + 1) % rowCount;
|
||||
blend = blend - Mathf.Floor(blend);
|
||||
for (int i = 0; i < TotalAxisDevisions; i++)
|
||||
{
|
||||
float factor = ((float)(i + 1) / (float)TotalAxisDevisions);
|
||||
float rad = Radius * factor + mItemLabels.Seperation;
|
||||
string value = ChartAdancedSettings.Instance.FormatFractionDigits(mItemLabels.FractionDigits,(float)(Mathf.Lerp((float)minValue,(float)maxValue,factor)), CustomNumberFormat);
|
||||
Vector3 position = Vector3.Lerp(mDirections[index] , mDirections[nextIndex] , blend) * rad;
|
||||
position.z = mItemLabels.Location.Depth;
|
||||
string toSet = mItemLabels.TextFormat.Format(value, "", "");
|
||||
BillboardText billboard = ChartCommon.CreateBillboardText(null,mItemLabels.TextPrefab, transform, toSet, position.x, position.y, position.z,0f, transform,hideHierarchy, mItemLabels.FontSize, mItemLabels.FontSharpness);
|
||||
billboard.UserData = (float)(maxValue * factor);
|
||||
TextController.AddText(billboard);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnItemSelected(object userData)
|
||||
{
|
||||
base.OnItemSelected(userData);
|
||||
RadarEventArgs args = userData as RadarEventArgs;
|
||||
if (args == null)
|
||||
return;
|
||||
mOccupiedCateogies.Add(args.Category);
|
||||
if(PointClicked != null)
|
||||
PointClicked.Invoke(args);
|
||||
}
|
||||
|
||||
protected override void OnItemLeave(object userData,string type)
|
||||
{
|
||||
base.OnItemLeave(userData, type);
|
||||
RadarEventArgs args = userData as RadarEventArgs;
|
||||
foreach (BillboardText t in mActiveTexts)
|
||||
{
|
||||
foreach (ChartItemEffect effect in t.UIText.GetComponents<ChartItemEffect>())
|
||||
{
|
||||
if (t.UIText == null)
|
||||
continue;
|
||||
effect.TriggerOut(false);
|
||||
}
|
||||
}
|
||||
mActiveTexts.Clear();
|
||||
|
||||
string category = args.Category;
|
||||
mOccupiedCateogies.Remove(category);
|
||||
mOccupiedCateogies.RemoveWhere(x => !Data.HasCategory(x));
|
||||
if (mOccupiedCateogies.Count == 0)
|
||||
{
|
||||
if (NonHovered != null)
|
||||
NonHovered.Invoke();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected override void OnItemHoverted(object userData)
|
||||
{
|
||||
base.OnItemHoverted(userData);
|
||||
List<BillboardText> catgoryTexts;
|
||||
RadarEventArgs args = userData as RadarEventArgs;
|
||||
if (args == null)
|
||||
return;
|
||||
foreach (BillboardText t in mActiveTexts)
|
||||
{
|
||||
if (t.UIText == null)
|
||||
continue;
|
||||
foreach (ChartItemEffect effect in t.UIText.GetComponents<ChartItemEffect>())
|
||||
effect.TriggerOut(false);
|
||||
}
|
||||
|
||||
mActiveTexts.Clear();
|
||||
|
||||
|
||||
if (mTexts.TryGetValue(args.Category, out catgoryTexts))
|
||||
{
|
||||
if (args.Index < catgoryTexts.Count)
|
||||
{
|
||||
BillboardText b = catgoryTexts[args.Index];
|
||||
mActiveTexts.Add(b);
|
||||
GameObject t = b.UIText;
|
||||
if (t != null)
|
||||
{
|
||||
foreach (ChartItemEffect effect in t.GetComponents<ChartItemEffect>())
|
||||
effect.TriggerIn(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
mOccupiedCateogies.Add(args.Category);
|
||||
if(PointHovered != null)
|
||||
PointHovered.Invoke(args);
|
||||
}
|
||||
|
||||
protected abstract GameObject CreateCategoryObject(Vector3[] path, int category);
|
||||
protected abstract GameObject CreateAxisObject(float thickness, Vector3[] path);
|
||||
|
||||
protected override bool HasValues(AxisBase axis)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override double MaxValue(AxisBase axis)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
protected override double MinValue(AxisBase axis)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Assets/Chart And Graph/Script/RadarChart/RadarChart.cs.meta
Normal file
12
Assets/Chart And Graph/Script/RadarChart/RadarChart.cs.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67b6b20133932f844b6b8b7a364e1c97
|
||||
timeCreated: 1489344710
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,98 @@
|
||||
#define Graph_And_Chart_PRO
|
||||
using ChartAndGraph.DataSource;
|
||||
using ChartAndGraph.Exceptions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ChartAndGraph
|
||||
{
|
||||
public partial class RadarChartData : AbstractChartData, IInternalRadarData, IChartData
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds a new category to the radar chart. Each category has it's own materials and name.
|
||||
/// Note: you must also add groups to the radar data.
|
||||
/// Example: you can set the chart categories to be "Player 1","Player 2","Player 3" in order to compare player achivments
|
||||
/// </summary>
|
||||
public void Add3DCategory(string name, PathGenerator linePrefab, Material lineMaterial, float lineThickness, GameObject pointPrefab, Material pointMaterial, float pointSize, Material fillMaterial,int fillSmoothing, float curve, float seperation)
|
||||
{
|
||||
AddInnerCategory(name, linePrefab, lineMaterial, lineThickness, pointPrefab, pointMaterial, pointSize, fillMaterial, fillSmoothing, curve, seperation);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void Set3DCategoryOrientation(string category, float seperation, float curve)
|
||||
{
|
||||
try
|
||||
{
|
||||
CategoryData data = mDataSource.Columns[category].UserData as CategoryData;
|
||||
if (data == null)
|
||||
throw new Exception("category not set"); // should never happen
|
||||
data.Seperation = seperation;
|
||||
data.Curve = curve;
|
||||
RaiseDataChanged();
|
||||
}
|
||||
catch
|
||||
{
|
||||
Debug.LogWarning("Invalid category name. Make sure the category is present in the graph");
|
||||
}
|
||||
}
|
||||
public void Set3DCategoryFill(string category, Material fillMaterial,int fillSmoothing)
|
||||
{
|
||||
try
|
||||
{
|
||||
CategoryData data = mDataSource.Columns[category].UserData as CategoryData;
|
||||
if (data == null)
|
||||
throw new Exception("category not set"); // should never happen
|
||||
data.FillMaterial = fillMaterial;
|
||||
if (fillSmoothing < 1)
|
||||
fillSmoothing = 1;
|
||||
data.FillSmoothing = fillSmoothing;
|
||||
RaiseDataChanged();
|
||||
}
|
||||
catch
|
||||
{
|
||||
Debug.LogWarning("Invalid category name. Make sure the category is present in the graph");
|
||||
}
|
||||
}
|
||||
|
||||
public void Set3DCategoryLine(string category, PathGenerator linePrefab, Material lineMaterial, float lineThickness)
|
||||
{
|
||||
try
|
||||
{
|
||||
CategoryData data = mDataSource.Columns[category].UserData as CategoryData;
|
||||
if (data == null)
|
||||
throw new Exception("category not set"); // should never happen
|
||||
data.LineMaterial = lineMaterial;
|
||||
data.LinePrefab = linePrefab;
|
||||
data.LineThickness = lineThickness;
|
||||
RaiseDataChanged();
|
||||
}
|
||||
catch
|
||||
{
|
||||
Debug.LogWarning("Invalid category name. Make sure the category is present in the graph");
|
||||
}
|
||||
}
|
||||
|
||||
public void Set3DCategoryPoint(string category, GameObject prefab, Material pointMaterial, float pointSize)
|
||||
{
|
||||
try
|
||||
{
|
||||
CategoryData data = mDataSource.Columns[category].UserData as CategoryData;
|
||||
if (data == null)
|
||||
throw new Exception("category not set"); // should never happen
|
||||
data.PointPrefab = prefab;
|
||||
data.PointMaterial = pointMaterial;
|
||||
data.PointSize = pointSize;
|
||||
RaiseDataChanged();
|
||||
}
|
||||
catch
|
||||
{
|
||||
Debug.LogWarning("Invalid category name. Make sure the category is present in the graph");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9f713b3cf6feafc4bbe929f2e5dbafd2
|
||||
timeCreated: 1560540959
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
685
Assets/Chart And Graph/Script/RadarChart/RadarChartData.cs
Normal file
685
Assets/Chart And Graph/Script/RadarChart/RadarChartData.cs
Normal file
@@ -0,0 +1,685 @@
|
||||
#define Graph_And_Chart_PRO
|
||||
using ChartAndGraph.DataSource;
|
||||
using ChartAndGraph.Exceptions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ChartAndGraph
|
||||
{
|
||||
[Serializable]
|
||||
public partial class RadarChartData : AbstractChartData, IInternalRadarData, IChartData
|
||||
{
|
||||
[Serializable]
|
||||
internal class CategoryData
|
||||
{
|
||||
public string Name;
|
||||
public float Seperation;
|
||||
public float Curve;
|
||||
public Material FillMaterial;
|
||||
public int FillSmoothing = 5;
|
||||
public PathGenerator LinePrefab;
|
||||
public ChartItemEffect LineHover;
|
||||
public float LineThickness;
|
||||
public Material LineMaterial;
|
||||
public GameObject PointPrefab;
|
||||
public ChartItemEffect PointHover;
|
||||
public float PointSize;
|
||||
public Material PointMaterial;
|
||||
[HideInInspector]
|
||||
public double MaxValue = -1f;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
class DataEntry
|
||||
{
|
||||
public string GroupName;
|
||||
public string ColumnName;
|
||||
public double Amount;
|
||||
}
|
||||
|
||||
private ChartSparseDataSource mDataSource = new ChartSparseDataSource();
|
||||
ChartSparseDataSource IInternalRadarData.InternalDataSource { get { return mDataSource; } }
|
||||
[SerializeField]
|
||||
private CategoryData[] mCategories = new CategoryData[0];
|
||||
[SerializeField]
|
||||
private string[] mGroups = new string[0];
|
||||
[SerializeField]
|
||||
private DataEntry[] mData = new DataEntry[0];
|
||||
|
||||
private event EventHandler DataChanged;
|
||||
public event Action ProperyUpdated;
|
||||
|
||||
protected void RaisePropertyUpdated()
|
||||
{
|
||||
if (ProperyUpdated != null)
|
||||
ProperyUpdated();
|
||||
}
|
||||
|
||||
private void RaiseDataChanged()
|
||||
{
|
||||
if (mDataSource.SuspendEvents)
|
||||
return;
|
||||
if (DataChanged != null)
|
||||
DataChanged(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the number of categories in the data source
|
||||
/// </summary>
|
||||
public int TotalCategories { get { return mDataSource.Columns.Count; } }
|
||||
/// <summary>
|
||||
/// the number of groups in the data source
|
||||
/// </summary>
|
||||
public int TotalGroups { get { return mDataSource.Rows.Count; } }
|
||||
/// <summary>
|
||||
/// set this to true to automatically detect the highest radar value int the chart. This value will be used to scale all other radar entries
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private bool automaticMaxValue = true;
|
||||
|
||||
/// <summary>
|
||||
/// renames a category. throw an exception on error
|
||||
/// </summary>
|
||||
/// <param name="prevName"></param>
|
||||
/// <param name="newName"></param>
|
||||
public void RenameCategory(string prevName, string newName)
|
||||
{
|
||||
mDataSource.Columns[prevName].Name = newName;
|
||||
RaisePropertyUpdated();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// renames a group. throw an exception on error
|
||||
/// </summary>
|
||||
/// <param name="prevName"></param>
|
||||
/// <param name="newName"></param>
|
||||
public void RenameGroup(string prevName, string newName)
|
||||
{
|
||||
mDataSource.Rows[prevName].Name = newName;
|
||||
RaisePropertyUpdated();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// set this to true to automatically detect the highest radar value int the chart. This value will be used to scale all other radar entries
|
||||
/// </summary>
|
||||
public bool AutomaticMaxValue
|
||||
{
|
||||
get { return automaticMaxValue; }
|
||||
set
|
||||
{
|
||||
automaticMaxValue = value;
|
||||
RaisePropertyUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Mannualy set the maximum value , all radar entires will be scaled based on this value. If a radar entry value is larger than this value it will be clamped
|
||||
/// Note: set AutomaticMaxValue to false in order to use this field
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private double maxValue = 10;
|
||||
|
||||
/// <summary>
|
||||
/// Mannualy set the maximum value , all radar entires will be scaled based on this value. If a radar entry value is larger than this value it will be clamped
|
||||
/// Note: set AutomaticMaxValue to false in order to use this field
|
||||
/// </summary>
|
||||
public double MaxValue
|
||||
{
|
||||
get { return maxValue; }
|
||||
set
|
||||
{
|
||||
maxValue = value;
|
||||
RaisePropertyUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// set this to true to automatically detect the lowest radar value int the chart. This value will be used to scale all other radar entries
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private bool automaticMinValue = false;
|
||||
|
||||
/// <summary>
|
||||
/// set this to true to automatically detect the highest radar value int the chart. This value will be used to scale all other radar entries
|
||||
/// </summary>
|
||||
public bool AutomaticMinValue
|
||||
{
|
||||
get { return automaticMinValue; }
|
||||
set
|
||||
{
|
||||
automaticMinValue = value;
|
||||
RaisePropertyUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mannualy set the minimum value , all radar entires will be scaled based on this value. If a radar entry value is larger than this value it will be clamped
|
||||
/// Note: set AutomaticMinValue to false in order to use this field
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private double minValue = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Mannualy set the minimum value , all radar entires will be scaled based on this value. If a radar entry value is larger than this value it will be clamped
|
||||
/// Note: set AutomaticMinValue to false in order to use this field
|
||||
/// </summary>
|
||||
public double MinValue
|
||||
{
|
||||
get { return minValue; }
|
||||
set
|
||||
{
|
||||
minValue = value;
|
||||
RaisePropertyUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
UpdateSliders();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// call this to suspend chart redrawing while updating the data of the chart
|
||||
/// </summary>
|
||||
public void StartBatch()
|
||||
{
|
||||
mDataSource.SuspendEvents = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// call this after StartBatch , this will apply all the changed made between the StartBatch call to this call
|
||||
/// </summary>
|
||||
public void EndBatch()
|
||||
{
|
||||
mDataSource.SuspendEvents = false;
|
||||
}
|
||||
|
||||
public double GetMinValue()
|
||||
{
|
||||
double min = MinValue;
|
||||
double? rawMin = mDataSource.getRawMinValue();
|
||||
|
||||
if (AutomaticMinValue && rawMin.HasValue)
|
||||
min = rawMin.Value;
|
||||
return min;
|
||||
}
|
||||
public bool HasGroup(string groupName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var row = mDataSource.Rows[groupName];
|
||||
if (row != null)
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public double GetMaxValue()
|
||||
{
|
||||
double max = MaxValue;
|
||||
double? rawMax = mDataSource.getRawMaxValue();
|
||||
|
||||
if (AutomaticMaxValue && rawMax.HasValue)
|
||||
max = rawMax.Value;
|
||||
return max;
|
||||
}
|
||||
|
||||
public bool HasCategory(string category)
|
||||
{
|
||||
try
|
||||
{
|
||||
var col = mDataSource.Columns[category];
|
||||
if (col != null)
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public string GetCategoryName(int index)
|
||||
{
|
||||
return mDataSource.Columns[index].Name;
|
||||
}
|
||||
public double GetCategoryMaxValue(int index)
|
||||
{
|
||||
return ((CategoryData)mDataSource.Columns[index].UserData).MaxValue;
|
||||
}
|
||||
public void SetCategoryMaxValue(string category,double maxValue)
|
||||
{
|
||||
((CategoryData)mDataSource.Columns[category].UserData).MaxValue = maxValue;
|
||||
}
|
||||
public int GetGroupIndex(String name)
|
||||
{
|
||||
for (int i = 0; i < mGroups.Length; i++)
|
||||
if (mGroups[i] == name)
|
||||
return i;
|
||||
throw new Exception("group does not exist");
|
||||
}
|
||||
public string GetGroupName(int index)
|
||||
{
|
||||
return mDataSource.Rows[index].Name;
|
||||
}
|
||||
/// <summary>
|
||||
/// used intenally , do not call
|
||||
/// </summary>
|
||||
/// <param name="cats"></param>
|
||||
public object[] StoreAllCategoriesinOrder()
|
||||
{
|
||||
return mCategories.ToArray();
|
||||
}
|
||||
public void OnBeforeSerialize()
|
||||
{
|
||||
int totalColumns = mDataSource.Columns.Count;
|
||||
mCategories = new CategoryData[totalColumns];
|
||||
for (int i = 0; i < totalColumns; i++)
|
||||
{
|
||||
CategoryData data = mDataSource.Columns[i].UserData as CategoryData;
|
||||
if (data.FillSmoothing < 1)
|
||||
data.FillSmoothing = 1;
|
||||
data.Name = mDataSource.Columns[i].Name;
|
||||
mCategories[i] = data;
|
||||
}
|
||||
|
||||
int totalRows = mDataSource.Rows.Count;
|
||||
mGroups = new string[totalRows];
|
||||
for (int i = 0; i < totalRows; i++)
|
||||
mGroups[i] = mDataSource.Rows[i].Name;
|
||||
|
||||
double[,] raw = mDataSource.getRawData();
|
||||
int current = 0;
|
||||
mData = new DataEntry[raw.GetLength(0) * raw.GetLength(1)];
|
||||
for (int i = 0; i < raw.GetLength(0); ++i)
|
||||
{
|
||||
for (int j = 0; j < raw.GetLength(1); ++j)
|
||||
{
|
||||
DataEntry entry = new DataEntry();
|
||||
entry.ColumnName = mDataSource.Columns[j].Name;
|
||||
entry.GroupName = mDataSource.Rows[i].Name;
|
||||
entry.Amount = raw[i, j];
|
||||
mData[current++] = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnAfterDeserialize()
|
||||
{
|
||||
mDataSource = new ChartSparseDataSource();
|
||||
mDataSource.SuspendEvents = true;
|
||||
mDataSource.Clear();
|
||||
if (mCategories == null)
|
||||
mCategories = new CategoryData[0];
|
||||
if (mGroups == null)
|
||||
mGroups = new string[0];
|
||||
if (mData == null)
|
||||
mData = new DataEntry[0];
|
||||
for (int i = 0; i < mCategories.Length; i++)
|
||||
AddCategory(mCategories[i].Name, mCategories[i]);
|
||||
for (int i = 0; i < mGroups.Length; i++)
|
||||
AddGroup(mGroups[i]);
|
||||
|
||||
for (int i = 0; i < mData.Length; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
DataEntry entry = mData[i];
|
||||
mDataSource.SetValue(entry.ColumnName, entry.GroupName, entry.Amount);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
mDataSource.SuspendEvents = false;
|
||||
}
|
||||
|
||||
private void AddCategory(string name, CategoryData data)
|
||||
{
|
||||
ChartDataColumn column = new ChartDataColumn(name);
|
||||
column.UserData = data;
|
||||
mDataSource.mColumns.Add(column);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// clears all groups in the radar chart
|
||||
/// </summary>
|
||||
public void ClearGroups()
|
||||
{
|
||||
string[] groups = mDataSource.Rows.Select(x => x.Name).ToArray();
|
||||
foreach (string s in groups)
|
||||
{
|
||||
RemoveGroup(s);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// clears alll categories in the radar chart
|
||||
/// </summary>
|
||||
public void ClearCategories()
|
||||
{
|
||||
string[] groups = mDataSource.Columns.Select(x => x.Name).ToArray();
|
||||
foreach (string s in groups)
|
||||
{
|
||||
RemoveCategory(s);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new category to the radar chart. Each category has it's own materials and name.
|
||||
/// Note: you must also add groups to the radar data.
|
||||
/// Example: you can set the chart categories to be "Player 1","Player 2","Player 3" in order to compare player achivments
|
||||
public void AddCategory(string name, PathGenerator linePrefab, Material lineMaterial, float lineThickness, GameObject pointPrefab, Material pointMaterial, float pointSize, Material fillMaterial)
|
||||
{
|
||||
AddInnerCategory(name, null, lineMaterial, lineThickness, null, pointMaterial, pointSize, fillMaterial,5, 0f, 0f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new category to the radar chart. Each category has it's own materials and name.
|
||||
/// Note: you must also add groups to the radar data.
|
||||
/// Example: you can set the chart categories to be "Player 1","Player 2","Player 3" in order to compare player achivments
|
||||
/// </summary>
|
||||
protected void AddInnerCategory(string name, PathGenerator linePrefab, Material lineMaterial, float lineThickness, GameObject pointPrefab, Material pointMaterial, float pointSize, Material fillMaterial,int fillSmoothing, float curve, float seperation)
|
||||
{
|
||||
ChartDataColumn column = new ChartDataColumn(name);
|
||||
CategoryData data = new CategoryData();
|
||||
data.LinePrefab = linePrefab;
|
||||
data.LineMaterial = lineMaterial;
|
||||
data.LineThickness = lineThickness;
|
||||
data.PointMaterial = pointMaterial;
|
||||
data.PointSize = pointSize;
|
||||
data.PointPrefab = pointPrefab;
|
||||
data.FillMaterial = fillMaterial;
|
||||
if (fillSmoothing < 1)
|
||||
fillSmoothing = 1;
|
||||
data.FillSmoothing = fillSmoothing;
|
||||
data.Curve = curve;
|
||||
data.Seperation = seperation;
|
||||
data.Name = name;
|
||||
column.UserData = data;
|
||||
mDataSource.mColumns.Add(column);
|
||||
}
|
||||
|
||||
public void SetCategoryHover(string category, ChartItemEffect lineHover, ChartItemEffect pointHover)
|
||||
{
|
||||
try
|
||||
{
|
||||
CategoryData data = mDataSource.Columns[category].UserData as CategoryData;
|
||||
if (data == null)
|
||||
throw new Exception("category not set"); // should never happen
|
||||
data.LineHover = lineHover;
|
||||
data.PointHover = pointHover;
|
||||
RaiseDataChanged();
|
||||
}
|
||||
catch
|
||||
{
|
||||
Debug.LogWarning("Invalid category name. Make sure the category is present in the graph");
|
||||
}
|
||||
}
|
||||
|
||||
protected void SetInnerCategoryFill(string category, Material fillMaterial, int fillSmoothing)
|
||||
{
|
||||
try
|
||||
{
|
||||
CategoryData data = mDataSource.Columns[category].UserData as CategoryData;
|
||||
if (data == null)
|
||||
throw new Exception("category not set"); // should never happen
|
||||
data.FillMaterial = fillMaterial;
|
||||
if (fillSmoothing < 1)
|
||||
fillSmoothing = 1;
|
||||
data.FillSmoothing = fillSmoothing;
|
||||
RaiseDataChanged();
|
||||
}
|
||||
catch
|
||||
{
|
||||
Debug.LogWarning("Invalid category name. Make sure the category is present in the graph");
|
||||
}
|
||||
}
|
||||
|
||||
protected void SetInnerCategoryLine(string category, PathGenerator linePrefab, Material lineMaterial, float lineThickness)
|
||||
{
|
||||
try
|
||||
{
|
||||
CategoryData data = mDataSource.Columns[category].UserData as CategoryData;
|
||||
if (data == null)
|
||||
throw new Exception("category not set"); // should never happen
|
||||
data.LineMaterial = lineMaterial;
|
||||
data.LinePrefab = linePrefab;
|
||||
data.LineThickness = lineThickness;
|
||||
RaiseDataChanged();
|
||||
}
|
||||
catch
|
||||
{
|
||||
Debug.LogWarning("Invalid category name. Make sure the category is present in the graph");
|
||||
}
|
||||
}
|
||||
|
||||
protected void SetInnerCategoryPoint(string category, GameObject prefab, Material pointMaterial, float pointSize)
|
||||
{
|
||||
try
|
||||
{
|
||||
CategoryData data = mDataSource.Columns[category].UserData as CategoryData;
|
||||
if (data == null)
|
||||
throw new Exception("category not set"); // should never happen
|
||||
data.PointPrefab = prefab;
|
||||
data.PointMaterial = pointMaterial;
|
||||
data.PointSize = pointSize;
|
||||
RaiseDataChanged();
|
||||
}
|
||||
catch
|
||||
{
|
||||
Debug.LogWarning("Invalid category name. Make sure the category is present in the graph");
|
||||
}
|
||||
}
|
||||
public void SetCategoryFill(string category, Material fillMaterial)
|
||||
{
|
||||
SetInnerCategoryFill(category, fillMaterial,5);
|
||||
}
|
||||
public void SetCategoryLine(string category, Material lineMaterial, float lineThickness)
|
||||
{
|
||||
SetInnerCategoryLine(category, null, lineMaterial, lineThickness);
|
||||
}
|
||||
public void SetCategoryPoint(string category, Material pointMaterial, float pointSize)
|
||||
{
|
||||
SetInnerCategoryPoint(category, null, pointMaterial, pointSize);
|
||||
}
|
||||
/// <summary>
|
||||
/// sets the material for the specified category
|
||||
/// </summary>
|
||||
/// <param name="category">the name of the category</param>
|
||||
/// <param name="material">the material of the category</param>
|
||||
public void SetMaterial(string category, Material material)
|
||||
{
|
||||
SetMaterial(category, new ChartDynamicMaterial(material));
|
||||
}
|
||||
|
||||
internal ChartDynamicMaterial GetMaterial(string category)
|
||||
{
|
||||
return mDataSource.Columns[category].Material;
|
||||
}
|
||||
/// <summary>
|
||||
/// sets the material for the specified category
|
||||
/// </summary>
|
||||
/// <param name="category">the name of the category</param>
|
||||
/// <param name="material">the dynamic material of the category. dynamic materials allows setting the material for different events</param>
|
||||
public void SetMaterial(string category, ChartDynamicMaterial material)
|
||||
{
|
||||
mDataSource.Columns[category].Material = material;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// removes a category from the radar chart
|
||||
/// </summary>
|
||||
/// <param name="name">the name of the category to remove</param>
|
||||
public void RemoveCategory(string name)
|
||||
{
|
||||
ChartDataColumn column = mDataSource.Columns[name];
|
||||
RemoveSliderForCategory(name);
|
||||
mDataSource.Columns.Remove(column);
|
||||
}
|
||||
public void RestoreCategory(string category, object data)
|
||||
{
|
||||
var toSet = (CategoryData)data;
|
||||
CategoryData current = (CategoryData)(mDataSource.Columns[category].UserData);
|
||||
current.Curve = toSet.Curve;
|
||||
current.FillMaterial = toSet.FillMaterial;
|
||||
current.FillSmoothing = toSet.FillSmoothing;
|
||||
current.LineHover = toSet.LineHover;
|
||||
current.LineMaterial = toSet.LineMaterial;
|
||||
current.LinePrefab = toSet.LinePrefab;
|
||||
current.LineThickness= toSet.LineThickness;
|
||||
current.PointHover= toSet.PointHover;
|
||||
current.PointMaterial = toSet.PointMaterial;
|
||||
current.PointPrefab = toSet.PointPrefab;
|
||||
current.PointSize = toSet.PointSize;
|
||||
current.Seperation = toSet.Seperation;
|
||||
current.MaxValue = toSet.MaxValue;
|
||||
RaisePropertyUpdated();
|
||||
}
|
||||
/// <summary>
|
||||
/// removes a group from the radar chart
|
||||
/// </summary>
|
||||
/// <param name="name">the name of the group to remove</param>
|
||||
public void RemoveGroup(string name)
|
||||
{
|
||||
ChartDataRow row = mDataSource.Rows[name];
|
||||
RemoveSliderForGroup(name);
|
||||
mDataSource.Rows.Remove(row);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a group to the radar chart. Each group holds a double value for each category.
|
||||
/// Note: you must also add at least one category to the radar chart
|
||||
/// Example: you can set the categories to "Player 1","Player 2","Player 3" and the groups to "Gold","Wood","Oil","Total"
|
||||
/// in order to compare the resources the players have gather during a level
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
public void AddGroup(string name)
|
||||
{
|
||||
mDataSource.Rows.Add(new ChartDataRow(name));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// gets the value for the specified group and category
|
||||
/// </summary>
|
||||
/// <param name="category">the category name</param>
|
||||
/// <param name="group">the group name</param>
|
||||
/// <returns></returns>
|
||||
public double GetValue(string category, string group)
|
||||
{
|
||||
return mDataSource.GetValue(category, group);
|
||||
}
|
||||
|
||||
public bool CheckAnimationEnded(float time, AnimationCurve curve)
|
||||
{
|
||||
if (curve.length == 0)
|
||||
return true;
|
||||
return time > curve.keys[curve.length - 1].time;
|
||||
}
|
||||
|
||||
private void FixEaseFunction(AnimationCurve curve)
|
||||
{
|
||||
curve.postWrapMode = WrapMode.Once;
|
||||
curve.preWrapMode = WrapMode.Once;
|
||||
}
|
||||
|
||||
private void SlideValue(string category, string group, double slideTo, float totalTime, AnimationCurve curve)
|
||||
{
|
||||
try
|
||||
{
|
||||
RemoveSlider(category, group);
|
||||
curve.postWrapMode = WrapMode.Once;
|
||||
curve.preWrapMode = WrapMode.Once;
|
||||
float time = 0f;
|
||||
if (curve.length > 0)
|
||||
time = curve.keys[curve.length - 1].time;
|
||||
Slider s = new Slider();
|
||||
s.category = category;
|
||||
s.group = group;
|
||||
s.from = GetValue(category, group);
|
||||
s.to = slideTo;
|
||||
s.startTime = Time.time;
|
||||
s.timeScale = time / totalTime;
|
||||
s.totalTime = time;
|
||||
s.curve = curve;
|
||||
mSliders.Add(s);
|
||||
}
|
||||
catch (ChartException e)
|
||||
{
|
||||
Debug.LogWarning(e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private void SlideValue(string category, string group, double slideTo, float time)
|
||||
{
|
||||
try
|
||||
{
|
||||
RemoveSlider(category, group);
|
||||
Slider s = new Slider();
|
||||
s.category = category;
|
||||
s.group = group;
|
||||
s.from = GetValue(category, group);
|
||||
s.to = slideTo;
|
||||
s.startTime = Time.time;
|
||||
s.totalTime = time;
|
||||
mSliders.Add(s);
|
||||
}
|
||||
catch (ChartException e)
|
||||
{
|
||||
Debug.LogWarning(e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// sets the value for the specified group and category
|
||||
/// </summary>
|
||||
/// <param name="category">the category name</param>
|
||||
/// <param name="group">the group name</param>
|
||||
/// <param name="amount">the value for the radar entry</param>
|
||||
public void SetValue(string category, string group, double amount)
|
||||
{
|
||||
RemoveSlider(category, group);
|
||||
SetValueInternal(category, group, amount);
|
||||
}
|
||||
|
||||
protected override void SetValueInternal(string category, string group, double amount)
|
||||
{
|
||||
try
|
||||
{
|
||||
mDataSource.SetValue(category, group, amount);
|
||||
}
|
||||
catch (ChartException e)
|
||||
{
|
||||
Debug.LogWarning(e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
CategoryData IInternalRadarData.getCategoryData(int i)
|
||||
{
|
||||
return mDataSource.Columns[i].UserData as CategoryData;
|
||||
}
|
||||
|
||||
event EventHandler IInternalRadarData.InternalDataChanged
|
||||
{
|
||||
add
|
||||
{
|
||||
DataChanged += value;
|
||||
}
|
||||
|
||||
remove
|
||||
{
|
||||
DataChanged -= value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 423e4cd2d8cf5ac4e8d4dd6b5ccda032
|
||||
timeCreated: 1489336525
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
140
Assets/Chart And Graph/Script/RadarChart/RadarFill.cs
Normal file
140
Assets/Chart And Graph/Script/RadarChart/RadarFill.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
#define Graph_And_Chart_PRO
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace ChartAndGraph
|
||||
{
|
||||
public class RadarFill : MaskableGraphic
|
||||
{
|
||||
Material mCachedMaterial;
|
||||
Vector3[] mPath;
|
||||
Rect mPathRect;
|
||||
|
||||
public RadarFill()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// sets the lines for this renderer
|
||||
/// </summary>
|
||||
/// <param name="lines"></param>
|
||||
internal void SetPath(Vector3[] path,float radius)
|
||||
{
|
||||
mPath = path;
|
||||
if (mPath.Length == 0)
|
||||
mPath = null;
|
||||
mPathRect = new Rect(-radius, -radius, radius * 2f, radius * 2f);
|
||||
SetAllDirty();
|
||||
Rebuild(CanvasUpdate.PreRender);
|
||||
}
|
||||
|
||||
protected override void UpdateMaterial()
|
||||
{
|
||||
base.UpdateMaterial();
|
||||
canvasRenderer.SetTexture(material.mainTexture);
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
ChartCommon.SafeDestroy(mCachedMaterial);
|
||||
}
|
||||
|
||||
public override Material material
|
||||
{
|
||||
get
|
||||
{
|
||||
return base.material;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
ChartCommon.SafeDestroy(mCachedMaterial);
|
||||
if (value == null)
|
||||
{
|
||||
mCachedMaterial = null;
|
||||
base.material = null;
|
||||
return;
|
||||
}
|
||||
mCachedMaterial = new Material(value);
|
||||
mCachedMaterial.hideFlags = HideFlags.DontSave;
|
||||
base.material = mCachedMaterial;
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 InterpolateInViewRect(Vector3 position)
|
||||
{
|
||||
float x = position.x - mPathRect.xMin;
|
||||
float y = position.y - mPathRect.yMin;
|
||||
return new Vector2(x / mPathRect.width, y / mPathRect.height);
|
||||
}
|
||||
|
||||
IEnumerable<UIVertex> getVerices()
|
||||
{
|
||||
if (mPath == null)
|
||||
yield break;
|
||||
UIVertex origin = new UIVertex();
|
||||
origin.position = new Vector3();
|
||||
origin.uv0 = InterpolateInViewRect(origin.position);
|
||||
for (int i=0; i<mPath.Length; i++)
|
||||
{
|
||||
UIVertex current = new UIVertex();
|
||||
current.position = mPath[i];
|
||||
current.uv0 = InterpolateInViewRect(current.position);
|
||||
yield return current;
|
||||
}
|
||||
yield return origin;
|
||||
}
|
||||
|
||||
#if (!UNITY_5_2_0) && (!UNITY_5_2_1)
|
||||
protected override void OnPopulateMesh(VertexHelper vh)
|
||||
{
|
||||
base.OnPopulateMesh(vh);
|
||||
if (mPath == null)
|
||||
{
|
||||
vh.Clear();
|
||||
return;
|
||||
}
|
||||
vh.Clear();
|
||||
foreach (UIVertex v in getVerices())
|
||||
vh.AddVert(v);
|
||||
for (int i = 0; i < mPath.Length; i++)
|
||||
{
|
||||
int prev = i - 1;
|
||||
if (prev < 0)
|
||||
prev = mPath.Length - 1;
|
||||
vh.AddTriangle(prev, i, mPath.Length);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#pragma warning disable 0672
|
||||
#if !UNITY_2017_1_OR_NEWER
|
||||
protected override void OnPopulateMesh(Mesh m)
|
||||
{
|
||||
if (mPath == null)
|
||||
{
|
||||
m.Clear();
|
||||
return;
|
||||
}
|
||||
WorldSpaceChartMesh mesh = new WorldSpaceChartMesh(1);
|
||||
foreach (UIVertex v in getVerices())
|
||||
mesh.AddVertex(v);
|
||||
for (int i = 0; i < mPath.Length; i++)
|
||||
{
|
||||
int prev = i - 1;
|
||||
if (prev < 0)
|
||||
prev = mPath.Length - 1;
|
||||
mesh.AddTringle(prev, i, mPath.Length);
|
||||
}
|
||||
mesh.ApplyToMesh(m);
|
||||
}
|
||||
#endif
|
||||
#pragma warning restore 0672
|
||||
|
||||
}
|
||||
}
|
||||
12
Assets/Chart And Graph/Script/RadarChart/RadarFill.cs.meta
Normal file
12
Assets/Chart And Graph/Script/RadarChart/RadarFill.cs.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba48626d4c97aed489456156ae2740f6
|
||||
timeCreated: 1489872231
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
135
Assets/Chart And Graph/Script/RadarChart/RadarFillGenerator.cs
Normal file
135
Assets/Chart And Graph/Script/RadarChart/RadarFillGenerator.cs
Normal file
@@ -0,0 +1,135 @@
|
||||
#define Graph_And_Chart_PRO
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ChartAndGraph
|
||||
{
|
||||
[RequireComponent(typeof(MeshRenderer))]
|
||||
[RequireComponent(typeof(MeshFilter))]
|
||||
public class RadarFillGenerator : MonoBehaviour
|
||||
{
|
||||
public int Smoothing = 3;
|
||||
/// <summary>
|
||||
/// Contains a mesh that was generate for this object only and should be destoryed once the object is cleaned
|
||||
/// </summary>
|
||||
Mesh mCleanMesh = null;
|
||||
/// <summary>
|
||||
/// the mesh filter for this object
|
||||
/// </summary>
|
||||
MeshFilter mFilter;
|
||||
|
||||
Vector3[] mPath;
|
||||
Rect mPathRect;
|
||||
float mCurve;
|
||||
|
||||
private bool EnsureMeshFilter()
|
||||
{
|
||||
if (mFilter == null)
|
||||
mFilter = GetComponent<MeshFilter>();
|
||||
if (mFilter == null)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Vector2 InterpolateInViewRect(Vector3 position)
|
||||
{
|
||||
float x = position.x - mPathRect.xMin;
|
||||
float y = position.y - mPathRect.yMin;
|
||||
return new Vector2(x / mPathRect.width, y / mPathRect.height);
|
||||
}
|
||||
|
||||
Vector3 curve(Vector3 origin,Vector3 end,float t)
|
||||
{
|
||||
Vector3 cont = Vector3.Lerp(origin, end, 0.5f);
|
||||
cont.z *= 1.5f;
|
||||
float invT = 1f - t;
|
||||
return (invT * invT * origin) + (2 * invT * t * cont) + (t * t * end);
|
||||
}
|
||||
|
||||
IEnumerable<UIVertex> getVerices()
|
||||
{
|
||||
if (mPath == null)
|
||||
yield break;
|
||||
UIVertex origin = new UIVertex();
|
||||
origin.position = new Vector3();
|
||||
origin.position.z = mCurve;
|
||||
origin.uv0 = InterpolateInViewRect(origin.position);
|
||||
for (int i = 0; i < mPath.Length; i++)
|
||||
{
|
||||
UIVertex current = new UIVertex();
|
||||
current.position = mPath[i];
|
||||
current.uv0 = InterpolateInViewRect(current.position);
|
||||
|
||||
for(int j=0; j<Smoothing; j++)
|
||||
{
|
||||
float t = ((float)(j + 1)) / (float)(Smoothing);
|
||||
UIVertex smooth = new UIVertex();
|
||||
smooth.position = curve(origin.position, current.position, t);
|
||||
smooth.uv0 = InterpolateInViewRect(smooth.position);
|
||||
yield return smooth;
|
||||
}
|
||||
}
|
||||
yield return origin;
|
||||
}
|
||||
public void Generate(Vector3[] path, float radius, float curve)
|
||||
{
|
||||
if (EnsureMeshFilter() == false) // No mesh filter attached
|
||||
return;
|
||||
|
||||
mPath = path;
|
||||
mPathRect = new Rect(-radius, -radius, radius * 2f, radius * 2f);
|
||||
mCurve = curve;
|
||||
WorldSpaceChartMesh mesh = new WorldSpaceChartMesh(1);
|
||||
int origin = 0;
|
||||
|
||||
foreach (UIVertex v in getVerices())
|
||||
origin = mesh.AddVertex(v);
|
||||
|
||||
for (int i = 0; i < mPath.Length; i++)
|
||||
{
|
||||
int prev = i - 1;
|
||||
if (prev < 0)
|
||||
prev = mPath.Length - 1;
|
||||
mesh.AddTringle(origin, i * Smoothing, prev * Smoothing);
|
||||
}
|
||||
|
||||
for (int j = 1; j < Smoothing; j++)
|
||||
{
|
||||
int current = j;
|
||||
int prev = j - 1;
|
||||
for (int i = 0; i < mPath.Length; i++)
|
||||
{
|
||||
int prevI = i - 1;
|
||||
if (prevI < 0)
|
||||
prevI = mPath.Length - 1;
|
||||
int a = (i * Smoothing) + current;
|
||||
int b = (i * Smoothing) + prev;
|
||||
int c = (prevI * Smoothing) + current;
|
||||
int d = (prevI * Smoothing) + prev;
|
||||
mesh.AddTringle(c, b, a);
|
||||
mesh.AddTringle(b, c, d);
|
||||
}
|
||||
}
|
||||
|
||||
Mesh newMesh = mesh.Generate();
|
||||
newMesh.hideFlags = HideFlags.DontSave;
|
||||
newMesh.RecalculateNormals();
|
||||
|
||||
mFilter.sharedMesh = newMesh;
|
||||
ChartCommon.CleanMesh(newMesh, ref mCleanMesh);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
ChartCommon.CleanMesh(null, ref mCleanMesh);
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3019ac406abf0214fa2995309b44054d
|
||||
timeCreated: 1490032967
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
233
Assets/Chart And Graph/Script/RadarChart/WorldSpaceRadarChart.cs
Normal file
233
Assets/Chart And Graph/Script/RadarChart/WorldSpaceRadarChart.cs
Normal file
@@ -0,0 +1,233 @@
|
||||
#define Graph_And_Chart_PRO
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ChartAndGraph
|
||||
{
|
||||
public class WorldSpaceRadarChart : RadarChart
|
||||
{
|
||||
GameObject mEmptyPointPrefab;
|
||||
|
||||
/// <summary>
|
||||
/// If this value is set all the text in the chart will be rendered to this specific camera. otherwise text is rendered to the main camera
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
[Tooltip("If this value is set all the text in the chart will be rendered to this specific camera. otherwise text is rendered to the main camera")]
|
||||
private Camera textCamera;
|
||||
|
||||
/// <summary>
|
||||
/// If this value is set all the text in the chart will be rendered to this specific camera. otherwise text is rendered to the main camera
|
||||
/// </summary>
|
||||
public Camera TextCamera
|
||||
{
|
||||
get { return textCamera; }
|
||||
set
|
||||
{
|
||||
textCamera = value;
|
||||
OnPropertyUpdated();
|
||||
}
|
||||
}
|
||||
protected override Camera TextCameraLink
|
||||
{
|
||||
get
|
||||
{
|
||||
return TextCamera;
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private PathGenerator axisPrefab;
|
||||
public PathGenerator AxisPrefab
|
||||
{
|
||||
get
|
||||
{
|
||||
return axisPrefab;
|
||||
}
|
||||
set
|
||||
{
|
||||
axisPrefab = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
[SerializeField]
|
||||
private GameObject axisPointPrefab;
|
||||
public GameObject AxisPointPrefab
|
||||
{
|
||||
get
|
||||
{
|
||||
return axisPointPrefab;
|
||||
}
|
||||
set
|
||||
{
|
||||
axisPointPrefab = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
protected override GameObject CreateAxisObject(float thickness, Vector3[] path)
|
||||
{
|
||||
GameObject obj = ChartCommon.CreateChartItem();
|
||||
ChartCommon.HideObject(obj, true);
|
||||
if (AxisPrefab != null && AxisThickness > 0.0001f)
|
||||
{
|
||||
GameObject axis = GameObject.Instantiate(AxisPrefab.gameObject);
|
||||
axis.AddComponent<ChartItem>();
|
||||
ChartCommon.HideObject(axis, hideHierarchy);
|
||||
axis.transform.SetParent(obj.transform, true);
|
||||
axis.transform.localScale = new Vector3(1f, 1f, 1f);
|
||||
axis.transform.localPosition = Vector3.zero;
|
||||
axis.transform.rotation = Quaternion.identity;
|
||||
Renderer rend = axis.GetComponent<Renderer>();
|
||||
if (rend != null && AxisLineMaterial != null)
|
||||
rend.material = AxisLineMaterial;
|
||||
PathGenerator gen = axis.GetComponent<PathGenerator>();
|
||||
gen.Generator(path, thickness, true);
|
||||
}
|
||||
|
||||
if (AxisPointPrefab != null && AxisPointSize > 0.0001f)
|
||||
{
|
||||
for(int i=0; i< path.Length; i++)
|
||||
{
|
||||
GameObject point = GameObject.Instantiate(AxisPointPrefab.gameObject);
|
||||
ChartCommon.HideObject(point, hideHierarchy);
|
||||
point.transform.SetParent(obj.transform, true);
|
||||
point.transform.localScale = new Vector3(AxisPointSize, AxisPointSize, AxisPointSize);
|
||||
point.transform.localPosition = path[i];
|
||||
point.transform.rotation = Quaternion.identity;
|
||||
Renderer rend = point.GetComponent<Renderer>();
|
||||
if(rend != null && AxisPointMaterial != null)
|
||||
rend.material = AxisPointMaterial;
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
protected GameObject CreatePrefab(GameObject container,GameObject prefab)
|
||||
{
|
||||
GameObject obj = GameObject.Instantiate(prefab);
|
||||
ChartCommon.HideObject(obj, hideHierarchy);
|
||||
ChartCommon.EnsureComponent<ChartItem>(obj);
|
||||
obj.transform.SetParent(container.transform, false);
|
||||
obj.transform.localScale = new Vector3(1f, 1f, 1f);
|
||||
obj.transform.localPosition = Vector3.zero;
|
||||
obj.transform.localRotation = Quaternion.identity;
|
||||
return obj;
|
||||
}
|
||||
|
||||
protected RadarFillGenerator CreateFillObject(GameObject conatiner)
|
||||
{
|
||||
GameObject obj = ChartCommon.CreateChartItem();
|
||||
ChartCommon.HideObject(obj, hideHierarchy);
|
||||
obj.AddComponent<ChartItem>();
|
||||
RadarFillGenerator fill = obj.AddComponent<RadarFillGenerator>();
|
||||
obj.transform.SetParent(conatiner.transform, false);
|
||||
obj.transform.localScale = new Vector3(1f, 1f, 1f);
|
||||
obj.transform.localPosition = Vector3.zero;
|
||||
obj.transform.localRotation = Quaternion.identity;
|
||||
return fill;
|
||||
}
|
||||
public override bool IsCanvas
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
protected override GameObject CreateCategoryObject(Vector3[] path, int category)
|
||||
{
|
||||
RadarChartData.CategoryData cat = ((IInternalRadarData)DataSource).getCategoryData(category);
|
||||
GameObject container = ChartCommon.CreateChartItem();
|
||||
ChartCommon.HideObject(container, hideHierarchy);
|
||||
container.transform.SetParent(transform, false);
|
||||
container.transform.localScale = new Vector3(1f, 1f, 1f);
|
||||
container.transform.localPosition = new Vector3(0f,0f,cat.Seperation);
|
||||
container.transform.localRotation = Quaternion.identity;
|
||||
|
||||
if (cat.FillMaterial != null)
|
||||
{
|
||||
|
||||
RadarFillGenerator fill = CreateFillObject(container);
|
||||
fill.Smoothing = cat.FillSmoothing;
|
||||
Renderer rend = fill.GetComponent<Renderer>();
|
||||
if(rend != null)
|
||||
rend.material = cat.FillMaterial;
|
||||
fill.Generate(path, Radius, cat.Curve);
|
||||
}
|
||||
|
||||
if (cat.LinePrefab != null && cat.LineMaterial != null && cat.LineThickness > 0)
|
||||
{
|
||||
GameObject line = CreatePrefab(container,cat.LinePrefab.gameObject);
|
||||
PathGenerator pathGen = line.GetComponent<PathGenerator>();
|
||||
Renderer rend = line.GetComponent<Renderer>();
|
||||
if (rend != null)
|
||||
rend.material = cat.LineMaterial;
|
||||
|
||||
pathGen.Generator(path, cat.LineThickness, true);
|
||||
}
|
||||
GameObject prefab = cat.PointPrefab;
|
||||
if(prefab == null)
|
||||
{
|
||||
if (mEmptyPointPrefab == null)
|
||||
mEmptyPointPrefab = (GameObject)Resources.Load("Chart And Graph/SelectHandle");
|
||||
prefab = mEmptyPointPrefab;
|
||||
}
|
||||
if (prefab != null)
|
||||
{
|
||||
for (int i=0; i<path.Length; i++)
|
||||
{
|
||||
GameObject point = CreatePrefab(container, prefab);
|
||||
string group = DataSource.GetGroupName(i);
|
||||
double value = DataSource.GetValue(cat.Name, group);
|
||||
RadarEventArgs args = new RadarEventArgs(cat.Name, group, value, path[i], i);
|
||||
point.transform.localPosition = path[i];
|
||||
point.transform.localScale = new Vector3(cat.PointSize, cat.PointSize, cat.PointSize);
|
||||
|
||||
Renderer rend = point.GetComponent<Renderer>();
|
||||
if (rend != null)
|
||||
rend.material = cat.PointMaterial;
|
||||
ChartMaterialController controller = point.GetComponent<ChartMaterialController>();
|
||||
if (controller != null && controller.Materials != null)
|
||||
{
|
||||
Color hover = controller.Materials.Hover;
|
||||
Color selected = controller.Materials.Selected;
|
||||
controller.Materials = new ChartDynamicMaterial(cat.PointMaterial, hover, selected);
|
||||
}
|
||||
ChartItemEvents[] events = point.GetComponentsInChildren<ChartItemEvents>();
|
||||
for (int j = 0; j < events.Length; ++j)
|
||||
{
|
||||
if (events[j] == null)
|
||||
continue;
|
||||
InternalItemEvents comp = (InternalItemEvents)events[j];
|
||||
comp.Parent = this;
|
||||
comp.UserData = args;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mCategoryLabels != null && mCategoryLabels.isActiveAndEnabled)
|
||||
{
|
||||
for (int i = 0; i < path.Length ; i++)
|
||||
{
|
||||
string group = DataSource.GetGroupName(i);
|
||||
double val = DataSource.GetValue(cat.Name, group);
|
||||
Vector3 labelPos = path[i];
|
||||
Vector3 dir = labelPos.normalized;
|
||||
labelPos += dir * mCategoryLabels.Seperation;
|
||||
labelPos += new Vector3(mCategoryLabels.Location.Breadth, 0f, mCategoryLabels.Location.Depth);
|
||||
int fractionDigits = 2;
|
||||
if (mItemLabels != null)
|
||||
fractionDigits = mItemLabels.FractionDigits;
|
||||
string toSet = mCategoryLabels.TextFormat.Format(ChartAdancedSettings.Instance.FormatFractionDigits(fractionDigits, val, CustomNumberFormat), cat.Name, group);
|
||||
BillboardText billboard = ChartCommon.CreateBillboardText(null,mCategoryLabels.TextPrefab, transform, toSet, labelPos.x, labelPos.y, labelPos.z, 0f, null, hideHierarchy, mCategoryLabels.FontSize, mCategoryLabels.FontSharpness);
|
||||
TextController.AddText(billboard);
|
||||
AddBillboardText(cat.Name, billboard);
|
||||
}
|
||||
}
|
||||
return container;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2aa7b1dfc92745e4b9dfb1886a0124b3
|
||||
timeCreated: 1489791118
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user