Repository: PixeyeHQ/InspectorFoldoutGroup Branch: master Commit: 8f6fbe7724a9 Files: 7 Total size: 20.0 KB Directory structure: gitextract_ia10q94b/ ├── .gitignore ├── Homebrew/ │ └── DecorateFoldout/ │ ├── Attributes/ │ │ └── FoldAttribute.cs │ └── Editor/ │ ├── EditorOverride.cs │ └── Resources/ │ ├── IN foldout focus on-5718.png.meta │ └── IN foldout focus-6510.png.meta ├── LICENSE └── README.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ [Ll]ibrary/ [Tt]emp/ [Oo]bj/ [Bb]uild/ [Bb]uilds/ Assets/AssetStoreTools* # Visual Studio cache directory .vs/ # Autogenerated VS/MD/Consulo solution and project files ExportedObj/ .consulo/ *.csproj *.unityproj *.sln *.suo *.tmp *.user *.userprefs *.pidb *.booproj *.svd *.pdb *.opendb # Unity3D generated meta files *.pidb.meta *.pdb.meta # Unity3D Generated File On Crash Reports sysinfo.txt # Builds *.apk *.unitypackage ================================================ FILE: Homebrew/DecorateFoldout/Attributes/FoldAttribute.cs ================================================ // Project : UNITY FOLDOUT // Contacts : Pix - ask@pixeye.games using UnityEngine; 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; } } } ================================================ FILE: Homebrew/DecorateFoldout/Editor/EditorOverride.cs ================================================ // Project : UNITY FOLDOUT // Contacts : Pix - ask@pixeye.games using Homebrew; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using UnityEditor; using UnityEngine; using Object = UnityEngine.Object; namespace Pixeye.Unity { [CustomEditor(typeof(Object), true, isFallback = true)] [CanEditMultipleObjects] public class EditorOverride : Editor { //===============================// // Members //===============================// Dictionary cacheFolds = new Dictionary(); List props = new List(); List methods = new List(); bool initialized; //===============================// // Logic //===============================// void OnEnable() { initialized = false; } void OnDisable() { //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.GetInstanceID()}"), c.Value.expanded); c.Value.Dispose(); } } public override bool RequiresConstantRepaint() { return EditorFramework.needToRepaint; } public override void OnInspectorGUI() { serializedObject.Update(); Setup(); if (props.Count == 0) { DrawDefaultInspector(); return; } Header(); Body(); serializedObject.ApplyModifiedProperties(); void Header() { using (new EditorGUI.DisabledScope("m_Script" == props[0].propertyPath)) { EditorGUILayout.Space(); EditorGUILayout.PropertyField(props[0], true); EditorGUILayout.Space(); } } void Body() { foreach (var pair in cacheFolds) { this.UseVerticalLayout(() => Foldout(pair.Value), StyleFramework.box); EditorGUI.indentLevel = 0; } EditorGUILayout.Space(); for (var i = 1; i < props.Count; i++) { // if (props[i].isArray) // { // DrawPropertySortableArray(props[i]); // } // else // { EditorGUILayout.PropertyField(props[i], true); //} } EditorGUILayout.Space(); if (methods == null) return; foreach (MethodInfo memberInfo in methods) { this.UseButton(memberInfo); } } void Foldout(CacheFoldProp cache) { cache.expanded = EditorGUILayout.Foldout(cache.expanded, cache.atr.name, true, StyleFramework.foldout); if (cache.expanded) { EditorGUI.indentLevel = 1; for (int i = 0; i < cache.props.Count; i++) { this.UseVerticalLayout(() => Child(i), StyleFramework.boxChild); } } void Child(int i) { // if (cache.props[i].isArray) // { // DrawPropertySortableArray(cache.props[i]); // } // else // { EditorGUILayout.PropertyField(cache.props[i], new GUIContent(ObjectNames.NicifyVariableName(cache.props[i].name)), true); //} } } void Setup() { EditorFramework.currentEvent = Event.current; if (!initialized) { // SetupButtons(); List objectFields; FoldoutAttribute prevFold = default; var length = EditorTypes.Get(target, out objectFields); for (var i = 0; i < length; i++) { #region FOLDERS 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; } prevFold = fold; if (!cacheFolds.TryGetValue(fold.name, out c)) { var expanded = EditorPrefs.GetBool(string.Format($"{fold.name}{objectFields[i].Name}{target.GetInstanceID()}"), false); cacheFolds.Add(fold.name, new CacheFoldProp {atr = fold, types = new HashSet {objectFields[i].Name}, expanded = expanded}); } else c.types.Add(objectFields[i].Name); #endregion } var property = serializedObject.GetIterator(); var next = property.NextVisible(true); if (next) { do { HandleFoldProp(property); } while (property.NextVisible(false)); } initialized = true; } } // 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 HandleFoldProp(SerializedProperty prop) { bool shouldBeFolded = false; foreach (var pair in cacheFolds) { if (pair.Value.types.Contains(prop.name)) { var pr = prop.Copy(); shouldBeFolded = true; pair.Value.props.Add(pr); break; } } if (shouldBeFolded == false) { 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); // } // bool CheckButtonAttribute(MemberInfo memberInfo) // { // return Attribute.IsDefined(memberInfo, typeof(ButtonAttribute)); // } class CacheFoldProp { public HashSet types = new HashSet(); public List props = new List(); public FoldoutAttribute atr; public bool expanded; public void Dispose() { props.Clear(); types.Clear(); atr = null; } } } 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); } } } 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; var a = s.ToCharArray(); a[0] = char.ToUpper(a[0]); return new string(a); } public static IList GetTypeTree(this Type t) { var types = new List(); while (t.BaseType != null) { types.Add(t); t = t.BaseType; } 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; } } } ================================================ FILE: Homebrew/DecorateFoldout/Editor/Resources/IN foldout focus on-5718.png.meta ================================================ fileFormatVersion: 2 guid: 07896d08487bbb049b494e9e216360ad TextureImporter: fileIDToRecycleName: {} externalObjects: {} serializedVersion: 5 mipmaps: mipMapMode: 0 enableMipMap: 0 sRGBTexture: 1 linearTexture: 0 fadeOut: 0 borderMipMap: 0 mipMapsPreserveCoverage: 0 alphaTestReferenceValue: 0.5 mipMapFadeDistanceStart: 1 mipMapFadeDistanceEnd: 3 bumpmap: convertToNormalMap: 0 externalNormalMap: 0 heightScale: 0.25 normalMapFilter: 0 isReadable: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 seamlessCubemap: 0 textureFormat: 1 maxTextureSize: 2048 textureSettings: serializedVersion: 2 filterMode: 0 aniso: -1 mipBias: -1 wrapU: 1 wrapV: 1 wrapW: -1 nPOTScale: 0 lightmap: 0 compressionQuality: 50 spriteMode: 1 spriteExtrude: 1 spriteMeshType: 1 alignment: 0 spritePivot: {x: 0.5, y: 0.5} spritePixelsToUnits: 100 spriteBorder: {x: 0, y: 0, z: 0, w: 0} spriteGenerateFallbackPhysicsShape: 1 alphaUsage: 1 alphaIsTransparency: 1 spriteTessellationDetail: -1 textureType: 8 textureShape: 1 singleChannelComponent: 0 maxTextureSizeSet: 0 compressionQualitySet: 0 textureFormatSet: 0 platformSettings: - serializedVersion: 2 buildTarget: DefaultTexturePlatform maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 compressionQuality: 50 crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 androidETC2FallbackOverride: 0 - serializedVersion: 2 buildTarget: Standalone maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 compressionQuality: 50 crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 androidETC2FallbackOverride: 0 - serializedVersion: 2 buildTarget: WebGL maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 compressionQuality: 50 crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 androidETC2FallbackOverride: 0 spriteSheet: serializedVersion: 2 sprites: [] outline: [] physicsShape: [] bones: [] spriteID: vertices: [] indices: edges: [] weights: [] spritePackingTag: userData: assetBundleName: assetBundleVariant: ================================================ FILE: Homebrew/DecorateFoldout/Editor/Resources/IN foldout focus-6510.png.meta ================================================ fileFormatVersion: 2 guid: 795626f49ade9024a86e0c1a58aa004b TextureImporter: fileIDToRecycleName: {} externalObjects: {} serializedVersion: 5 mipmaps: mipMapMode: 0 enableMipMap: 0 sRGBTexture: 1 linearTexture: 0 fadeOut: 0 borderMipMap: 0 mipMapsPreserveCoverage: 0 alphaTestReferenceValue: 0.5 mipMapFadeDistanceStart: 1 mipMapFadeDistanceEnd: 3 bumpmap: convertToNormalMap: 0 externalNormalMap: 0 heightScale: 0.25 normalMapFilter: 0 isReadable: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 seamlessCubemap: 0 textureFormat: 1 maxTextureSize: 2048 textureSettings: serializedVersion: 2 filterMode: 0 aniso: -1 mipBias: -1 wrapU: 1 wrapV: 1 wrapW: -1 nPOTScale: 0 lightmap: 0 compressionQuality: 50 spriteMode: 1 spriteExtrude: 1 spriteMeshType: 1 alignment: 0 spritePivot: {x: 0.5, y: 0.5} spritePixelsToUnits: 100 spriteBorder: {x: 0, y: 0, z: 0, w: 0} spriteGenerateFallbackPhysicsShape: 1 alphaUsage: 1 alphaIsTransparency: 1 spriteTessellationDetail: -1 textureType: 8 textureShape: 1 singleChannelComponent: 0 maxTextureSizeSet: 0 compressionQualitySet: 0 textureFormatSet: 0 platformSettings: - serializedVersion: 2 buildTarget: DefaultTexturePlatform maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 compressionQuality: 50 crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 androidETC2FallbackOverride: 0 - serializedVersion: 2 buildTarget: Standalone maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 compressionQuality: 50 crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 androidETC2FallbackOverride: 0 - serializedVersion: 2 buildTarget: WebGL maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 compressionQuality: 50 crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 androidETC2FallbackOverride: 0 spriteSheet: serializedVersion: 2 sprites: [] outline: [] physicsShape: [] bones: [] spriteID: vertices: [] indices: edges: [] weights: [] spritePackingTag: userData: assetBundleName: assetBundleVariant: ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2018 Dimitry Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ [![license](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](https://github.com/dimmpixeye/InspectorFoldoutGroup/blob/master/LICENSE) [![Join the chat at https://discord.gg/ukhzx83](https://img.shields.io/badge/discord-join%20channel-brightgreen.svg?style=flat-square)](https://discord.gg/ukhzx83) # InspectorFoldoutGroup Group variables in Unity 3d inspector with style! [![https://gyazo.com/9f18eab9dfb123d928aecf7daa3e01da](https://i.gyazo.com/9f18eab9dfb123d928aecf7daa3e01da.gif)](https://gyazo.com/9f18eab9dfb123d928aecf7daa3e01da) [![https://gyazo.com/4e6566c2fca783e4cd557f95713a4ab5](https://i.gyazo.com/4e6566c2fca783e4cd557f95713a4ab5.gif)](https://gyazo.com/4e6566c2fca783e4cd557f95713a4ab5) ## How to use Put attribute before variable and you are done ! ```csharp [Foldout("DESIRED_NAME")] ``` ```csharp public class Player : MonoBehaviour { [Foldout("Setup")] public Transform selfTransform; [Foldout("Data")] public int HP; [Foldout("Data")] public int AT; } ``` You don't need to write [Foldout] attribute each time! Instead, you can add "true" bool check afther naming to put all properties to the specified group ```csharp public class Player : MonoBehaviour { [Foldout("DATA OBJECT", true)] public int hp; public int attack = 20; [SerializeField] private GameObject self; [Foldout("DATA ATTACK")] public int AT; } ``` [![https://gyazo.com/2ce500e63fd604de8098aece2fa354fa](https://i.gyazo.com/2ce500e63fd604de8098aece2fa354fa.png)](https://gyazo.com/2ce500e63fd604de8098aece2fa354fa) ## Other content * [Tag filters](https://github.com/dimmpixeye/Unity3d-Tags-Filters) - an extension to add foldable groups to the inspector. * [ACTORS](https://github.com/dimmpixeye/Actors-Unity3d-Framework) - Unity3d data-driven framework I'm currently working on.