#define Graph_And_Chart_PRO using System; using System.Collections.Generic; using UnityEditor; using UnityEngine; namespace ChartAndGraph { [CustomEditor(typeof(CandleChart), true)] class CandleChartInspector : Editor { bool mCategories = false; string mCategoryError = null; string mNewCategoryName = ""; GUIStyle mRedStyle; GUIStyle mBold; HashSet mAllNames = new HashSet(); GUIStyle mSplitter; List mToRemove = new List(); List mToUp = new List(); Dictionary mOperations = new Dictionary(); ChartDataEditor mWindow; Texture mSettings; RenameWindow mRenameWindow = null; public void OnEnable() { mRedStyle = new GUIStyle(); mRedStyle.normal.textColor = Color.red; mSplitter = new GUIStyle(); mSplitter.normal.background = EditorGUIUtility.whiteTexture; mSplitter.stretchWidth = true; mSplitter.margin = new RectOffset(0, 0, 7, 7); } public void Splitter() { Rect position = GUILayoutUtility.GetRect(GUIContent.none, mSplitter, GUILayout.Height(1f)); if (Event.current.type == EventType.Repaint) { Color restoreColor = GUI.color; GUI.color = new Color(0.5f, 0.5f, 0.5f); mSplitter.Draw(position, false, false, false, false); GUI.color = restoreColor; } } private static bool IsAlphaNum(string str) { if (string.IsNullOrEmpty(str)) return false; for (int i = 0; i < str.Length; i++) { if (!(char.IsLetter(str[i])) && (!(char.IsNumber(str[i]))) && str[i] != ' ') return false; } return true; } private void DoOperations(SerializedProperty items, int size, string type) { mToRemove.Clear(); mToUp.Clear(); bool up = false; for (int i = 0; i < size; i++) { SerializedProperty entry = items.GetArrayElementAtIndex(i); if (entry == null) continue; SerializedProperty nameProp = entry.FindPropertyRelative("Name"); string name = null; if (nameProp == null) name = entry.stringValue; else name = nameProp.stringValue; string arg = type + "|" + name; string res = null; if (up == true) { mToUp.Add(i); up = false; } if (mOperations.TryGetValue(arg, out res)) { if (res == "remove") mToRemove.Add(i); if (res == "up" && i > 0) mToUp.Add(i); if (res == "down") up = true; mOperations.Remove(arg); } } for (int i = 0; i < mToRemove.Count; i++) { items.DeleteArrayElementAtIndex(mToRemove[i]); } for (int i = 0; i < mToUp.Count; i++) { int cur = mToUp[i]; items.MoveArrayElement(cur, cur - 1); } } private void CandleSettings(SerializedProperty item) { SerializedProperty entry = item.Copy(); EditorGUILayout.LabelField(entry.name); EditorGUI.indentLevel++; SerializedProperty end = entry.GetEndProperty(true); entry.Next(true); if (SerializedProperty.EqualContents(entry, end) == false) { do { if (target is CandleChart) // canvas graph chart { if ((entry.name == "CandlePrefab")) { continue; } } else { if (entry.name == "CandleHoverPrefab") continue; } EditorGUILayout.PropertyField(entry, true); } while (entry.Next(false) && SerializedProperty.EqualContents(entry, end) == false); } EditorGUI.indentLevel--; } private void NamedItemEditor(SerializedProperty data, string type, string property, string caption, ref string errorMessage, ref bool foldout, ref string newName) { SerializedProperty items = data.FindPropertyRelative(property); items.isExpanded = EditorGUILayout.Foldout(items.isExpanded, caption); //bool up, down; mAllNames.Clear(); int size = items.arraySize; if (Event.current.type == EventType.Layout) DoOperations(items, size, type); size = items.arraySize; if (items.isExpanded) { EditorGUI.indentLevel++; for (int i = 0; i < size; i++) { SerializedProperty entry = items.GetArrayElementAtIndex(i); if (entry == null) continue; SerializedProperty nameProp = entry.FindPropertyRelative("Name"); string name = null; if (nameProp == null) name = entry.stringValue; else name = nameProp.stringValue; mAllNames.Add(name); bool toogle = false; EditorGUILayout.BeginHorizontal(); if (nameProp != null) toogle = entry.isExpanded = EditorGUILayout.Foldout(entry.isExpanded, name); else { toogle = false; EditorGUILayout.LabelField(name); } GUILayout.FlexibleSpace(); if (GUILayout.Button("...")) DoContext(type, name); EditorGUILayout.EndHorizontal(); if (toogle) { EditorGUI.indentLevel++; if (nameProp != null) { SerializedProperty end = entry.GetEndProperty(true); entry.Next(true); if (SerializedProperty.EqualContents(entry, end) == false) { do { if (entry.name != "Name" && entry.name != "Data") { if (target is CandleChart) // canvas graph chart { if ((entry.name == "LinePrefab") || (entry.name == "FillPrefab") || (entry.name == "DotPrefab") || (entry.name == "Depth")) { continue; } } else { if ((entry.name == "LineHoverPrefab") || (entry.name == "PointHoverPrefab")) continue; } if (entry.name == "UpCandle" || entry.name == "DownCandle") CandleSettings(entry); else EditorGUILayout.PropertyField(entry, true); } } while (entry.Next(false) && SerializedProperty.EqualContents(entry, end) == false); } } EditorGUI.indentLevel--; } } if (errorMessage != null) EditorGUILayout.LabelField(errorMessage, mRedStyle); EditorGUILayout.LabelField(string.Format("Add new {0} :", type)); //Rect indentAdd = EditorGUI.IndentedRect(new Rect(0f, 0f, 1000f, 1000f)); EditorGUILayout.BeginHorizontal(); newName = EditorGUILayout.TextField(newName); //GUILayout.Space(indentAdd.xMin); if (GUILayout.Button("Add")) { bool error = false; if (newName.Trim().Length == 0) { errorMessage = "Name can't be empty"; error = true; } else if (IsAlphaNum(newName) == false) { errorMessage = "Name conatins invalid characters"; error = true; } else if (mAllNames.Contains(newName)) { errorMessage = string.Format("A {0} named {1} already exists in this chart", type, newName); error = true; } if (error == false) { errorMessage = null; items.InsertArrayElementAtIndex(size); SerializedProperty newItem = items.GetArrayElementAtIndex(size); SerializedProperty newItemName = newItem.FindPropertyRelative("Name"); if (newItemName == null) newItem.stringValue = newName; else newItemName.stringValue = newName; newName = ""; UpdateWindow(); } } EditorGUILayout.EndHorizontal(); EditorGUI.indentLevel--; } else { errorMessage = null; } UpdateWindow(); } void callback(object val) { KeyValuePair pair = (KeyValuePair)val; mOperations[pair.Key] = pair.Value; } bool RenameCategory(string oldName, string newName) { CandleChart graph = (CandleChart)serializedObject.targetObject; try { graph.DataSource.RenameCategory(oldName, newName); } catch (Exception) { return false; } serializedObject.Update(); if (graph.gameObject.activeInHierarchy) graph.GenerateChart(); else EditorUtility.SetDirty(graph); return true; } void RenameCalled(object val) { var data = (KeyValuePair)val; RenameWindow window = EditorWindow.GetWindow(); mRenameWindow = window; window.ShowDialog(data.Value, data.Key, RenameCategory); } void DoContext(string type, string name) { string arg = type + "|" + name; GenericMenu menu = new GenericMenu(); menu.AddItem(new GUIContent("Move Up"), false, callback, new KeyValuePair(arg, "up")); menu.AddItem(new GUIContent("Move Down"), false, callback, new KeyValuePair(arg, "down")); menu.AddItem(new GUIContent("Remove"), false, callback, new KeyValuePair(arg, "remove")); menu.AddItem(new GUIContent("Rename.."), false, RenameCalled, new KeyValuePair(type, name)); menu.ShowAsContext(); } void UpdateWindow() { } void OnDisable() { if (mRenameWindow != null) { mRenameWindow.Close(); mRenameWindow = null; } if (mWindow != null) { mWindow.Close(); mWindow = null; } } public override void OnInspectorGUI() { base.OnInspectorGUI(); SerializedProperty autoScrollHorizontally = serializedObject.FindProperty("autoScrollHorizontally"); SerializedProperty horizontalScrolling = serializedObject.FindProperty("horizontalScrolling"); SerializedProperty autoScrollVertically = serializedObject.FindProperty("autoScrollVertically"); SerializedProperty verticalScrolling = serializedObject.FindProperty("verticalScrolling"); // SerializedProperty scrollable = serializedObject.FindProperty("scrollable"); // EditorGUILayout.PropertyField(scrollable); // if (scrollable.boolValue == true) { EditorGUI.indentLevel++; EditorGUILayout.PropertyField(autoScrollHorizontally); if (autoScrollHorizontally.boolValue == false) EditorGUILayout.PropertyField(horizontalScrolling); EditorGUILayout.PropertyField(autoScrollVertically); if (autoScrollVertically.boolValue == false) EditorGUILayout.PropertyField(verticalScrolling); EditorGUI.indentLevel--; } SerializedProperty graphData = serializedObject.FindProperty("Data"); EditorGUILayout.BeginVertical(); Splitter(); if (mBold == null) mBold = new GUIStyle(EditorStyles.foldout); EditorGUILayout.LabelField("Data", EditorStyles.boldLabel); EditorGUI.indentLevel++; NamedItemEditor(graphData, "category", "mSerializedData", "Categories", ref mCategoryError, ref mCategories, ref mNewCategoryName); EditorGUI.indentLevel--; SerializedProperty horizontalOrigin = graphData.FindPropertyRelative("horizontalViewOrigin"); SerializedProperty horizontalSize = graphData.FindPropertyRelative("horizontalViewSize"); SerializedProperty automaticcHorizontaViewGap = graphData.FindPropertyRelative("automaticcHorizontaViewGap"); SerializedProperty verticalOrigin = graphData.FindPropertyRelative("verticalViewOrigin"); SerializedProperty verticalSize = graphData.FindPropertyRelative("verticalViewSize"); SerializedProperty automaticVerticalViewGap = graphData.FindPropertyRelative("automaticVerticalViewGap"); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Horizontal View", EditorStyles.boldLabel); SerializedProperty automaticProp = graphData.FindPropertyRelative("automaticHorizontalView"); bool automatic = automaticProp.boolValue; automatic = GUILayout.Toggle(automatic, "Auto"); GUILayout.FlexibleSpace(); automaticProp.boolValue = automatic; EditorGUILayout.EndHorizontal(); if (automatic == false) { EditorGUILayout.PropertyField(horizontalOrigin); EditorGUILayout.PropertyField(horizontalSize); // if (horizontalSize.doubleValue < 0.0) // horizontalSize.doubleValue = 0.0001; } else { EditorGUILayout.PropertyField(automaticcHorizontaViewGap, new GUIContent("Horizontal Gap")); } EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Vertical View", EditorStyles.boldLabel); automaticProp = graphData.FindPropertyRelative("automaticVerticallView"); automatic = automaticProp.boolValue; automatic = GUILayout.Toggle(automatic, "Auto"); GUILayout.FlexibleSpace(); automaticProp.boolValue = automatic; EditorGUILayout.EndHorizontal(); if (automatic == false) { EditorGUILayout.PropertyField(verticalOrigin); EditorGUILayout.PropertyField(verticalSize); // if (verticalSize.doubleValue < 0.0) // verticalSize.doubleValue = 0.0001; } else { EditorGUILayout.PropertyField(automaticVerticalViewGap, new GUIContent("Vertical Gap")); } EditorGUILayout.EndVertical(); serializedObject.ApplyModifiedProperties(); serializedObject.Update(); } } }