#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 class PieData : AbstractChartData, IInternalPieData , IChartData { [Serializable] internal class CategoryData { public string Name; public ChartDynamicMaterial Materials; [Range(0f, 1f)] public float RadiusScale =1f; [Range(0f, 1f)] public float DepthScale = 1f; [Range(0f, 1f)] public float DepthOffset = 0f; } [Serializable] class DataEntry { public string GroupName; public string ColumnName; public double Amount; } public PieData() { mDataSource = new ChartSparseDataSource(); mDataSource.Rows.Add(new DataSource.ChartDataRow("Pie")); } private ChartSparseDataSource mDataSource; ChartSparseDataSource IInternalPieData.InternalDataSource { get { return mDataSource; } } [SerializeField] private CategoryData[] mCategories = new CategoryData[0]; [SerializeField] private string[] mGroups = new string[1] { "Pie" }; [SerializeField] private DataEntry[] mData = new DataEntry[0]; public int TotalCategories { get { return mDataSource.Columns.Count; } } public void Update() { UpdateSliders(); } public string GetCategoryName(int index) { return mDataSource.Columns[index].Name; } public void OnBeforeSerialize() { int totalColumns = mDataSource.Columns.Count; mCategories = new CategoryData[totalColumns]; for (int i = 0; i < totalColumns; i++) { CategoryData data = new CategoryData(); data.Name = mDataSource.Columns[i].Name; data.Materials = mDataSource.Columns[i].Material; object userData = mDataSource.Columns[i].UserData; if (userData != null && userData is CategoryData) { data.RadiusScale = ((CategoryData)userData).RadiusScale; data.DepthScale = ((CategoryData)userData).DepthScale; data.DepthOffset = ((CategoryData)userData).DepthOffset; } else { data.RadiusScale = 1f; data.DepthScale = 1f; data.DepthOffset = 1f; } 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 event Action ProperyUpdated; protected void RaisePropertyUpdated() { if (ProperyUpdated != null) ProperyUpdated(); } public bool HasCategory(string category) { try { var col = mDataSource.Columns[category]; if (col != null) return true; } catch { } return false; } /// /// rename a category. throws an exception on error /// /// /// public void RenameCategory(string prevName, string newName) { mDataSource.Columns[prevName].Name = newName; RaisePropertyUpdated(); } public object StoreCategory(string category) { CategoryData data = (CategoryData)(mDataSource.Columns[category].UserData); data.Materials = mDataSource.Columns[category].Material; return data; } public void RestoreCategory(string category, object data) { var toSet = (CategoryData)data; CategoryData current = (CategoryData)(mDataSource.Columns[category].UserData); current.DepthOffset = toSet.DepthOffset; current.Materials = toSet.Materials; current.RadiusScale = toSet.RadiusScale; current.DepthScale = toSet.DepthScale; mDataSource.Columns[category].Material = toSet.Materials; RaisePropertyUpdated(); } public void SetCateogryParams(string category, float radiusScale, float depthScale, float depthOffset) { var col = mDataSource.Columns[category]; CategoryData data = col.UserData as CategoryData; data.RadiusScale = radiusScale; data.DepthScale = depthScale; data.DepthOffset = depthOffset; } /// /// call this to suspend chart redrawing while updating the data of the chart /// public void StartBatch() { mDataSource.SuspendEvents = true; } /// /// call this after StartBatch , this will apply all the changed made between the StartBatch call to this call /// public void EndBatch() { mDataSource.SuspendEvents = false; } 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].Materials, mCategories[i].RadiusScale, mCategories[i].DepthScale,mCategories[i].DepthOffset); // for (int i = 0; i < mGroups.Length; i++) // AddGroup(mGroups[i]); mDataSource.Rows.Add(new DataSource.ChartDataRow("Pie")); 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 AddGroup(string name) { mDataSource.Rows.Add(new ChartDataRow(name)); } /// /// Adds a new category to the pie chart. Each category has it's own material and name. each category corresponds to one pie slice /// /// the name of the category /// the material of the category public void AddCategory(string name, Material material) { AddCategory(name, new ChartDynamicMaterial(material), 1f,1f,0f); } /// /// clears the pie chart data /// public void Clear() { string[] groups = mDataSource.Columns.Select(x => x.Name).ToArray(); foreach (string s in groups) { RemoveCategory(s); } } /// /// Adds a new category to the pie chart. Each category has it's own material and name. each category corresponds to one pie slice /// /// the name of the category /// the dynamic material of the category. dynamic materials allows setting the material for different events public void AddCategory(string name, ChartDynamicMaterial material, float radiusScale,float depthScale,float depthOffset) { radiusScale = Mathf.Clamp(radiusScale, 0f, 1f); ChartDataColumn column = new ChartDataColumn(name); column.Material = material; CategoryData d = new CategoryData(); d.RadiusScale = radiusScale; d.DepthScale = depthScale; d.DepthOffset = depthOffset; column.UserData = d; mDataSource.mColumns.Add(column); } /// /// sets the material for the specified category /// /// the name of the category /// the material of the category public void SetMaterial(string category, Material material) { SetMaterial(category, new ChartDynamicMaterial(material)); } internal ChartDynamicMaterial GetMaterial(string category) { return mDataSource.Columns[category].Material; } /// /// sets the material for the specified category /// /// the name of the category /// the dynamic material of the category. dynamic materials allow setting the material for different events public void SetMaterial(string category, ChartDynamicMaterial material) { mDataSource.Columns[category].Material = material; RaisePropertyUpdated(); } /// /// removes a category from the pie chart /// /// the name of the category to remove public void RemoveCategory(string name) { ChartDataColumn column = mDataSource.Columns[name]; RemoveSlider(name, "Pie"); mDataSource.Columns.Remove(column); } /// /// gets the value for the specified category /// /// the category name /// the group name /// public double GetValue(string category) { return mDataSource.GetValue(category, "Pie"); } public bool CheckAnimationEnded(float time, AnimationCurve curve) { if (curve.length == 0) return true; return time > curve.keys[curve.length - 1].time; } /// /// used intenally , do not call /// /// public object[] StoreAllCategoriesinOrder() { return mCategories.ToArray(); } private void FixEaseFunction(AnimationCurve curve) { curve.postWrapMode = WrapMode.Once; curve.preWrapMode = WrapMode.Once; } public void SlideValue(string category, double slideTo, float timeScale, AnimationCurve curve) { try { RemoveSlider(category, "Pie"); string group = "Pie"; 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); s.to = slideTo; s.startTime = Time.time; s.timeScale = timeScale; s.totalTime = time; s.curve = curve; mSliders.Add(s); } catch (ChartException e) { Debug.LogWarning(e.Message); } } public void SlideValue(string category, double slideTo, float time) { try { RemoveSlider(category, "Pie"); string group = "Pie"; Slider s = new Slider(); s.category = category; s.group = group; s.from = GetValue(category); s.to = slideTo; s.startTime = Time.time; s.totalTime = time; mSliders.Add(s); } catch (ChartException e) { Debug.LogWarning(e.Message); } } /// /// sets the value for the specified category /// /// the category name /// the value of the pie item public void SetValue(string category, double amount) { RemoveSlider(category, "Pie"); SetValueInternal(category, "Pie", amount); } protected override void SetValueInternal(string column, string row, double value) { try { mDataSource.SetValue(column, "Pie", value); } catch(ChartException e) { Debug.LogWarning(e.Message); } } } }