diff --git a/Editor/ObjectEditor.cs b/Editor/ObjectEditor.cs index a1f1fb3..681a290 100644 --- a/Editor/ObjectEditor.cs +++ b/Editor/ObjectEditor.cs @@ -1,4 +1,5 @@ -using Module.Inspector.Editor.Utilities; +using System.Reflection; +using Module.Inspector.Editor.Utilities; using UnityEditor; using UnityEngine; @@ -11,17 +12,21 @@ namespace Module.Inspector.Editor public override void OnInspectorGUI() { DrawDefaultInspector(); + DrawHiddenInspector(); DrawMethodInspector(); } - private void DrawMethodInspector() + private void DrawHiddenInspector() { - if (!IsValidMethodTarget()) + if (!IsValidTarget()) return; - EditorMethodUtility.ResultPrimary[] primaries = EditorMethodUtility.QueryPrimary(target); + FieldInfo[] fields = EditorHiddenFieldUtility.Query(target); + + if (fields.Length == 0) + return; - float totalHeight = CalculateMethodHeight(primaries); + float totalHeight = EditorHiddenFieldUtility.CalculateHeight(fields) + EditorGUIUtility.singleLineHeight * 2; GUILayout.Space(totalHeight); var position = new Rect(0, 0, 1, 1); @@ -37,8 +42,49 @@ namespace Module.Inspector.Editor } position.y = position.yMax + EditorGUIUtility.singleLineHeight; - position.height = 0.0f; + position.height = EditorGUIUtility.singleLineHeight; + EditorGUI.LabelField(position, "Hidden fields", EditorStyles.miniBoldLabel); + + position.y += EditorGUIUtility.singleLineHeight; + + for (var i = 0; i < fields.Length; i++) + { + EditorHiddenFieldUtility.Draw(position, fields[i], target); + position.y += position.height; + } + } + + private void DrawMethodInspector() + { + if (!IsValidTarget()) + return; + EditorMethodUtility.ResultPrimary[] primaries = EditorMethodUtility.QueryPrimary(target); + + if (primaries == null || primaries.Length == 0) + return; + + float totalHeight = EditorMethodUtility.CalculateHeight(target, primaries) + EditorGUIUtility.singleLineHeight * 2; + GUILayout.Space(totalHeight); + + var position = new Rect(0, 0, 1, 1); + + if (Event.current.type == EventType.Repaint) + { + position = GUILayoutUtility.GetLastRect(); + position.y -= totalHeight; + + #if UNITY_2020_1_OR_NEWER + position.width = EditorGUIUtility.currentViewWidth - 22.0f; + #endif + } + + position.y = position.yMax + EditorGUIUtility.singleLineHeight; + position.height = EditorGUIUtility.singleLineHeight; + EditorGUI.LabelField(position, "Buttons", EditorStyles.miniBoldLabel); + + position.y += EditorGUIUtility.singleLineHeight; + for (var i = 0; i < primaries.Length; i++) { EditorMethodUtility.ResultPrimary primary = primaries[i]; @@ -51,20 +97,7 @@ namespace Module.Inspector.Editor } } - private float CalculateMethodHeight(EditorMethodUtility.ResultPrimary[] primaries) - { - float total = EditorGUIUtility.singleLineHeight; - - for (var i = 0; i < primaries.Length; i++) - { - EditorMethodUtility.ResultPrimary primary = primaries[i]; - total += primary.drawer.GetHeight(target, primary.methodInfo); - } - - return total; - } - - private bool IsValidMethodTarget() + private bool IsValidTarget() { return target != null && targets.Length == 1; } diff --git a/Editor/Predrawers/FieldLabelFromAttributeDrawer.cs b/Editor/Predrawers/FieldLabelFromAttributeDrawer.cs index 49ea717..fb90aa2 100644 --- a/Editor/Predrawers/FieldLabelFromAttributeDrawer.cs +++ b/Editor/Predrawers/FieldLabelFromAttributeDrawer.cs @@ -18,7 +18,7 @@ namespace Module.Inspector.Editor if (att.nicify) str = ObjectNames.NicifyVariableName(str); - + label.text = str; } } diff --git a/Editor/Utilities/EditorHiddenFieldUtility.cs b/Editor/Utilities/EditorHiddenFieldUtility.cs new file mode 100644 index 0000000..109b95d --- /dev/null +++ b/Editor/Utilities/EditorHiddenFieldUtility.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using UnityEditor; +using UnityEngine; +using Object = UnityEngine.Object; + +namespace Module.Inspector.Editor.Utilities +{ + internal static class EditorHiddenFieldUtility + { + private static Dictionary CACHED_TYPE_TO_PRIMARIES; + + public static FieldInfo[] Query(Object target) + { + Type type = target.GetType(); + var att = type.GetCustomAttribute(); + + if (att == null) + return new FieldInfo[0]; + + if (CACHED_TYPE_TO_PRIMARIES == null) + CACHED_TYPE_TO_PRIMARIES = new Dictionary(); + + if (CACHED_TYPE_TO_PRIMARIES.TryGetValue(type, out FieldInfo[] fields)) + return fields; + + fields = InternalFetch(type, att.UseFieldProperty); + CACHED_TYPE_TO_PRIMARIES.Add(type, fields); + return fields; + } + + public static float CalculateHeight(FieldInfo[] fields) + { + return EditorGUIUtility.singleLineHeight * fields.Length; + } + + public static void Draw(Rect rect, FieldInfo field, Object target) + { + bool prevEnabled = GUI.enabled; + GUI.enabled = false; + string nicifiedName = ObjectNames.NicifyVariableName(field.Name); + + if (field.FieldType == typeof(float)) + EditorGUI.FloatField(rect, nicifiedName, (float)field.GetValue(target)); + else if (field.FieldType == typeof(int)) + EditorGUI.IntField(rect, nicifiedName, (int)field.GetValue(target)); + else if (field.FieldType == typeof(double)) + EditorGUI.DoubleField(rect, nicifiedName, (double)field.GetValue(target)); + else if (field.FieldType == typeof(string)) + EditorGUI.TextField(rect, nicifiedName, (string)field.GetValue(target)); + else if (typeof(Object).IsAssignableFrom(field.FieldType)) + EditorGUI.ObjectField(rect, nicifiedName, (Object)field.GetValue(target), typeof(Object), true); + else + EditorGUI.LabelField(rect, ObjectNames.NicifyVariableName(field.Name), "Unsupported type"); + + GUI.enabled = prevEnabled; + } + + private static FieldInfo[] InternalFetch(Type type, bool useFieldProperty) + { + const BindingFlags FLAGS = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; + + FieldInfo[] fields = type.GetFields(FLAGS); + var list = new List(fields.Length); + + for (var i = 0; i < fields.Length; i++) + { + FieldInfo fi = fields[i]; + + if (fi.GetCustomAttribute() == null && fi.GetCustomAttribute() == null) + continue; + if (!useFieldProperty || fi.GetCustomAttribute() != null) + list.Add(fi); + } + + return list.ToArray(); + } + } +} \ No newline at end of file diff --git a/Editor/Utilities/EditorHiddenFieldUtility.cs.meta b/Editor/Utilities/EditorHiddenFieldUtility.cs.meta new file mode 100644 index 0000000..151fb3a --- /dev/null +++ b/Editor/Utilities/EditorHiddenFieldUtility.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 83e464a05c8246f2a9e67edd640b5b6c +timeCreated: 1658598364 \ No newline at end of file diff --git a/Editor/Utilities/EditorMethodUtility.cs b/Editor/Utilities/EditorMethodUtility.cs index 69d1cf8..1b70ba5 100644 --- a/Editor/Utilities/EditorMethodUtility.cs +++ b/Editor/Utilities/EditorMethodUtility.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using UnityEditor; namespace Module.Inspector.Editor.Utilities { @@ -79,6 +80,19 @@ namespace Module.Inspector.Editor.Utilities return result; } + + public static float CalculateHeight(UnityEngine.Object target, ResultPrimary[] primaries) + { + float total = EditorGUIUtility.singleLineHeight; + + for (var i = 0; i < primaries.Length; i++) + { + ResultPrimary primary = primaries[i]; + total += primary.drawer.GetHeight(target, primary.methodInfo); + } + + return total; + } private static ResultPrimary[] InternalFetchPrimary(Type type) { diff --git a/README.md b/README.md index 7c2eb08..0f627be 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ List of all available drawer attributes: * `MethodButton` * Adds a button in the inspector that invokes the method (Requirement: No arguments) * `Naming` - * Adds button to apply naming scheme to string value + * Adds button to apply naming scheme to string value * Types: Camel, Pascal, Snake, Snake (All caps), Kebab, Kebab (All caps) * `Percentage` * Convert float value to percentage and back again (1% = 0.01f) @@ -156,4 +156,15 @@ List of all decorator attributes: * `HorizontalLine` * Draws a horizontal line above the field * `MethodHeader` - * Draws a header/title/category text above the method (button) \ No newline at end of file + * Draws a header/title/category text above the method (button) + + + +## Show Hidden Fields + +To allow fields hidden from inspector either by `NonSerialized` or `HideInInspector` add the following to the class: + +* `EnableShowHiddenFields` + * Enables an additional search to find any "hidden" fields and draw them below `DefaultInspector` +* `ShowHiddenField` + * Optional attribute for fields, if `EnableShowHiddenFields` has parameter `true` \ No newline at end of file diff --git a/Runtime/HiddenFields.meta b/Runtime/HiddenFields.meta new file mode 100644 index 0000000..82667fd --- /dev/null +++ b/Runtime/HiddenFields.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5da89eb276ee4f529122d85ca855054e +timeCreated: 1658598477 \ No newline at end of file diff --git a/Runtime/HiddenFields/EnableShowHiddenFieldsAttribute.cs b/Runtime/HiddenFields/EnableShowHiddenFieldsAttribute.cs new file mode 100644 index 0000000..4241743 --- /dev/null +++ b/Runtime/HiddenFields/EnableShowHiddenFieldsAttribute.cs @@ -0,0 +1,16 @@ +using System; +using UnityEngine; + +namespace Module.Inspector +{ + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public sealed class EnableShowHiddenFieldsAttribute : PropertyAttribute + { + public bool UseFieldProperty { get; } + + public EnableShowHiddenFieldsAttribute(bool useFieldProperty = false) + { + UseFieldProperty = useFieldProperty; + } + } +} \ No newline at end of file diff --git a/Runtime/HiddenFields/EnableShowHiddenFieldsAttribute.cs.meta b/Runtime/HiddenFields/EnableShowHiddenFieldsAttribute.cs.meta new file mode 100644 index 0000000..7616800 --- /dev/null +++ b/Runtime/HiddenFields/EnableShowHiddenFieldsAttribute.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c287a3fb88c74b888ac05e1c3b34238b +timeCreated: 1658598444 \ No newline at end of file diff --git a/Runtime/HiddenFields/ShowHiddenFieldAttribute.cs b/Runtime/HiddenFields/ShowHiddenFieldAttribute.cs new file mode 100644 index 0000000..65fe610 --- /dev/null +++ b/Runtime/HiddenFields/ShowHiddenFieldAttribute.cs @@ -0,0 +1,10 @@ +using System; +using UnityEngine; + +namespace Module.Inspector +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public sealed class ShowHiddenFieldAttribute : PropertyAttribute + { + } +} \ No newline at end of file diff --git a/Runtime/HiddenFields/ShowHiddenFieldAttribute.cs.meta b/Runtime/HiddenFields/ShowHiddenFieldAttribute.cs.meta new file mode 100644 index 0000000..0153e4b --- /dev/null +++ b/Runtime/HiddenFields/ShowHiddenFieldAttribute.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ddf507506d4745f6904b2801b85e95bd +timeCreated: 1658598416 \ No newline at end of file diff --git a/package.json b/package.json index 2d2fcc9..1cfd52f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.module.inspector", - "version": "1.6.0", + "version": "1.7.0", "displayName": "Module.Inspector", "description": "Custom inspector with various useful property drawers", "unity": "2019.2",