0.2.0: Moved into inspector drawer from module.toolbox to module.inspector

This commit is contained in:
Anders Ejlersen 2021-09-18 15:48:14 +02:00
parent 5671c2c754
commit ffec2abdf4
227 changed files with 5306 additions and 29 deletions

8
Editor.meta Normal file
View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9631ae317a3e9894987ef0394a83e49d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,72 @@
using System.Reflection;
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
public abstract class AbstractMethodDrawer
{
public void OnGUI(Rect position, Object target, MethodInfo method)
{
EditorMethodUtility.Result result = EditorMethodUtility.Query(method);
EAccessType accessType = GetAccessType(target, method, result);
if (accessType == EAccessType.Hidden)
return;
if (result.decorator != null)
{
var rect = new Rect(position);
rect.height = result.decorator.drawer.GetHeight(result.decorator.attribute);
result.decorator.drawer.Draw(rect, result.decorator.attribute);
position.height -= rect.height;
position.y += rect.height;
}
bool prevEnabled = GUI.enabled;
GUI.enabled = accessType == EAccessType.Enabled;
if (result.draw != null)
{
if (!result.draw.drawer.Draw(position, result.draw.attribute, target, method))
EditorGUI.LabelField(position, method.Name, result.draw.drawer.GetErrorMessage());
}
GUI.enabled = prevEnabled;
}
public float GetHeight(Object target, MethodInfo method)
{
EditorMethodUtility.Result result = EditorMethodUtility.Query(method);
EAccessType accessType = GetAccessType(target, method, result);
if (accessType == EAccessType.Hidden)
return 0.0f;
float height = EditorGUIUtility.singleLineHeight;
if (result.decorator != null)
height += result.decorator.drawer.GetHeight(result.decorator.attribute);
return height;
}
private EAccessType GetAccessType(Object target, MethodInfo method, EditorMethodUtility.Result result)
{
if (result.accessModifiers.Count == 0)
return EAccessType.Enabled;
EAccessType accessType = 0;
for (var i = 0; i < result.accessModifiers.Count; i++)
{
EditorMethodUtility.ResultValue<AccessModifierMethodAttribute, AccessModifierMethodDrawer> value = result.accessModifiers[i];
accessType = value.drawer.GetAccessType(value.attribute, target, method, accessType);
}
return accessType;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 85c9c674ca2f9684e908299eb744003b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,63 @@
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
public abstract class AbstractPropertyDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorPropertyUtility.Result result = EditorPropertyUtility.Query(fieldInfo);
EAccessType accessType = GetAccessType(property, result);
if (accessType == EAccessType.Hidden)
return;
label.tooltip = result.tooltip;
bool prevEnabled = GUI.enabled;
GUI.enabled = accessType == EAccessType.Enabled;
if (result.draw != null)
{
if (!result.draw.drawer.Draw(position, result.draw.attribute, property, label, result))
EditorGUI.LabelField(position, label, result.draw.drawer.GetErrorMessage(property));
}
else
{
EditorGUI.PropertyField(position, property, label, true);
}
GUI.enabled = prevEnabled;
for (var i = 0; i < result.valueModifiers.Count; i++)
{
EditorPropertyUtility.ResultValue<ValueModifierPropertyAttribute, ValueModifierPropertyDrawer> value = result.valueModifiers[i];
value.drawer.Modify(value.attribute, property);
}
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
EditorPropertyUtility.Result result = EditorPropertyUtility.Query(fieldInfo);
EAccessType accessType = GetAccessType(property, result);
return accessType != EAccessType.Hidden ? EditorGUI.GetPropertyHeight(property, label) : 0.0f;
}
private EAccessType GetAccessType(SerializedProperty property, EditorPropertyUtility.Result result)
{
if (result.accessModifiers.Count == 0)
return EAccessType.Enabled;
EAccessType accessType = 0;
for (var i = 0; i < result.accessModifiers.Count; i++)
{
EditorPropertyUtility.ResultValue<AccessModifierPropertyAttribute, AccessModifierPropertyDrawer> value = result.accessModifiers[i];
accessType = value.drawer.GetAccessType(value.attribute, property, accessType);
}
return accessType;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ebb1fc3d392a82042a858ac883eca766
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,10 @@
using System.Reflection;
using UnityEngine;
namespace Module.Inspector.Editor
{
public abstract class AccessModifierMethodDrawer : AbstractMethodDrawer
{
public abstract EAccessType GetAccessType(AccessModifierMethodAttribute attribute, Object target, MethodInfo methodInfo, EAccessType currentAccessType);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a50e42f517c92654a87605522f40d195
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,9 @@
using UnityEditor;
namespace Module.Inspector.Editor
{
public abstract class AccessModifierPropertyDrawer : AbstractPropertyDrawer
{
public abstract EAccessType GetAccessType(AccessModifierPropertyAttribute attribute, SerializedProperty property, EAccessType currentAccessType);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 09d80e9b13b703243a0ab5a617d37bd9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1b4c05f846705b04a90e7915c297d3b7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,13 @@
using UnityEditor;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(Disable))]
internal sealed class DrawerDisable : AccessModifierPropertyDrawer
{
public override EAccessType GetAccessType(AccessModifierPropertyAttribute attribute, SerializedProperty property, EAccessType currentAccessType)
{
return currentAccessType == EAccessType.Enabled ? EAccessType.ReadOnly : currentAccessType;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2316fa6e2ad8e9a42bdb9ed80642dc59
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,18 @@
using UnityEditor;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(DisableField))]
internal sealed class DrawerDisableField : AccessModifierPropertyDrawer
{
public override EAccessType GetAccessType(AccessModifierPropertyAttribute attribute, SerializedProperty property, EAccessType currentAccessType)
{
var att = (DisableField)attribute;
if (currentAccessType == EAccessType.Enabled && property.IsSiblingValue(att.fieldName, att.fieldValue, att.useFieldValue))
currentAccessType = EAccessType.ReadOnly;
return currentAccessType;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9ec3d1bd46217bb4fad7a327db680308
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,17 @@
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(DisableFieldInPlayMode))]
internal sealed class DrawerDisableFieldInPlayMode : AccessModifierPropertyDrawer
{
public override EAccessType GetAccessType(AccessModifierPropertyAttribute attribute, SerializedProperty property, EAccessType currentAccessType)
{
if (currentAccessType == EAccessType.Enabled && Application.isPlaying)
currentAccessType = EAccessType.ReadOnly;
return currentAccessType;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3ec994dc0b7f864468db321f5835e8cd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,20 @@
using System.Reflection;
using Module.Inspector.Editor.Utilities;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomMethodDrawer(typeof(DisableMethod))]
internal sealed class DrawerDisableMethod : AccessModifierMethodDrawer
{
public override EAccessType GetAccessType(AccessModifierMethodAttribute attribute, Object target, MethodInfo methodInfo, EAccessType currentAccessType)
{
var att = (DisableMethod)attribute;
if (currentAccessType == EAccessType.Enabled && EditorSerializedPropertyUtility.IsValue(target, att.fieldName, att.fieldValue, att.useFieldValue))
currentAccessType = EAccessType.ReadOnly;
return currentAccessType;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 07430432f9a75d4438828e69575e934a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,17 @@
using System.Reflection;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomMethodDrawer(typeof(DisableMethodInPlayMode))]
internal sealed class DrawerDisableMethodInPlayMode : AccessModifierMethodDrawer
{
public override EAccessType GetAccessType(AccessModifierMethodAttribute attribute, Object target, MethodInfo methodInfo, EAccessType currentAccessType)
{
if (currentAccessType == EAccessType.Enabled && Application.isPlaying)
currentAccessType = EAccessType.ReadOnly;
return currentAccessType;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b8fdd66054fd39f4bb0ce7e8c9adda2c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,18 @@
using UnityEditor;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(EnableField))]
internal sealed class DrawerEnableField : AccessModifierPropertyDrawer
{
public override EAccessType GetAccessType(AccessModifierPropertyAttribute attribute, SerializedProperty property, EAccessType currentAccessType)
{
var att = (EnableField)attribute;
if (currentAccessType == EAccessType.Enabled && !property.IsSiblingValue(att.fieldName, att.fieldValue, att.useFieldValue))
currentAccessType = EAccessType.ReadOnly;
return currentAccessType;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9b0a6e090f984d149b527950fe2e7dd5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,17 @@
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(EnableFieldInPlayMode))]
internal sealed class DrawerEnableFieldInPlayMode : AccessModifierPropertyDrawer
{
public override EAccessType GetAccessType(AccessModifierPropertyAttribute attribute, SerializedProperty property, EAccessType currentAccessType)
{
if (currentAccessType == EAccessType.Enabled && !Application.isPlaying)
currentAccessType = EAccessType.ReadOnly;
return currentAccessType;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 04f4d99527d9e864ab1e2f31c3b1d1c8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,20 @@
using System.Reflection;
using Module.Inspector.Editor.Utilities;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomMethodDrawer(typeof(EnableMethod))]
internal sealed class DrawerEnableMethod : AccessModifierMethodDrawer
{
public override EAccessType GetAccessType(AccessModifierMethodAttribute attribute, Object target, MethodInfo methodInfo, EAccessType currentAccessType)
{
var att = (EnableMethod)attribute;
if (currentAccessType == EAccessType.Enabled && !EditorSerializedPropertyUtility.IsValue(target, att.fieldName, att.fieldValue, att.useFieldValue))
currentAccessType = EAccessType.ReadOnly;
return currentAccessType;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 84998c5d066c48449be3941bff24c9ac
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,17 @@
using System.Reflection;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomMethodDrawer(typeof(EnableMethodInPlayMode))]
internal sealed class DrawerEnableMethodInPlayMode : AccessModifierMethodDrawer
{
public override EAccessType GetAccessType(AccessModifierMethodAttribute attribute, Object target, MethodInfo methodInfo, EAccessType currentAccessType)
{
if (currentAccessType == EAccessType.Enabled && !Application.isPlaying)
currentAccessType = EAccessType.ReadOnly;
return currentAccessType;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 32d72b7d351e15e4ab0b9575d6c9d5b8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,22 @@
using UnityEditor;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(HideField))]
internal sealed class DrawerHideField : AccessModifierPropertyDrawer
{
public override EAccessType GetAccessType(AccessModifierPropertyAttribute attribute, SerializedProperty property, EAccessType currentAccessType)
{
if (currentAccessType != EAccessType.Hidden && GetHideValue(attribute, property))
currentAccessType = EAccessType.Hidden;
return currentAccessType;
}
private static bool GetHideValue(AccessModifierPropertyAttribute attribute, SerializedProperty sp)
{
var att = (HideField)attribute;
return string.IsNullOrEmpty(att.fieldName) || sp.IsSiblingValue(att.fieldName, att.fieldValue, att.useFieldValue);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 732135ced1df7c44789c998f46fc6721
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,14 @@
using System.Reflection;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomMethodDrawer(typeof(HideInNormalInspector))]
internal sealed class DrawerHideInNormalInspector : AccessModifierMethodDrawer
{
public override EAccessType GetAccessType(AccessModifierMethodAttribute attribute, Object target, MethodInfo methodInfo, EAccessType currentAccessType)
{
return EAccessType.Hidden;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 496445fc2cf9fd240a488bbfb7705445
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,24 @@
using System.Reflection;
using Module.Inspector.Editor.Utilities;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomMethodDrawer(typeof(HideMethod))]
internal sealed class DrawerHideMethod : AccessModifierMethodDrawer
{
public override EAccessType GetAccessType(AccessModifierMethodAttribute attribute, Object target, MethodInfo methodInfo, EAccessType currentAccessType)
{
if (currentAccessType != EAccessType.Hidden && GetHideValue(attribute, target))
currentAccessType = EAccessType.Hidden;
return currentAccessType;
}
private static bool GetHideValue(AccessModifierMethodAttribute attribute, Object target)
{
var att = (HideMethod)attribute;
return string.IsNullOrEmpty(att.fieldName) || EditorSerializedPropertyUtility.IsValue(target, att.fieldName, att.fieldValue, att.useFieldValue);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4686038179cf33344a8a6dec3179b932
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,22 @@
using UnityEditor;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(ShowField))]
internal sealed class DrawerShowField : AccessModifierPropertyDrawer
{
public override EAccessType GetAccessType(AccessModifierPropertyAttribute attribute, SerializedProperty property, EAccessType currentAccessType)
{
if (currentAccessType != EAccessType.Hidden && !GetVisibleValue(attribute, property))
currentAccessType = EAccessType.Hidden;
return currentAccessType;
}
private static bool GetVisibleValue(AccessModifierPropertyAttribute attribute, SerializedProperty sp)
{
var att = (ShowField)attribute;
return sp.IsSiblingValue(att.fieldName, att.fieldValue, att.useFieldValue);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7e4fa1a32ce6ef14ca13bf140184ae12
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,24 @@
using System.Reflection;
using Module.Inspector.Editor.Utilities;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomMethodDrawer(typeof(ShowMethod))]
internal sealed class DrawerShowMethod : AccessModifierMethodDrawer
{
public override EAccessType GetAccessType(AccessModifierMethodAttribute attribute, Object target, MethodInfo methodInfo, EAccessType currentAccessType)
{
if (currentAccessType != EAccessType.Hidden && !GetVisibleValue(attribute, target))
currentAccessType = EAccessType.Hidden;
return currentAccessType;
}
private static bool GetVisibleValue(AccessModifierMethodAttribute attribute, Object target)
{
var att = (ShowMethod)attribute;
return EditorSerializedPropertyUtility.IsValue(target, att.fieldName, att.fieldValue, att.useFieldValue);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e66db62cd711351498512295d52b893a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,15 @@
using System;
namespace Module.Inspector.Editor
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
internal sealed class CustomMethodDrawer : Attribute
{
internal readonly Type type;
public CustomMethodDrawer(Type type)
{
this.type = type;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 01267e432205df340b4b6f463f28d10e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,10 @@
using UnityEngine;
namespace Module.Inspector.Editor
{
public abstract class DecoratorMethodDrawer : AbstractMethodDrawer
{
public abstract bool Draw(Rect position, DecoratorMethodAttribute attribute);
public abstract float GetHeight(DecoratorMethodAttribute attribute);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3e42594d91afa7a468cefa6e58e45dfa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Editor/Decorators.meta Normal file
View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: df76db5adb2d9db49b4b56e133a41397
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,40 @@
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(HorizontalLine))]
public sealed class DrawerHorizontalLine : DecoratorDrawer
{
private const float LINE_HEIGHT = 1.0f;
private const float VERTICAL_SPACING = 4.0f;
public override void OnGUI(Rect position)
{
var att = (HorizontalLine)attribute;
// Title
if (!string.IsNullOrEmpty(att.title))
{
var style = new GUIStyle(GUI.skin.label)
{
fontStyle = FontStyle.Bold
};
EditorGUI.LabelField(position, att.title, style);
}
// Line
Color oldColor = GUI.color;
GUI.color = GUI.skin.label.normal.textColor;
var rect = new Rect(position.x, position.yMax - LINE_HEIGHT - VERTICAL_SPACING, position.width, LINE_HEIGHT);
GUI.DrawTexture(rect, EditorGUIUtility.whiteTexture, ScaleMode.StretchToFill);
GUI.color = oldColor;
}
public override float GetHeight()
{
return base.GetHeight() + VERTICAL_SPACING;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f4e57076f58a444468405664e6419b6c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,32 @@
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomMethodDrawer(typeof(MethodHeader))]
public sealed class DrawerMethodHeader : DecoratorMethodDrawer
{
public override bool Draw(Rect position, DecoratorMethodAttribute attribute)
{
var att = (MethodHeader)attribute;
if (string.IsNullOrEmpty(att.title))
return false;
var style = new GUIStyle(GUI.skin.label)
{
fontStyle = FontStyle.Bold,
alignment = TextAnchor.LowerLeft
};
EditorGUI.LabelField(position, att.title, style);
return true;
}
public override float GetHeight(DecoratorMethodAttribute attribute)
{
var att = (MethodHeader)attribute;
return !string.IsNullOrEmpty(att.title) ? EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing : 0.0f;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 05076317e0ef8ff409d10caede0335a2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,11 @@
using System.Reflection;
using UnityEngine;
namespace Module.Inspector.Editor
{
public abstract class DrawerMethodDrawer : AbstractMethodDrawer
{
public abstract bool Draw(Rect position, DrawerMethodAttribute attribute, Object target, MethodInfo methodInfo);
public abstract string GetErrorMessage();
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 949e32ae16f265c4b84659f66c60b086
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,12 @@
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
public abstract class DrawerPropertyDrawer : AbstractPropertyDrawer
{
public abstract bool Draw(Rect position, DrawerPropertyAttribute attribute, SerializedProperty property, GUIContent label, EditorPropertyUtility.Result result);
public abstract string GetErrorMessage(SerializedProperty property);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 798fbdcc1b4452a4985c4f9d7393a5f5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Editor/Drawers.meta Normal file
View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d90bced66263817419bf0f3e7d2f3de5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,33 @@
using System;
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(EnumFlag))]
internal sealed class DrawerEnumFlag : DrawerPropertyDrawer
{
public override bool Draw(Rect position, DrawerPropertyAttribute attribute, SerializedProperty property, GUIContent label, EditorPropertyUtility.Result result)
{
if (property.propertyType != SerializedPropertyType.Enum)
return false;
Type type = property.GetValueType();
EditorGUI.BeginProperty(position, label, property);
{
var e = (Enum)Enum.ToObject(type, property.intValue);
e = EditorGUI.EnumFlagsField(position, label, e);
property.intValue = Convert.ToInt32(e);
}
EditorGUI.EndProperty();
return true;
}
public override string GetErrorMessage(SerializedProperty property)
{
return "Only supports enum";
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 87df0640e8498c44fb2dde2702ef30fd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,50 @@
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(FilePath))]
internal sealed class DrawerFilePath : DrawerPropertyDrawer
{
public override bool Draw(Rect position, DrawerPropertyAttribute attribute, SerializedProperty property, GUIContent label, EditorPropertyUtility.Result result)
{
if (property.propertyType != SerializedPropertyType.String)
return false;
var att = (FilePath)attribute;
EditorGUI.BeginProperty(position, label, property);
{
const float WIDTH = 80;
var rect0 = new Rect(position.x, position.y, position.width - WIDTH, position.height);
var rect1 = new Rect(rect0.xMax, position.y, WIDTH, position.height);
EditorGUI.PropertyField(rect0, property, label);
if (GUI.Button(rect1, "Find"))
{
string path = EditorUtility.OpenFilePanel("File", "Assets/", att.extension);
if (!string.IsNullOrEmpty(path))
{
if (!att.useAbsolute && path.StartsWith(Application.dataPath))
path = path.Remove(0, Application.dataPath.Length - 6);
property.stringValue = path;
property.serializedObject.ApplyModifiedProperties();
}
}
}
EditorGUI.EndProperty();
return true;
}
public override string GetErrorMessage(SerializedProperty property)
{
return "Only supports strings";
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bc4ff235b2ee1fa409b5d2e2de824159
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,49 @@
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(FolderPath))]
internal sealed class DrawerFolderPath : DrawerPropertyDrawer
{
public override bool Draw(Rect position, DrawerPropertyAttribute attribute, SerializedProperty property, GUIContent label, EditorPropertyUtility.Result result)
{
if (property.propertyType != SerializedPropertyType.String)
return false;
var att = (FolderPath)attribute;
EditorGUI.BeginProperty(position, label, property);
{
const float WIDTH = 80;
var rect0 = new Rect(position.x, position.y, position.width - WIDTH, position.height);
var rect1 = new Rect(rect0.xMax, position.y, WIDTH, position.height);
EditorGUI.PropertyField(rect0, property, label);
if (GUI.Button(rect1, "Find"))
{
string path = EditorUtility.OpenFolderPanel("Folder", "Assets/", string.Empty);
if (!string.IsNullOrEmpty(path))
{
if (!att.useAbsolute && path.StartsWith(Application.dataPath))
path = path.Remove(0, Application.dataPath.Length - 6);
property.stringValue = path;
property.serializedObject.ApplyModifiedProperties();
}
}
}
EditorGUI.EndProperty();
return true;
}
public override string GetErrorMessage(SerializedProperty property)
{
return "Only supports strings";
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d7135fc5f0bd8a54cb9378694247551d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,64 @@
using System;
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(IntToEnum))]
internal sealed class DrawerIntToEnum : DrawerPropertyDrawer
{
private GUIContent[] names;
private int[] values;
public override bool Draw(Rect position, DrawerPropertyAttribute attribute, SerializedProperty property, GUIContent label, EditorPropertyUtility.Result result)
{
if (property.propertyType != SerializedPropertyType.Integer)
return false;
var att = (IntToEnum)attribute;
FetchLayerNames(att);
EditorGUI.BeginChangeCheck();
EditorGUI.BeginProperty(position, label, property);
{
int index = Array.IndexOf(values, property.intValue);
int newIndex = EditorGUI.Popup(position, label, index, names);
if (newIndex != -1 && index != newIndex)
property.intValue = values[newIndex];
}
EditorGUI.EndProperty();
bool changed = EditorGUI.EndChangeCheck();
if (changed)
property.serializedObject.ApplyModifiedProperties();
return true;
}
public override string GetErrorMessage(SerializedProperty property)
{
return "Only supports integers";
}
private void FetchLayerNames(IntToEnum attribute)
{
if (names != null)
return;
Type type = attribute.GetValidType();
string[] arrNames = Enum.GetNames(type);
Array arrValues = Enum.GetValues(type);
names = new GUIContent[arrNames.Length];
values = new int[arrValues.Length];
for (var i = 0; i < names.Length; i++)
{
names[i] = new GUIContent(arrNames[i]);
values[i] = Convert.ToInt32(arrValues.GetValue(i));
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b3b20e9cb8fa0894f9a41a0fff58cb8b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(IntToLayer))]
internal sealed class DrawerIntToLayer : DrawerPropertyDrawer
{
private static GUIContent[] NAMES;
private static int[] INDICES;
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);
{
int index = Array.IndexOf(INDICES, property.intValue);
int newIndex = EditorGUI.Popup(position, label, index, NAMES);
if (newIndex != -1 && index != newIndex)
property.intValue = INDICES[newIndex];
}
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;
var listNames = new List<GUIContent>(32);
var listIndices = new List<int>(32);
for (var i = 0; i < 32; i++)
{
string name = LayerMask.LayerToName(i);
if (string.IsNullOrEmpty(name))
continue;
listNames.Add(new GUIContent(name));
listIndices.Add(i);
}
NAMES = listNames.ToArray();
INDICES = listIndices.ToArray();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d256c1ba203028245a0d8bffc2f1558b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,25 @@
using System.Reflection;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomMethodDrawer(typeof(MethodButton))]
internal sealed class DrawerMethodButton : DrawerMethodDrawer
{
public override bool Draw(Rect position, DrawerMethodAttribute attribute, Object target, MethodInfo methodInfo)
{
var att = (MethodButton)attribute;
string name = string.IsNullOrEmpty(att.name) ? methodInfo.Name : att.name;
if (GUI.Button(position, name))
methodInfo.Invoke(methodInfo.IsStatic ? null : target, null);
return true;
}
public override string GetErrorMessage()
{
return string.Empty;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ed6fa023ff3f3434aadacc9aa3594459
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,42 @@
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(Naming))]
internal sealed class DrawerNaming : DrawerPropertyDrawer
{
public override bool Draw(Rect position, DrawerPropertyAttribute attribute, SerializedProperty property, GUIContent label, EditorPropertyUtility.Result result)
{
if (property.propertyType != SerializedPropertyType.String)
return false;
var att = (Naming)attribute;
EditorGUI.BeginProperty(position, label, property);
{
const float WIDTH = 80;
var rect0 = new Rect(position.x, position.y, position.width - WIDTH, position.height);
var rect1 = new Rect(rect0.xMax, position.y, WIDTH, position.height);
EditorGUI.PropertyField(rect0, property);
if (GUI.Button(rect1, "Go"))
{
string str = EditorNamingUtility.ConvertTo(att.type, property.stringValue);
property.stringValue = str;
property.serializedObject.ApplyModifiedProperties();
}
}
EditorGUI.EndProperty();
return true;
}
public override string GetErrorMessage(SerializedProperty property)
{
return "Only supports strings";
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8cecc94b8bbefe64d824ba528b4e99a1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,42 @@
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(Percentage))]
internal sealed class DrawerPercentage : DrawerPropertyDrawer
{
public override bool Draw(Rect position, DrawerPropertyAttribute attribute, SerializedProperty property, GUIContent label, EditorPropertyUtility.Result result)
{
if (property.propertyType != SerializedPropertyType.Float)
return false;
EditorGUI.BeginChangeCheck();
EditorGUI.BeginProperty(position, label, property);
{
float v = property.floatValue * 100.0f;
string str = EditorGUI.TextField(position, label, v.ToString("0.0") + "%");
str = str.Replace('%', ' ').Trim();
if (float.TryParse(str, out float temp))
v = temp;
v *= 0.01f;
property.floatValue = v;
}
EditorGUI.EndProperty();
bool changed = EditorGUI.EndChangeCheck();
if (changed)
property.serializedObject.ApplyModifiedProperties();
return true;
}
public override string GetErrorMessage(SerializedProperty property)
{
return "Only supports float";
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5fccdfb1ef2fe074aa547033c1433c06
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,72 @@
using System;
using System.Linq;
using System.Reflection;
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(PopupFromConst))]
internal sealed class DrawerPopupFromConst : DrawerPropertyDrawer
{
private GUIContent[] names;
private string[] values;
public override bool Draw(Rect position, DrawerPropertyAttribute attribute, SerializedProperty property, GUIContent label, EditorPropertyUtility.Result result)
{
if (property.propertyType != SerializedPropertyType.String)
return false;
var att = (PopupFromConst)attribute;
FetchConstArray(att);
EditorGUI.BeginChangeCheck();
EditorGUI.BeginProperty(position, label, property);
{
int index = Array.IndexOf(values, property.stringValue);
int newIndex = EditorGUI.Popup(position, label, index, names);
if (newIndex != -1 && index != newIndex)
property.stringValue = values[newIndex];
}
EditorGUI.EndProperty();
bool changed = EditorGUI.EndChangeCheck();
if (changed)
property.serializedObject.ApplyModifiedProperties();
return true;
}
public override string GetErrorMessage(SerializedProperty property)
{
return "Only supports integers";
}
private void FetchConstArray(PopupFromConst attribute)
{
if (names != null)
return;
FieldInfo[] fields = attribute.type.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
.Where(fi => fi.IsLiteral && !fi.IsInitOnly && fi.FieldType == typeof(string))
.ToArray();
names = new GUIContent[fields.Length + 1];
values = new string[fields.Length + 1];
names[0] = new GUIContent("-- Empty --");
values[0] = string.Empty;
for (var i = 0; i < fields.Length; i++)
{
FieldInfo fi = fields[i];
var value = (string)fi.GetValue(null);
names[i + 1] = new GUIContent(value);
values[i + 1] = value;
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8a5a9feab54affb45bde1a4eda91d439
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,36 @@
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(QuaternionToEuler))]
internal sealed class DrawerQuaternionToEuler : DrawerPropertyDrawer
{
public override bool Draw(Rect position, DrawerPropertyAttribute attribute, SerializedProperty property, GUIContent label, EditorPropertyUtility.Result result)
{
if (property.propertyType != SerializedPropertyType.Quaternion)
return false;
EditorGUI.BeginChangeCheck();
EditorGUI.BeginProperty(position, label, property);
{
Vector3 euler = property.quaternionValue.eulerAngles;
Vector3 temp = EditorGUI.Vector3Field(position, label, euler);
property.quaternionValue = Quaternion.Euler(temp);
}
EditorGUI.EndProperty();
bool changed = EditorGUI.EndChangeCheck();
if (changed)
property.serializedObject.ApplyModifiedProperties();
return true;
}
public override string GetErrorMessage(SerializedProperty property)
{
return "Only supports quaternions";
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8954c2ee521537a49a53bf4de92575e7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(SceneDropdown))]
internal sealed class DrawerSceneDropdown : DrawerPropertyDrawer
{
private static GUIContent[] NAMES;
private static string[] PATHS;
public override bool Draw(Rect position, DrawerPropertyAttribute attribute, SerializedProperty property, GUIContent label, EditorPropertyUtility.Result result)
{
if (property.propertyType != SerializedPropertyType.String)
return false;
FetchScenes();
EditorGUI.BeginChangeCheck();
EditorGUI.BeginProperty(position, label, property);
{
int index = Array.IndexOf(PATHS, property.stringValue);
int newIndex = EditorGUI.Popup(position, label, index, NAMES);
if (newIndex != -1 && index != newIndex)
property.stringValue = PATHS[newIndex];
}
EditorGUI.EndProperty();
bool changed = EditorGUI.EndChangeCheck();
if (changed)
property.serializedObject.ApplyModifiedProperties();
return true;
}
public override string GetErrorMessage(SerializedProperty property)
{
return "Only supports strings";
}
private static string ToSceneName(string path)
{
return !string.IsNullOrEmpty(path) ? path.Substring(7, path.Length - 13).Replace('/', '\\') : string.Empty;
}
private static void FetchScenes()
{
if (NAMES != null)
return;
EditorBuildSettingsScene[] scenes = EditorBuildSettings.scenes;
var listNames = new List<GUIContent>(scenes.Length);
var listPaths = new List<string>(scenes.Length);
for (var i = 0; i < scenes.Length; i++)
{
string path = scenes[i].path;
if (string.IsNullOrEmpty(path))
continue;
listNames.Add(new GUIContent(ToSceneName(path)));
listPaths.Add(path);
}
NAMES = listNames.ToArray();
PATHS = listPaths.ToArray();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dff7a960f4e593145a913cd65ed37da1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,134 @@
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(Slider))]
internal sealed class DrawerSlider : DrawerPropertyDrawer
{
public override bool Draw(Rect position, DrawerPropertyAttribute attribute, SerializedProperty property, GUIContent label, EditorPropertyUtility.Result result)
{
var min = result.GetValueModifier<MinValue>();
var max = result.GetValueModifier<MaxValue>();
if (min == null || max == null)
return false;
switch (property.propertyType)
{
case SerializedPropertyType.Integer:
case SerializedPropertyType.Float:
DrawRange(position, property, label, min, max);
break;
case SerializedPropertyType.Vector2:
case SerializedPropertyType.Vector2Int:
DrawerMinMax(position, property, label, min, max);
break;
default:
return false;
}
return true;
}
public override string GetErrorMessage(SerializedProperty property)
{
switch (property.propertyType)
{
case SerializedPropertyType.Integer:
case SerializedPropertyType.Float:
case SerializedPropertyType.Vector2:
case SerializedPropertyType.Vector2Int:
return "Requires MinValue and MaxValue";
}
return "Only supports integer, float, vector2 and vector2int";
}
private void DrawRange(Rect position, SerializedProperty property, GUIContent label, MinValue minValue, MaxValue maxValue)
{
int indentLevel = EditorGUI.indentLevel;
float indentSpacing = indentLevel * 15.0f;
EditorGUI.indentLevel = 0;
EditorGUI.BeginProperty(position, label, property);
{
float xMin = position.x + indentSpacing;
var r0 = new Rect(xMin, position.y, EditorGUIUtility.labelWidth - indentSpacing + 2.0f, position.height);
var r1 = new Rect(r0.xMax, r0.y, position.width - r0.width - indentSpacing, r0.height);
EditorGUI.LabelField(r0, label);
switch (property.propertyType)
{
case SerializedPropertyType.Integer:
property.intValue = EditorGUI.IntSlider(r1, property.intValue, minValue.intValue, maxValue.intValue);
break;
case SerializedPropertyType.Float:
property.floatValue = EditorGUI.Slider(r1, property.floatValue, minValue.floatValue, maxValue.floatValue);
break;
}
}
EditorGUI.EndProperty();
EditorGUI.indentLevel = indentLevel;
}
private void DrawerMinMax(Rect position, SerializedProperty property, GUIContent label, MinValue min, MaxValue max)
{
const float FLOAT_WIDTH = 50.0f;
const float FLOAT_SPACING = 8.0f;
int indentLevel = EditorGUI.indentLevel;
float indentSpacing = indentLevel * 15.0f;
EditorGUI.indentLevel = 0;
EditorGUI.BeginProperty(position, label, property);
{
float xMin = position.x + indentSpacing;
float width = position.width - indentSpacing;
var r0 = new Rect(xMin, position.y, EditorGUIUtility.labelWidth - indentSpacing + 2.0f, position.height);
var r1 = new Rect(r0.xMax, r0.y, FLOAT_WIDTH, r0.height);
var r2 = new Rect(r1.xMax + FLOAT_SPACING, r1.y, width - r0.width - (FLOAT_WIDTH + FLOAT_SPACING) * 2, r1.height);
var r3 = new Rect(r2.xMax + FLOAT_SPACING, r2.y, FLOAT_WIDTH, r2.height);
EditorGUI.LabelField(r0, label);
switch (property.propertyType)
{
case SerializedPropertyType.Vector2:
Vector2 v = property.vector2Value;
float minValue = v.x;
float maxValue = v.y;
minValue = EditorGUI.FloatField(r1, minValue);
maxValue = EditorGUI.FloatField(r3, maxValue);
EditorGUI.MinMaxSlider(r2, ref minValue, ref maxValue, min.floatValue, max.floatValue);
v.x = minValue;
v.y = maxValue;
property.vector2Value = v;
break;
case SerializedPropertyType.Vector2Int:
Vector2Int v2Int = property.vector2IntValue;
float minIntValue = v2Int.x;
float maxIntValue = v2Int.y;
minIntValue = EditorGUI.IntField(r1, Mathf.RoundToInt(minIntValue));
maxIntValue = EditorGUI.IntField(r3, Mathf.RoundToInt(maxIntValue));
EditorGUI.MinMaxSlider(r2, ref minIntValue, ref maxIntValue, min.floatValue, max.floatValue);
v2Int.x = Mathf.RoundToInt(minIntValue);
v2Int.y = Mathf.RoundToInt(maxIntValue);
property.vector2IntValue = v2Int;
break;
}
}
EditorGUI.EndProperty();
EditorGUI.indentLevel = indentLevel;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 485f79e819f053d41b57536ca476ec1f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,38 @@
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(StringToField))]
internal sealed class DrawerStringToField : DrawerPropertyDrawer
{
public override bool Draw(Rect position, DrawerPropertyAttribute attribute, SerializedProperty property, GUIContent label, EditorPropertyUtility.Result result)
{
if (property.propertyType != SerializedPropertyType.String)
return false;
var att = (StringToField)attribute;
EditorGUI.BeginProperty(position, label, property);
{
const float WIDTH = 80;
var rect0 = new Rect(position.x, position.y, position.width - WIDTH, position.height);
var rect1 = new Rect(rect0.xMax, position.y, WIDTH, position.height);
EditorGUI.PropertyField(rect0, property, label);
if (GUI.Button(rect1, "Find"))
EditorWindowStringToField.Open(att.type, property);
}
EditorGUI.EndProperty();
return true;
}
public override string GetErrorMessage(SerializedProperty property)
{
return "Only supports strings";
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fef0de5c591508a43ad30e46920f7e08
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,39 @@
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(StringToType))]
internal sealed class DrawerStringToType : DrawerPropertyDrawer
{
public override bool Draw(Rect position, DrawerPropertyAttribute attribute, SerializedProperty property, GUIContent label, EditorPropertyUtility.Result result)
{
if (property.propertyType != SerializedPropertyType.String)
return false;
var att = (StringToType)attribute;
EditorGUI.BeginProperty(position, label, property);
{
const float WIDTH = 80;
var rect0 = new Rect(position.x, position.y, position.width - WIDTH, position.height);
var rect1 = new Rect(rect0.xMax, position.y, WIDTH, position.height);
EditorGUI.PropertyField(rect0, property, label);
if (GUI.Button(rect1, "Find"))
EditorWindowStringToType.Open(att.assignableFrom, property);
}
EditorGUI.EndProperty();
return true;
}
public override string GetErrorMessage(SerializedProperty property)
{
return "Only supports strings";
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5bd5ab3cdc645674d84151133c5b5b78
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,36 @@
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(UrlGoTo))]
internal sealed class DrawerUrlGoTo : DrawerPropertyDrawer
{
public override bool Draw(Rect position, DrawerPropertyAttribute attribute, SerializedProperty property, GUIContent label, EditorPropertyUtility.Result result)
{
if (property.propertyType != SerializedPropertyType.String)
return false;
EditorGUI.BeginProperty(position, label, property);
{
const float WIDTH = 80;
var r0 = new Rect(position.x, position.y, position.width - WIDTH, position.height);
var r1 = new Rect(r0.xMax, r0.y, WIDTH, r0.height);
EditorGUI.PropertyField(r0, property, label);
if (GUI.Button(r1, "Go"))
Application.OpenURL(property.stringValue);
}
EditorGUI.EndProperty();
return true;
}
public override string GetErrorMessage(SerializedProperty property)
{
return "Only supports strings";
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c78fde2b0fd08fa42ae7a1c8ee72a0e5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Editor/Enums.meta Normal file
View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ceee61977f5a0e74abc8a7387abf9440
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,9 @@
namespace Module.Inspector.Editor
{
public enum EAccessType : byte
{
Enabled,
Hidden,
ReadOnly,
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a1b0d189dd82df440bf3328e0086c0c5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Editor/Extensions.meta Normal file
View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5e03154e5871d7140ad3a7193d223d81
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,430 @@
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace Module.Inspector.Editor
{
public static class SerializedPropertyExtension
{
public enum ECompareType : byte { False, True, Unknown };
public static SerializedProperty GetParent(this SerializedProperty sp)
{
string propertyPath = GetRootPath(sp.propertyPath);
return !propertyPath.Equals(sp.propertyPath) ? sp.serializedObject.FindProperty(propertyPath) : null;
}
public static SerializedProperty GetSibling(this SerializedProperty sp, string fieldName)
{
string propertyPath = GetRootPath(sp.propertyPath);
if (string.IsNullOrEmpty(propertyPath))
propertyPath = fieldName;
else
propertyPath += "." + fieldName;
return sp.serializedObject.FindProperty(propertyPath);
}
public static SerializedProperty GetRelativeProperty(this SerializedProperty sp, string relativePath)
{
SerializedProperty rp = sp;
string[] split = relativePath.Split('/');
for (var i = 0; i < split.Length; i++)
{
rp = split[i].Equals("PARENT") ? GetParent(rp) : GetSibling(rp, split[i]);
if (rp == null)
break;
}
return rp;
}
public static bool IsSiblingValue(this SerializedProperty sp, string siblingFieldName, object siblingFieldValue, bool useFieldValue)
{
if (string.IsNullOrEmpty(siblingFieldName))
return false;
SerializedProperty spSibling = sp.GetRelativeProperty(siblingFieldName);
return EditorSerializedPropertyUtility.IsValue(spSibling, siblingFieldValue, useFieldValue);
}
public static ECompareType IsGreaterOrEqualToSiblingValue(this SerializedProperty sp, string siblingFieldName)
{
if (string.IsNullOrEmpty(siblingFieldName))
return ECompareType.Unknown;
SerializedProperty spSibling = sp.GetRelativeProperty(siblingFieldName);
if (spSibling == null)
return ECompareType.Unknown;
if (spSibling.propertyType != sp.propertyType)
return ECompareType.Unknown;
if (sp.propertyType == SerializedPropertyType.Integer)
return sp.IsGreaterOrEqualToSiblingValue(siblingFieldName, sp.intValue);
if (sp.propertyType == SerializedPropertyType.Float)
return sp.IsGreaterOrEqualToSiblingValue(siblingFieldName, sp.floatValue);
if (sp.propertyType == SerializedPropertyType.Enum)
return sp.IsGreaterOrEqualToSiblingValue(siblingFieldName, sp.intValue);
return ECompareType.Unknown;
}
public static ECompareType IsGreaterOrEqualToSiblingValue(this SerializedProperty sp, string siblingFieldName, object siblingFieldValue)
{
if (string.IsNullOrEmpty(siblingFieldName))
return ECompareType.Unknown;
SerializedProperty spSibling = sp.GetRelativeProperty(siblingFieldName);
if (spSibling == null)
return ECompareType.Unknown;
if (spSibling.propertyType == SerializedPropertyType.Integer && siblingFieldValue is int i)
return spSibling.intValue <= i ? ECompareType.True : ECompareType.False;
if (spSibling.propertyType == SerializedPropertyType.Float && siblingFieldValue is float f)
return spSibling.floatValue <= f ? ECompareType.True : ECompareType.False;
if (spSibling.propertyType == SerializedPropertyType.Enum && siblingFieldValue is int e)
return spSibling.intValue <= e ? ECompareType.True : ECompareType.False;
return ECompareType.Unknown;
}
public static ECompareType IsSmallerOrEqualToSiblingValue(this SerializedProperty sp, string siblingFieldName)
{
if (string.IsNullOrEmpty(siblingFieldName))
return ECompareType.Unknown;
SerializedProperty spSibling = sp.GetRelativeProperty(siblingFieldName);
if (spSibling == null)
return ECompareType.Unknown;
if (spSibling.propertyType != sp.propertyType)
return ECompareType.Unknown;
if (sp.propertyType == SerializedPropertyType.Integer)
return sp.IsSmallerOrEqualToSiblingValue(siblingFieldName, sp.intValue);
if (sp.propertyType == SerializedPropertyType.Float)
return sp.IsSmallerOrEqualToSiblingValue(siblingFieldName, sp.floatValue);
if (sp.propertyType == SerializedPropertyType.Enum)
return sp.IsSmallerOrEqualToSiblingValue(siblingFieldName, sp.intValue);
return ECompareType.Unknown;
}
public static ECompareType IsSmallerOrEqualToSiblingValue(this SerializedProperty sp, string siblingFieldName, object siblingFieldValue)
{
if (string.IsNullOrEmpty(siblingFieldName))
return ECompareType.Unknown;
SerializedProperty spSibling = sp.GetRelativeProperty(siblingFieldName);
if (spSibling == null)
return ECompareType.Unknown;
if (spSibling.propertyType == SerializedPropertyType.Integer && siblingFieldValue is int i)
return spSibling.intValue >= i ? ECompareType.True : ECompareType.False;
if (spSibling.propertyType == SerializedPropertyType.Float && siblingFieldValue is float f)
return spSibling.floatValue >= f ? ECompareType.True : ECompareType.False;
if (spSibling.propertyType == SerializedPropertyType.Enum && siblingFieldValue is int e)
return spSibling.intValue >= e ? ECompareType.True : ECompareType.False;
return ECompareType.Unknown;
}
public static void SetValueTo(this SerializedProperty sp, SerializedProperty other)
{
if (sp.propertyType != other.propertyType)
return;
switch (sp.propertyType)
{
case SerializedPropertyType.LayerMask:
case SerializedPropertyType.Integer:
case SerializedPropertyType.Enum:
sp.intValue = other.intValue;
break;
case SerializedPropertyType.Boolean:
sp.boolValue = other.boolValue;
break;
case SerializedPropertyType.Float:
sp.floatValue = other.floatValue;
break;
case SerializedPropertyType.String:
sp.stringValue = other.stringValue;
break;
case SerializedPropertyType.Color:
sp.colorValue = other.colorValue;
break;
case SerializedPropertyType.ObjectReference:
sp.objectReferenceValue = other.objectReferenceValue;
break;
case SerializedPropertyType.Vector2:
sp.vector2Value = other.vector2Value;
break;
case SerializedPropertyType.Vector3:
sp.vector3Value = other.vector3Value;
break;
case SerializedPropertyType.Vector4:
sp.vector4Value = other.vector4Value;
break;
case SerializedPropertyType.Rect:
sp.rectValue = other.rectValue;
break;
case SerializedPropertyType.AnimationCurve:
sp.animationCurveValue = other.animationCurveValue;
break;
case SerializedPropertyType.Bounds:
sp.boundsValue = other.boundsValue;
break;
case SerializedPropertyType.Quaternion:
sp.quaternionValue = other.quaternionValue;
break;
case SerializedPropertyType.Vector2Int:
sp.vector2IntValue = other.vector2IntValue;
break;
case SerializedPropertyType.Vector3Int:
sp.vector3IntValue = other.vector3IntValue;
break;
case SerializedPropertyType.RectInt:
sp.rectIntValue = other.rectIntValue;
break;
case SerializedPropertyType.BoundsInt:
sp.boundsIntValue = other.boundsIntValue;
break;
}
}
public static bool TrySetValueTo(this SerializedProperty sp, object value, bool allowDuplicate)
{
if (sp.isArray && sp.propertyType != SerializedPropertyType.String)
{
if (!allowDuplicate && sp.Contains(value))
return true;
Type type = value.GetType();
if (!type.IsArray)
{
sp.InsertArrayElementAtIndex(sp.arraySize);
sp = sp.GetArrayElementAtIndex(sp.arraySize - 1);
}
}
switch (sp.propertyType)
{
case SerializedPropertyType.LayerMask:
case SerializedPropertyType.Integer:
case SerializedPropertyType.Enum:
if (!(value is int i))
return false;
sp.intValue = i;
return true;
case SerializedPropertyType.Boolean:
if (!(value is bool b))
return false;
sp.boolValue = b;
return true;
case SerializedPropertyType.Float:
if (!(value is float f))
return false;
sp.floatValue = f;
return true;
case SerializedPropertyType.String:
if (!(value is string str))
return false;
sp.stringValue = str;
return true;
case SerializedPropertyType.Color:
if (!(value is Color c))
return false;
sp.colorValue = c;
return true;
case SerializedPropertyType.ObjectReference:
if (!(value is Object o))
return false;
sp.objectReferenceValue = o;
return true;
case SerializedPropertyType.Vector2:
if (!(value is Vector2 v2))
return false;
sp.vector2Value = v2;
return true;
case SerializedPropertyType.Vector3:
if (!(value is Vector3 v3))
return false;
sp.vector3Value = v3;
return true;
case SerializedPropertyType.Vector4:
if (!(value is Vector4 v4))
return false;
sp.vector4Value = v4;
return true;
case SerializedPropertyType.Rect:
if (!(value is Rect r))
return false;
sp.rectValue = r;
return true;
case SerializedPropertyType.AnimationCurve:
if (!(value is AnimationCurve ac))
return false;
sp.animationCurveValue = ac;
return true;
case SerializedPropertyType.Bounds:
if (!(value is Bounds bounds))
return false;
sp.boundsValue = bounds;
return true;
case SerializedPropertyType.Quaternion:
if (!(value is Quaternion q))
return false;
sp.quaternionValue = q;
return true;
case SerializedPropertyType.Vector2Int:
if (!(value is Vector2Int v2i))
return false;
sp.vector2IntValue = v2i;
return true;
case SerializedPropertyType.Vector3Int:
if (!(value is Vector3Int v3i))
return false;
sp.vector3IntValue = v3i;
return true;
case SerializedPropertyType.RectInt:
if (!(value is RectInt ri))
return false;
sp.rectIntValue = ri;
return true;
case SerializedPropertyType.BoundsInt:
if (!(value is BoundsInt bi))
return false;
sp.boundsIntValue = bi;
return true;
}
return false;
}
private static bool Contains(this SerializedProperty sp, object value)
{
if (sp.isArray)
{
for (var i = 0; i < sp.arraySize; i++)
{
SerializedProperty temp = sp.GetArrayElementAtIndex(i);
if (temp.Contains(value))
return true;
}
}
else
{
try
{
switch (sp.propertyType)
{
case SerializedPropertyType.LayerMask:
case SerializedPropertyType.Integer:
case SerializedPropertyType.Enum:
return Convert.ToInt32(value) == sp.intValue;
case SerializedPropertyType.Boolean:
return Convert.ToBoolean(value) == sp.boolValue;
case SerializedPropertyType.Float:
return Mathf.Approximately(Convert.ToSingle(value), sp.floatValue);
case SerializedPropertyType.String:
return Convert.ToString(value).Equals(sp.stringValue);
case SerializedPropertyType.ObjectReference:
if (!(value is Object))
return false;
return sp.objectReferenceValue == (Object)value;
}
}
catch (Exception e)
{
Debug.LogException(e);
}
}
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static string GetRootPath(string propertyPath)
{
int lastIndex = propertyPath.LastIndexOf('.');
return lastIndex != -1 ? propertyPath.Remove(lastIndex) : string.Empty;
}
public static T GetValue<T>(this SerializedProperty property) where T : class
{
return property.GetValue() as T;
}
private static object GetValue(this SerializedProperty property)
{
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);
}
return obj;
}
public static Type GetValueType(this SerializedProperty property)
{
object obj = property.serializedObject.targetObject;
Type type = null;
foreach (string path in property.propertyPath.Split('.'))
{
type = obj.GetType();
FieldInfo field = type.GetField(path);
obj = field.GetValue(obj);
type = field.FieldType;
}
return type;
}
public static void SetArray<T>(this SerializedProperty property, T[] array) where T : Object
{
property.ClearArray();
for (var i = 0; i < array.Length; i++)
{
property.InsertArrayElementAtIndex(i);
SerializedProperty sp = property.GetArrayElementAtIndex(i);
sp.objectReferenceValue = array[i];
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7c74edadbcd71ad4aa3293e00a4d4d47
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,18 @@
{
"name": "Module.Inspector.Editor",
"rootNamespace": "Module.Inspector.Editor",
"references": [
"GUID:a58be6d007e5e434ebc9bf7f902990a7"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 2002c0ac45f161445a6fa998a273f22a
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

68
Editor/ObjectEditor.cs Normal file
View file

@ -0,0 +1,68 @@
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CanEditMultipleObjects]
[CustomEditor(typeof(Object), true, isFallback = true)]
public sealed class ObjectEditor : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
DrawMethodInspector();
}
private void DrawMethodInspector()
{
if (!IsValidMethodTarget())
return;
EditorMethodUtility.ResultPrimary[] primaries = EditorMethodUtility.QueryPrimary(target);
float totalHeight = CalculateMethodHeight(primaries);
GUILayout.Space(totalHeight);
var position = new Rect(0, 0, 1, 1);
if (Event.current.type == EventType.Repaint)
{
position = GUILayoutUtility.GetLastRect();
position.y -= totalHeight;
}
position.y = position.yMax + EditorGUIUtility.singleLineHeight;
position.height = 0.0f;
for (var i = 0; i < primaries.Length; i++)
{
EditorMethodUtility.ResultPrimary primary = primaries[i];
float height = primary.drawer.GetHeight(target, primary.methodInfo);
position.height = height;
primary.drawer.OnGUI(position, target, primary.methodInfo);
position.y += height;
}
}
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()
{
return target != null && targets.Length == 1;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bd743fb74f77a5f40936b202ff6f35d4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Editor/Utilities.meta Normal file
View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 743152a66f1aba046b489eb2b8907a29
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,233 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Module.Inspector.Editor.Utilities
{
internal static class EditorMethodUtility
{
private static Dictionary<Type, ResultPrimary[]> CACHED_TYPE_TO_PRIMARIES;
private static Dictionary<MethodInfo, Result> CACHED_RESULTS;
private static Dictionary<Type, Type> CACHED_ATT_TO_DRAWER;
private static void InitializeCache()
{
if (CACHED_ATT_TO_DRAWER != null)
return;
CACHED_ATT_TO_DRAWER = new Dictionary<Type, Type>();
Type baseDrawerType = typeof(AbstractMethodDrawer);
var assembly = Assembly.GetAssembly(baseDrawerType);
Type[] types = assembly.GetTypes();
for (var i = 0; i < types.Length; i++)
{
Type type = types[i];
if (type.IsAbstract || !baseDrawerType.IsAssignableFrom(type))
continue;
IList<CustomAttributeData> attributes = type.GetCustomAttributesData();
for (var j = 0; j < attributes.Count; j++)
{
CustomAttributeData attData = attributes[j];
IList<CustomAttributeTypedArgument> arguments = attData.ConstructorArguments;
for (var k = 0; k < arguments.Count; k++)
{
if (arguments[k].Value is Type argType)
CACHED_ATT_TO_DRAWER.Add(argType, type);
}
}
}
}
public static ResultPrimary[] QueryPrimary(Object target)
{
InitializeCache();
if (CACHED_TYPE_TO_PRIMARIES == null)
CACHED_TYPE_TO_PRIMARIES = new Dictionary<Type, ResultPrimary[]>();
Type type = target.GetType();
if (CACHED_TYPE_TO_PRIMARIES.TryGetValue(type, out ResultPrimary[] primaries))
return primaries;
primaries = InternalFetchPrimary(type);
CACHED_TYPE_TO_PRIMARIES.Add(type, primaries);
return primaries;
}
public static Result Query(MethodInfo methodInfo)
{
InitializeCache();
if (CACHED_RESULTS == null)
CACHED_RESULTS = new Dictionary<MethodInfo, Result>();
if (CACHED_RESULTS.TryGetValue(methodInfo, out Result result))
return result;
result = InternalFetchProperties(methodInfo);
if (result != null)
CACHED_RESULTS.Add(methodInfo, result);
return result;
}
private static ResultPrimary[] InternalFetchPrimary(Type type)
{
const BindingFlags FLAGS = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
MethodInfo[] methods = type.GetMethods(FLAGS)
.Where(m => m.GetParameters().Length == 0)
.ToArray();
var list = new List<ResultPrimary>(methods.Length);
for (var i = 0; i < methods.Length; i++)
{
Result result = Query(methods[i]);
if (result != null)
list.Add(new ResultPrimary(methods[i], result));
}
return list.ToArray();
}
private static Result InternalFetchProperties(MethodInfo methodInfo)
{
ResultValue<DrawerMethodAttribute, DrawerMethodDrawer> drawer = null;
ResultValue<DecoratorMethodAttribute, DecoratorMethodDrawer> decorator = null;
var accessModifiers = new List<ResultValue<AccessModifierMethodAttribute, AccessModifierMethodDrawer>>(2);
object[] attributes = methodInfo.GetCustomAttributes(false);
for (var i = 0; i < attributes.Length; i++)
{
object att = attributes[i];
if (att is DrawerMethodAttribute attDrawer)
{
if (drawer != null)
continue;
var prop = InternalCreateInstanceOf<DrawerMethodDrawer>(attDrawer);
if (prop != null)
drawer = new ResultValue<DrawerMethodAttribute, DrawerMethodDrawer>(attDrawer, prop);
}
else if (att is AccessModifierMethodAttribute accessModifier)
{
var prop = InternalCreateInstanceOf<AccessModifierMethodDrawer>(accessModifier);
if (prop != null)
accessModifiers.Add(new ResultValue<AccessModifierMethodAttribute, AccessModifierMethodDrawer>(accessModifier, prop));
}
else if (att is DecoratorMethodAttribute attDecorator)
{
if (decorator != null)
continue;
var prop = InternalCreateInstanceOf<DecoratorMethodDrawer>(attDecorator);
if (prop != null)
decorator = new ResultValue<DecoratorMethodAttribute, DecoratorMethodDrawer>(attDecorator, prop);
}
}
if (drawer == null && decorator == null && accessModifiers.Count == 0)
return null;
return new Result(drawer, decorator, accessModifiers);
}
private static T InternalCreateInstanceOf<T>(AbstractMethodAttribute att) where T : AbstractMethodDrawer
{
if (CACHED_ATT_TO_DRAWER.TryGetValue(att.GetType(), out Type drawerType))
return Activator.CreateInstance(drawerType) as T;
return null;
}
/// <summary>
/// Class: Result from method query
/// </summary>
public sealed class Result
{
public readonly ResultValue<DrawerMethodAttribute, DrawerMethodDrawer> draw;
public readonly ResultValue<DecoratorMethodAttribute, DecoratorMethodDrawer> decorator;
public readonly List<ResultValue<AccessModifierMethodAttribute, AccessModifierMethodDrawer>> accessModifiers;
public Result(ResultValue<DrawerMethodAttribute, DrawerMethodDrawer> draw,
ResultValue<DecoratorMethodAttribute, DecoratorMethodDrawer> decorator,
List<ResultValue<AccessModifierMethodAttribute, AccessModifierMethodDrawer>> accessModifiers)
{
this.draw = draw;
this.decorator = decorator;
this.accessModifiers = accessModifiers;
}
public T GetAccessModifier<T>() where T : AccessModifierMethodAttribute
{
for (var i = 0; i < accessModifiers.Count; i++)
{
if (accessModifiers[i].attribute is T att)
return att;
}
return null;
}
}
/// <summary>
/// Class: Contains attribute and drawer values
/// </summary>
/// <typeparam name="T0"></typeparam>
/// <typeparam name="T1"></typeparam>
public sealed class ResultValue<T0, T1> where T0 : AbstractMethodAttribute
where T1 : AbstractMethodDrawer
{
public readonly T0 attribute;
public readonly T1 drawer;
public ResultValue(T0 attribute, T1 drawer)
{
this.attribute = attribute;
this.drawer = drawer;
}
}
/// <summary>
/// Class: Contains primary method info and drawer for a specific method
/// </summary>
public sealed class ResultPrimary
{
public readonly MethodInfo methodInfo;
public readonly AbstractMethodDrawer drawer;
public ResultPrimary(MethodInfo methodInfo, AbstractMethodDrawer drawer)
{
this.methodInfo = methodInfo;
this.drawer = drawer;
}
public ResultPrimary(MethodInfo methodInfo, Result result)
{
this.methodInfo = methodInfo;
if (result.draw != null)
drawer = result.draw.drawer;
else if (result.decorator != null)
drawer = result.decorator.drawer;
else if (result.accessModifiers != null && result.accessModifiers.Count > 0)
drawer = result.accessModifiers[0].drawer;
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8084cb44127a2464ab72b4d104b7b622
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,76 @@
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
namespace Module.Inspector.Editor.Utilities
{
public static class EditorNamingUtility
{
public static string ConvertTo(Naming.EPatternType type, string str)
{
switch (type)
{
case Naming.EPatternType.CamelCasing:
return ToCamel(str);
case Naming.EPatternType.PascalCasing:
return ToPascal(str);
case Naming.EPatternType.SnakeCasing:
return ToSnake(str);
case Naming.EPatternType.SnakeCasingAllCaps:
return ToSnake(str).ToUpper();
case Naming.EPatternType.KebabCasing:
return ToKebab(str);
case Naming.EPatternType.KebabCasingAllCaps:
return ToKebab(str).ToUpper();
default:
return str;
}
}
public static string ToPascal(string str)
{
var pattern = new Regex(@"[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+");
MatchCollection matches = pattern.Matches(str);
if (matches.Count != 0)
str = matches.Cast<Match>().Select(c => c.Value).Aggregate(( a, b ) => a + " " + b);
var culture = new CultureInfo("en-US", false);
str = culture.TextInfo.ToTitleCase(str);
str = str.Replace(@" ", "");
return str;
}
public static string ToCamel(string str)
{
str = ToPascal(str);
if (str.Length > 0)
str = char.ToLower(str[0]) + str.Substring(1);
return str;
}
public static string ToSnake(string str)
{
var pattern = new Regex(@"[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+");
MatchCollection matches = pattern.Matches(str);
if (matches.Count != 0)
str = matches.Cast<Match>().Select(c => c.Value).Aggregate(( a, b ) => a + "_" + b);
return str;
}
public static string ToKebab(string str)
{
var pattern = new Regex(@"[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+");
MatchCollection matches = pattern.Matches(str);
if (matches.Count != 0)
str = matches.Cast<Match>().Select(c => c.Value).Aggregate(( a, b ) => a + "-" + b);
return str;
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cbf1a9393f7c4425b846686ccc5445e0
timeCreated: 1625650972

View file

@ -0,0 +1,208 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
namespace Module.Inspector.Editor.Utilities
{
public static class EditorPropertyUtility
{
private static Dictionary<FieldInfo, Result> CACHED_RESULTS;
private static Dictionary<Type, Type> CACHED_ATT_TO_DRAWER;
private static void InitializeCache()
{
if (CACHED_ATT_TO_DRAWER != null)
return;
CACHED_ATT_TO_DRAWER = new Dictionary<Type, Type>();
Type baseDrawerType = typeof(AbstractPropertyDrawer);
var assembly = Assembly.GetAssembly(baseDrawerType);
Type[] types = assembly.GetTypes();
for (var i = 0; i < types.Length; i++)
{
Type type = types[i];
if (type.IsAbstract || !baseDrawerType.IsAssignableFrom(type))
continue;
IList<CustomAttributeData> attributes = type.GetCustomAttributesData();
for (var j = 0; j < attributes.Count; j++)
{
CustomAttributeData attData = attributes[j];
IList<CustomAttributeTypedArgument> arguments = attData.ConstructorArguments;
for (var k = 0; k < arguments.Count; k++)
{
if (arguments[k].Value is Type argType)
CACHED_ATT_TO_DRAWER.Add(argType, type);
}
}
}
}
public static Result Query(FieldInfo fieldInfo)
{
InitializeCache();
if (CACHED_RESULTS == null)
CACHED_RESULTS = new Dictionary<FieldInfo, Result>();
if (CACHED_RESULTS.TryGetValue(fieldInfo, out Result result))
return result;
result = InternalFetchProperties(fieldInfo);
CACHED_RESULTS.Add(fieldInfo, result);
return result;
}
private static Result InternalFetchProperties(FieldInfo fieldInfo)
{
ResultValue<DrawerPropertyAttribute, DrawerPropertyDrawer> drawer = null;
var typeDrawer = InternalCreateInstanceOf<DrawerPropertyDrawer>(fieldInfo);
if (typeDrawer != null)
drawer = new ResultValue<DrawerPropertyAttribute, DrawerPropertyDrawer>(null, typeDrawer);
var valueModifiers = new List<ResultValue<ValueModifierPropertyAttribute, ValueModifierPropertyDrawer>>(2);
var accessModifiers = new List<ResultValue<AccessModifierPropertyAttribute, AccessModifierPropertyDrawer>>(2);
object[] attributes = fieldInfo.GetCustomAttributes(false);
string tooltip = null;
var isObsolete = false;
string obsoleteText = null;
for (var i = 0; i < attributes.Length; i++)
{
object att = attributes[i];
if (att is DrawerPropertyAttribute attDrawer)
{
if (drawer != null)
continue;
var prop = InternalCreateInstanceOf<DrawerPropertyDrawer>(attDrawer);
if (prop != null)
drawer = new ResultValue<DrawerPropertyAttribute, DrawerPropertyDrawer>(attDrawer, prop);
}
else if (att is ValueModifierPropertyAttribute valueModifier)
{
var prop = InternalCreateInstanceOf<ValueModifierPropertyDrawer>(valueModifier);
if (prop != null)
valueModifiers.Add(new ResultValue<ValueModifierPropertyAttribute, ValueModifierPropertyDrawer>(valueModifier, prop));
}
else if (att is AccessModifierPropertyAttribute accessModifier)
{
var prop = InternalCreateInstanceOf<AccessModifierPropertyDrawer>(accessModifier);
if (prop != null)
accessModifiers.Add(new ResultValue<AccessModifierPropertyAttribute, AccessModifierPropertyDrawer>(accessModifier, prop));
}
else if (att is TooltipAttribute attTooltip)
{
tooltip = attTooltip.tooltip;
}
else if (att is ObsoleteAttribute attObsolete)
{
isObsolete = true;
obsoleteText = attObsolete.Message;
}
}
if (!string.IsNullOrEmpty(obsoleteText))
{
if (tooltip != null)
tooltip += $"\n[Obsolete: {obsoleteText}";
else
tooltip = $"Obsolete: {obsoleteText}";
}
return new Result(drawer, valueModifiers, accessModifiers, tooltip, isObsolete);
}
private static T InternalCreateInstanceOf<T>(AbstractPropertyAttribute att) where T : AbstractPropertyDrawer
{
if (CACHED_ATT_TO_DRAWER.TryGetValue(att.GetType(), out Type drawerType))
return Activator.CreateInstance(drawerType) as T;
return null;
}
private static T InternalCreateInstanceOf<T>(FieldInfo fieldInfo) where T : AbstractPropertyDrawer
{
if (CACHED_ATT_TO_DRAWER.TryGetValue(fieldInfo.FieldType, out Type drawerType))
return Activator.CreateInstance(drawerType) as T;
return null;
}
/// <summary>
/// Class: Result from property query
/// </summary>
public sealed class Result
{
public readonly ResultValue<DrawerPropertyAttribute, DrawerPropertyDrawer> draw;
public readonly List<ResultValue<ValueModifierPropertyAttribute, ValueModifierPropertyDrawer>> valueModifiers;
public readonly List<ResultValue<AccessModifierPropertyAttribute, AccessModifierPropertyDrawer>> accessModifiers;
public readonly string tooltip;
public readonly bool isObsolete;
public Result(ResultValue<DrawerPropertyAttribute, DrawerPropertyDrawer> draw,
List<ResultValue<ValueModifierPropertyAttribute, ValueModifierPropertyDrawer>> valueModifiers,
List<ResultValue<AccessModifierPropertyAttribute, AccessModifierPropertyDrawer>> accessModifiers,
string tooltip,
bool isObsolete)
{
this.draw = draw;
this.valueModifiers = valueModifiers;
this.accessModifiers = accessModifiers;
this.tooltip = tooltip;
this.isObsolete = isObsolete;
}
public T GetValueModifier<T>() where T : ValueModifierPropertyAttribute
{
for (var i = 0; i < valueModifiers.Count; i++)
{
if (valueModifiers[i].attribute is T att)
return att;
}
return null;
}
public T GetAccessModifier<T>() where T : AccessModifierPropertyAttribute
{
for (var i = 0; i < accessModifiers.Count; i++)
{
if (accessModifiers[i].attribute is T att)
return att;
}
return null;
}
}
/// <summary>
/// Class: Contains attribute and drawer values
/// </summary>
/// <typeparam name="T0"></typeparam>
/// <typeparam name="T1"></typeparam>
public sealed class ResultValue<T0, T1> where T0 : AbstractPropertyAttribute
where T1 : AbstractPropertyDrawer
{
public readonly T0 attribute;
public readonly T1 drawer;
public ResultValue(T0 attribute, T1 drawer)
{
this.attribute = attribute;
this.drawer = drawer;
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dd20b0ba8f5857e4d89bd475e38b7c13
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,56 @@
using System;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace Module.Inspector.Editor.Utilities
{
internal static class EditorSerializedPropertyUtility
{
public static bool IsValue(Object obj, string fieldName, object value, bool useFieldValue)
{
if (obj == null || string.IsNullOrEmpty(fieldName))
return false;
var so = new SerializedObject(obj);
SerializedProperty sp = so.FindProperty(fieldName);
return IsValue(sp, value, useFieldValue);
}
public static bool IsValue(SerializedProperty sp, object value, bool useFieldValue)
{
if (sp == null)
return false;
if (useFieldValue)
{
switch (sp.propertyType)
{
case SerializedPropertyType.Generic:
return value == (object)sp.objectReferenceValue;
case SerializedPropertyType.Integer:
return value is int i && sp.intValue == i;
case SerializedPropertyType.Boolean:
return value is bool b && sp.boolValue == b;
case SerializedPropertyType.Float:
return value is float f && Mathf.Approximately(sp.floatValue, f);
case SerializedPropertyType.String:
return value is string s && sp.stringValue == s;
case SerializedPropertyType.LayerMask:
return value is LayerMask l && sp.intValue == l;
case SerializedPropertyType.Enum:
return value is Enum && sp.intValue == Convert.ToInt32(value);
}
}
else
{
if (sp.propertyType == SerializedPropertyType.Boolean)
return sp.boolValue;
if (sp.propertyType == SerializedPropertyType.ObjectReference)
return sp.objectReferenceValue != null;
}
return true;
}
}
}

Some files were not shown because too many files have changed in this diff Show more