작업 조건 분석 기능 개발

This commit is contained in:
정영민
2025-03-10 16:42:23 +09:00
parent 840638c6e3
commit f2029fd8c9
2988 changed files with 569938 additions and 2342 deletions

View 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);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: c464cf59e9a4ba541a0d4e7075fca70a
timeCreated: 1489791118
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 046040936f1f8ea4284661c490961035
timeCreated: 1489344710
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}
}

View 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:

View File

@@ -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");
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 9f713b3cf6feafc4bbe929f2e5dbafd2
timeCreated: 1560540959
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 423e4cd2d8cf5ac4e8d4dd6b5ccda032
timeCreated: 1489336525
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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
}
}

View 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:

View 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();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 3019ac406abf0214fa2995309b44054d
timeCreated: 1490032967
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2aa7b1dfc92745e4b9dfb1886a0124b3
timeCreated: 1489791118
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: