diff --git a/Homebrew/DecorateFoldout/Attributes/FoldAttribute.cs b/Homebrew/DecorateFoldout/Attributes/FoldAttribute.cs index de4470c..1c9998b 100644 --- a/Homebrew/DecorateFoldout/Attributes/FoldAttribute.cs +++ b/Homebrew/DecorateFoldout/Attributes/FoldAttribute.cs @@ -1,27 +1,23 @@ -/*=============================================================== -Product: ActorBasedBehaviors -Developer: Dimitry Pixeye - info@pixeye,games -Company: Homebrew -Date: 5/17/2018 6:31 AM -================================================================*/ +// Project : UNITY FOLDOUT +// Contacts : Pix - ask@pixeye.games using UnityEngine; -namespace Homebrew +namespace Pixeye.Unity { public class FoldoutAttribute : PropertyAttribute { public string name; public bool foldEverything; - + /// Adds the property to the specified foldout group. /// Name of the foldout group. /// Toggle to put all properties to the specified group public FoldoutAttribute(string name, bool foldEverything = false) { this.foldEverything = foldEverything; - this.name = name; + this.name = name; } } } \ No newline at end of file diff --git a/Homebrew/DecorateFoldout/Editor/EditorOverride.cs b/Homebrew/DecorateFoldout/Editor/EditorOverride.cs index f81ef6d..0eaa7e3 100644 --- a/Homebrew/DecorateFoldout/Editor/EditorOverride.cs +++ b/Homebrew/DecorateFoldout/Editor/EditorOverride.cs @@ -1,3 +1,7 @@ +// Project : UNITY FOLDOUT +// Contacts : Pix - ask@pixeye.games + + using System; using System.Collections.Generic; using System.Linq; @@ -6,227 +10,236 @@ using UnityEngine; using Object = UnityEngine.Object; -namespace Homebrew + +namespace Pixeye.Unity { [CustomEditor(typeof(Object), true, isFallback = true)] [CanEditMultipleObjects] public class EditorOverride : Editor { - private Dictionary cache = new Dictionary(); - private List props = new List(); - private SerializedProperty propScript; - private Type type; - private int length; - private List objectFields; - private bool initialized; - private Colors colors; - private FoldoutAttribute prevFold; - private GUIStyle style; - - private void Awake() - { - var uiTex_in = Resources.Load("IN foldout focus-6510"); - var uiTex_in_on = Resources.Load("IN foldout focus on-5718"); + //===============================// + // Members + //===============================// - var c_on = Color.white; - - style = new GUIStyle(EditorStyles.foldout); + Dictionary cacheFolds = new Dictionary(); + List props = new List(); + List methods = new List(); + bool initialized; - style.overflow = new RectOffset(-10, 0, 3, 0); - style.padding = new RectOffset(25, 0, -3, 0); - style.active.textColor = c_on; - style.active.background = uiTex_in; - style.onActive.textColor = c_on; - style.onActive.background = uiTex_in_on; + //===============================// + // Logic + //===============================// - style.focused.textColor = c_on; - style.focused.background = uiTex_in; - style.onFocused.textColor = c_on; - style.onFocused.background = uiTex_in_on; - - - - } void OnEnable() { - - bool pro = EditorGUIUtility.isProSkin; - if (!pro) - { - colors = new Colors(); - colors.col0 = new Color(0.2f, 0.2f, 0.2f, 1f); - colors.col1 = new Color(1, 1, 1, 0.55f); - colors.col2 = new Color(0.7f, 0.7f, 0.7f, 1f); - } - else - { - colors = new Colors(); - colors.col0 = new Color(0.2f, 0.2f, 0.2f, 1f); - colors.col1 = new Color(1, 1, 1, 0.1f); - colors.col2 = new Color(0.25f, 0.25f, 0.25f, 1f); - } - - var t = target.GetType(); - var typeTree = t.GetTypeTree(); - objectFields = target.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | - BindingFlags.Instance) - .OrderByDescending(x => typeTree.IndexOf(x.DeclaringType)).ToList(); - - - length = objectFields.Count; - - - Repaint(); initialized = false; - } - private void OnDisable() + + void OnDisable() { - foreach (var cach in cache) - { - cach.Value.Dispose(); - } + //if (Application.wantsToQuit) + //if (applicationIsQuitting) return; + // if (Toolbox.isQuittingOrChangingScene()) return; + if (target != null) + foreach (var c in cacheFolds) + { + EditorPrefs.SetBool(string.Format($"{c.Value.atr.name}{c.Value.props[0].name}{target.name}"), c.Value.expanded); + c.Value.Dispose(); + } } + public override bool RequiresConstantRepaint() + { + return EditorFramework.needToRepaint; + } + public override void OnInspectorGUI() { serializedObject.Update(); - if (!initialized) + Setup(); + + if (props.Count == 0) + { + DrawDefaultInspector(); + return; + } + + Header(); + Body(); + + serializedObject.ApplyModifiedProperties(); + + void Header() { - for (var i = 0; i < length; i++) + using (new EditorGUI.DisabledScope("m_Script" == props[0].propertyPath)) { - var fold = Attribute.GetCustomAttribute(objectFields[i], typeof(FoldoutAttribute)) as FoldoutAttribute; + EditorGUILayout.Space(); + EditorGUILayout.PropertyField(props[0], true); + EditorGUILayout.Space(); + } + } - Cache c; - if (fold == null) - { - if (prevFold != null && prevFold.foldEverything) - { - if (!cache.TryGetValue(prevFold.name, out c)) - { - cache.Add(prevFold.name, new Cache {atr = prevFold, types = new HashSet {objectFields[i].Name}}); - } - else - { - c.types.Add(objectFields[i].Name); - } - } + void Body() + { + foreach (var pair in cacheFolds) + { + this.UseVerticalLayout(() => Foldout(pair.Value), StyleFramework.box); + EditorGUI.indentLevel = 0; + } - continue; - } + EditorGUILayout.Space(); - prevFold = fold; - if (!cache.TryGetValue(fold.name, out c)) - { - cache.Add(fold.name, new Cache {atr = fold, types = new HashSet {objectFields[i].Name}}); - } - else - { - c.types.Add(objectFields[i].Name); - } + for (var i = 1; i < props.Count; i++) + { + // if (props[i].isArray) + // { + // DrawPropertySortableArray(props[i]); + // } + // else + // { + EditorGUILayout.PropertyField(props[i], true); + //} } + EditorGUILayout.Space(); - var property = serializedObject.GetIterator(); - var next = property.NextVisible(true); - if (next) + if (methods == null) return; + foreach (MethodInfo memberInfo in methods) { - do - { - HandleProp(property); - } while (property.NextVisible(false)); + this.UseButton(memberInfo); } } - - if (props.Count == 0) + void Foldout(CacheFoldProp cache) { - DrawDefaultInspector(); - return; - } + cache.expanded = EditorGUILayout.Foldout(cache.expanded, cache.atr.name, true, + StyleFramework.foldout); - initialized = true; + if (cache.expanded) + { + EditorGUI.indentLevel = 1; - using (new EditorGUI.DisabledScope("m_Script" == props[0].propertyPath)) - { - EditorGUILayout.PropertyField(props[0], true); - } + for (int i = 0; i < cache.props.Count; i++) + { + this.UseVerticalLayout(() => Child(i), StyleFramework.boxChild); + } + } - EditorGUILayout.Space(); + void Child(int i) + { + // if (cache.props[i].isArray) + // { + // DrawPropertySortableArray(cache.props[i]); + // } + // else + // { + EditorGUILayout.PropertyField(cache.props[i], new GUIContent(cache.props[i].name.FirstLetterToUpperCase()), true); + //} + } + } - foreach (var pair in cache) + void Setup() { - var rect = EditorGUILayout.BeginVertical(); - - EditorGUILayout.Space(); + EditorFramework.currentEvent = Event.current; + if (!initialized) + { + // SetupButtons(); - EditorGUI.DrawRect(new Rect(rect.x - 1, rect.y - 1, rect.width + 1, rect.height + 1), - colors.col0); + List objectFields; + FoldoutAttribute prevFold = default; - EditorGUI.DrawRect(new Rect(rect.x - 1, rect.y - 1, rect.width + 1, rect.height + 1), colors.col1); + var length = EditorTypes.Get(target, out objectFields); + for (var i = 0; i < length; i++) + { + #region FOLDERS - pair.Value.expanded = EditorGUILayout.Foldout(pair.Value.expanded, pair.Value.atr.name, true, - style != null ? style : EditorStyles.foldout); + var fold = Attribute.GetCustomAttribute(objectFields[i], typeof(FoldoutAttribute)) as FoldoutAttribute; + CacheFoldProp c; + if (fold == null) + { + if (prevFold != null && prevFold.foldEverything) + { + if (!cacheFolds.TryGetValue(prevFold.name, out c)) + { + cacheFolds.Add(prevFold.name, new CacheFoldProp {atr = prevFold, types = new HashSet {objectFields[i].Name}}); + } + else + { + c.types.Add(objectFields[i].Name); + } + } + continue; + } - EditorGUILayout.EndVertical(); + prevFold = fold; - rect = EditorGUILayout.BeginVertical(); + if (!cacheFolds.TryGetValue(fold.name, out c)) + { + var expanded = EditorPrefs.GetBool(string.Format($"{fold.name}{objectFields[i].Name}{target.name}"), false); + cacheFolds.Add(fold.name, new CacheFoldProp {atr = fold, types = new HashSet {objectFields[i].Name}, expanded = expanded}); + } + else c.types.Add(objectFields[i].Name); - EditorGUI.DrawRect(new Rect(rect.x - 1, rect.y - 1, rect.width + 1, rect.height + 1), - colors.col2); + #endregion + } - if (pair.Value.expanded) - { - EditorGUILayout.Space(); + var property = serializedObject.GetIterator(); + var next = property.NextVisible(true); + if (next) { - for (int i = 0; i < pair.Value.props.Count; i++) + do { - EditorGUI.indentLevel = 1; - - EditorGUILayout.PropertyField(pair.Value.props[i], - new GUIContent(pair.Value.props[i].displayName), true); - if (i == pair.Value.props.Count - 1) - EditorGUILayout.Space(); - } + HandleFoldProp(property); + } while (property.NextVisible(false)); } - } - - EditorGUI.indentLevel = 0; - EditorGUILayout.EndVertical(); - EditorGUILayout.Space(); - } - - for (var i = 1; i < props.Count; i++) - { - EditorGUILayout.PropertyField(props[i], true); + initialized = true; + } } - - serializedObject.ApplyModifiedProperties(); - EditorGUILayout.Space(); + // void SetupButtons() + // { + // var members = GetButtonMembers(target); + // + // foreach (var memberInfo in members) + // { + // var method = memberInfo as MethodInfo; + // if (method == null) + // { + // continue; + // } + // + // if (method.GetParameters().Length > 0) + // { + // continue; + // } + // + // if (methods == null) methods = new List(); + // methods.Add(method); + // } + // } } - - public void HandleProp(SerializedProperty prop) + public void HandleFoldProp(SerializedProperty prop) { bool shouldBeFolded = false; - foreach (var pair in cache) + foreach (var pair in cacheFolds) { if (pair.Value.types.Contains(prop.name)) { + var pr = prop.Copy(); shouldBeFolded = true; - pair.Value.props.Add(prop.Copy()); + pair.Value.props.Add(pr); break; } @@ -234,19 +247,24 @@ public void HandleProp(SerializedProperty prop) if (shouldBeFolded == false) { - props.Add(prop.Copy()); + var pr = prop.Copy(); + props.Add(pr); } } + // IEnumerable GetButtonMembers(object target) + // { + // return target.GetType() + // .GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic) + // .Where(CheckButtonAttribute); + // } - private struct Colors - { - public Color col0; - public Color col1; - public Color col2; - } + // bool CheckButtonAttribute(MemberInfo memberInfo) + // { + // return Attribute.IsDefined(memberInfo, typeof(ButtonAttribute)); + // } - private class Cache + class CacheFoldProp { public HashSet types = new HashSet(); public List props = new List(); @@ -262,15 +280,108 @@ public void Dispose() } } + static class ditorUIHelper + { + public static void UseVerticalLayout(this Editor e, Action action, GUIStyle style) + { + EditorGUILayout.BeginVertical(style); + action(); + EditorGUILayout.EndVertical(); + } + + public static void UseButton(this Editor e, MethodInfo m) + { + if (GUILayout.Button(m.Name)) + { + m.Invoke(e.target, null); + } + } + } + - public static partial class FrameworkExtensions + static class StyleFramework { + public static GUIStyle box; + public static GUIStyle boxChild; + public static GUIStyle foldout; + public static GUIStyle button; + public static GUIStyle text; + + static StyleFramework() + { + bool pro = EditorGUIUtility.isProSkin; + + var uiTex_in = Resources.Load("IN foldout focus-6510"); + var uiTex_in_on = Resources.Load("IN foldout focus on-5718"); + + var c_on = pro ? Color.white : new Color(51 / 255f, 102 / 255f, 204 / 255f, 1); + + button = new GUIStyle(EditorStyles.miniButton); + button.font = Font.CreateDynamicFontFromOSFont(new[] {"Terminus (TTF) for Windows", "Calibri"}, 17); + + text = new GUIStyle(EditorStyles.label); + text.richText = true; + text.contentOffset = new Vector2(0, 5); + text.font = Font.CreateDynamicFontFromOSFont(new[] {"Terminus (TTF) for Windows", "Calibri"}, 14); + + foldout = new GUIStyle(EditorStyles.foldout); + + foldout.overflow = new RectOffset(-10, 0, 3, 0); + foldout.padding = new RectOffset(25, 0, -3, 0); + + foldout.active.textColor = c_on; + foldout.active.background = uiTex_in; + foldout.onActive.textColor = c_on; + foldout.onActive.background = uiTex_in_on; + + foldout.focused.textColor = c_on; + foldout.focused.background = uiTex_in; + foldout.onFocused.textColor = c_on; + foldout.onFocused.background = uiTex_in_on; + + foldout.hover.textColor = c_on; + foldout.hover.background = uiTex_in; + + foldout.onHover.textColor = c_on; + foldout.onHover.background = uiTex_in_on; + + box = new GUIStyle(GUI.skin.box); + box.padding = new RectOffset(10, 0, 10, 0); + + boxChild = new GUIStyle(GUI.skin.box); + boxChild.active.textColor = c_on; + boxChild.active.background = uiTex_in; + boxChild.onActive.textColor = c_on; + boxChild.onActive.background = uiTex_in_on; + + boxChild.focused.textColor = c_on; + boxChild.focused.background = uiTex_in; + boxChild.onFocused.textColor = c_on; + boxChild.onFocused.background = uiTex_in_on; + + EditorStyles.foldout.active.textColor = c_on; + EditorStyles.foldout.active.background = uiTex_in; + EditorStyles.foldout.onActive.textColor = c_on; + EditorStyles.foldout.onActive.background = uiTex_in_on; + + EditorStyles.foldout.focused.textColor = c_on; + EditorStyles.foldout.focused.background = uiTex_in; + EditorStyles.foldout.onFocused.textColor = c_on; + EditorStyles.foldout.onFocused.background = uiTex_in_on; + + EditorStyles.foldout.hover.textColor = c_on; + EditorStyles.foldout.hover.background = uiTex_in; + + EditorStyles.foldout.onHover.textColor = c_on; + EditorStyles.foldout.onHover.background = uiTex_in_on; + } + public static string FirstLetterToUpperCase(this string s) { if (string.IsNullOrEmpty(s)) return string.Empty; - char[] a = s.ToCharArray(); + var a = s.ToCharArray(); a[0] = char.ToUpper(a[0]); return new string(a); } @@ -287,4 +398,84 @@ public static IList GetTypeTree(this Type t) return types; } } -} + + static class EditorTypes + { + public static Dictionary> fields = new Dictionary>(FastComparable.Default); + + public static int Get(Object target, out List objectFields) + { + var t = target.GetType(); + var hash = t.GetHashCode(); + + if (!fields.TryGetValue(hash, out objectFields)) + { + var typeTree = t.GetTypeTree(); + objectFields = target.GetType() + .GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic) + .OrderByDescending(x => typeTree.IndexOf(x.DeclaringType)) + .ToList(); + fields.Add(hash, objectFields); + } + + return objectFields.Count; + } + } + + + class FastComparable : IEqualityComparer + { + public static FastComparable Default = new FastComparable(); + + public bool Equals(int x, int y) + { + return x == y; + } + + public int GetHashCode(int obj) + { + return obj.GetHashCode(); + } + } + + + [InitializeOnLoad] + public static class EditorFramework + { + internal static bool needToRepaint; + + internal static Event currentEvent; + internal static float t; + + static EditorFramework() + { + EditorApplication.update += Updating; + } + + + static void Updating() + { + CheckMouse(); + + if (needToRepaint) + { + t += Time.deltaTime; + + if (t >= 0.3f) + { + t -= 0.3f; + needToRepaint = false; + } + } + } + + static void CheckMouse() + { + var ev = currentEvent; + if (ev == null) return; + + if (ev.type == EventType.MouseMove) + needToRepaint = true; + } + } +} \ No newline at end of file