From 7d99d62e11217791627551f9eabc70e83e7bfb4d Mon Sep 17 00:00:00 2001 From: Anders Ejlersen Date: Sun, 26 Jun 2022 15:06:52 +0200 Subject: [PATCH] 1.5.0: Added IntToLayerMask, marked QuaternionToEuler as obsolete as of 2021 and fixed a couple of bugs - Drawer: Added IntToLayerMaskAttribute, if a raw int is wanted instead of LayerMask - Drawer: Added option to either use full or short type name, when using SerializeReferenceTo - Extension: Fixed issue, where GetValueType and GetValue for SerializedProperty would throw exceptions, if field is private --- .../Drawers/IntToLayerMaskAttributeDrawer.cs | 57 +++++++++++++++++++ .../IntToLayerMaskAttributeDrawer.cs.meta | 3 + .../QuaternionToEulerAttributeDrawer.cs | 6 +- ...=> SerializeReferenceToAttributeDrawer.cs} | 9 ++- ...rializeReferenceToAttributeDrawer.cs.meta} | 0 .../Extensions/SerializedPropertyExtension.cs | 13 ++++- Editor/Utilities/EditorTypeUtility.cs | 8 ++- README.md | 4 +- Runtime/Drawers/IntToLayerMaskAttribute.cs | 14 +++++ .../Drawers/IntToLayerMaskAttribute.cs.meta | 3 + Runtime/Drawers/QuaternionToEulerAttribute.cs | 3 + ...te.cs => SerializeReferenceToAttribute.cs} | 9 ++- ... => SerializeReferenceToAttribute.cs.meta} | 0 package.json | 2 +- 14 files changed, 114 insertions(+), 17 deletions(-) create mode 100644 Editor/Drawers/IntToLayerMaskAttributeDrawer.cs create mode 100644 Editor/Drawers/IntToLayerMaskAttributeDrawer.cs.meta rename Editor/Drawers/{SerializableReferenceToAttributeDrawer.cs => SerializeReferenceToAttributeDrawer.cs} (94%) rename Editor/Drawers/{SerializableReferenceToAttributeDrawer.cs.meta => SerializeReferenceToAttributeDrawer.cs.meta} (100%) create mode 100644 Runtime/Drawers/IntToLayerMaskAttribute.cs create mode 100644 Runtime/Drawers/IntToLayerMaskAttribute.cs.meta rename Runtime/Drawers/{SerializableReferenceToAttribute.cs => SerializeReferenceToAttribute.cs} (51%) rename Runtime/Drawers/{SerializableReferenceToAttribute.cs.meta => SerializeReferenceToAttribute.cs.meta} (100%) diff --git a/Editor/Drawers/IntToLayerMaskAttributeDrawer.cs b/Editor/Drawers/IntToLayerMaskAttributeDrawer.cs new file mode 100644 index 0000000..6e5f144 --- /dev/null +++ b/Editor/Drawers/IntToLayerMaskAttributeDrawer.cs @@ -0,0 +1,57 @@ +using Module.Inspector.Editor.Utilities; +using UnityEditor; +using UnityEngine; + +namespace Module.Inspector.Editor +{ + [CustomPropertyDrawer(typeof(IntToLayerMaskAttribute))] + internal sealed class IntToLayerMaskAttributeDrawer : DrawerPropertyDrawer + { + private static string[] NAMES; + + public override bool Draw(Rect position, DrawerPropertyAttribute attribute, SerializedProperty property, GUIContent label, EditorPropertyUtility.Result result) + { + if (property.propertyType != SerializedPropertyType.Integer) + return false; + + FetchLayerNames(); + + EditorGUI.BeginChangeCheck(); + EditorGUI.BeginProperty(position, label, property); + { + property.intValue = EditorGUI.MaskField(position, label, property.intValue, NAMES); + } + EditorGUI.EndProperty(); + bool changed = EditorGUI.EndChangeCheck(); + + if (changed) + property.serializedObject.ApplyModifiedProperties(); + + return true; + } + + public override string GetErrorMessage(SerializedProperty property) + { + return "Only supports integers"; + } + + + private static void FetchLayerNames() + { + if (NAMES != null) + return; + + NAMES = new string[32]; + + for (var i = 0; i < 32; i++) + { + string str = LayerMask.LayerToName(i); + + if (string.IsNullOrEmpty(str)) + str = $"Unused Layer #{i:00}"; + + NAMES[i] = str; + } + } + } +} \ No newline at end of file diff --git a/Editor/Drawers/IntToLayerMaskAttributeDrawer.cs.meta b/Editor/Drawers/IntToLayerMaskAttributeDrawer.cs.meta new file mode 100644 index 0000000..edeecc6 --- /dev/null +++ b/Editor/Drawers/IntToLayerMaskAttributeDrawer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 71ec06fd224544c0b6df1cb7657b7869 +timeCreated: 1656194575 \ No newline at end of file diff --git a/Editor/Drawers/QuaternionToEulerAttributeDrawer.cs b/Editor/Drawers/QuaternionToEulerAttributeDrawer.cs index ec4e8c8..f510694 100644 --- a/Editor/Drawers/QuaternionToEulerAttributeDrawer.cs +++ b/Editor/Drawers/QuaternionToEulerAttributeDrawer.cs @@ -1,4 +1,5 @@ -using Module.Inspector.Editor.Utilities; +#if !UNITY_2021_1_OR_NEWER +using Module.Inspector.Editor.Utilities; using UnityEditor; using UnityEngine; @@ -33,4 +34,5 @@ namespace Module.Inspector.Editor return "Only supports quaternions"; } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/Editor/Drawers/SerializableReferenceToAttributeDrawer.cs b/Editor/Drawers/SerializeReferenceToAttributeDrawer.cs similarity index 94% rename from Editor/Drawers/SerializableReferenceToAttributeDrawer.cs rename to Editor/Drawers/SerializeReferenceToAttributeDrawer.cs index d1ff0a0..37c313d 100644 --- a/Editor/Drawers/SerializableReferenceToAttributeDrawer.cs +++ b/Editor/Drawers/SerializeReferenceToAttributeDrawer.cs @@ -9,8 +9,8 @@ using Object = UnityEngine.Object; namespace Module.Inspector.Editor { - [CustomPropertyDrawer(typeof(SerializableReferenceToAttribute))] - internal sealed class SerializableReferenceToAttributeDrawer : DrawerPropertyDrawer + [CustomPropertyDrawer(typeof(SerializeReferenceToAttribute))] + internal sealed class SerializeReferenceToAttributeDrawer : DrawerPropertyDrawer { private enum ESupportType { @@ -27,10 +27,10 @@ namespace Module.Inspector.Editor if (IsSupported(property) != ESupportType.Supported) return false; - var att = (SerializableReferenceToAttribute)attribute; + var att = (SerializeReferenceToAttribute)attribute; Type type = att.useType ? att.type : property.GetValueType(); string[] arrStrings = EditorTypeUtility.GetAssignableFromAsStrings(type); - GUIContent[] arrGui = EditorTypeUtility.GetAssignableFromAsGUI(type); + GUIContent[] arrGui = EditorTypeUtility.GetAssignableFromAsGUI(type, att.useFullname); EditorGUI.BeginChangeCheck(); EditorGUI.BeginProperty(position, label, property); @@ -46,7 +46,6 @@ namespace Module.Inspector.Editor if (newIndex != -1 && index != newIndex) { Type newType = EditorTypeUtility.GetType(arrStrings[newIndex]); - if (newType != null && IsSupported(newType)) property.managedReferenceValue = FormatterServices.GetUninitializedObject(newType); diff --git a/Editor/Drawers/SerializableReferenceToAttributeDrawer.cs.meta b/Editor/Drawers/SerializeReferenceToAttributeDrawer.cs.meta similarity index 100% rename from Editor/Drawers/SerializableReferenceToAttributeDrawer.cs.meta rename to Editor/Drawers/SerializeReferenceToAttributeDrawer.cs.meta diff --git a/Editor/Extensions/SerializedPropertyExtension.cs b/Editor/Extensions/SerializedPropertyExtension.cs index c97bbdb..9805517 100644 --- a/Editor/Extensions/SerializedPropertyExtension.cs +++ b/Editor/Extensions/SerializedPropertyExtension.cs @@ -402,13 +402,17 @@ namespace Module.Inspector.Editor private static object GetValue(this SerializedProperty property) { + const BindingFlags FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; + object obj = property.serializedObject.targetObject; foreach (string path in property.propertyPath.Split('.')) { Type type = obj.GetType(); - FieldInfo field = type.GetField(path); - obj = field.GetValue(obj); + FieldInfo field = type.GetField(path, FLAGS); + + if (field != null) + obj = field.GetValue(obj); } return obj; @@ -416,12 +420,15 @@ namespace Module.Inspector.Editor public static Type GetValueType(this SerializedProperty property) { + const BindingFlags FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; + object obj = property.serializedObject.targetObject; Type type = null; foreach (string path in property.propertyPath.Split('.')) { - FieldInfo field = obj.GetType().GetField(path); + Type objType = obj.GetType(); + FieldInfo field = objType.GetField(path, FLAGS); if (field == null) continue; diff --git a/Editor/Utilities/EditorTypeUtility.cs b/Editor/Utilities/EditorTypeUtility.cs index c78ffbf..a9094fd 100644 --- a/Editor/Utilities/EditorTypeUtility.cs +++ b/Editor/Utilities/EditorTypeUtility.cs @@ -15,6 +15,7 @@ namespace Module.Inspector.Editor private static readonly Dictionary DICT_AS_STRS = new Dictionary(); private static readonly Dictionary DICT_AS_DESCS = new Dictionary(); private static readonly Dictionary DICT_AS_GUI = new Dictionary(); + private static readonly Dictionary DICT_AS_GUI_SHORTNAME = new Dictionary(); private static readonly Dictionary DICT_AS_GUI_DESC = new Dictionary(); private static readonly Dictionary DICT_AS_FIELDS = new Dictionary(); @@ -99,12 +100,12 @@ namespace Module.Inspector.Editor return DICT_AS_STRS[type]; } - internal static GUIContent[] GetAssignableFromAsGUI(Type type) + internal static GUIContent[] GetAssignableFromAsGUI(Type type, bool useFullname = true) { if (!DICT_AS_GUI.ContainsKey(type)) InternalFetch(type); - return DICT_AS_GUI[type]; + return useFullname ? DICT_AS_GUI[type] : DICT_AS_GUI_SHORTNAME[type]; } internal static string[] GetAssignableFromAsDescriptions(Type type) @@ -183,6 +184,7 @@ namespace Module.Inspector.Editor var fullnames = new string[listTypes.Count]; var descs = new string[listTypes.Count]; var guiFullNames = new GUIContent[listTypes.Count]; + var guiShortnames = new GUIContent[listTypes.Count]; var guiDescs = new GUIContent[listTypes.Count]; for (var i = 0; i < fullnames.Length; i++) @@ -190,6 +192,7 @@ namespace Module.Inspector.Editor fullnames[i] = listTypes[i].FullName; descs[i] = $"{listTypes[i].Name} ({fullnames[i]})"; guiFullNames[i] = new GUIContent(fullnames[i]); + guiShortnames[i] = new GUIContent(listTypes[i].Name); guiDescs[i] = new GUIContent(descs[i]); } @@ -197,6 +200,7 @@ namespace Module.Inspector.Editor DICT_AS_STRS.Add(assignableFrom, fullnames); DICT_AS_DESCS.Add(assignableFrom, descs); DICT_AS_GUI.Add(assignableFrom, guiFullNames); + DICT_AS_GUI_SHORTNAME.Add(assignableFrom, guiShortnames); DICT_AS_GUI_DESC.Add(assignableFrom, guiDescs); } diff --git a/README.md b/README.md index e09003b..df6c0ae 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,9 @@ List of all available drawer attributes: * `IntToEnum` * Adds a popup with enum type provided and converts it to an integer * `IntToLayer` - * Adds a popup with layers and converts it to an integer + * Adds a popup with a single layer selection and converts it to an integer +* `IntToLayerMask` + * Adds a popup with a multiple layer selection and converts it to an integer * `MethodButton` * Adds a button in the inspector that invokes the method (Requirement: No arguments) * `Naming` diff --git a/Runtime/Drawers/IntToLayerMaskAttribute.cs b/Runtime/Drawers/IntToLayerMaskAttribute.cs new file mode 100644 index 0000000..411a81f --- /dev/null +++ b/Runtime/Drawers/IntToLayerMaskAttribute.cs @@ -0,0 +1,14 @@ +using System; +using UnityEngine.Scripting; + +namespace Module.Inspector +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public sealed class IntToLayerMaskAttribute : DrawerPropertyAttribute + { + [Preserve] + public IntToLayerMaskAttribute() + { + } + } +} \ No newline at end of file diff --git a/Runtime/Drawers/IntToLayerMaskAttribute.cs.meta b/Runtime/Drawers/IntToLayerMaskAttribute.cs.meta new file mode 100644 index 0000000..05e23e0 --- /dev/null +++ b/Runtime/Drawers/IntToLayerMaskAttribute.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 02a846340b4b4fc584555df887f68f9a +timeCreated: 1656194556 \ No newline at end of file diff --git a/Runtime/Drawers/QuaternionToEulerAttribute.cs b/Runtime/Drawers/QuaternionToEulerAttribute.cs index f679ef7..400c92d 100644 --- a/Runtime/Drawers/QuaternionToEulerAttribute.cs +++ b/Runtime/Drawers/QuaternionToEulerAttribute.cs @@ -3,6 +3,9 @@ using UnityEngine.Scripting; namespace Module.Inspector { + #if UNITY_2021_1_OR_NEWER + [Obsolete] + #endif [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] public sealed class QuaternionToEulerAttribute : DrawerPropertyAttribute { diff --git a/Runtime/Drawers/SerializableReferenceToAttribute.cs b/Runtime/Drawers/SerializeReferenceToAttribute.cs similarity index 51% rename from Runtime/Drawers/SerializableReferenceToAttribute.cs rename to Runtime/Drawers/SerializeReferenceToAttribute.cs index 88ea13b..fd607a0 100644 --- a/Runtime/Drawers/SerializableReferenceToAttribute.cs +++ b/Runtime/Drawers/SerializeReferenceToAttribute.cs @@ -4,18 +4,21 @@ using System; namespace Module.Inspector { [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] - public sealed class SerializableReferenceToAttribute : DrawerPropertyAttribute + public sealed class SerializeReferenceToAttribute : DrawerPropertyAttribute { public readonly bool useType; public readonly Type type; + public readonly bool useFullname; - public SerializableReferenceToAttribute() + public SerializeReferenceToAttribute(bool useFullname = true) { useType = false; + this.useFullname = useFullname; } - public SerializableReferenceToAttribute(Type type) + public SerializeReferenceToAttribute(Type type, bool useFullname = true) { + this.useFullname = useFullname; this.type = type; useType = true; } diff --git a/Runtime/Drawers/SerializableReferenceToAttribute.cs.meta b/Runtime/Drawers/SerializeReferenceToAttribute.cs.meta similarity index 100% rename from Runtime/Drawers/SerializableReferenceToAttribute.cs.meta rename to Runtime/Drawers/SerializeReferenceToAttribute.cs.meta diff --git a/package.json b/package.json index 55ac4b0..dd08bcd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.module.inspector", - "version": "1.4.0", + "version": "1.5.0", "displayName": "Module.Inspector", "description": "Custom inspector with various useful property drawers", "unity": "2019.2",