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
This commit is contained in:
Anders Ejlersen 2022-06-26 15:06:52 +02:00
parent ee7326c33a
commit 7d99d62e11
14 changed files with 114 additions and 17 deletions

View file

@ -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;
}
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 71ec06fd224544c0b6df1cb7657b7869
timeCreated: 1656194575

View file

@ -1,4 +1,5 @@
using Module.Inspector.Editor.Utilities;
#if !UNITY_2021_1_OR_NEWER
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
@ -34,3 +35,4 @@ namespace Module.Inspector.Editor
}
}
}
#endif

View file

@ -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);
@ -47,7 +47,6 @@ namespace Module.Inspector.Editor
{
Type newType = EditorTypeUtility.GetType(arrStrings[newIndex]);
if (newType != null && IsSupported(newType))
property.managedReferenceValue = FormatterServices.GetUninitializedObject(newType);
else

View file

@ -402,12 +402,16 @@ 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);
FieldInfo field = type.GetField(path, FLAGS);
if (field != null)
obj = field.GetValue(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;

View file

@ -15,6 +15,7 @@ namespace Module.Inspector.Editor
private static readonly Dictionary<Type, string[]> DICT_AS_STRS = new Dictionary<Type, string[]>();
private static readonly Dictionary<Type, string[]> DICT_AS_DESCS = new Dictionary<Type, string[]>();
private static readonly Dictionary<Type, GUIContent[]> DICT_AS_GUI = new Dictionary<Type, GUIContent[]>();
private static readonly Dictionary<Type, GUIContent[]> DICT_AS_GUI_SHORTNAME = new Dictionary<Type, GUIContent[]>();
private static readonly Dictionary<Type, GUIContent[]> DICT_AS_GUI_DESC = new Dictionary<Type, GUIContent[]>();
private static readonly Dictionary<Type, FieldInfo[]> DICT_AS_FIELDS = new Dictionary<Type, FieldInfo[]>();
@ -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} (<i>{fullnames[i]}</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);
}

View file

@ -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`

View file

@ -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()
{
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 02a846340b4b4fc584555df887f68f9a
timeCreated: 1656194556

View file

@ -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
{

View file

@ -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;
}

View file

@ -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",