#define Graph_And_Chart_PRO using UnityEngine; using System.Collections; using System; using ChartAndGraph; using System.Collections.Generic; using System.Globalization; #if UNITY_2018_1_OR_NEWER using UnityEngine.Networking; #endif public class GraphDataFiller : MonoBehaviour { [Serializable] public enum DataType { VectorArray, ArrayForEachElement, ObjectArray, } public enum DocumentFormat { XML, JSON } public enum VectorFormat { X_Y, Y_X, X_Y_SIZE, Y_X_SIZE, SIZE_X_Y, SIZE_Y_X, X_Y_GAP_SIZE, Y_X_GAP_SIZE } class VectorFormatData { public int X, Y, Size, Length; public VectorFormatData(int x, int y, int size, int length) { X = x; Y = y; Size = size; Length = length; } } [Serializable] public class CategoryData { public bool Enabled = true; [ChartFillerEditor(DataType.ObjectArray)] [ChartFillerEditor(DataType.ArrayForEachElement)] [ChartFillerEditorAttribute(DataType.VectorArray)] public string Name; /// /// The way the data is stored in the object /// public DataType DataType; [ChartFillerEditorAttribute(DataType.VectorArray)] public VectorFormat DataFormat; /// /// the amount of items to skip after each dataformat instance /// [ChartFillerEditorAttribute(DataType.VectorArray)] public int Skip = 0; /// /// if this is empty then DataObjectName is not relative /// [ChartFillerEditor(DataType.ObjectArray)] [ChartFillerEditor(DataType.ArrayForEachElement)] public string ParentObjectName; [ChartFillerEditorAttribute(DataType.VectorArray)] public string DataObjectName; [ChartFillerEditor(DataType.ObjectArray)] [ChartFillerEditor(DataType.ArrayForEachElement)] public string XDataObjectName; [ChartFillerEditor(DataType.ObjectArray)] [ChartFillerEditor(DataType.ArrayForEachElement)] public string YDataObjectName; [ChartFillerEditor(DataType.ObjectArray)] [ChartFillerEditor(DataType.ArrayForEachElement)] public string SizeDataObjectName; /// /// set to empty null or "none" for numbers. Set to a date format for a date : https://docs.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings /// [ChartFillerEditor(DataType.ObjectArray)] [ChartFillerEditor(DataType.ArrayForEachElement)] public string XDateFormat = ""; [ChartFillerEditor(DataType.ObjectArray)] [ChartFillerEditor(DataType.ArrayForEachElement)] public string YDateFormat = ""; } public GraphChartBase GraphObject; /// /// assign a graph chart prefab that will be used to copy category data /// public GraphChartBase CategoryPrefab; public DocumentFormat Format; public string RemoteUrl; public bool FillOnStart; public CategoryData[] Categories = new CategoryData[0]; private object[] mCategoryVisualStyle; delegate void CategoryLoader(CategoryData data); private Dictionary mLoaders; private static Dictionary mVectorFormats; private ChartParser mParser; static GraphDataFiller() { CreateVectorFormats(); } void EnsureCreateDataTypes() { if (mLoaders != null) return; mLoaders = new Dictionary(); mLoaders[DataType.ArrayForEachElement] = LoadArrayForEachElement; mLoaders[DataType.ObjectArray] = LoadObjectArray; mLoaders[DataType.VectorArray] = LoadVectorArray; } static void CreateVectorFormats() { mVectorFormats = new Dictionary(); mVectorFormats[VectorFormat.X_Y] = new VectorFormatData(0, 1, -1, 2); mVectorFormats[VectorFormat.Y_X] = new VectorFormatData(1, 0, -1, 2); mVectorFormats[VectorFormat.X_Y_SIZE] = new VectorFormatData(0, 1, 2, 3); mVectorFormats[VectorFormat.Y_X_SIZE] = new VectorFormatData(1, 0, 2, 3); mVectorFormats[VectorFormat.SIZE_X_Y] = new VectorFormatData(1, 2, 0, 3); mVectorFormats[VectorFormat.SIZE_Y_X] = new VectorFormatData(2, 1, 0, 3); mVectorFormats[VectorFormat.X_Y_GAP_SIZE] = new VectorFormatData(0, 1, 3, 4); mVectorFormats[VectorFormat.Y_X_GAP_SIZE] = new VectorFormatData(1, 0, 3, 4); } private double ParseItem(string item, string format) { if (String.IsNullOrEmpty(format) || format.Equals("none", StringComparison.OrdinalIgnoreCase)) { double outputValueDouble; double.TryParse(string.Format(CultureInfo.InvariantCulture, "{0}", item), NumberStyles.Any, CultureInfo.InvariantCulture, out outputValueDouble); return outputValueDouble; } return ChartDateUtility.DateToValue(DateTime.ParseExact(item, format, CultureInfo.InvariantCulture)); } void LoadArrayForEachElement(CategoryData data) { GraphChartBase graph = GraphObject.GetComponent(); if (mParser.SetPathRelativeTo(data.ParentObjectName) == false) { Debug.LogWarning("Object " + data.ParentObjectName + " does not exist in the document"); return; } var xObj = mParser.GetObject(data.XDataObjectName); var yObj = mParser.GetObject(data.YDataObjectName); object sizeObj = null; if (String.IsNullOrEmpty(data.SizeDataObjectName) == false) sizeObj = mParser.GetObject(data.SizeDataObjectName); int length = Math.Min(mParser.GetArraySize(xObj), mParser.GetArraySize(yObj)); if (sizeObj != null) length = Math.Min(length, mParser.GetArraySize(sizeObj)); try { for (int i = 0; i < length; i++) { double x = ParseItem(mParser.GetItem(xObj, i), data.XDateFormat); double y = ParseItem(mParser.GetItem(yObj, i), data.YDateFormat); double pointSize = -1; if (sizeObj != null) pointSize = double.Parse(mParser.GetItem(sizeObj, i)); graph.DataSource.AddPointToCategory(data.Name, x, y, pointSize); } } catch (Exception e) { Debug.LogWarning("Data for category " + data.Name + " does not match the specified format. Ended with exception : " + e.ToString()); } } void LoadObjectArray(CategoryData data) { GraphChartBase graph = GraphObject.GetComponent(); var parent = mParser.GetObject(data.ParentObjectName); if (parent == null) { Debug.LogWarning("Object " + data.ParentObjectName + " does not exist in the document"); return; } int length = mParser.GetArraySize(parent); try { for (int i = 0; i < length; i++) { object item = mParser.GetItemObject(parent, i); double x = ParseItem(mParser.GetChildObjectValue(item, data.XDataObjectName), data.XDateFormat); double y = ParseItem(mParser.GetChildObjectValue(item, data.YDataObjectName), data.YDateFormat); double pointSize = -1; if (String.IsNullOrEmpty(data.SizeDataObjectName) == false) pointSize = double.Parse(mParser.GetChildObjectValue(item, data.SizeDataObjectName)); graph.DataSource.AddPointToCategory(data.Name, x, y, pointSize); } } catch (Exception e) { Debug.LogWarning("Data for category " + data.Name + " does not match the specified format. Ended with exception : " + e.ToString()); } } void LoadVectorArray(CategoryData data) { GraphChartBase graph = GraphObject.GetComponent(); var obj = mParser.GetObject(data.DataObjectName); int size = mParser.GetArraySize(obj); VectorFormatData formatData = mVectorFormats[data.DataFormat]; if (size < 0) // this is not an array , show warning { Debug.LogWarning("DataType " + data.DataType + " does not match category " + data.Name); return; } int itemLength = data.Skip + formatData.Length; try { for (int i = 0; i < size; i += itemLength) { double x = ParseItem(mParser.GetItem(obj, i + formatData.X), data.XDateFormat); double y = ParseItem(mParser.GetItem(obj, i + formatData.Y), data.YDateFormat); double pointSize = -1; if (formatData.Size >= 0) pointSize = double.Parse(mParser.GetItem(obj, i + formatData.Size)); graph.DataSource.AddPointToCategory(data.Name, x, y, pointSize); } } catch (Exception e) { Debug.LogWarning("Data for category " + data.Name + " does not match the specified format. Ended with exception : " + e.ToString()); } } void Start() { if (FillOnStart) Fill(); } public void Fill() { Fill(null); } public void Fill(WWWForm postData) { StartCoroutine(GetData(postData)); } void LoadCategoryVisualStyle(GraphChartBase graph) { var prefab = CategoryPrefab; if (prefab == null) { if (graph is GraphChart) prefab = ((GameObject)Resources.Load("Chart And Graph/DefualtGraphCategoryStyle2D")).GetComponent(); else prefab = ((GameObject)Resources.Load("Chart And Graph/DefualtGraphCategoryStyle3D")).GetComponent(); // load default } if (prefab == null) Debug.LogError("missing resources for graph and chart, please reimport the package"); else mCategoryVisualStyle = prefab.DataSource.StoreAllCategoriesinOrder(); } public void ApplyData(string text) { GraphChartBase graph = GraphObject.GetComponent(); if (Format == DocumentFormat.JSON) mParser = new JsonParser(text); else mParser = new XMLParser(text); LoadCategoryVisualStyle(graph); EnsureCreateDataTypes(); if (mCategoryVisualStyle.Length == 0) { Debug.LogWarning("no visual styles defeind for GraphDataFiller, aborting"); return; } if (mCategoryVisualStyle.Length < Categories.Length) Debug.LogWarning("not enough visual styles in GraphDataFiller"); graph.DataSource.StartBatch(); for (int i = 0; i < Categories.Length; i++) { var cat = Categories[i]; if (cat.Enabled == false) continue; int visualIndex = Math.Min(i, mCategoryVisualStyle.Length - 1); object visualStyle = mCategoryVisualStyle[visualIndex]; if (graph.DataSource.HasCategory(cat.Name)) graph.DataSource.RemoveCategory(cat.Name); graph.DataSource.AddCategory(cat.Name, null, 0, new MaterialTiling(), null, false, null, 0); graph.DataSource.RestoreCategory(cat.Name, visualStyle); // set the visual style of the category to the one in the prefab var loader = mLoaders[cat.DataType]; // find the loader based on the data type loader(cat); // load the category data } graph.DataSource.EndBatch(); } #if UNITY_2018_1_OR_NEWER UnityWebRequest CreateRequest(WWWForm postData) { if (postData == null) return UnityWebRequest.Get(RemoteUrl); return UnityWebRequest.Post(RemoteUrl, postData); } IEnumerator GetData(WWWForm postData) { using (UnityWebRequest webRequest = CreateRequest(postData)) { yield return webRequest.SendWebRequest(); #if UNITY_2020_1_OR_NEWER if (webRequest.result != UnityWebRequest.Result.Success) #else if (webRequest.isNetworkError) #endif Debug.LogError("Graph Data Filler : URL request failed ," + webRequest.error); else { try { string text = webRequest.downloadHandler.text; ApplyData(text); } catch (Exception e) { Debug.LogError("Graph Data Filler : Invalid document format, please check your settings , with exception " + e.ToString()); } } } } #else IEnumerator GetData(WWWForm postData) { WWW request; if (postData != null) { request = new WWW(RemoteUrl, postData); } else request = new WWW(RemoteUrl); yield return request; if (String.IsNullOrEmpty(request.error)) { try { string text = request.text; ApplyData(text); } catch (Exception e) { Debug.LogError("Graph Data Filler : Invalid document format, please check your settings , with exception " + e.ToString()); } } else { Debug.LogError("Graph Data Filler : URL request failed ," + request.error); } } #endif void Update() { } }