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:
parent
ee7326c33a
commit
7d99d62e11
57
Editor/Drawers/IntToLayerMaskAttributeDrawer.cs
Normal file
57
Editor/Drawers/IntToLayerMaskAttributeDrawer.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
Editor/Drawers/IntToLayerMaskAttributeDrawer.cs.meta
Normal file
3
Editor/Drawers/IntToLayerMaskAttributeDrawer.cs.meta
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 71ec06fd224544c0b6df1cb7657b7869
|
||||||
|
timeCreated: 1656194575
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using Module.Inspector.Editor.Utilities;
|
#if !UNITY_2021_1_OR_NEWER
|
||||||
|
using Module.Inspector.Editor.Utilities;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
|
|
@ -33,4 +34,5 @@ namespace Module.Inspector.Editor
|
||||||
return "Only supports quaternions";
|
return "Only supports quaternions";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -9,8 +9,8 @@ using Object = UnityEngine.Object;
|
||||||
|
|
||||||
namespace Module.Inspector.Editor
|
namespace Module.Inspector.Editor
|
||||||
{
|
{
|
||||||
[CustomPropertyDrawer(typeof(SerializableReferenceToAttribute))]
|
[CustomPropertyDrawer(typeof(SerializeReferenceToAttribute))]
|
||||||
internal sealed class SerializableReferenceToAttributeDrawer : DrawerPropertyDrawer
|
internal sealed class SerializeReferenceToAttributeDrawer : DrawerPropertyDrawer
|
||||||
{
|
{
|
||||||
private enum ESupportType
|
private enum ESupportType
|
||||||
{
|
{
|
||||||
|
|
@ -27,10 +27,10 @@ namespace Module.Inspector.Editor
|
||||||
if (IsSupported(property) != ESupportType.Supported)
|
if (IsSupported(property) != ESupportType.Supported)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var att = (SerializableReferenceToAttribute)attribute;
|
var att = (SerializeReferenceToAttribute)attribute;
|
||||||
Type type = att.useType ? att.type : property.GetValueType();
|
Type type = att.useType ? att.type : property.GetValueType();
|
||||||
string[] arrStrings = EditorTypeUtility.GetAssignableFromAsStrings(type);
|
string[] arrStrings = EditorTypeUtility.GetAssignableFromAsStrings(type);
|
||||||
GUIContent[] arrGui = EditorTypeUtility.GetAssignableFromAsGUI(type);
|
GUIContent[] arrGui = EditorTypeUtility.GetAssignableFromAsGUI(type, att.useFullname);
|
||||||
|
|
||||||
EditorGUI.BeginChangeCheck();
|
EditorGUI.BeginChangeCheck();
|
||||||
EditorGUI.BeginProperty(position, label, property);
|
EditorGUI.BeginProperty(position, label, property);
|
||||||
|
|
@ -46,7 +46,6 @@ namespace Module.Inspector.Editor
|
||||||
if (newIndex != -1 && index != newIndex)
|
if (newIndex != -1 && index != newIndex)
|
||||||
{
|
{
|
||||||
Type newType = EditorTypeUtility.GetType(arrStrings[newIndex]);
|
Type newType = EditorTypeUtility.GetType(arrStrings[newIndex]);
|
||||||
|
|
||||||
|
|
||||||
if (newType != null && IsSupported(newType))
|
if (newType != null && IsSupported(newType))
|
||||||
property.managedReferenceValue = FormatterServices.GetUninitializedObject(newType);
|
property.managedReferenceValue = FormatterServices.GetUninitializedObject(newType);
|
||||||
|
|
@ -402,13 +402,17 @@ namespace Module.Inspector.Editor
|
||||||
|
|
||||||
private static object GetValue(this SerializedProperty property)
|
private static object GetValue(this SerializedProperty property)
|
||||||
{
|
{
|
||||||
|
const BindingFlags FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||||
|
|
||||||
object obj = property.serializedObject.targetObject;
|
object obj = property.serializedObject.targetObject;
|
||||||
|
|
||||||
foreach (string path in property.propertyPath.Split('.'))
|
foreach (string path in property.propertyPath.Split('.'))
|
||||||
{
|
{
|
||||||
Type type = obj.GetType();
|
Type type = obj.GetType();
|
||||||
FieldInfo field = type.GetField(path);
|
FieldInfo field = type.GetField(path, FLAGS);
|
||||||
obj = field.GetValue(obj);
|
|
||||||
|
if (field != null)
|
||||||
|
obj = field.GetValue(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
|
|
@ -416,12 +420,15 @@ namespace Module.Inspector.Editor
|
||||||
|
|
||||||
public static Type GetValueType(this SerializedProperty property)
|
public static Type GetValueType(this SerializedProperty property)
|
||||||
{
|
{
|
||||||
|
const BindingFlags FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||||
|
|
||||||
object obj = property.serializedObject.targetObject;
|
object obj = property.serializedObject.targetObject;
|
||||||
Type type = null;
|
Type type = null;
|
||||||
|
|
||||||
foreach (string path in property.propertyPath.Split('.'))
|
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)
|
if (field == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -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_STRS = new Dictionary<Type, string[]>();
|
||||||
private static readonly Dictionary<Type, string[]> DICT_AS_DESCS = 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 = 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, GUIContent[]> DICT_AS_GUI_DESC = new Dictionary<Type, GUIContent[]>();
|
||||||
|
|
||||||
private static readonly Dictionary<Type, FieldInfo[]> DICT_AS_FIELDS = new Dictionary<Type, FieldInfo[]>();
|
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];
|
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))
|
if (!DICT_AS_GUI.ContainsKey(type))
|
||||||
InternalFetch(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)
|
internal static string[] GetAssignableFromAsDescriptions(Type type)
|
||||||
|
|
@ -183,6 +184,7 @@ namespace Module.Inspector.Editor
|
||||||
var fullnames = new string[listTypes.Count];
|
var fullnames = new string[listTypes.Count];
|
||||||
var descs = new string[listTypes.Count];
|
var descs = new string[listTypes.Count];
|
||||||
var guiFullNames = new GUIContent[listTypes.Count];
|
var guiFullNames = new GUIContent[listTypes.Count];
|
||||||
|
var guiShortnames = new GUIContent[listTypes.Count];
|
||||||
var guiDescs = new GUIContent[listTypes.Count];
|
var guiDescs = new GUIContent[listTypes.Count];
|
||||||
|
|
||||||
for (var i = 0; i < fullnames.Length; i++)
|
for (var i = 0; i < fullnames.Length; i++)
|
||||||
|
|
@ -190,6 +192,7 @@ namespace Module.Inspector.Editor
|
||||||
fullnames[i] = listTypes[i].FullName;
|
fullnames[i] = listTypes[i].FullName;
|
||||||
descs[i] = $"{listTypes[i].Name} (<i>{fullnames[i]}</i>)";
|
descs[i] = $"{listTypes[i].Name} (<i>{fullnames[i]}</i>)";
|
||||||
guiFullNames[i] = new GUIContent(fullnames[i]);
|
guiFullNames[i] = new GUIContent(fullnames[i]);
|
||||||
|
guiShortnames[i] = new GUIContent(listTypes[i].Name);
|
||||||
guiDescs[i] = new GUIContent(descs[i]);
|
guiDescs[i] = new GUIContent(descs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -197,6 +200,7 @@ namespace Module.Inspector.Editor
|
||||||
DICT_AS_STRS.Add(assignableFrom, fullnames);
|
DICT_AS_STRS.Add(assignableFrom, fullnames);
|
||||||
DICT_AS_DESCS.Add(assignableFrom, descs);
|
DICT_AS_DESCS.Add(assignableFrom, descs);
|
||||||
DICT_AS_GUI.Add(assignableFrom, guiFullNames);
|
DICT_AS_GUI.Add(assignableFrom, guiFullNames);
|
||||||
|
DICT_AS_GUI_SHORTNAME.Add(assignableFrom, guiShortnames);
|
||||||
DICT_AS_GUI_DESC.Add(assignableFrom, guiDescs);
|
DICT_AS_GUI_DESC.Add(assignableFrom, guiDescs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,9 @@ List of all available drawer attributes:
|
||||||
* `IntToEnum`
|
* `IntToEnum`
|
||||||
* Adds a popup with enum type provided and converts it to an integer
|
* Adds a popup with enum type provided and converts it to an integer
|
||||||
* `IntToLayer`
|
* `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`
|
* `MethodButton`
|
||||||
* Adds a button in the inspector that invokes the method (Requirement: No arguments)
|
* Adds a button in the inspector that invokes the method (Requirement: No arguments)
|
||||||
* `Naming`
|
* `Naming`
|
||||||
|
|
|
||||||
14
Runtime/Drawers/IntToLayerMaskAttribute.cs
Normal file
14
Runtime/Drawers/IntToLayerMaskAttribute.cs
Normal 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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
Runtime/Drawers/IntToLayerMaskAttribute.cs.meta
Normal file
3
Runtime/Drawers/IntToLayerMaskAttribute.cs.meta
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 02a846340b4b4fc584555df887f68f9a
|
||||||
|
timeCreated: 1656194556
|
||||||
|
|
@ -3,6 +3,9 @@ using UnityEngine.Scripting;
|
||||||
|
|
||||||
namespace Module.Inspector
|
namespace Module.Inspector
|
||||||
{
|
{
|
||||||
|
#if UNITY_2021_1_OR_NEWER
|
||||||
|
[Obsolete]
|
||||||
|
#endif
|
||||||
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
|
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
|
||||||
public sealed class QuaternionToEulerAttribute : DrawerPropertyAttribute
|
public sealed class QuaternionToEulerAttribute : DrawerPropertyAttribute
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,18 +4,21 @@ using System;
|
||||||
namespace Module.Inspector
|
namespace Module.Inspector
|
||||||
{
|
{
|
||||||
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
|
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
|
||||||
public sealed class SerializableReferenceToAttribute : DrawerPropertyAttribute
|
public sealed class SerializeReferenceToAttribute : DrawerPropertyAttribute
|
||||||
{
|
{
|
||||||
public readonly bool useType;
|
public readonly bool useType;
|
||||||
public readonly Type type;
|
public readonly Type type;
|
||||||
|
public readonly bool useFullname;
|
||||||
|
|
||||||
public SerializableReferenceToAttribute()
|
public SerializeReferenceToAttribute(bool useFullname = true)
|
||||||
{
|
{
|
||||||
useType = false;
|
useType = false;
|
||||||
|
this.useFullname = useFullname;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SerializableReferenceToAttribute(Type type)
|
public SerializeReferenceToAttribute(Type type, bool useFullname = true)
|
||||||
{
|
{
|
||||||
|
this.useFullname = useFullname;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
useType = true;
|
useType = true;
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "com.module.inspector",
|
"name": "com.module.inspector",
|
||||||
"version": "1.4.0",
|
"version": "1.5.0",
|
||||||
"displayName": "Module.Inspector",
|
"displayName": "Module.Inspector",
|
||||||
"description": "Custom inspector with various useful property drawers",
|
"description": "Custom inspector with various useful property drawers",
|
||||||
"unity": "2019.2",
|
"unity": "2019.2",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue